def runTest(self):
     self.setUp()
     try:
         self.RoundTrip()
         self.BackwardsCompatibility()
     finally:
         # otherwise test hangs waiting for Timer thread to finish
         waitForDeferred(MasterPassword.clear())
Example #2
0
 def runTest(self):
     self.setUp()
     try:
         self.RoundTrip()
         self.BackwardsCompatibility()
     finally:
         # otherwise test hangs waiting for Timer thread to finish
         waitForDeferred(MasterPassword.clear())
    def runTest(self):
        self.setUp()
        self.dir = os.path.join(
            os.getenv("CHANDLERHOME") or ".", "parcels", "osaf", "tests")
        self.restoreSettings()

        prefs = schema.ns("osaf.framework.MasterPassword",
                          self.view).masterPasswordPrefs
        saved = os.path.join(self.dir, 'save.ini')

        settings.save(self.view, saved)

        try:
            self.restoreSettings(filename='save.ini')
            MasterPassword._change('', 'foo', self.view, prefs)
            settings.save(self.view, saved)
            self.restoreSettings(filename='save.ini', masterPassword='******')
        finally:
            os.remove(saved)
            waitForDeferred(MasterPassword.clear())
Example #4
0
    def runTest(self):
        self.setUp()
        self.dir = os.path.join(os.getenv("CHANDLERHOME") or ".",
            "parcels", "osaf", "tests")
        self.restoreSettings()

        prefs = schema.ns("osaf.framework.MasterPassword",
                  self.view).masterPasswordPrefs
        saved = os.path.join(self.dir, 'save.ini')
        
        settings.save(self.view, saved)
        
        try:
            self.restoreSettings(filename='save.ini')
            MasterPassword._change('', 'foo', self.view, prefs)
            settings.save(self.view, saved)
            self.restoreSettings(filename='save.ini', masterPassword='******')
        finally:
            os.remove(saved)
            waitForDeferred(MasterPassword.clear())
Example #5
0
    def encryptPassword(self, password, masterPassword=None, window=None):
        """
        Encrypt and store password.
        
        @raise NoMasterPassword: NoMasterPassword will be raised if 
                                 masterPassword parameter is None and we have a
                                 non-default master password that has timed out,
                                 and the user cancels the dialog where we ask for
                                 it.

        @raise PasswordTooLong:  Password is too long.

        @param password: The password to store
        @type param:     str or unicode
        """
        if masterPassword is None:
            masterPassword = waitForDeferred(MasterPassword.get(self.itsView, window))
            
        # the crypto algorithms are unicode unfriendly
        if isinstance(password, unicode):
            password = password.encode('utf8')
        if isinstance(masterPassword, unicode):
            masterPassword = masterPassword.encode('utf8')
        
        # get 256 bit random encryption salt
        self.salt = os.urandom(32)
        # derive 256 bit encryption key using the pbkdf2 standard
        key = EVP.pbkdf2(masterPassword, self.salt, iter=1000, keylen=32)
        
        # Derive encryption key and HMAC key from it
        # See Practical Cryptography section 8.4.1.
        hmacKey = sha256(key + 'MAC').digest()
        encKey = sha256(key + 'encrypt').digest()
        del key

        # get 256 bit random iv
        self.iv = os.urandom(32)

        # Add HMAC to password so that we can check during decrypt if we got
        # the right password back. We are doing sign-then-encrypt, which let's
        # us encrypt empty passwords (otherwise we'd need to pad with some
        # string to encrypt). Practical Cryptography by Schneier & Ferguson
        # also recommends doing it in this order in section 8.2.
        mac = hmac.new(hmacKey,
                       password + self.iv + self.salt,
                       sha256).hexdigest()
        del hmacKey

        # encrypt using AES (Rijndael)
        try:
            self.ciphertext = encrypt(password + mac, encKey, self.iv)
        except EVP.EVPError, e:
            raise EncryptionError(str(e))
Example #6
0
    def decryptPassword(self, masterPassword=None, window=None):
        """
        Decrypt password and return it.
        
        @raise NoMasterPassword: NoMasterPassword will be raised if 
                                 masterPassword parameter is None and we have a
                                 non-default master password that has timed out,
                                 and the user cancels the dialog where we ask for
                                 it.

        @raise PasswordTooLong:  Password is too long.

        @return: Return password.
        @rtype:  unicode
        """
        try:
            if not self.ciphertext or not self.iv or not self.salt:
                return u''
        except AttributeError:
            # We can determine the correct master password by iterating over
            # passwords, decrypting them, and getting at least one non-empty
            # password.
            return u''
        
        if len(self.ciphertext) > 1024:
            waitForDeferred(self.clear())
            raise PasswordTooLong(_(u'Password is too long'))
        
        if masterPassword is None:
            masterPassword = waitForDeferred(MasterPassword.get(self.itsView, window))
        
        # the crypto algorithms are unicode unfriendly
        if isinstance(masterPassword, unicode):
            masterPassword = masterPassword.encode('utf8')

        # derive 256 bit key using the pbkdf2 standard
        key = EVP.pbkdf2(masterPassword, self.salt, iter=1000, keylen=32)

        # Derive encryption key and HMAC key from it
        # See Practical Cryptography section 8.4.1.
        hmacKey = sha256(key + 'MAC').digest()
        encKey = sha256(key + 'encrypt').digest()
        del key
        
        # decrypt
        try:
            ret = decrypt(self.ciphertext, encKey, self.iv)
        except EVP.EVPError, e:
            raise DecryptionError(str(e))
    def RoundTrip(self):

        filename = "tmp_dump_file"

        view0 = self.views[0]
        view1 = self.views[1]

        # uuids to dump; add your items to this:
        uuids = set()

        # Prepare test data

        coll0 = pim.SmartCollection("testCollection",
                                    itsView=view0,
                                    displayName="Test Collection")
        uuids.add(coll0.itsUUID)

        titles = [
            u"dunder",
            u"mifflin",
        ]

        tzinfo = view0.tzinfo.floating
        createdOn = datetime.datetime(2007, 3, 1, 10, 0, 0, 0, tzinfo)
        lastModified = datetime.datetime(2007, 3, 1, 12, 0, 0, 0, tzinfo)
        email = "*****@*****.**"
        emailAddress = pim.EmailAddress.getEmailAddress(view0, email)

        count = len(titles)
        for i in xrange(count):
            n = pim.Note(itsView=view0)
            n.createdOn = createdOn
            n.displayName = titles[i % count]
            n.body = u"Here is the body"
            n.lastModifiedBy = emailAddress
            n.lastModified = lastModified
            coll0.add(n)
            uuids.add(n.itsUUID)

        # Read/unread items
        readNote = pim.Note(itsView=view0, read=True)
        unreadNote = pim.Note(itsView=view0, read=False)

        # "Private" items
        publicNote = pim.Note(itsView=view0, private=False)
        privateNote = pim.Note(itsView=view0, private=True)

        # Mine/Not-Mine/Dashboard

        directlyInDashboard = pim.Note(itsView=view0)
        dashboard = schema.ns("osaf.pim", view0).allCollection
        dashboard.add(directlyInDashboard)

        aMineCollection = pim.SmartCollection(itsView=view0)
        schema.ns('osaf.pim', view0).mine.addSource(aMineCollection)
        inMine = pim.Note(itsView=view0)
        aMineCollection.add(inMine)

        aNotMineCollection = pim.SmartCollection(itsView=view0)
        inNotMine = pim.Note(itsView=view0)
        aNotMineCollection.add(inNotMine)

        trash = schema.ns("osaf.pim", view0).trashCollection
        trashTestCollection = pim.SmartCollection(itsView=view0)
        trashedItem = pim.Note(itsView=view0)
        trashTestCollection.add(trashedItem)
        trash.add(trashedItem)
        self.assert_(trashedItem in trashTestCollection.inclusions)
        self.assert_(trashedItem not in trashTestCollection)
        self.assert_(trashedItem in trash)

        # Sharing related items
        account0 = sharing.CosmoAccount(itsView=view0,
                                        host="chandler.o11n.org",
                                        port=8080,
                                        path="/cosmo",
                                        username="******",
                                        password=Password(itsView=view0),
                                        useSSL=True)
        waitForDeferred(account0.password.encryptPassword('4cc0unt0'))
        uuids.add(account0.itsUUID)
        cosmo_conduit0 = sharing.CosmoConduit(
            itsView=view0,
            account=account0,
            shareName=coll0.itsUUID.str16(),
            translator=sharing.SharingTranslator,
            serializer=sharing.EIMMLSerializer)
        uuids.add(cosmo_conduit0.itsUUID)
        cosmo_share0 = sharing.Share(itsView=view0,
                                     contents=coll0,
                                     conduit=cosmo_conduit0)
        uuids.add(cosmo_share0.itsUUID)

        hub_account0 = sharing.HubAccount(
            itsView=view0,
            username="******",
            password=Password(itsView=view0),
        )
        waitForDeferred(hub_account0.password.encryptPassword('4cc0unt0'))
        uuids.add(hub_account0.itsUUID)

        inmemory_conduit0 = sharing.InMemoryDiffRecordSetConduit(
            itsView=view0,
            shareName="in_memory",
            translator=sharing.SharingTranslator,
            serializer=sharing.EIMMLSerializer)
        uuids.add(inmemory_conduit0.itsUUID)

        inmemory_share0 = sharing.Share(itsView=view0,
                                        conduit=inmemory_conduit0,
                                        contents=coll0)
        uuids.add(inmemory_share0.itsUUID)

        # Create some State objects
        inmemory_share0.create()
        view0.commit()
        inmemory_share0.sync()
        for state in inmemory_share0.states:
            uuids.add(state.itsUUID)
        # Set one of the states to be a pendingRemoval
        pendingRemoval = state.itsUUID
        state.pendingRemoval = True

        # Peer states
        peerNote = pim.Note(itsView=view0)
        peerAddress = pim.EmailAddress(
            itsView=view0,
            fullName="Michael Scott",
            emailAddress="*****@*****.**")
        peerState = sharing.State(
            itsView=view0,
            conflictFor=peerNote,
            peer=peerAddress,
        )
        sharing.SharedItem(peerNote).add()
        sharedPeerNote = sharing.SharedItem(peerNote)
        sharedPeerNote.peerStates = []
        sharedPeerNote.peerStates.append(peerState,
                                         peerAddress.itsUUID.str16())
        uuids.add(peerNote.itsUUID)
        uuids.add(peerAddress.itsUUID)
        uuids.add(peerState.itsUUID)

        # Sharing proxy
        proxy = sharing.getProxy(view0)
        proxy.host = "host"
        proxy.port = 123
        proxy.username = "******"
        proxy.passwd = "password"
        proxy.active = True
        proxy.useAuth = True
        proxy.bypass = "******"
        uuids.add(proxy.itsUUID)

        # Online state
        schema.ns('osaf.app', view0).prefs.isOnline = False
        schema.ns('osaf.sharing', view0).prefs.isOnline = False

        #Mail Accounts

        imapAddress = mail.EmailAddress.getEmailAddress(
            view0, "*****@*****.**", "test")

        popAddress = mail.EmailAddress.getEmailAddress(view0, "*****@*****.**",
                                                       "test1")

        smtpOldAddress = mail.EmailAddress.getEmailAddress(
            view0, "*****@*****.**", "test2")

        smtpNewAddress = mail.EmailAddress.getEmailAddress(
            view0, "*****@*****.**", "test3")

        testFolder = mail.IMAPFolder(itsView=view0,
                                     displayName="TestFolder",
                                     folderName="INBOX.TestFolder",
                                     folderType="MAIL")

        queuedMessage0 = pim.MailStamp(pim.Note(itsView=view0))
        queuedMessage0.add()

        queuedMessage0.subject = "Test for SMTP Queue"

        uuids.add(queuedMessage0.itsItem.itsUUID)

        imapaccount0 = mail.IMAPAccount(
            itsView=view0,
            displayName="IMAP Test",
            host="localhost",
            port=143,
            username="******",
            password=Password(itsView=view0),
            connectionSecurity="TLS",
            numRetries=2,
            pollingFrequency=300,
            isActive=False,
            replyToAddress=imapAddress,
            folders=[testFolder],
        )
        waitForDeferred(imapaccount0.password.encryptPassword('imap4acc0unt0'))

        uuids.add(imapaccount0.itsUUID)

        popaccount0 = mail.POPAccount(
            itsView=view0,
            displayName="POP Test",
            host="localhost",
            port=110,
            username="******",
            password=Password(itsView=view0),
            connectionSecurity="NONE",
            numRetries=3,
            pollingFrequency=200,
            isActive=True,
            replyToAddress=popAddress,
        )
        waitForDeferred(popaccount0.password.encryptPassword('pop4acc0unt0'))

        uuids.add(popaccount0.itsUUID)

        smtpaccount0 = mail.SMTPAccount(
            itsView=view0,
            displayName="SMTP Test",
            host="localhost",
            port=587,
            username="******",
            password=Password(itsView=view0),
            connectionSecurity="SSL",
            numRetries=5,
            pollingFrequency=500,
            isActive=True,
            fromAddress=smtpOldAddress,
            useAuth=True,
            messageQueue=[queuedMessage0.itsItem],
        )
        waitForDeferred(smtpaccount0.password.encryptPassword('smtp4acc0unt0'))

        # This orphans smtpOldAddress leaving it as
        # an old me address which is stored in the
        # meEmailAddressCollection.
        # The purpose of this is to test dump and reload
        # of the meEmailAddressCollection.
        smtpaccount0.fromAddress = smtpNewAddress

        uuids.add(smtpaccount0.itsUUID)

        #Take the mail service offline
        schema.ns("osaf.pim", view0).MailPrefs.isOnline = False

        # Calendar prefs
        pref = schema.ns('osaf.pim', view0).TimezonePrefs
        pref.showUI = True  # change from default
        pref.showPrompt = False  # change from default

        pref = schema.ns('osaf.framework.blocks.calendar', view0).calendarPrefs
        pref.hourHeightMode = "auto"
        pref.visibleHours = 20

        # TODO: TimeZoneInfo

        # passwords
        pw = Password(itsView=view0)
        waitForDeferred(pw.encryptPassword('foobar'))
        uuids.add(pw.itsUUID)
        # password prefs
        mpwPrefs = schema.ns("osaf.framework.MasterPassword",
                             view0).masterPasswordPrefs
        MasterPassword._change('', 'secret', view0, mpwPrefs)
        mpwPrefs.timeout = 10

        # backup on quit preference
        backupPrefs = schema.ns("osaf.app", view0).prefs
        self.assertFalse(hasattr(backupPrefs, 'backupOnQuit'))
        backupPrefs.backupOnQuit = True

        # tip of the day prefs
        self.assertFalse(backupPrefs.showTip)
        self.assertEqual(backupPrefs.tipIndex, 0)
        backupPrefs.tipIndex = 1

        # Ensure sidebar is loaded in view1
        sidebar1 = schema.ns("osaf.app", view1).sidebarCollection

        try:

            dumpreload.dump(view0, filename)
            dumpreload.reload(view1, filename, testmode=True)

            # Ensure the items are now in view1
            for uuid in uuids:
                item0 = view0.findUUID(uuid)
                item1 = view1.findUUID(uuid)

                self.assert_(item1 is not None)
                if hasattr(item0, 'displayName'):
                    self.assertEqual(item0.displayName, item1.displayName)
                if hasattr(item0, 'body'):
                    self.assertEqual(item0.body, item1.body)

            # Verify ContentItem.read
            self.assert_(view1.findUUID(readNote.itsUUID).read is True)
            self.assert_(view1.findUUID(unreadNote.itsUUID).read is False)

            # Verify ContentItem.private
            self.assert_(view1.findUUID(publicNote.itsUUID).private is False)
            self.assert_(view1.findUUID(privateNote.itsUUID).private is True)

            # Verify Mine/Not-Mine/Dashboard
            dashboard = schema.ns("osaf.pim", view1).allCollection
            self.assert_(
                view1.findUUID(directlyInDashboard.itsUUID) in
                dashboard.inclusions)

            self.assert_(view1.findUUID(inMine.itsUUID) in dashboard)
            self.assert_(view1.findUUID(inNotMine.itsUUID) not in dashboard)

            # Verify collection membership:
            coll1 = view1.findUUID(coll0.itsUUID)
            for item0 in coll0:
                item1 = view1.findUUID(item0.itsUUID)
                self.assert_(item1 in coll1)

            # Verify trash membership
            trash = schema.ns("osaf.pim", view1).trashCollection
            trashedItem = view1.findUUID(trashedItem.itsUUID)
            self.assert_(trashedItem in trash)
            trashTestCollection = view1.findUUID(trashTestCollection.itsUUID)
            self.assert_(trashedItem not in trashTestCollection)
            self.assert_(trashedItem in trashTestCollection.inclusions)

            # Verify passwords
            pw1 = view1.findUUID(pw.itsUUID)
            self.assertEqual(waitForDeferred(pw1.decryptPassword('secret')),
                             'foobar')

            mpwPrefs1 = schema.ns("osaf.framework.MasterPassword",
                                  view1).masterPasswordPrefs
            self.assertEqual(mpwPrefs1.masterPassword, True)
            self.assertEqual(mpwPrefs1.timeout, 10)

            pwPrefs1 = schema.ns("osaf.framework.password",
                                 view1).passwordPrefs
            self.assertEqual(
                len(
                    waitForDeferred(
                        pwPrefs1.dummyPassword.decryptPassword('secret'))), 16)
            self.assertEqual(str(pwPrefs1.dummyPassword.itsUUID),
                             'dd555441-9ddc-416c-b55a-77b073c7bd15')
            dummyByUUID = view1.findUUID(
                'dd555441-9ddc-416c-b55a-77b073c7bd15')
            self.assertEqual(dummyByUUID, pwPrefs1.dummyPassword)

            count = 0
            for item in Password.iterItems(view0):
                waitForDeferred(item.decryptPassword('secret'))
                count += 1

            count1 = 0
            for item in Password.iterItems(view1):
                waitForDeferred(item.decryptPassword('secret'))
                count1 += 1

            self.assertEqual(count + 2, count1)  # XXX Shouldn't count==count1?

            # Verify sharing
            account1 = view1.findUUID(account0.itsUUID)
            self.assertEquals(account1.host, "chandler.o11n.org")
            self.assertEquals(account1.port, 8080)
            self.assertEquals(account1.path, "/cosmo")
            self.assertEquals(account1.username, "test")
            self.assertEquals(account1.useSSL, True)
            self.assertEquals(
                waitForDeferred(account1.password.decryptPassword('secret')),
                '4cc0unt0')

            hub_account1 = view1.findUUID(hub_account0.itsUUID)
            self.assert_(isinstance(hub_account0, sharing.HubAccount))

            inmemory_share1 = view1.findUUID(inmemory_share0.itsUUID)
            self.assert_(inmemory_share1 is not None)
            self.assertEqual(inmemory_share0.contents.itsUUID,
                             inmemory_share1.contents.itsUUID)
            self.assertEqual(inmemory_share0.conduit.syncToken,
                             inmemory_share1.conduit.syncToken)
            for state0 in inmemory_share0.states:
                state1 = view1.findUUID(state0.itsUUID)
                self.assert_(state1 in inmemory_share1.states)
                self.assertEqual(state0.agreed, state1.agreed)
                self.assertEqual(state0.pending, state1.pending)
                self.assertEqual(state1.pendingRemoval,
                                 state1.itsUUID == pendingRemoval)
            for item0 in coll0:
                item1 = view1.findUUID(item0.itsUUID)
                sharedItem1 = sharing.SharedItem(item1)
                self.assert_(inmemory_share1 in sharedItem1.sharedIn)

            # Peer states
            peerNote1 = view1.findUUID(peerNote.itsUUID)
            sharedPeerNote1 = sharing.SharedItem(peerNote1)
            peerAddress1 = view1.findUUID(peerAddress.itsUUID)
            peerState1 = view1.findUUID(peerState.itsUUID)
            self.assert_(peerState1 in sharedPeerNote1.peerStates)
            self.assertEquals(sharedPeerNote1.peerStates.getAlias(peerState1),
                              peerAddress1.itsUUID.str16())
            self.assert_(peerState1 in sharedPeerNote1.conflictingStates)
            self.assert_(isinstance(peerAddress1, pim.EmailAddress))

            proxy1 = view1.findUUID(proxy.itsUUID)
            self.assertEquals(proxy1.host, "host")
            self.assertEquals(proxy1.port, 123)
            self.assertEquals(proxy1.username, "username")
            self.assertEquals(proxy1.bypass, "192.168.1, localhost")

            pw = waitForDeferred(proxy1.password.decryptPassword('secret'))
            self.assertEquals(pw, "password")
            self.assertEquals(proxy1.active, True)
            self.assertEquals(proxy1.useAuth, True)

            self.assertEquals(
                schema.ns('osaf.app', view1).prefs.isOnline, False)
            self.assertEquals(
                schema.ns('osaf.sharing', view1).prefs.isOnline, False)

            # Verify Calendar prefs
            pref = schema.ns('osaf.pim', view1).TimezonePrefs
            self.assertEqual(pref.showUI, True)
            self.assertEqual(pref.showPrompt, False)

            pref = schema.ns('osaf.framework.blocks.calendar',
                             view1).calendarPrefs
            self.assertEqual(pref.hourHeightMode, "auto")
            self.assertEqual(pref.visibleHours, 20)

            #Verify Mail Accounts

            imapaccount1 = view1.findUUID(imapaccount0.itsUUID)
            self.assertEquals(imapaccount1.host, "localhost")
            self.assertEquals(imapaccount1.port, 143)
            self.assertEquals(imapaccount1.username, "test")
            self.assertEquals(imapaccount1.connectionSecurity, "TLS")
            self.assertEquals(imapaccount1.numRetries, 2)
            self.assertEquals(imapaccount1.pollingFrequency, 300)
            self.assertEquals(imapaccount1.isActive, False)
            self.assertEquals(imapaccount1.replyToAddress.format(),
                              imapAddress.format())
            self.assertEquals(
                waitForDeferred(
                    imapaccount1.password.decryptPassword('secret')),
                'imap4acc0unt0')

            folder = imapaccount1.folders.first()
            self.assertEquals(folder.displayName, "TestFolder")
            self.assertEquals(folder.folderName, "INBOX.TestFolder")
            self.assertEquals(folder.folderType, "MAIL")

            popaccount1 = view1.findUUID(popaccount0.itsUUID)

            self.assertEquals(popaccount1.host, "localhost")
            self.assertEquals(popaccount1.port, 110)
            self.assertEquals(popaccount1.username, "test1")
            self.assertEquals(popaccount1.connectionSecurity, "NONE")
            self.assertEquals(popaccount1.numRetries, 3)
            self.assertEquals(popaccount1.pollingFrequency, 200)
            self.assertEquals(popaccount1.isActive, True)
            self.assertEquals(popaccount1.replyToAddress.format(),
                              popAddress.format())
            self.assertEquals(
                waitForDeferred(
                    popaccount1.password.decryptPassword('secret')),
                'pop4acc0unt0')

            smtpaccount1 = view1.findUUID(smtpaccount0.itsUUID)

            self.assertEquals(smtpaccount1.host, "localhost")
            self.assertEquals(smtpaccount1.port, 587)
            self.assertEquals(smtpaccount1.username, "test2")
            self.assertEquals(smtpaccount1.connectionSecurity, "SSL")
            self.assertEquals(smtpaccount1.numRetries, 5)
            self.assertEquals(smtpaccount1.pollingFrequency, 500)
            self.assertEquals(smtpaccount1.isActive, True)
            self.assertEquals(smtpaccount1.useAuth, True)
            self.assertEquals(smtpaccount1.fromAddress.format(),
                              smtpNewAddress.format())
            self.assertEquals(
                waitForDeferred(
                    smtpaccount1.password.decryptPassword('secret')),
                'smtp4acc0unt0')

            queuedMessage1 = smtpaccount1.messageQueue[0]

            self.assertEquals(queuedMessage1.itsUUID,
                              queuedMessage0.itsItem.itsUUID)
            self.assertEquals(
                schema.ns("osaf.pim", view1).MailPrefs.isOnline, False)

            col = schema.ns("osaf.pim", view1).meEmailAddressCollection

            found = False
            oldAddr = smtpOldAddress.format()

            # Confirm that the old email address smtpOldAddress
            # is in the meEmailAddressCollection for calculating
            # the MailStamp.fromMe and MailStamp.toMe attributes
            for ea in col:
                if ea.format() == oldAddr:
                    found = True
                    break

            self.assertTrue(found)

            # backup on quit preference
            backupPrefs1 = schema.ns("osaf.app", view1).prefs
            self.assertTrue(backupPrefs1.backupOnQuit)

            # tip of the day prefs
            self.assertFalse(backupPrefs1.showTip)
            self.assertEqual(backupPrefs1.tipIndex, 1)

        finally:
            try:
                os.remove(filename)
            except:
                pass
Example #8
0
def reload(rv, filename, serializer=PickleSerializer, activity=None,
    testmode=False):
    """ Loads EIM records from a file and applies them """

    translator = getTranslator()

    if not testmode:
        oldMaster = waitForDeferred(MasterPassword.get(rv))
    else:
        oldMaster = ''
        newMaster = 'secret'

    if activity is not None:
        activity.update(totalWork=None, msg=_(u"Counting records..."))
        input = open(filename, "rb")
        load = serializer.loader(input)
        i = 0
        while True:
            record = load()
            if not record:
                break
            i += 1
        input.close()
        activity.update(totalWork=i)


    trans = translator(rv)
    trans.startImport()

    input = open(filename, "rb")
    try:
        load = serializer.loader(input)
        i = 0
        while True:
            record = load()
            if not record:
                break
            trans.importRecord(record)
            i += 1
            if activity is not None:
                activity.update(msg=_(u"Imported %(total)d records") % {'total':i}, work=1)
            if i % 1000 == 0: # Commit every 1,000 records
                if activity is not None:
                    activity.update(msg=_(u"Saving..."))
                rv.commit()

        logger.info("Imported %d records", i)

        del load
    finally:
        input.close()

    trans.finishImport()

    if activity is not None:
        activity.update(msg=_(u"Saving..."))
    rv.commit()


    # Passwords that existed before reload are encrypted with oldMaster, and
    # passwords that we reloaded are encrypted with newMaster, so now we need
    # to go through all passwords and re-encrypt all the old ones with
    # newMaster.
    
    # First, let's get the newMaster
    waitForDeferred(MasterPassword.clear())
    if not testmode:
        prefs = schema.ns("osaf.framework.MasterPassword",
                          rv).masterPasswordPrefs
        if prefs.masterPassword:
            wx.MessageBox (_(u"Please enter the master password you used to protect this file to reload account passwords."),
                           _(u'Protect Passwords'),
                           parent=wx.GetApp().mainFrame)
        
        dummy = schema.ns("osaf.framework.password",
                          rv).passwordPrefs.dummyPassword

        while True:
            try:
                newMaster = waitForDeferred(MasterPassword.get(rv, testPassword=dummy))
                break
            except password.NoMasterPassword:
                if wx.MessageBox(_(u'If you do not remember your master password, all account passwords will be deleted. Delete account passwords?'),
                                 _(u'Reset Master Password'),
                                 style = wx.YES_NO,
                                 parent=wx.GetApp().mainFrame) == wx.YES:
                    MasterPassword.reset(rv)
                    return
    
    # Then re-encrypt
    for item in password.Password.iterItems(rv):
        if not waitForDeferred(item.initialized()):
            # Don't need to re-encrypt uninitialized passwords
            continue
        
        try:
            pw = waitForDeferred(item.decryptPassword(masterPassword=oldMaster))
        except password.DecryptionError:
            # Maybe this was one of the new passwords loaded from
            # dump, so let's try the new master password
            try:
                waitForDeferred(item.decryptPassword(masterPassword=newMaster))
            except password.DecryptionError:
                # Oops, we are in trouble, can't really do much but
                # reset() to avoid further problems.
                logger.exception('found passwords that could not be decrypted; clearing passwords')
                MasterPassword.reset(rv)
                break
            # Since this is already encrypted with the new
            # master password we don't need to re-encrypt
            continue

        waitForDeferred(item.encryptPassword(pw, masterPassword=newMaster))
Example #9
0
def reload(rv, filename, serializer=PickleSerializer, activity=None, testmode=False):
    """ Loads EIM records from a file and applies them """

    translator = getTranslator()

    if not testmode:
        oldMaster = waitForDeferred(MasterPassword.get(rv))
    else:
        oldMaster = ""
        newMaster = "secret"

    if activity is not None:
        activity.update(totalWork=None, msg=_(u"Counting records..."))
        input = open(filename, "rb")
        load = serializer.loader(input)
        i = 0
        while True:
            record = load()
            if not record:
                break
            i += 1
        input.close()
        activity.update(totalWork=i)

    trans = translator(rv)
    trans.startImport()

    input = open(filename, "rb")
    try:
        load = serializer.loader(input)
        i = 0
        while True:
            record = load()
            if not record:
                break
            trans.importRecord(record)
            i += 1
            if activity is not None:
                activity.update(msg=_(u"Imported %(total)d records") % {"total": i}, work=1)
            if i % 1000 == 0:  # Commit every 1,000 records
                if activity is not None:
                    activity.update(msg=_(u"Saving..."))
                rv.commit()

        logger.info("Imported %d records", i)

        del load
    finally:
        input.close()

    trans.finishImport()

    if activity is not None:
        activity.update(msg=_(u"Saving..."))
    rv.commit()

    # Passwords that existed before reload are encrypted with oldMaster, and
    # passwords that we reloaded are encrypted with newMaster, so now we need
    # to go through all passwords and re-encrypt all the old ones with
    # newMaster.

    # First, let's get the newMaster
    waitForDeferred(MasterPassword.clear())
    if not testmode:
        prefs = schema.ns("osaf.framework.MasterPassword", rv).masterPasswordPrefs
        if prefs.masterPassword:
            wx.MessageBox(
                _(u"Please enter the master password you used to protect this file to reload account passwords."),
                _(u"Protect Passwords"),
                parent=wx.GetApp().mainFrame,
            )

        dummy = schema.ns("osaf.framework.password", rv).passwordPrefs.dummyPassword

        while True:
            try:
                newMaster = waitForDeferred(MasterPassword.get(rv, testPassword=dummy))
                break
            except password.NoMasterPassword:
                if (
                    wx.MessageBox(
                        _(
                            u"If you do not remember your master password, all account passwords will be deleted. Delete account passwords?"
                        ),
                        _(u"Reset Master Password"),
                        style=wx.YES_NO,
                        parent=wx.GetApp().mainFrame,
                    )
                    == wx.YES
                ):
                    MasterPassword.reset(rv)
                    return

    # Then re-encrypt
    for item in password.Password.iterItems(rv):
        if not waitForDeferred(item.initialized()):
            # Don't need to re-encrypt uninitialized passwords
            continue

        try:
            pw = waitForDeferred(item.decryptPassword(masterPassword=oldMaster))
        except password.DecryptionError:
            # Maybe this was one of the new passwords loaded from
            # dump, so let's try the new master password
            try:
                waitForDeferred(item.decryptPassword(masterPassword=newMaster))
            except password.DecryptionError:
                # Oops, we are in trouble, can't really do much but
                # reset() to avoid further problems.
                logger.exception("found passwords that could not be decrypted; clearing passwords")
                MasterPassword.reset(rv)
                break
            # Since this is already encrypted with the new
            # master password we don't need to re-encrypt
            continue

        waitForDeferred(item.encryptPassword(pw, masterPassword=newMaster))
    def testMasterPassword(self):
        self.loadParcel("osaf.framework.MasterPassword")
        self.loadParcel("osaf.framework.password")
        self.loadParcel("osaf.app") # Include default Passwords in count

        # Check master password when it is not set
        masterPassword = waitForDeferred(MasterPassword.get(self.view))
        self.assertEqual(masterPassword, '')

        prefs = schema.ns("osaf.framework.MasterPassword",
                          self.view).masterPasswordPrefs

        # check prefs
        self.assertEqual(prefs.masterPassword, False)
        self.assertEqual(prefs.timeout, 15)

        prefs.masterPassword = True

        # make sure that get at least tries to use wx, and creates MasterPassword
        self.assertRaises(wx.PyNoAppError, waitForDeferred, MasterPassword.get(self.view))
        self.assertTrue(MasterPassword._masterPassword is None)
        self.assertTrue(MasterPassword._timer is None)

        # make sure we get the password ok when it's set
        MasterPassword._masterPassword = '******'
        self.assertEqual(waitForDeferred(MasterPassword.get(self.view)), 'pass')
        
        # timeout
        prefs.timeout = 1.0/60.0 # 1 second
        MasterPassword._setTimedPassword('pass', 1)
        self.assertEqual(waitForDeferred(MasterPassword.get(self.view)), 'pass')
        time.sleep(1.1)
        # XXX Don't know how to test timeout, _clear is called and d.addCallback has been called
        # XXX but what do we need to do to process those callbacks?
        #self.assertRaises(wx.PyNoAppError, waitForDeferred, MasterPassword.get(self.view))
        prefs.timeout = 15

        waitForDeferred(MasterPassword.clear())
        
        # make sure that change at least tries to use wx, and creates MasterPassword
        self.assertRaises(wx.PyNoAppError, waitForDeferred, MasterPassword.change(self.view))
        self.assertTrue(MasterPassword._masterPassword is None)
        self.assertTrue(MasterPassword._timer is None)

        # change for real
        # make some passwords to change
        pw1 = password.Password(itsView=self.view)
        pw2 = password.Password(itsView=self.view)
        waitForDeferred(pw1.encryptPassword('foobar', masterPassword=''))
        waitForDeferred(pw2.encryptPassword('barfoo', masterPassword=''))
        # try with bad old password first
        self.assertFalse(MasterPassword._change('dont know',
                                                'secret',
                                                self.view,
                                                prefs))
        # now change
        self.assertTrue(MasterPassword._change('', 'secret',
                                               self.view,
                                               prefs))
        # verify that the new password works
        self.assertEqual(waitForDeferred(pw1.decryptPassword(masterPassword='******')), u'foobar')
        self.assertEqual(waitForDeferred(pw2.decryptPassword(masterPassword='******')), u'barfoo')
        # and that the old raises the correct exception
        self.assertRaises(password.DecryptionError, waitForDeferred, pw1.decryptPassword(masterPassword=''))
        self.assertRaises(password.DecryptionError, waitForDeferred, pw2.decryptPassword(masterPassword=''))

        # clear
        MasterPassword._masterPassword = '******'
        waitForDeferred(MasterPassword.clear())
        self.assertTrue(MasterPassword._masterPassword is None)
        self.assertTrue(MasterPassword._timer is None)

        # reset
        count = 0
        for item in password.Password.iterItems(self.view):
            count += 1
        self.assertEqual(count, 8) # dummy + 2 above + 6 default
        MasterPassword.reset(self.view) # now reset
        self.assertTrue(MasterPassword._masterPassword is None)
        self.assertTrue(MasterPassword._timer is None)
        # we should have just one initialized password (the dummy)
        count = 0
        for item in password.Password.iterItems(self.view):
            if not waitForDeferred(item.initialized()):
                continue
            
            waitForDeferred(item.decryptPassword(masterPassword=''))
            self.assertEqual(item.itsName, 'dummyPassword')
            count += 1
        self.assertEqual(count, 1)
        
        # quality tests
        self.assertEqual(MasterPassword.quality(''), (0, 35))
        self.assertEqual(MasterPassword.quality('a'), (0, 35))
        self.assertEqual(MasterPassword.quality('abb'), (6, 35))
        self.assertEqual(MasterPassword.quality('aghj5s'), (14, 35))
        self.assertEqual(MasterPassword.quality('aGhj5s'), (16, 35))
        self.assertEqual(MasterPassword.quality('aGh!5s'), (21, 35))
        self.assertEqual(MasterPassword.quality('aGh!5s.Vos2dd'), (34, 35))
        self.assertEqual(MasterPassword.quality('aGh!5s.Vos2ddd'), (35, 35))
        self.assertEqual(MasterPassword.quality('aGh!5s.Vos2dddF#@8'), (35, 35))
        self.assertEqual(MasterPassword.quality(uw('aghj5s')), (18, 35)) #i18n
Example #11
0
def restoreMasterPassword(rv, cfg, testmode, oldMaster, newMaster):
    for sectionname, section in cfg.iteritems():
        if sectionname == u"master_password":
            prefs = schema.ns("osaf.framework.MasterPassword", rv).masterPasswordPrefs
            if section.has_key(u"masterPassword"):
                prefs.masterPassword = section.as_bool(u"masterPassword")
            if section.has_key(u"timeout"):
                prefs.timeout = section.as_int(u"timeout")
            if section.has_key(u"protect"):
                prefs.protect = section.as_bool(u"protect")
            dummy = schema.ns("osaf.framework.password", rv).passwordPrefs.dummyPassword
            try:
                iv, salt, ciphertext = section[u"dummyPassword"].split('|')
                dummy.iv = unhexlify(iv)
                dummy.salt = unhexlify(salt)
                dummy.ciphertext = unhexlify(ciphertext)
            except:
                # Oops, we are in trouble, can't really do much but reset()
                # to avoid further problems.
                logger.exception('settings had master_password section but no dummyPassword; clearing passwords')
                MasterPassword.reset(rv)
                break
            else:
                # Now let's try to re-encrypt all passwords with the new master
                # password.
                waitForDeferred(MasterPassword.clear())
                if not testmode:
                    if prefs.masterPassword:
                        wx.MessageBox(_(u'Please enter the master password you used to protect this file to reload account passwords.'),
                                      _(u'Protect Passwords'),
                                      parent = wx.GetApp().mainFrame)                    
                    while True:
                        try:
                            newMaster = waitForDeferred(MasterPassword.get(rv, testPassword=dummy))
                            break
                        except password.NoMasterPassword:
                            if wx.MessageBox(_(u'If you do not remember your master password, all account passwords will be deleted. Delete account passwords?'),
                                             _(u'Reset Master Password'),
                                             style = wx.YES_NO,
                                             parent = wx.GetApp().mainFrame) == wx.YES:
                                MasterPassword.reset(rv)
                                break
                            
                    if newMaster == '':
                        break
                
                for item in password.Password.iterItems(rv):
                    if not waitForDeferred(item.initialized()):
                        # Don't need to re-encrypt uninitialized passwords
                        continue
                    
                    try:
                        pw = waitForDeferred(item.decryptPassword(masterPassword=oldMaster))
                    except password.DecryptionError:
                        # Maybe this was one of the new passwords loaded from
                        # settings, so let's try the new master password
                        try:
                            waitForDeferred(item.decryptPassword(masterPassword=newMaster))
                        except password.DecryptionError:
                            # Oops, we are in trouble, can't really do much but
                            # reset() to avoid further problems.
                            logger.exception('found passwords that could not be decrypted; clearing passwords')
                            MasterPassword.reset(rv)
                            break
                        # Since this is already encrypted with the new
                        # master password we don't need to re-encrypt
                        continue

                    waitForDeferred(item.encryptPassword(pw, masterPassword=newMaster))
Example #12
0
def restore(rv, filename, testmode=False, newMaster=''):
    """
    Restore accounts and shares from an INI file.

    @param rv:        repository view
    @param filename:  Path to INI file to load.
    @param testmode:  Are we running a test or not
    @param newMaster: Used in testmode only
    """
    subscribes = []

    if not testmode:
        oldMaster = waitForDeferred(MasterPassword.get(rv))
    else:
        oldMaster = ''

    cfg = ConfigObj(filename, encoding="UTF8")

    for sectionname, section in cfg.iteritems():
        if section.has_key(u"type"):
            sectiontype = section[u"type"]
        else:
            sectiontype = ""
        # sharing accounts
        if sectiontype in (u"webdav account", u"cosmo account", u"hub account"):

            if sectiontype == u"webdav account":
                klass = sharing.WebDAVAccount
            elif sectiontype == u"hub account":
                klass = sharing.HubAccount
            else:
                klass = sharing.CosmoAccount

            if section.has_key(u"uuid"):
                uuid = section[u"uuid"]
                uuid = UUID(uuid)
                account = rv.findUUID(uuid)
                if account is None:
                    kind = klass.getKind(rv)
                    parent = schema.Item.getDefaultParent(rv)
                    account = kind.instantiateItem(None, parent, uuid,
                        withInitialValues=True)
                    account.password = password.Password(itsView=rv,
                                                         itsParent=account)

            account.displayName = section[u"title"]
            account.host = section[u"host"]
            account.path = section[u"path"]
            account.username = section[u"username"]
            restorePassword(account, section)
            account.port = section.as_int(u"port")
            account.useSSL = section.as_bool(u"usessl")


    for sectionname, section in cfg.iteritems():
        if section.has_key(u"type"):
            sectiontype = section[u"type"]
        else:
            sectiontype = ""
        # shares
        if sectiontype == u"share":
            url = section[u"url"]

            mine = False
            if section.has_key(u"mine"):
                # Add to my items
                mine = section.as_bool(u"mine")

            publisher = False
            if section.has_key(u"publisher"):
                # make me the publisher
                publisher = section.as_bool(u"publisher")

            subscribed = False
            for share in sharing.Share.iterItems(rv):
                if url == share.getLocation():
                    subscribed = True

            filters = None
            if section.has_key(u"filters"):
                filterStr = section[u"filters"]
                if filterStr:
                    filters = set(filterStr.split(","))

            if not subscribed:
                if section.has_key(u"ticket"):
                    url = section[u"ticket"]
                title = section[u"title"]

                if section.has_key(u"red"):
                    # Backwards-compatibility fix for bug 6899...
                    # Due to an earlier bug, some people's ini files
                    # still have floats in them, so let's cast just in case:
                    red = int(float(section.as_float(u"red")))
                    blue = int(float(section.as_float(u"blue")))
                    green = int(float(section.as_float(u"green")))
                    alpha = int(float(section.as_float(u"alpha")))
                    color = ColorType(red, green, blue, alpha)
                else:
                    color = None

                subscribes.append((url, title, mine, publisher, color, filters))

    for sectionname, section in cfg.iteritems():
        if section.has_key(u"type"):
            sectiontype = section[u"type"]
        else:
            sectiontype = ""
        # smtp accounts
        if sectiontype == u"smtp account":
            account = None
            current = getattr(schema.ns("osaf.pim", rv).currentOutgoingAccount,
                              "item", None)

            isEmpty = current is None or len(current.host.strip()) == 0

            makeCurrent = False

            if isEmpty:
                if current:
                    current.isActive = False
                makeCurrent = True

            if section.has_key(u"uuid") and account is None:
                uuid = section[u"uuid"]
                uuid = UUID(uuid)
                account = rv.findUUID(uuid)
                if account is None:
                    kind = pim.mail.SMTPAccount.getKind(rv)
                    parent = schema.Item.getDefaultParent(rv)
                    account = kind.instantiateItem(None, parent, uuid,
                        withInitialValues=True)
            elif account is None:
                account = pim.mail.SMTPAccount(itsView=rv)

            if makeCurrent or (section.has_key(u"default") and \
               section[u"default"]):
                schema.ns("osaf.pim", rv).currentOutgoingAccount.item = account

            account.displayName = section[u"title"]
            account.host = section[u"host"]
            account.useAuth = section.as_bool(u"auth")
            account.username = section[u"username"]
            restorePassword(account, section)
            account.port = section.as_int(u"port")
            account.connectionSecurity = section[u"security"]

            if section.has_key(u"address"):
                emailAddress = pim.mail.EmailAddress.getEmailAddress(rv,
                                     section[u"address"], section[u"name"])
                account.fromAddress = emailAddress

    for sectionname, section in cfg.iteritems():
        if section.has_key(u"type"):
            sectiontype = section[u"type"]
        else:
            sectiontype = ""
        # imap accounts
        if sectiontype == u"imap account":
            account = None

            current = getattr(schema.ns("osaf.pim", rv).currentIncomingAccount,
                              "item", None)

            isEmpty = current is None or \
                      (len(current.host.strip()) == 0 and \
                       not hasattr(current.password, 'ciphertext') and \
                       len(current.username.strip()) == 0)

            makeCurrent = False

            if isEmpty:
                if current:
                    current.isActive = False
                makeCurrent = True

            if section.has_key(u"uuid") and account is None:
                uuid = section[u"uuid"]
                uuid = UUID(uuid)
                account = rv.findUUID(uuid)
                if account is None:
                   #XXX overwrite the default account info
                    kind = pim.mail.IMAPAccount.getKind(rv)
                    parent = schema.Item.getDefaultParent(rv)
                    account = kind.instantiateItem(None, parent, uuid,
                                                   withInitialValues=True)

            if account is None:
                account = pim.mail.IMAPAccount(itsView=rv)

            # Remove any existing folders since the
            # account will be repopulated with the
            # folders in the ini file
            for folder in account.folders:
                account.folders.remove(folder)
                #The folders are not deleted because it
                # will cause the IMAP accounts folders to go stale
                # if the MailService is currently downloading.
                #folder.delete()

            account.displayName = section[u"title"]
            account.host = section[u"host"]
            account.username = section[u"username"]
            restorePassword(account, section)
            account.port = section.as_int(u"port")
            account.connectionSecurity = section[u"security"]
            account.isActive = True

            if section.has_key(u"address"):
                emailAddress = pim.mail.EmailAddress.getEmailAddress(rv,
                                    section[u"address"], section[u"name"])
                account.replyToAddress = emailAddress

            if makeCurrent or (section.has_key(u"default") and \
               section[u"default"]):
                schema.ns("osaf.pim", rv).currentIncomingAccount.item = account

            if section.has_key(u"imap_folder_num"):
                fnum = section.as_int("imap_folder_num")

                for i in xrange(0, fnum):
                    fcfg = section['imap_folder_%d' % i]

                    if fcfg.has_key(u"uuid"):
                        uuid = fcfg[u"uuid"]
                        uuid = UUID(uuid)
                        folder = rv.findUUID(uuid)
                        if folder is None:
                            kind = pim.mail.IMAPFolder.getKind(rv)
                            parent = schema.Item.getDefaultParent(rv)
                            folder = kind.instantiateItem(None, parent, uuid,
                                                 withInitialValues=True)
                    else:
                        folder = pim.mail.IMAPFolder(itsView=rv)

                    folder.displayName = fcfg['title']
                    folder.folderName = fcfg['name']
                    folder.folderType = fcfg['type']
                    # Since better performance has been established
                    # for 1.0 the max download feature is disabled
                    #folder.downloadMax = fcfg.as_int('max')

                    # To enable better performance for 1.0 the
                    # delete on download feature was temporarily disabled
                    #folder.deleteOnDownload = fcfg.as_bool('del')

                    account.folders.append(folder)
            else:
                # This is an Alpha 4 ini file which predates the 1.0 IMAP
                # foldering logic
                account._addInbox()

    for sectionname, section in cfg.iteritems():
        if section.has_key(u"type"):
            sectiontype = section[u"type"]
        else:
            sectiontype = ""
        # pop accounts
        if sectiontype == u"pop account":
            account = None

            current = getattr(schema.ns("osaf.pim", rv).currentIncomingAccount,
                              "item", None)

            isEmpty = current is None or \
                      (len(current.host.strip()) == 0 and \
                       not hasattr(current.password, 'ciphertext') and \
                       len(current.username.strip()) == 0)

            makeCurrent = False

            if isEmpty:
                if current:
                    current.isActive = False
                makeCurrent = True

            if section.has_key(u"uuid") and account is None:
                uuid = section[u"uuid"]
                uuid = UUID(uuid)
                account = rv.findUUID(uuid)
                if account is None:
                    kind = pim.mail.POPAccount.getKind(rv)
                    parent = schema.Item.getDefaultParent(rv)
                    account = kind.instantiateItem(None, parent, uuid,
                        withInitialValues=True)
            elif account is None:
                account = pim.mail.POPAccount(itsView=rv)

            account.displayName = section[u"title"]
            account.host = section[u"host"]
            account.username = section[u"username"]
            restorePassword(account, section)
            account.port = section.as_int(u"port")
            account.connectionSecurity = section[u"security"]
            account.isActive = True

            # To enable better performance for 1.0 the
            # delete on download feature was temporarily disabled
            #if section.has_key(u"del"):
            #    account.deleteOnDownload = section.as_bool(u"del")

            if section.has_key(u"address"):
                emailAddress = pim.mail.EmailAddress.getEmailAddress(rv,
                                    section[u"address"], section[u"name"])
                account.replyToAddress = emailAddress

            if makeCurrent or (section.has_key(u"default") and \
               section[u"default"]):
                schema.ns("osaf.pim", rv).currentIncomingAccount.item = account

    for sectionname, section in cfg.iteritems():
        if section.has_key(u"type"):
            sectiontype = section[u"type"]
        else:
            sectiontype = ""
        # timezones
        if sectionname == u"timezones":
            if section.has_key(u"show_timezones"):
                show = section.as_bool(u"show_timezones")
                schema.ns("osaf.pim", rv).TimezonePrefs.showUI = show
        
        # Visible hours
        elif sectionname == u"visible_hours":
            calPrefs = schema.ns("osaf.framework.blocks.calendar", rv).calendarPrefs
            if section.has_key(u"height_mode"):
                calPrefs.hourHeightMode = section[u"height_mode"]
            if section.has_key(u"num_hours"):
                calPrefs.visibleHours = section.as_int(u"num_hours")

    # Master password, must be done after accounts have been handled
    restoreMasterPassword(rv, cfg, testmode, oldMaster, newMaster)

    # Subscribe
    for url, title, mine, publisher, color, filters in subscribes:
        if testmode:
            # Fake the subscribes so unit tests don't have to
            # access the network
            collection = pim.SmartCollection(itsView=rv)
            collection.displayName = title
            if mine:
                schema.ns('osaf.pim', rv).mine.addSource(collection)
            usercollections.UserCollection(collection).color = color
        else:
            SubscribeCollection.Show(view=rv, url=url,
                                     name=title, modal=True,
                                     immediate=True, mine=mine,
                                     publisher=publisher,
                                     color=color,
                                     filters=filters)
Example #13
0
    def RoundTrip(self):

        filename = "tmp_dump_file"

        view0 = self.views[0]
        view1 = self.views[1]

        # uuids to dump; add your items to this:
        uuids = set()

        # Prepare test data

        coll0 = pim.SmartCollection("testCollection", itsView=view0,
            displayName="Test Collection")
        uuids.add(coll0.itsUUID)

        titles = [
            u"dunder",
            u"mifflin",
        ]

        tzinfo = view0.tzinfo.floating
        createdOn = datetime.datetime(2007, 3, 1, 10, 0, 0, 0, tzinfo)
        lastModified = datetime.datetime(2007, 3, 1, 12, 0, 0, 0, tzinfo)
        email = "*****@*****.**"
        emailAddress = pim.EmailAddress.getEmailAddress(view0, email)

        count = len(titles)
        for i in xrange(count):
            n = pim.Note(itsView=view0)
            n.createdOn = createdOn
            n.displayName = titles[i % count]
            n.body = u"Here is the body"
            n.lastModifiedBy = emailAddress
            n.lastModified = lastModified
            coll0.add(n)
            uuids.add(n.itsUUID)


        # Read/unread items
        readNote = pim.Note(itsView=view0, read=True)
        unreadNote = pim.Note(itsView=view0, read=False)


        # "Private" items
        publicNote = pim.Note(itsView=view0, private=False)
        privateNote = pim.Note(itsView=view0, private=True)


        # Mine/Not-Mine/Dashboard

        directlyInDashboard = pim.Note(itsView=view0)
        dashboard = schema.ns("osaf.pim", view0).allCollection
        dashboard.add(directlyInDashboard)

        aMineCollection = pim.SmartCollection(itsView=view0)
        schema.ns('osaf.pim', view0).mine.addSource(aMineCollection)
        inMine = pim.Note(itsView=view0)
        aMineCollection.add(inMine)

        aNotMineCollection = pim.SmartCollection(itsView=view0)
        inNotMine = pim.Note(itsView=view0)
        aNotMineCollection.add(inNotMine)


        trash = schema.ns("osaf.pim", view0).trashCollection
        trashTestCollection = pim.SmartCollection(itsView=view0)
        trashedItem = pim.Note(itsView=view0)
        trashTestCollection.add(trashedItem)
        trash.add(trashedItem)
        self.assert_(trashedItem in trashTestCollection.inclusions)
        self.assert_(trashedItem not in trashTestCollection)
        self.assert_(trashedItem in trash)

        # Sharing related items
        account0 = sharing.CosmoAccount(itsView=view0,
            host="chandler.o11n.org",
            port=8080,
            path="/cosmo",
            username="******",
            password=Password(itsView=view0),
            useSSL=True
        )
        waitForDeferred(account0.password.encryptPassword('4cc0unt0'))
        uuids.add(account0.itsUUID)
        cosmo_conduit0 = sharing.CosmoConduit(itsView=view0,
            account=account0,
            shareName=coll0.itsUUID.str16(),
            translator=sharing.SharingTranslator,
            serializer=sharing.EIMMLSerializer
        )
        uuids.add(cosmo_conduit0.itsUUID)
        cosmo_share0 = sharing.Share(itsView=view0,
            contents=coll0,
            conduit=cosmo_conduit0
        )
        uuids.add(cosmo_share0.itsUUID)


        hub_account0 = sharing.HubAccount(itsView=view0,
            username="******",
            password=Password(itsView=view0),
        )
        waitForDeferred(hub_account0.password.encryptPassword('4cc0unt0'))
        uuids.add(hub_account0.itsUUID)


        inmemory_conduit0 = sharing.InMemoryDiffRecordSetConduit(itsView=view0,
            shareName="in_memory",
            translator=sharing.SharingTranslator,
            serializer=sharing.EIMMLSerializer
        )
        uuids.add(inmemory_conduit0.itsUUID)

        inmemory_share0 = sharing.Share(itsView=view0,
            conduit=inmemory_conduit0,
            contents=coll0
        )
        uuids.add(inmemory_share0.itsUUID)

        # Create some State objects
        inmemory_share0.create()
        view0.commit()
        inmemory_share0.sync()
        for state in inmemory_share0.states:
            uuids.add(state.itsUUID)
        # Set one of the states to be a pendingRemoval
        pendingRemoval = state.itsUUID
        state.pendingRemoval = True


        # Peer states
        peerNote = pim.Note(itsView=view0)
        peerAddress = pim.EmailAddress(itsView=view0,
            fullName="Michael Scott",
            emailAddress="*****@*****.**")
        peerState = sharing.State(itsView=view0,
            conflictFor=peerNote,
            peer=peerAddress,
        )
        sharing.SharedItem(peerNote).add()
        sharedPeerNote = sharing.SharedItem(peerNote)
        sharedPeerNote.peerStates = []
        sharedPeerNote.peerStates.append(peerState, peerAddress.itsUUID.str16())
        uuids.add(peerNote.itsUUID)
        uuids.add(peerAddress.itsUUID)
        uuids.add(peerState.itsUUID)

        # Sharing proxy
        proxy = sharing.getProxy(view0)
        proxy.host = "host"
        proxy.port = 123
        proxy.username = "******"
        proxy.passwd = "password"
        proxy.active = True
        proxy.useAuth = True
        proxy.bypass = "******"
        uuids.add(proxy.itsUUID)

        # Online state
        schema.ns('osaf.app', view0).prefs.isOnline = False
        schema.ns('osaf.sharing', view0).prefs.isOnline = False

        #Mail Accounts

        imapAddress = mail.EmailAddress.getEmailAddress(view0, "*****@*****.**", 
                                                        "test")

        popAddress = mail.EmailAddress.getEmailAddress(view0, "*****@*****.**", 
                                                       "test1")

        smtpOldAddress = mail.EmailAddress.getEmailAddress(view0, 
                                                           "*****@*****.**", 
                                                           "test2")

        smtpNewAddress = mail.EmailAddress.getEmailAddress(view0, 
                                                           "*****@*****.**", 
                                                           "test3")


        testFolder = mail.IMAPFolder(itsView=view0,
                                    displayName = "TestFolder",
                                    folderName = "INBOX.TestFolder",
                                    folderType = "MAIL")

        queuedMessage0 = pim.MailStamp(pim.Note(itsView=view0))
        queuedMessage0.add()

        queuedMessage0.subject = "Test for SMTP Queue"

        uuids.add(queuedMessage0.itsItem.itsUUID)

        imapaccount0 = mail.IMAPAccount(itsView=view0,
            displayName = "IMAP Test",
            host="localhost",
            port=143,
            username="******",
            password=Password(itsView=view0),
            connectionSecurity = "TLS",
            numRetries = 2,
            pollingFrequency = 300,
            isActive = False,
            replyToAddress = imapAddress,
            folders = [testFolder],
        )
        waitForDeferred(imapaccount0.password.encryptPassword('imap4acc0unt0'))

        uuids.add(imapaccount0.itsUUID)

        popaccount0 = mail.POPAccount(itsView=view0,
            displayName = "POP Test",
            host="localhost",
            port=110,
            username="******",
            password=Password(itsView=view0),
            connectionSecurity = "NONE",
            numRetries = 3,
            pollingFrequency = 200,
            isActive = True,
            replyToAddress = popAddress,
        )
        waitForDeferred(popaccount0.password.encryptPassword('pop4acc0unt0'))

        uuids.add(popaccount0.itsUUID)

        smtpaccount0 = mail.SMTPAccount(itsView=view0,
            displayName = "SMTP Test",
            host="localhost",
            port=587,
            username="******",
            password=Password(itsView=view0),
            connectionSecurity = "SSL",
            numRetries = 5,
            pollingFrequency = 500,
            isActive = True,
            fromAddress = smtpOldAddress,
            useAuth = True,
            messageQueue = [queuedMessage0.itsItem],
        )
        waitForDeferred(smtpaccount0.password.encryptPassword('smtp4acc0unt0'))

        # This orphans smtpOldAddress leaving it as
        # an old me address which is stored in the
        # meEmailAddressCollection.
        # The purpose of this is to test dump and reload
        # of the meEmailAddressCollection.
        smtpaccount0.fromAddress = smtpNewAddress

        uuids.add(smtpaccount0.itsUUID)

        #Take the mail service offline
        schema.ns("osaf.pim", view0).MailPrefs.isOnline = False

        # Calendar prefs
        pref = schema.ns('osaf.pim', view0).TimezonePrefs
        pref.showUI = True # change from default
        pref.showPrompt = False # change from default

        pref = schema.ns('osaf.framework.blocks.calendar', view0).calendarPrefs
        pref.hourHeightMode = "auto"
        pref.visibleHours = 20

        # TODO: TimeZoneInfo

        # passwords
        pw = Password(itsView=view0)
        waitForDeferred(pw.encryptPassword('foobar'))
        uuids.add(pw.itsUUID)
        # password prefs
        mpwPrefs = schema.ns("osaf.framework.MasterPassword",
                             view0).masterPasswordPrefs
        MasterPassword._change('', 'secret', view0, mpwPrefs)
        mpwPrefs.timeout = 10

        # backup on quit preference
        backupPrefs = schema.ns("osaf.app",
                                view0).prefs
        self.assertFalse(hasattr(backupPrefs, 'backupOnQuit'))
        backupPrefs.backupOnQuit = True

        # tip of the day prefs
        self.assertFalse(backupPrefs.showTip)
        self.assertEqual(backupPrefs.tipIndex, 0)
        backupPrefs.tipIndex = 1

        # Ensure sidebar is loaded in view1
        sidebar1 = schema.ns("osaf.app", view1).sidebarCollection

        try:

            dumpreload.dump(view0, filename)
            dumpreload.reload(view1, filename, testmode=True)

            # Ensure the items are now in view1
            for uuid in uuids:
                item0 = view0.findUUID(uuid)
                item1 = view1.findUUID(uuid)

                self.assert_(item1 is not None)
                if hasattr(item0, 'displayName'):
                    self.assertEqual(item0.displayName, item1.displayName)
                if hasattr(item0, 'body'):
                    self.assertEqual(item0.body, item1.body)

            # Verify ContentItem.read
            self.assert_(view1.findUUID(readNote.itsUUID).read is True)
            self.assert_(view1.findUUID(unreadNote.itsUUID).read is False)

            # Verify ContentItem.private
            self.assert_(view1.findUUID(publicNote.itsUUID).private is False)
            self.assert_(view1.findUUID(privateNote.itsUUID).private is True)


            # Verify Mine/Not-Mine/Dashboard
            dashboard = schema.ns("osaf.pim", view1).allCollection
            self.assert_(view1.findUUID(directlyInDashboard.itsUUID) in
                dashboard.inclusions)

            self.assert_(view1.findUUID(inMine.itsUUID) in dashboard)
            self.assert_(view1.findUUID(inNotMine.itsUUID) not in dashboard)


            # Verify collection membership:
            coll1 = view1.findUUID(coll0.itsUUID)
            for item0 in coll0:
                item1 = view1.findUUID(item0.itsUUID)
                self.assert_(item1 in coll1)


            # Verify trash membership
            trash = schema.ns("osaf.pim", view1).trashCollection
            trashedItem = view1.findUUID(trashedItem.itsUUID)
            self.assert_(trashedItem in trash)
            trashTestCollection = view1.findUUID(trashTestCollection.itsUUID)
            self.assert_(trashedItem not in trashTestCollection)
            self.assert_(trashedItem in trashTestCollection.inclusions)



            # Verify passwords
            pw1 = view1.findUUID(pw.itsUUID)
            self.assertEqual(waitForDeferred(pw1.decryptPassword('secret')),
                             'foobar')
            
            mpwPrefs1 = schema.ns("osaf.framework.MasterPassword",
                                  view1).masterPasswordPrefs
            self.assertEqual(mpwPrefs1.masterPassword, True)
            self.assertEqual(mpwPrefs1.timeout, 10)
            
            pwPrefs1 = schema.ns("osaf.framework.password",
                                 view1).passwordPrefs
            self.assertEqual(len(waitForDeferred(pwPrefs1.dummyPassword.decryptPassword('secret'))), 16)
            self.assertEqual(str(pwPrefs1.dummyPassword.itsUUID),
                             'dd555441-9ddc-416c-b55a-77b073c7bd15')
            dummyByUUID = view1.findUUID('dd555441-9ddc-416c-b55a-77b073c7bd15')
            self.assertEqual(dummyByUUID, pwPrefs1.dummyPassword)
            
            count = 0
            for item in Password.iterItems(view0):
                waitForDeferred(item.decryptPassword('secret'))
                count += 1

            count1 = 0
            for item in Password.iterItems(view1):
                waitForDeferred(item.decryptPassword('secret'))
                count1 += 1
            
            self.assertEqual(count+2, count1) # XXX Shouldn't count==count1?
                
            # Verify sharing
            account1 = view1.findUUID(account0.itsUUID)
            self.assertEquals(account1.host, "chandler.o11n.org")
            self.assertEquals(account1.port, 8080)
            self.assertEquals(account1.path, "/cosmo")
            self.assertEquals(account1.username, "test")
            self.assertEquals(account1.useSSL, True)
            self.assertEquals(waitForDeferred(account1.password.decryptPassword('secret')),
                              '4cc0unt0')

            hub_account1 = view1.findUUID(hub_account0.itsUUID)
            self.assert_(isinstance(hub_account0, sharing.HubAccount))

            inmemory_share1 = view1.findUUID(inmemory_share0.itsUUID)
            self.assert_(inmemory_share1 is not None)
            self.assertEqual(inmemory_share0.contents.itsUUID,
                inmemory_share1.contents.itsUUID)
            self.assertEqual(inmemory_share0.conduit.syncToken,
                inmemory_share1.conduit.syncToken)
            for state0 in inmemory_share0.states:
                state1 = view1.findUUID(state0.itsUUID)
                self.assert_(state1 in inmemory_share1.states)
                self.assertEqual(state0.agreed, state1.agreed)
                self.assertEqual(state0.pending, state1.pending)
                self.assertEqual(state1.pendingRemoval,
                    state1.itsUUID == pendingRemoval)
            for item0 in coll0:
                item1 = view1.findUUID(item0.itsUUID)
                sharedItem1 = sharing.SharedItem(item1)
                self.assert_(inmemory_share1 in sharedItem1.sharedIn)

            # Peer states
            peerNote1 = view1.findUUID(peerNote.itsUUID)
            sharedPeerNote1 = sharing.SharedItem(peerNote1)
            peerAddress1 = view1.findUUID(peerAddress.itsUUID)
            peerState1 = view1.findUUID(peerState.itsUUID)
            self.assert_(peerState1 in sharedPeerNote1.peerStates)
            self.assertEquals(sharedPeerNote1.peerStates.getAlias(peerState1),
                peerAddress1.itsUUID.str16())
            self.assert_(peerState1 in sharedPeerNote1.conflictingStates)
            self.assert_(isinstance(peerAddress1, pim.EmailAddress))


            proxy1 = view1.findUUID(proxy.itsUUID)
            self.assertEquals(proxy1.host, "host")
            self.assertEquals(proxy1.port, 123)
            self.assertEquals(proxy1.username, "username")
            self.assertEquals(proxy1.bypass, "192.168.1, localhost")

            pw = waitForDeferred(proxy1.password.decryptPassword('secret'))
            self.assertEquals(pw, "password")
            self.assertEquals(proxy1.active, True)
            self.assertEquals(proxy1.useAuth, True)

            self.assertEquals(schema.ns('osaf.app', view1).prefs.isOnline,
                False)
            self.assertEquals(schema.ns('osaf.sharing', view1).prefs.isOnline,
                False)

            # Verify Calendar prefs
            pref = schema.ns('osaf.pim', view1).TimezonePrefs
            self.assertEqual(pref.showUI, True)
            self.assertEqual(pref.showPrompt, False)

            pref = schema.ns('osaf.framework.blocks.calendar',
                view1).calendarPrefs
            self.assertEqual(pref.hourHeightMode, "auto")
            self.assertEqual(pref.visibleHours, 20)

            #Verify Mail Accounts

            imapaccount1 = view1.findUUID(imapaccount0.itsUUID)
            self.assertEquals(imapaccount1.host, "localhost")
            self.assertEquals(imapaccount1.port, 143)
            self.assertEquals(imapaccount1.username, "test")
            self.assertEquals(imapaccount1.connectionSecurity, "TLS")
            self.assertEquals(imapaccount1.numRetries, 2)
            self.assertEquals(imapaccount1.pollingFrequency, 300)
            self.assertEquals(imapaccount1.isActive, False)
            self.assertEquals(imapaccount1.replyToAddress.format(), imapAddress.format())
            self.assertEquals(waitForDeferred(imapaccount1.password.decryptPassword('secret')),
                              'imap4acc0unt0')

            folder = imapaccount1.folders.first()
            self.assertEquals(folder.displayName, "TestFolder")
            self.assertEquals(folder.folderName, "INBOX.TestFolder")
            self.assertEquals(folder.folderType, "MAIL")

            popaccount1 = view1.findUUID(popaccount0.itsUUID)

            self.assertEquals(popaccount1.host, "localhost")
            self.assertEquals(popaccount1.port, 110)
            self.assertEquals(popaccount1.username, "test1")
            self.assertEquals(popaccount1.connectionSecurity, "NONE")
            self.assertEquals(popaccount1.numRetries, 3)
            self.assertEquals(popaccount1.pollingFrequency, 200)
            self.assertEquals(popaccount1.isActive, True)
            self.assertEquals(popaccount1.replyToAddress.format(), popAddress.format())
            self.assertEquals(waitForDeferred(popaccount1.password.decryptPassword('secret')),
                              'pop4acc0unt0')

            smtpaccount1 = view1.findUUID(smtpaccount0.itsUUID)

            self.assertEquals(smtpaccount1.host, "localhost")
            self.assertEquals(smtpaccount1.port, 587)
            self.assertEquals(smtpaccount1.username, "test2")
            self.assertEquals(smtpaccount1.connectionSecurity, "SSL")
            self.assertEquals(smtpaccount1.numRetries, 5)
            self.assertEquals(smtpaccount1.pollingFrequency, 500)
            self.assertEquals(smtpaccount1.isActive, True)
            self.assertEquals(smtpaccount1.useAuth, True)
            self.assertEquals(smtpaccount1.fromAddress.format(), smtpNewAddress.format())
            self.assertEquals(waitForDeferred(smtpaccount1.password.decryptPassword('secret')),
                              'smtp4acc0unt0')

            queuedMessage1 = smtpaccount1.messageQueue[0]

            self.assertEquals(queuedMessage1.itsUUID, queuedMessage0.itsItem.itsUUID)
            self.assertEquals(schema.ns("osaf.pim", view1).MailPrefs.isOnline, False)

            col = schema.ns("osaf.pim", view1).meEmailAddressCollection

            found = False
            oldAddr = smtpOldAddress.format()

            # Confirm that the old email address smtpOldAddress
            # is in the meEmailAddressCollection for calculating
            # the MailStamp.fromMe and MailStamp.toMe attributes
            for ea in col:
                if ea.format() == oldAddr:
                    found = True
                    break

            self.assertTrue(found)

            # backup on quit preference
            backupPrefs1 = schema.ns("osaf.app",
                                     view1).prefs
            self.assertTrue(backupPrefs1.backupOnQuit)
            
            # tip of the day prefs
            self.assertFalse(backupPrefs1.showTip)
            self.assertEqual(backupPrefs1.tipIndex, 1)
            
        finally:
            try:
                os.remove(filename)
            except:
                pass