Beispiel #1
0
    def __init__(self, dbPath):
        globs.log.write(1, 'Database.__init__({})'.format(dbPath))

        # First, see if the database is there. If not, need to create it
        isThere = os.path.isfile(dbPath)

        if self.dbConn:
            globs.log.err(
                'SQLite3 error: trying to reinitialize the database connection. Exiting program.'
            )
            globs.closeEverythingAndExit(
                1)  # Abort program. Can't continue with DB error

        try:
            self.dbConn = sqlite3.connect(dbPath)
        except sqlite3.Error as err:
            globs.log.err(
                'SQLite3 error connecting to {}: {}. Exiting program.'.format(
                    dbPath, err.args[0]))
            globs.closeEverythingAndExit(
                1)  # Abort program. Can't continue with DB error

        if not isThere:
            self.dbInitialize()
        return None
Beispiel #2
0
def timeStampCrash(msg):
    globs.log.write(1, msg)
    globs.log.write(
        1,
        'This is likely caused by an email using a different date or time format than expected,\nparticularly if you\'re collecting emails from multiple locations or time zones.'
    )
    globs.log.write(
        1,
        'Please check the \'dateformat=\' and \'timeformat=\' value(s) in the [main] section\nand any [<source>-<destination>] sections of your .rc file for accuracy.'
    )
    globs.log.err(
        'Date/time format specification mismatch. See log file for details. Exiting program.'
    )
    globs.closeEverythingAndExit(1)
Beispiel #3
0
    def execSqlStmt(self, stmt):
        globs.log.write(1, 'Database.execSqlStmt(): Executing SQL command.')
        globs.log.write(3, 'SQL stmt=[{}]'.format(stmt))

        if not self.dbConn:
            return None

        curs = self.dbConn.cursor()
        try:
            curs.execute(stmt)
        except sqlite3.Error as err:
            globs.log.err('SQLite error: {}\n'.format(err.args[0]))
            globs.log.write(1, 'SQLite error: {}\n'.format(err.args[0]))
            globs.closeEverythingAndExit(
                1)  # Abort program. Can't continue with DB error
        return curs
Beispiel #4
0
    def execSqlStmt(self, stmt):
        globs.log.write(globs.SEV_NOTICE, function='Database', action='execSqlStmt', msg='Executing SQL statement: [{}]'.format(stmt))

        if not self.dbConn:
            return None

        # Set db cursor
        curs = self.dbConn.cursor()
        try:
            curs.execute(stmt)
        except sqlite3.Error as err:
            globs.log.write(globs.SEV_ERROR, function='Database', action='execSqlStmt', msg='SQLite error: {}'.format(err.args[0]))
            globs.closeEverythingAndExit(1)  # Abort program. Can't continue with DB error
        
        # Return the cursor to the executed command result.    
        return curs
Beispiel #5
0
    def execReportInsertSql(self, sqlStmt, sqlData):  
        globs.log.write(globs.SEV_NOTICE, function='Database', action='execReportInsertSql', msg='Inserting into emails table: sqlStmt=[{}] sqlData=[{}]'.format(sqlStmt, sqlData))

        if not self.dbConn:
            return None

        # Set db cursor
        curs = self.dbConn.cursor()
        try:
            curs.execute(sqlStmt, sqlData)
        except sqlite3.Error as err:
            globs.log.write(globs.SEV_ERROR, function='Database', action='execReportInsertSql', msg='SQLite error: {}'.format(err.args[0]))
            globs.closeEverythingAndExit(1)  # Abort program. Can't continue with DB error
        
        self.dbCommit()
        return None
Beispiel #6
0
    def __init__(self, dbPath):
        globs.log.write(globs.SEV_NOTICE,function='Database', action='Init', msg='Initializing database manager.')

        # First, see if the database is there. If not, need to create it
        isThere = os.path.isfile(dbPath)

        if self.dbConn:     # If not None then DB connection already exists. This is bad.
            globs.log.write(globs.SEV_ERROR, function='Database', action='Init', msg='SQLite3 Error: trying to reinitialize the database connection. Exiting program.')
            globs.closeEverythingAndExit(1) # Abort program. Can't continue with DB error

        try:
            self.dbConn = sqlite3.connect(dbPath)   # Connect to database
        except sqlite3.Error as err:
            globs.log.write(globs.SEV_ERROR, function='Database', action='Init', msg='SQLite3 error connecting to database: {}. Exiting program.'.format(err.args[0]))
            globs.closeEverythingAndExit(1) # Abort program. Can't continue with DB error

        if not isThere:     # Database did not exist. Need to initialize contents
            globs.log.write(globs.SEV_NOTICE, function='Database', action='Init', msg='New database. Needs initializing.')
            self.dbInitialize()
        return None
Beispiel #7
0
    def execEmailInsertSql(self, emailParts):  
        globs.log.write(globs.SEV_NOTICE, function='Database', action='execEmailInsertSql', msg='Inserting into emails table: messageId={}  sourceComp={}  destComp={}'.format(emailParts['header']['messageId'], emailParts['header']['sourceComp'], emailParts['header']['destComp']))

        durVal = float(emailParts['body']['endTimestamp']) - float(emailParts['body']['beginTimestamp'])
        sqlStmt = "INSERT INTO emails(messageId, sourceComp, destComp, emailTimestamp, \
            deletedFiles, deletedFolders, modifiedFiles, examinedFiles, \
            openedFiles, addedFiles, sizeOfModifiedFiles, sizeOfAddedFiles, sizeOfExaminedFiles, \
            sizeOfOpenedFiles, notProcessedFiles, addedFolders, tooLargeFiles, filesWithError, \
            modifiedFolders, modifiedSymlinks, addedSymlinks, deletedSymlinks, partialBackup, \
            dryRun, mainOperation, parsedResult, verboseOutput, verboseErrors, endTimestamp, \
            beginTimestamp, duration, messages, warnings, errors, dbSeen, dupversion, logdata, bytesUploaded, bytesDownloaded) \
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)"

        data  = (emailParts['header']['messageId'], emailParts['header']['sourceComp'], emailParts['header']['destComp'], emailParts['header']['emailTimestamp'], emailParts['body']['deletedFiles'], \
                emailParts['body']['deletedFolders'], emailParts['body']['modifiedFiles'], emailParts['body']['examinedFiles'], emailParts['body']['openedFiles'], \
                emailParts['body']['addedFiles'], emailParts['body']['sizeOfModifiedFiles'], emailParts['body']['sizeOfAddedFiles'], emailParts['body']['sizeOfExaminedFiles'], emailParts['body']['sizeOfOpenedFiles'], \
                emailParts['body']['notProcessedFiles'], emailParts['body']['addedFolders'], emailParts['body']['tooLargeFiles'], emailParts['body']['filesWithError'], \
                emailParts['body']['modifiedFolders'], emailParts['body']['modifiedSymlinks'], emailParts['body']['addedSymlinks'], emailParts['body']['deletedSymlinks'], \
                emailParts['body']['partialBackup'], emailParts['body']['dryRun'], emailParts['body']['mainOperation'], emailParts['body']['parsedResult'], emailParts['body']['verboseOutput'], \
                emailParts['body']['verboseErrors'], emailParts['body']['endTimestamp'], emailParts['body']['beginTimestamp'], \
                durVal, emailParts['body']['messages'], emailParts['body']['warnings'], emailParts['body']['errors'], emailParts['body']['dupversion'], emailParts['body']['logdata'], emailParts['body']['bytesUploaded'], emailParts['body']['bytesDownloaded'])

        globs.log.write(globs.SEV_DEBUG, function='Database', action='execEmailInsertSql', msg='sqlStmt=[{}]'.format(sqlStmt))
        globs.log.write(globs.SEV_DEBUG, function='Database', action='execEmailInsertSql', msg='data=[{}]'.format(data))

        if not self.dbConn:
            return None

        # Set db cursor
        curs = self.dbConn.cursor()
        try:
            curs.execute(sqlStmt, data)
        except sqlite3.Error as err:
            globs.log.write(globs.SEV_ERROR, function='Database', action='execEmailInsertSql', msg='SQLite error: {}'.format(err.args[0]))
            globs.closeEverythingAndExit(1)  # Abort program. Can't continue with DB error
        
        self.dbCommit()
        return None
Beispiel #8
0
    def __init__(self):
        globs.log.write(1,'Report:__init__()')
        
        self.reportOpts = {}    # Dictionary of report options
        self.reportTits = {}    # Dictionary of report titles
        titTmp = {}
        
        # Read name/value pairs from [report] section
        self.reportOpts = globs.optionManager.getRcSection('report')

        # Fix some of the data field types
        self.reportOpts['border'] = int(self.reportOpts['border'])    # integer
        self.reportOpts['padding'] = int(self.reportOpts['padding'])  # integer
        self.reportOpts['showsizedisplay'] = self.reportOpts['showsizedisplay'].lower() in ('true')     # Convert to boolean
        self.reportOpts['displaymessages'] = self.reportOpts['displaymessages'].lower() in ('true')     # Convert to boolean
        self.reportOpts['displaywarnings'] = self.reportOpts['displaywarnings'].lower() in ('true')     # Convert to boolean
        self.reportOpts['displayerrors'] = self.reportOpts['displayerrors'].lower() in ('true')         # Convert to boolean
        self.reportOpts['repeatheaders'] = self.reportOpts['repeatheaders'].lower() in ('true')         # Convert to boolean
        self.reportOpts['nobackupwarn'] = int(self.reportOpts['nobackupwarn'])  # integer


        # Basic field value checking
        # See if valid report name
        rptName = globs.progPath + '/rpt_' + self.reportOpts['style'] + '.py'
        validReport = os.path.isfile(rptName)
        if not validReport:
            globs.log.err('Invalid RC report style option in [report] section: style cannot be \'{}\''.format(self.reportOpts['style']))
            globs.closeEverythingAndExit(1)

        if self.reportOpts['sortby'] not in ('source', 'destination', 'date', 'time'):
            globs.log.err('Invalid RC file sorting option in [report] section: sortby cannot be \'{}\''.format(self.reportOpts['sortby']))
            globs.closeEverythingAndExit(1)

        if self.reportOpts['sizedisplay'].lower()[:4] not in ('byte', 'mega', 'giga'):
            globs.log.err('Invalid RC file size display option in [report] section: sizedisplay cannot be \'{}\''.format(self.reportOpts['sizedisplay']))
            globs.closeEverythingAndExit(1)

        # Get list of existing headers in [headings] section
        titTmp = globs.optionManager.getRcSection('headings')
        if titTmp is not None:
            for name in titTmp:
                if titTmp[name] == '':  # Empty string means column is not to be displayed
                    rptColumns.remove(name)
                else:
                    self.reportTits[name] = titTmp[name]

        # Remove these columns from the column list. We deal with these separately in the reports
        rptColumns.remove('jobmessages')
        rptColumns.remove('jobwarnings')
        rptColumns.remove('joberrors')

        globs.log.write(3, 'Report: reportOps=[{}]'.format(self.reportOpts))
        globs.log.write(3, 'Report: reportTits=[{}]'.format(self.reportTits))
        globs.log.write(3, 'Report: rptColumns=[{}]'.format(rptColumns))

        return None
Beispiel #9
0
                    msg='Python version {}'.format(sys.version))
    globs.log.write(globs.SEV_NOTICE,
                    function='main',
                    action='startup',
                    msg='OS Platform: {}'.format(platform.platform()))
    globs.log.write(globs.SEV_NOTICE,
                    function='main',
                    action='startup',
                    msg='Program path: {}'.format(globs.progPath))
    # Check if we're running a compatible version of Python. Must be 3.0 or higher
    if sys.version_info.major < 3:
        globs.log.err(
            'dupReport requires Python 3.0 or higher to run. Your installation is on version {}.{}.{}.\nPlease install a newer version of Python.'
            .format(sys.version_info.major, sys.version_info.minor,
                    sys.version_info.micro))
        globs.closeEverythingAndExit(1)

    # Start Program Timer
    startTime = time.time()

    # Initialize program options
    # This includes command line options and .rc file options
    canContinue = options.initOptions()
    if not canContinue:  # Something changed in the .rc file that needs manual editing
        globs.closeEverythingAndExit(1)

    # Looking for version info on command line? (-V)
    if globs.opts['version']:  # Print version info & exit
        versionInfo()
        globs.closeEverythingAndExit(0)
Beispiel #10
0
    def __init__(self):
        globs.log.write(globs.SEV_NOTICE,
                        function='Apprise',
                        action='Init',
                        msg='Initializing Apprise support')

        import apprise

        # Read name/value pairs from [apprise] section
        self.appriseOpts = globs.optionManager.getRcSection('apprise')

        if 'services' not in self.appriseOpts:
            globs.log.write(
                globs.SEV_ERROR,
                function='Apprise',
                action='Init',
                msg='Error: No services defined for Apprise notification')
            globs.closeEverythingAndExit(1)  # Abort program. Can't continue

        # Set defaults for missing values
        self.appriseOpts[
            'title'] = 'Apprise Notification for #SRCDEST# Backup' if 'title' not in self.appriseOpts else self.appriseOpts[
                'title']
        self.appriseOpts[
            'body'] = 'Completed at #COMPLETETIME#: #RESULT# - #ERRMSG#' if 'body' not in self.appriseOpts else self.appriseOpts[
                'body']
        self.appriseOpts[
            'titletruncate'] = '0' if 'titletruncate' else self.appriseOpts[
                'titletruncate']
        self.appriseOpts[
            'bodytruncate'] = '0' if 'bodytruncate' not in self.appriseOpts else self.appriseOpts[
                'bodytruncate']
        self.appriseOpts[
            'msglevel'] = 'failure' if 'msglevel' not in self.appriseOpts else self.appriseOpts[
                'msglevel']

        # Normalize .rc values
        self.appriseOpts['titletruncate'] = int(
            self.appriseOpts['titletruncate'])
        self.appriseOpts['bodytruncate'] = int(
            self.appriseOpts['bodytruncate'])
        self.appriseOpts['msglevel'] = self.appriseOpts['msglevel'].lower()

        # Check for correct message level indicator
        if self.appriseOpts['msglevel'] not in ('success', 'warning',
                                                'failure'):
            globs.log.write(globs.SEV_ERROR,
                            function='Apprise',
                            action='Init',
                            msg='Error: Bad apprise message level: {}'.format(
                                self.appriseOpts['msglevel']))
            globs.closeEverythingAndExit(1)  # Abort program. Can't continue.

        # Initialize apprise library
        result = self.appriseConn = apprise.Apprise()
        globs.log.write(
            globs.SEV_NOTICE,
            function='Apprise',
            action='Init',
            msg='Initializing Apprise library. Result={}'.format(result))

        # Add individual service URLs to connection
        self.services = self.appriseOpts['services'].split(",")
        for i in self.services:
            result = self.appriseConn.add(i)
            globs.log.write(globs.SEV_NOTICE,
                            function='Apprise',
                            action='Init',
                            msg='Added service {}, result={}'.format(
                                i, result))

        globs.log.write(globs.SEV_NOTICE,
                        function='Apprise',
                        action='Init',
                        msg='Apprise Initialization complete.')
        return None
Beispiel #11
0
    def connect(self):
        globs.log.write(1, 'EmailServer.Connect({})'.format(self.dump()))
        globs.log.write(
            3, 'server={} keepalive={}'.format(self.server, self.keepalive))

        # See if a server connection is already established
        # This is the most common case, so check this first
        if self.server != None:
            if self.keepalive is False:  # Do we care about keepalives?
                return None

            globs.log.write(3, 'Cheeking server connection')
            if self.protocol == 'imap':
                try:
                    status = self.server.noop()[0]
                except:
                    status = 'NO'

                if status != 'OK':
                    globs.log.write(
                        1, 'Server {} timed out. Reconnecting.'.format(
                            self.address))
                    self.server = None
                    self.connect()
            elif self.protocol == 'pop3':
                try:
                    status = self.server.noop()
                except:
                    status = '+NO'

                if status != '+OK':
                    globs.log.write(
                        1, 'Server {} timed out. Reconnecting.'.format(
                            self.address))
                    self.server = None
                    self.connect()
            elif self.protocol == 'smtp':
                try:
                    status = self.server.noop()[0]
                except:  # smtplib.SMTPServerDisconnected
                    status = -1

                if status != 250:  # Disconnected. Need to reconnect to server
                    globs.log.write(
                        1, 'Server {} timed out. Reconnecting.'.format(
                            self.address))
                    self.server = None
                    self.connect()
        else:  # Need to establish server connection
            if self.protocol == 'imap':
                globs.log.write(1, 'Initial connect using  IMAP')
                try:
                    if self.encryption is not None:
                        self.server = imaplib.IMAP4_SSL(
                            self.address, self.port)
                    else:
                        self.server = imaplib.IMAP4(self.address, self.port)
                    retVal, data = self.server.login(self.accountname,
                                                     self.passwd)
                    globs.log.write(
                        3, 'IMAP Logged in. retVal={} data={}'.format(
                            retVal, data))
                    retVal, data = self.server.select(self.folder)
                    globs.log.write(
                        3, 'IMAP Setting folder. retVal={} data={}'.format(
                            retVal, data))
                    return retVal
                except imaplib.IMAP4.error:
                    return None
                except imaplib.socket.gaierror:
                    return None
            elif self.protocol == 'pop3':
                globs.log.write(1, 'Initial connect using POP3')
                try:
                    if self.encryption is not None:
                        self.server = poplib.POP3_SSL(self.address, self.port)
                    else:
                        self.server = poplib.POP3(self.address, self.port)
                    retVal = self.server.user(self.accountname)
                    globs.log.write(3, 'Logged in. retVal={}'.format(retVal))
                    retVal = self.server.pass_(self.passwd)
                    globs.log.write(
                        3, 'Entered password. retVal={}'.format(retVal))
                    return retVal.decode()
                except Exception:
                    return None
            elif self.protocol == 'smtp':
                globs.log.write(1, 'Initial connect using  SMTP')
                try:
                    self.server = smtplib.SMTP('{}:{}'.format(
                        self.address, self.port))
                    if self.encryption is not None:  # Do we need to use SSL/TLS?
                        self.server.starttls()
                    retVal, retMsg = self.server.login(self.accountname,
                                                       self.passwd)
                    globs.log.write(
                        3, 'Logged in. retVal={} retMsg={}'.format(
                            retVal, retMsg))
                    return retMsg.decode()
                except (smtplib.SMTPAuthenticationError,
                        smtplib.SMTPConnectError, smtplib.SMTPSenderRefused):
                    return None
            else:  # Bad protocol specification
                globs.log.err(
                    'Invalid protocol specification: {}. Aborting program.'.
                    format(self.protocol))
                globs.closeEverythingAndExit(1)
                return None
        return None