Exemple #1
0
    def testModifiable(self):

        view = self.view

        # Our test subject
        e1 = pim.CalendarEvent(itsView=view).itsItem

        # We need a currentContact set for isAttributeModifiable to work;
        # normally this is set by the app
        me = pim.Contact(
            itsView=view,
            references=[schema.ns('osaf.pim', view).currentContact])

        # Add the subject to a read-only share:

        share_ro = sharing.Share(itsView=view)
        share_ro.mode = 'get'

        share_ro.addSharedItem(e1)

        # Test modifiability against...

        # ...an attribute which is always shared
        self.assert_(not e1.isAttributeModifiable('displayName'))

        # ...an attribute that is sometimes shared (based on filterAttributes)
        self.assert_(
            not e1.isAttributeModifiable(pim.Remindable.reminders.name))

        ## disabling functionality (and thus tests) for 1.0, bug 9448
        ### ...an attribute which is pretty much never shared
        ##self.assert_(e1.isAttributeModifiable('read'))

        ### Filter out reminderTime, and it should become modifiable:
        ##share_ro.filterAttributes = [pim.Remindable.reminders.name]
        ##self.assert_(e1.isAttributeModifiable(pim.Remindable.reminders.name))

        # Now also add the subject to a read-write share:

        share_rw = sharing.Share(itsView=view)
        share_rw.mode = 'both'

        share_rw.addSharedItem(e1)

        # Test modifiability against...

        ## changed tests to all use not for 1.0, bug 9448
        # ...an attribute which is always shared
        self.assert_(not e1.isAttributeModifiable('displayName'))

        # ...an attribute that is sometimes shared (based on filterAttributes)
        self.assert_(
            not e1.isAttributeModifiable(pim.Remindable.reminders.name))

        # ...an attribute which is pretty much never shared
        self.assert_(not e1.isAttributeModifiable('read'))
Exemple #2
0
    def PrepareShares(self):

        servers = [
            ("qacosmo.osafoundation.org", 80, False, "/cosmo", "test", "test1"),
            ("localhost", 8080, False, "/cosmo", "test", "test1"),
            ("hub.chandlerproject.org", 80, False, "/", "username", "password"),
        ]
        server = 1

        view0 = self.views[0]
        coll0 = self.coll
        self.assert_(not pim.has_stamp(coll0, sharing.SharedItem))
        account = cosmo.CosmoAccount(itsView=view0,
            host=servers[server][0],
            port=servers[server][1],
            path=servers[server][3],
            username=servers[server][4],
            password=Password(itsView=view0),
            useSSL=servers[server][2]
        )
        waitForDeferred(account.password.encryptPassword(servers[server][5]))

        conduit = cosmo.CosmoConduit(itsView=view0,
            account=account,
            shareName=coll0.itsUUID.str16(),
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer
        )
        self.share0 = sharing.Share("share", itsView=view0,
            contents=coll0, conduit=conduit)


        view1 = self.views[1]
        account = cosmo.CosmoAccount(itsView=view1,
            host=servers[server][0],
            port=servers[server][1],
            path=servers[server][3],
            username=servers[server][4],
            password=Password(itsView=view1),
            useSSL=servers[server][2]
        )
        waitForDeferred(account.password.encryptPassword(servers[server][5]))

        conduit = cosmo.CosmoConduit(itsView=view1,
            account=account,
            shareName=coll0.itsUUID.str16(),
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer
        )
        self.share1 = sharing.Share("share", itsView=view1,
            conduit=conduit)
    def PrepareShares(self):

        view0 = self.views[0]
        view1 = self.views[1]
        coll0a = view0.findUUID(self.coluuida)
        coll0b = view0.findUUID(self.coluuidb)

        # First share in first repo
        conduit = recordset_conduit.InMemoryDiffRecordSetConduit(
            itsView=view0,
            shareName="foo",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share0a = sharing.Share(itsView=view0,
                                     contents=coll0a,
                                     conduit=conduit)

        if self.share0a.exists():
            self.share0a.destroy()

        # Second share in first repo
        conduit = recordset_conduit.InMemoryDiffRecordSetConduit(
            itsView=view0,
            shareName="bar",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share0b = sharing.Share(itsView=view0,
                                     contents=coll0b,
                                     conduit=conduit)

        if self.share0b.exists():
            self.share0b.destroy()

        # First share in second repo
        conduit = recordset_conduit.InMemoryDiffRecordSetConduit(
            itsView=view1,
            shareName="foo",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share1a = sharing.Share(itsView=view1, conduit=conduit)

        # Second share in second repo
        conduit = recordset_conduit.InMemoryDiffRecordSetConduit(
            itsView=view1,
            shareName="bar",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share1b = sharing.Share(itsView=view1, conduit=conduit)
 def subscribe(self, url):
     share = sharing.Share(itsView=self.itsView)
     conduit = GDataConduit(itsParent=share,
                            account=self,
                            url=url,
                            translator=sharing.SharingTranslator)
     share.conduit = conduit
     share.get()
     return share.contents
    def PrepareShares(self):

        conduit = recordset_conduit.InMemoryDiffRecordSetConduit(
            "conduit",
            itsView=self.views[0],
            shareName="OfficeCal",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share0 = sharing.Share("share",
                                    itsView=self.views[0],
                                    contents=self.coll0,
                                    conduit=conduit)

        conduit = recordset_conduit.InMemoryDiffRecordSetConduit(
            "conduit",
            itsView=self.views[1],
            shareName="OfficeCal",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share1 = sharing.Share("share",
                                    itsView=self.views[1],
                                    conduit=conduit)
Exemple #6
0
    def PrepareShares(self):

        view0 = self.views[0]
        coll0 = self.coll
        conduit = recordset_conduit.InMemoryResourceRecordSetConduit(
            "conduit",
            itsView=view0,
            shareName="exportedCollection",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share0 = sharing.Share("share",
                                    itsView=view0,
                                    contents=coll0,
                                    conduit=conduit)

        view1 = self.views[1]
        conduit = recordset_conduit.InMemoryResourceRecordSetConduit(
            "conduit",
            itsView=view1,
            shareName="exportedCollection",
            translator=translator.SharingTranslator,
            serializer=eimml.EIMMLSerializer)
        self.share1 = sharing.Share("share", itsView=view1, conduit=conduit)
    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 testChange(self):
        from osaf import sharing
        from osaf.pim import ListCollection

        self.tzprefs.showUI = False

        gayParee = self.view.tzinfo.getInstance("Europe/Paris")

        master = CalendarEvent(itsView=self.view,
                               anyTime=False,
                               startTime=datetime(
                                   2007,
                                   2,
                                   7,
                                   11,
                                   30,
                                   tzinfo=self.view.tzinfo.floating),
                               duration=timedelta(hours=1))

        master.rruleset = RecurrenceRuleSet(
            itsView=self.view,
            rrules=[RecurrenceRule(itsView=self.view, freq='daily')])

        ordinary = CalendarEvent(itsView=self.view,
                                 anyTime=False,
                                 startTime=datetime(
                                     2007,
                                     2,
                                     7,
                                     11,
                                     30,
                                     tzinfo=self.view.tzinfo.floating),
                                 duration=timedelta(hours=1))

        sharedFloating = CalendarEvent(itsView=self.view,
                                       anyTime=False,
                                       startTime=datetime(
                                           2002,
                                           12,
                                           22,
                                           tzinfo=self.view.tzinfo.floating))
        share = sharing.Share(itsView=self.view, hidden=False)
        item = sharing.SharedItem(sharedFloating)
        item.add()
        item.sharedIn = item.shares = [share]

        nonFloatingOccurrence = master.getNextOccurrence(
            after=datetime(2007, 5, 2, tzinfo=self.view.tzinfo.floating))

        nonFloatingOccurrence.changeThis(
            EventStamp.startTime.name,
            nonFloatingOccurrence.startTime.replace(tzinfo=gayParee))

        titleMod = nonFloatingOccurrence.getNextOccurrence()
        titleMod.itsItem.summary = "yabba dabba doo"

        self.tzprefs.showUI = True

        tzItem = TimeZoneInfo.get(self.view)

        # Make sure that floating is no longer the default
        self.failIfEqual(self.view.tzinfo.default, self.view.tzinfo.floating)
        self.failIfEqual(tzItem.default, self.view.tzinfo.floating)
        self.failUnlessEqual(tzItem.default, self.view.tzinfo.default)

        # Make sure the ordinary and master events acquired the default tz
        self.failUnlessEqual(ordinary.startTime.tzinfo,
                             self.view.tzinfo.default)
        self.failUnlessEqual(master.startTime.tzinfo, self.view.tzinfo.default)

        # Make sure the non-floating occurrence didn't have its tz changed
        self.failUnlessEqual(nonFloatingOccurrence.startTime.tzinfo, gayParee)

        # Check the master's occurrences ...
        for event in map(EventStamp, master.occurrences):
            # Everything but the modification we just made should have
            # the default timezone set for startTime ...
            if event != nonFloatingOccurrence:
                self.failUnlessEqual(event.startTime.tzinfo,
                                     self.view.tzinfo.default)

            # and recurrenceIDs should always have the master's tzinfo
            self.failUnlessEqual(event.recurrenceID.tzinfo,
                                 self.view.tzinfo.default)

        # ... and the shared item's tzinfo should not have changed
        self.failUnlessEqual(sharedFloating.startTime.tzinfo,
                             self.view.tzinfo.floating)

        self.tzprefs.showUI = False
        self.failUnlessEqual(tzItem.default, self.view.tzinfo.floating)
        self.failIfEqual(self.view.tzinfo.floating, self.view.tzinfo.default)
Exemple #9
0
def installParcel(parcel, oldVersion=None):

    pim_ns = schema.ns('osaf.pim', parcel)
    sharing_ns = schema.ns('osaf.sharing', parcel)

    ClientIdentifier.update(parcel, 'clientID')

    ApplicationPrefs.update(parcel, 'prefs')

    AutoRestorePrefs.update(parcel, "autoRestorePrefs")

    message = _(u'User')

    me = pim.Contact.update(
        parcel,
        'me',
        # L10N: The word 'Me' is used to represent the
        #       current Chandler user.
        displayName=_(u'Me'),
        contactName=pim.ContactName.update(
            parcel,
            'meName',
            firstName=u'Chandler',
            #XXX Since the notion of 'me' may be going away
            #    there is no current need to refactor the
            #    last name attribute to the LocalizableString type.
            #    Thus for now will convert the c{Message} object
            #    returned from the c{ChandlerMessageFactory}
            #    to Unicode. This decision will be revisited later.
            lastName=unicode(message),
        ),
        references=[pim_ns.currentContact])

    # The Sidebar collection
    sidebarListCollection = pim.ListCollection.update(
        parcel,
        'sidebarCollection',
        inclusions=[
            pim_ns.allCollection, pim_ns.inCollection, pim_ns.outCollection,
            pim_ns.trashCollection
        ])

    testReply = pim.mail.EmailAddress.update(parcel, 'TestReplyAddress')

    # [i18n] Test Accounts are not displayed to the user and
    # do not require localization
    testSmtp = pim.mail.SMTPAccount.update(parcel,
                                           'TestSMTPAccount',
                                           displayName=u'Test SMTP Account',
                                           password=password.Password.update(
                                               parcel,
                                               'TestSMTPAccountPassword'),
                                           isActive=False)

    pim.mail.IMAPAccount.update(parcel,
                                'TestIMAPAccount',
                                displayName=u'Test IMAP mail',
                                replyToAddress=testReply,
                                password=password.Password.update(
                                    parcel, 'TestIMAPAccountPassword'),
                                isActive=False)

    pim.mail.POPAccount.update(parcel,
                               'TestPOPAccount',
                               displayName=u'Test POP mail',
                               replyToAddress=testReply,
                               defaultSMTPAccount=testSmtp,
                               password=password.Password.update(
                                   parcel, 'TestPOPAccountPassword'),
                               isActive=False)

    osafDev = pim.Contact.update(parcel,
                                 'OSAFContact',
                                 emailAddress=u'*****@*****.**',
                                 contactName=pim.ContactName.update(
                                     parcel,
                                     'OSAFContactName',
                                     firstName=u'OSAF',
                                     lastName=u'Development'))

    # OOTB collections and items (bugs 6545, 11772)
    # http://chandlerproject.org/bin/view/Journal/PreviewOOTBChandlerExperience
    #
    # (1) Don't create these in //parcels, or they won't get dumped
    # (2) Don't create these if reloading, or else there will be endless
    #     duplication of items/events
    # (3) We do want new UUIDs, so different users can share these
    #     collections/items to the same morsecode server
    # (4) The Welcome Event should be created regardless of whether
    #     we're reloading, because summaryblocks references it.
    #     (Maybe there's a better way to have it selected in the
    #      detail view?) -- Grant
    # (5) We create

    triageWhenValues = [datetime.datetime.now(parcel.itsView.tzinfo.default)]

    def changeTriage(itemOrStamp, triageValue):
        triageWhen = triageWhenValues.pop()
        item = getattr(itemOrStamp, 'itsItem', itemOrStamp)
        item.setTriageStatus(triageValue, triageWhen)
        triageWhenValues.append(triageWhen - datetime.timedelta(seconds=5))

    # OOTB item: Welcome Event
    noonToday = datetime.datetime.combine(
        datetime.date.today(),
        datetime.time(12, tzinfo=parcel.itsView.tzinfo.floating))

    WelcomeEvent = pim.EventStamp.update(
        parcel,
        'WelcomeEvent',
        # L10N: The Trademark symbol "TM" is represented in Unicode as U+2122
        displayName=_(u'Welcome to Chandler\u2122'),
        startTime=noonToday,
        duration=datetime.timedelta(minutes=60),
        anyTime=False,
        read=False,
        creator=osafDev,
        location=pim.Location.update(
            parcel,
            "OSAFLocation",
            displayName="Open Source Applications Foundation",
        ),
    )

    # L10N: The Trademark symbol "TM" is represented in Unicode as U+2122
    body = _(
        u"""Welcome to Chandler\u2122 %(version)s. Here is a list of resources to help you get started:

1. Get a tour of Chandler
(http://chandlerproject.org/tour).

2. Learn how to import calendars and set up Chandler to back up and share
(http://chandlerproject.org/getstarted).

3. Back up your data and Share by signing up for a Chandler Hub account
(http://hub.chandlerproject.org/signup).

4. Ask for help by sending mail to mailto:[email protected].

5. Learn more about the project on our wiki
(http://chandlerproject.org/wikihome).

6. Get involved and contribute to the project
(http://chandlerproject.org/getinvolved).

Thank you for trying Chandler!

The Chandler Team""") % {
            'version': version.version
        }

    WelcomeEvent.body = body
    WelcomeEvent.changeEditState(pim.Modification.created)
    changeTriage(WelcomeEvent, pim.TriageEnum.now)
    pim.TaskStamp(WelcomeEvent).add()

    if Globals.options.reload:
        schema.ns('osaf.pim', parcel.itsView).allCollection.add(WelcomeEvent)
    else:
        # OOTB user defined collections: collections should be in mine
        mine = schema.ns("osaf.pim", parcel.itsView).mine

        def makeCollection(name, checked, color):
            collection = pim.SmartCollection(itsView=parcel.itsView,
                                             displayName=name)
            # include collection in overlays, as spec'ed
            UserCollection(collection).checked = checked
            # set the collection color as spec'ed
            UserCollection(collection).setColor(color)

            sidebarListCollection.add(collection)
            mine.addSource(collection)

            return collection

        # OOTB user defined collections: Work, Home and Fun
        work = makeCollection(_(u"Work"), True, u'Blue')
        home = makeCollection(_(u"Home"), True, u'Red')
        fun = makeCollection(_(u"Fun"), False, u'Plum')

        # OOTB shared collection: U.S. Holidays
        holidays = makeCollection(_(u"U.S. Holidays"), True, u'Green')

        holidaysPath = pkg_resources.resource_filename(__name__,
                                                       "us_holidays.ics")
        sharing.importFile(parcel.itsView, holidaysPath, collection=holidays)

        dashboard = schema.ns("osaf.pim", parcel.itsView).allCollection

        # Add Welcome item to OOTB collections
        home.add(WelcomeEvent)
        work.add(WelcomeEvent)

        thisWeek = CalendarUtility.getCalendarRange(noonToday.date())

        def getDayInThisWeek(weekday):

            res = thisWeek[0]
            while res.weekday() != weekday:
                res += datetime.timedelta(days=1)
            return res

        # OOTB item 1: Next dentist appointment?
        event1 = pim.CalendarEvent(
            itsView=parcel.itsView,
            displayName=_(u"Next dentist appointment?"),
            startTime=noonToday.replace(hour=9),
            anyTime=True,
            collections=[home],
            read=True,
        )
        event1.itsItem.changeEditState(pim.Modification.created,
                                       when=noonToday.replace(hour=8))
        changeTriage(event1, pim.TriageEnum.now)

        # OOTB item #2: Tell a friend about Chandler
        item2 = pim.Note(
            itsView=parcel.itsView,
            displayName=_(u"Tell a friend about Chandler"),
            read=True,
            body=_(
                u"""Try sharing a collection with family, friends or colleagues.

Sign up for a Chandler Hub account to get started: http://hub.chandlerproject.org
"""),
        )

        schema.ns("osaf.pim", parcel.itsView).allCollection.add(item2)
        item2.changeEditState(pim.Modification.created,
                              when=noonToday.replace(hour=8))
        changeTriage(item2, pim.TriageEnum.now)

        # OOTB item #3: Write-up
        task3 = pim.Task(
            itsView=parcel.itsView,
            displayName=_(u"Write-up..."),
            collections=[work],
            read=True,
            body=
            _(u"""Start jotting down ideas for that big write-up you should really have started last week!

.
.
.
"""),
        )
        task3.itsItem.changeEditState(pim.Modification.created)
        changeTriage(task3, pim.TriageEnum.now)

        # OOTB item #4: Follow up
        task4 = pim.Task(
            itsView=parcel.itsView,
            displayName=_(u"Follow up with...on..."),
            read=True,
            body=
            _(u"""Maintain a list of things you need to discuss with a colleague:
.
.
.

(Click on the clock icon to add this note to the calendar for the next time you're going to meet with them.)
"""),
        )
        dashboard.add(task4.itsItem)
        task4.itsItem.changeEditState(pim.Modification.created)
        changeTriage(task4, pim.TriageEnum.now)

        # OOTB item #5: Start planning vacation
        task5 = pim.Task(
            itsView=parcel.itsView,
            displayName=_(u"Start planning vacation"),
            read=True,
            collections=[home],
            body=_("""Places you could go?
.
.
.

Activities you'd like to try?
.
.
.

Interesting travel articles?
.
.
.
"""),
        )

        changeTriage(task5, pim.TriageEnum.now)
        task5.itsItem.changeEditState(pim.Modification.created)

        # OOTB item #6: Bi-Weekly Status Report
        event5 = pim.CalendarEvent(
            itsView=parcel.itsView,
            displayName=_(u"Bi-Weekly Status Report"),
            startTime=noonToday,
            anyTime=True,
            read=True,
            collections=[work],
            body=_("""What have you been up to the last couple of weeks?
.
.
.
"""),
        )

        def makeRecurring(event, **kw):
            rule = pim.calendar.Recurrence.RecurrenceRule(
                itsView=parcel.itsView, **kw)

            event.rruleset = pim.calendar.Recurrence.RecurrenceRuleSet(
                itsView=parcel.itsView, rrules=[rule])
            for item in event.modifications:
                changeTriage(item, item._triageStatus)

        pim.TaskStamp(event5).add()
        event5.itsItem.changeEditState(pim.Modification.created)

        makeRecurring(event5, freq='weekly', interval=2)

        # OOTB item #6: Office supplies order
        startTime6 = datetime.datetime.combine(getDayInThisWeek(4),
                                               noonToday.timetz())

        event6 = pim.CalendarEvent(
            itsView=parcel.itsView,
            displayName=_(u"Office supplies order"),
            startTime=startTime6,
            anyTime=True,
            read=True,
            collections=[work],
            body=_(u"""Maintain a list of supplies you need to get every month:
.
.
.

(Share it with others so you can all maintain the list together!)
"""))
        changeTriage(event6, pim.TriageEnum.done)
        event6.itsItem.changeEditState(pim.Modification.created)
        makeRecurring(event6, freq='monthly')

        # OOTB item #7: Salsa class
        startTime7 = noonToday.replace(hour=14, minute=30)
        delta = 14 + startTime7.date().weekday() - 6
        startTime7 -= datetime.timedelta(days=delta)
        until7 = startTime7 + datetime.timedelta(days=28)
        event7 = pim.CalendarEvent(itsView=parcel.itsView,
                                   displayName=_(u"Salsa Class"),
                                   startTime=startTime7,
                                   duration=datetime.timedelta(hours=1),
                                   anyTime=False,
                                   read=True,
                                   collections=[home, fun],
                                   body=_(u"""Assignment for this week:
.
.
.

Remember to bring:
.
.
.
"""))
        event7.itsItem.changeEditState(pim.Modification.created,
                                       when=startTime7)
        changeTriage(event7, pim.TriageEnum.done)
        makeRecurring(event7, freq='weekly', until=until7)

        # A hack to get this occurrence to appear in the dashboard
        event7.getFirstOccurrence().getNextOccurrence().changeThis()
        for m in sorted(event7.modifications,
                        key=lambda o: pim.EventStamp(o).startTime):
            changeTriage(m, m._triageStatus)

        # OOTB item #8: Brunch potluck...
        startTime8 = datetime.datetime.combine(
            getDayInThisWeek(6), datetime.time(11, 0, tzinfo=noonToday.tzinfo))

        event8 = pim.CalendarEvent(
            itsView=parcel.itsView,
            displayName=_(u"Brunch potluck..."),
            startTime=startTime8,
            duration=datetime.timedelta(hours=2),
            anyTime=False,
            read=True,
            collections=[home, fun],
            body=_(u"""Directions
.
.
.

Ideas for games to bring...
.
.
.

Sign up to bring food...
.
.
.
"""),
        )
        changeTriage(event8, event8.autoTriage())
        event8.itsItem.changeEditState(pim.Modification.created)

        # OOTB Item #9: Ideas for presents
        item9 = pim.Note(
            itsView=parcel.itsView,
            displayName=_(u"Ideas for presents"),
            read=True,
            collections=[home],
            body=
            _(u"""Maintain a list of possible presents for family, friends and colleagues so you're never short on ideas!
.
.
.
"""),
        )
        changeTriage(item9, pim.TriageEnum.later)
        item9.changeEditState(pim.Modification.edited)

        # OOTB Item #10: Thank you notes
        item10 = pim.Note(
            itsView=parcel.itsView,
            displayName=_(u"Thank you notes"),
            read=True,
            collections=[home],
            body=
            _(u"""Who do you need to write thank you notes to? and for what reason?
.
.
.


"""),
        )

        changeTriage(item10, pim.TriageEnum.later)
        item10.changeEditState(pim.Modification.created)

        # OOTB Item #11: Movie list
        item11 = pim.Note(
            itsView=parcel.itsView,
            displayName=_(u"Movie list"),
            read=True,
            collections=[fun, home],
            body=_(u"""Movies you want to see:

.
.
.
"""),
        )

        changeTriage(item11, pim.TriageEnum.later)
        item11.changeEditState(pim.Modification.created)

        # OOTB Item #12: Book list
        item12 = pim.Note(
            itsView=parcel.itsView,
            displayName=_(u"Book list"),
            read=True,
            collections=[fun, home],
            body=_(
                u"""Book recommendations you've been meaning to follow up on:

.
.
.
"""),
        )

        changeTriage(item12, pim.TriageEnum.later)
        item12.changeEditState(pim.Modification.created)

        # OOTB Item #13: File taxes
        startTime13 = noonToday.replace(month=4, day=15)
        alarmTime13 = startTime13.replace(day=1)
        if alarmTime13 < noonToday:
            alarmTime13 = alarmTime13.replace(year=alarmTime13.year + 1)
            startTime13 = startTime13.replace(year=startTime13.year + 1)

        event13 = pim.CalendarEvent(
            itsView=parcel.itsView,
            startTime=startTime13,
            displayName=_(u"File taxes!"),
            read=True,
            collections=[home],
            body=_(u"""What forms do you have in hand?
.
.
.

What are you missing?
.
.
.

Questions for your accountant?
.
.
.
"""),
        )

        pim.TaskStamp(event13).add()
        event13.itsItem.changeEditState(pim.Modification.created)
        changeTriage(event13, pim.TriageEnum.later)
        event13.itsItem.userReminderTime = alarmTime13

        # OOTB Item #14: Class Trip: Exhibit on Sound!
        location14 = pim.Location.update(
            parcel,
            "Exploratorium",
            displayName="Exploratorium",
        )

        startTime14 = datetime.datetime.combine(
            getDayInThisWeek(6), datetime.time(15, tzinfo=noonToday.tzinfo))

        event14 = pim.CalendarEvent(
            itsView=parcel.itsView,
            startTime=startTime14,
            displayName=_(u"Class Trip: Exhibit on Sound!"),
            read=True,
            location=location14,
            collections=[fun],
            body=_(u"""Directions...
.
.
.
"""),
        )
        event14.itsItem.changeEditState(pim.Modification.edited,
                                        when=startTime14)
        changeTriage(event14, pim.TriageEnum.done)

        # OOTB Item #15: Download Chandler!
        note15 = pim.Note(
            itsView=parcel.itsView,
            displayName=_(u"Download Chandler!"),
            read=True,
        )
        dashboard.add(note15)
        done15 = datetime.datetime.now(parcel.itsView.tzinfo.default)
        done15 -= datetime.timedelta(minutes=5)
        done15 = done15.replace(second=0, microsecond=0)
        changeTriage(note15, pim.TriageEnum.done)
        note15.changeEditState(pim.Modification.edited, when=done15)

        # Set up sharing for holidays
        share = sharing.Share(itsView=parcel.itsView,
                              mode='get',
                              contents=holidays,
                              established=True)
        filters = set([
            'cid:[email protected]', 'cid:[email protected]',
            'cid:[email protected]', 'cid:[email protected]',
            'cid:[email protected]'
        ])
        share.conduit = sharing.WebDAVMonolithicRecordSetConduit(
            itsParent=share,
            host=u'hub.chandlerproject.org',
            port=443,
            sharePath=u'webcal/collection',
            shareName=u'7febe2f4-324c-11dd-d9e4-0016cbca6aed?ticket=01q75n1sy0',
            useSSL=True,
            filters=filters,
            translator=sharing.SharingTranslator,
            serializer=sharing.ICSSerializer)
        share.conduit.ticketReadOnly = share.conduit.ticket
        sharing.SharedItem(share.contents).add()
        sharing.SharedItem(share.contents).shares.append(share)

    # Set up the main web server
    from osaf import webserver

    startup.Startup.update(parcel,
                           "startServers",
                           invoke="osaf.webserver.start_servers")

    webserver.Server.update(
        parcel,
        "mainServer",
        # Port to listen on.  1888 was the year Raymond Chandler was born.
        port=1888,

        # This path specifies the "doc root" of this web server, and is
        # relative to webserver/servers, but you may also put in an
        # absolute path if you wish.
        #
        path=unicode(os.path.join("parcels", "osaf", "app", "webhome")),
        resources=[
            webserver.Resource.update(
                parcel,
                "lobsResource",
                displayName=u"Lob Server",
                location=u"lobs",
                resourceClass=schema.importString(
                    "osaf.servlets.lobviewer.LobViewerResource"),
            ),
            webserver.Resource.update(
                parcel,
                "photoResource",
                displayName=u"Photo Viewer",
                location=u"photos",
                resourceClass=schema.importString(
                    "osaf.servlets.photo.PhotosResource"),
            ),
            webserver.Resource.update(parcel,
                                      "repoResource",
                                      displayName=u"Repository Viewer",
                                      location=u"repo",
                                      resourceClass=schema.importString(
                                          "osaf.servlets.repo.RepoResource"),
                                      autoView=False),
            webserver.Resource.update(parcel,
                                      "prefResource",
                                      displayName=u'Preference Editor',
                                      location=u"prefs",
                                      resourceClass=schema.importString(
                                          "osaf.servlets.prefs.PrefResource"),
                                      autoView=False),
            webserver.Resource.update(
                parcel,
                "xmlrpcResource",
                displayName=u'XML-RPC Service',
                location=u"xmlrpc",
                resourceClass=schema.importString(
                    "osaf.servlets.xmlrpc.XmlRpcResource"),
                autoView=False),
        ])

    from osaf.app import updates

    # Subtract 15 minutes from lastRun so that in a week's
    # time we don't conflict with the "compact" trask.
    updates.UpdateCheckTask.update(parcel,
                                   'updateCheckTask',
                                   interval=datetime.timedelta(days=1),
                                   lastRun=datetime.datetime.now() -
                                   datetime.timedelta(minutes=15))

    # Compact task should come last
    from osaf.app import compact
    compact.CompactTask.update(parcel, 'compactTask')
Exemple #10
0
def GetCollectionFromSearch(repoView, searchTerms):

    # We turn searchTerms into a URI, using the
    # above API.

    # ... need the app key (identifies Chandler).
    if APP_KEY is None:
        raise LicenseError

    query = 'ical?app_key=%s' % (urllib.quote_plus(APP_KEY))
    displayName = "EVDB"

    # ... add in keywords
    q = searchTerms.get('keywords', None)
    if q:
        query = '%s&q=%s' % (query, q.encode('UTF-8'))
        displayName = "%s %s" % (displayName, q)

    # ... location ...
    location = searchTerms.get('location', None)
    if location:
        query = '%s&location=%s' % (
            query, urllib.quote_plus(location).encode('UTF-8'))
        displayName = "%s %s" % (displayName, location)

    # ... and dates ...
    dates = searchTerms.get('dates', None)
    if dates:
        query = '%s&date=%s' % (query,
                                urllib.quote_plus(dates).encode('UTF-8'))
        displayName = "%s %s" % (displayName, dates)

    logger.info('sending query %s', query)

    collection = osaf.pim.SmartCollection(itsView=repoView,
                                          displayName=displayName)

    # Setting the preferredClass  to MissingClass is a hint to display it
    # in the All View
    UserCollection(collection).preferredClass = MissingClass

    share = sharing.Share(itsView=repoView, contents=collection)

    # /rest/events/ics returns all matching events in ics
    # (ICalendar) format, so we just need an ICalendarFormat
    # object to parse the data.
    share.format = sharing.ICalendarFormat(itsParent=share)

    # Since we're doing an HTTP GET to fetch all matching
    # events, we can use a SimpleHTTPConduit here.
    share.conduit = sharing.SimpleHTTPConduit(itsParent=share,
                                              shareName=query,
                                              account=None,
                                              host='api.evdb.com',
                                              port=80,
                                              sharePath='/rest/events')

    share.mode = "get"
    share.filterClasses = ["osaf.pim.calendar.Calendar.CalendarEventMixin"]

    try:
        share.get()

        return collection
    except sharing.TransformationFailed:
        return collection
    except vobject.base.ParseError, e:
        input = getattr(e, 'input', None)
        if (isinstance(input, basestring)
                and "authentication error" in input.lower()):
            raise LicenseError
        logger.exception("Error during GET from EVDB")
        repoView.cancel()
        raise