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())
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())
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))
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
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 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
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))
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)
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