Пример #1
0
        def test(response, path, isfile, sum, uri, depth, dst_path):
            if response.code != responsecode.CREATED:
                self.fail("Incorrect response code for COPY %s (depth=%r): %s != %s"
                          % (uri, depth, response.code, responsecode.CREATED))

            if response.headers.getHeader("location") is None:
                self.fail("Reponse to COPY %s (depth=%r) with CREATE status is missing location: header."
                          % (uri, depth))

            if os.path.isfile(path):
                if not os.path.isfile(dst_path):
                    self.fail("COPY %s (depth=%r) produced no output file" % (uri, depth))
                if not cmp(path, dst_path):
                    self.fail("COPY %s (depth=%r) produced different file" % (uri, depth))
                os.remove(dst_path)

            elif os.path.isdir(path):
                if not os.path.isdir(dst_path):
                    self.fail("COPY %s (depth=%r) produced no output directory" % (uri, depth))

                if depth in ("infinity", None):
                    if dircmp(path, dst_path):
                        self.fail("COPY %s (depth=%r) produced different directory" % (uri, depth))

                elif depth == "0":
                    for filename in os.listdir(dst_path):
                        self.fail("COPY %s (depth=%r) shouldn't copy directory contents (eg. %s)" % (uri, depth, filename))

                else: raise AssertionError("Unknown depth: %r" % (depth,))

                rmdir(dst_path)

            else:
                self.fail("Source %s is neither a file nor a directory"
                          % (path,))
Пример #2
0
    def test_make_calendar(self):
        """
        Make calendar
        """
        uri = "/calendars/users/user01/calendar_make/"
        path = os.path.join(self.docroot, uri[1:])

        if os.path.exists(path):
            rmdir(path)

        request = SimpleStoreRequest(self, "MKCALENDAR", uri, authPrincipal=self.authPrincipal)

        @inlineCallbacks
        def do_test(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("Incorrect response to successful MKCALENDAR: %s"
                          % (response.code,))
            resource = (yield request.locateResource(uri))

            if not resource:
                self.fail("MKCALENDAR made no calendar")

            if not resource.isCalendarCollection():
                self.fail("MKCALENDAR made non-calendar collection")

        return self.send(request, do_test)
Пример #3
0
 def restore(self):
     # Get rid of whatever messed up state the test has now so that we'll
     # get a fresh docroot.  This isn't very cool; tests should be doing
     # less so that they don't need a fresh copy of this state.
     if hasattr(self, "_docroot"):
         rmdir(self._docroot)
         del self._docroot
Пример #4
0
    def test_make_calendar(self):
        """
        Make calendar
        """
        uri = "/calendars/users/user01/calendar_make/"
        path = os.path.join(self.docroot, uri[1:])

        if os.path.exists(path):
            rmdir(path)

        request = SimpleStoreRequest(self,
                                     "MKCALENDAR",
                                     uri,
                                     authPrincipal=self.authPrincipal)

        @inlineCallbacks
        def do_test(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("Incorrect response to successful MKCALENDAR: %s" %
                          (response.code, ))
            resource = (yield request.locateResource(uri))

            if not resource:
                self.fail("MKCALENDAR made no calendar")

            if not resource.isCalendarCollection():
                self.fail("MKCALENDAR made non-calendar collection")

        return self.send(request, do_test)
Пример #5
0
    def test_MKCOL_invalid_body(self):
        """
        MKCOL request with invalid request body
        (Any body at all is invalid in our implementation; there is no
        such thing as a valid body.)
        """
        path, uri = self.mkdtemp("collection")

        rmdir(path)

        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.UNSUPPORTED_MEDIA_TYPE:
                self.fail("MKCOL response %s != %s" %
                          (response.code, responsecode.UNSUPPORTED_MEDIA_TYPE))

            if os.path.isdir(path):
                self.fail("MKCOL incorrectly created directory %s" % (path, ))

        request = SimpleRequest(self.site, "MKCOL", uri)
        request.stream = MemoryStream(
            "This is not a valid MKCOL request body.")

        return self.send(request, check_result)
Пример #6
0
        def test(response, path, isfile, sum, uri, depth, dst_path):
            if response.code != responsecode.CREATED:
                self.fail(
                    "Incorrect response code for COPY %s (depth=%r): %s != %s"
                    % (uri, depth, response.code, responsecode.CREATED))

            if response.headers.getHeader("location") is None:
                self.fail(
                    "Reponse to COPY %s (depth=%r) with CREATE status is missing location: header."
                    % (uri, depth))

            if os.path.isfile(path):
                if not os.path.isfile(dst_path):
                    self.fail("COPY %s (depth=%r) produced no output file" %
                              (uri, depth))
                if not cmp(path, dst_path):
                    self.fail("COPY %s (depth=%r) produced different file" %
                              (uri, depth))
                os.remove(dst_path)

            elif os.path.isdir(path):
                if not os.path.isdir(dst_path):
                    self.fail(
                        "COPY %s (depth=%r) produced no output directory" %
                        (uri, depth))

                if depth in ("infinity", None):
                    if dircmp(path, dst_path):
                        self.fail(
                            "COPY %s (depth=%r) produced different directory" %
                            (uri, depth))

                elif depth == "0":
                    for filename in os.listdir(dst_path):
                        self.fail(
                            "COPY %s (depth=%r) shouldn't copy directory contents (eg. %s)"
                            % (uri, depth, filename))

                else:
                    raise AssertionError("Unknown depth: %r" % (depth, ))

                rmdir(dst_path)

            else:
                self.fail("Source %s is neither a file nor a directory" %
                          (path, ))
    def test_addressBookHomeURLs(self):
        """
        DirectoryPrincipalResource.addressBookHomeURLs(),
        """
        # No addressbook home provisioner should result in no addressbook homes.
        for provisioningResource, _ignore_recordType, recordResource, record in self._allRecords():
            if record.enabledForAddressBooks:
                self.failIf(tuple(recordResource.addressBookHomeURLs()))

        # Need to create a addressbook home provisioner for each service.
        addressBookRootResources = {}

        for directory in self.directoryServices:
            path = os.path.join(self.docroot, directory.__class__.__name__)

            if os.path.exists(path):
                rmdir(path)
            os.mkdir(path)

            # Need a data store
            _newStore = CommonDataStore(path, None, None, True, False)

            provisioningResource = DirectoryAddressBookHomeProvisioningResource(
                directory,
                "/addressbooks/",
                _newStore
            )

            addressBookRootResources[directory.__class__.__name__] = provisioningResource

        # AddressBook home provisioners should result in addressBook homes.
        for provisioningResource, _ignore_recordType, recordResource, record in self._allRecords():
            if record.enabledForAddressBooks:
                homeURLs = tuple(recordResource.addressBookHomeURLs())
                self.failUnless(homeURLs)

                # Turn off enabledForAddressBooks and addressBookHomeURLs should
                # be empty
                record.enabledForAddressBooks = False
                self.failIf(tuple(recordResource.addressBookHomeURLs()))
                record.enabledForAddressBooks = True

                addressBookRootURL = addressBookRootResources[record.service.__class__.__name__].url()

                for homeURL in homeURLs:
                    self.failUnless(homeURL.startswith(addressBookRootURL))
Пример #8
0
def upgradeCalendarHome(homePath, directory, cuaCache):

    errorOccurred = False

    log.debug("Upgrading calendar home: {path}", path=homePath)

    try:
        for cal in os.listdir(homePath):
            calPath = os.path.join(homePath, cal)
            if not os.path.isdir(calPath):
                # Skip non-directories; these might have been uploaded by a
                # random DAV client, they can't be calendar collections.
                continue
            if cal == 'notifications':
                # Delete the old, now obsolete, notifications directory.
                rmdir(calPath)
                continue
            log.debug("Upgrading calendar: {path}", path=calPath)
            if not (yield upgradeCalendarCollection(calPath, directory,
                                                    cuaCache)):
                errorOccurred = True

            # Change the calendar-free-busy-set xattrs of the inbox to the
            # __uids__/<guid> form
            if cal == "inbox":
                try:
                    for attr, value in xattr.xattr(calPath).iteritems():
                        if attr == xattrname(
                                "{urn:ietf:params:xml:ns:caldav}calendar-free-busy-set"
                        ):
                            value = yield updateFreeBusySet(value, directory)
                            if value is not None:
                                # Need to write the xattr back to disk
                                xattr.setxattr(calPath, attr, value)
                except IOError, ioe:
                    if ioe.errno == errno.EOPNOTSUPP:
                        # On non-native xattr systems we cannot do this,
                        # but those systems will typically not be migrating
                        # from pre-v1
                        pass
                except:
                    raise
Пример #9
0
    def test_MKCOL(self):
        """
        MKCOL request
        """
        path, uri = self.mkdtemp("collection")

        rmdir(path)

        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("MKCOL response %s != %s" % (response.code, responsecode.CREATED))

            if not os.path.isdir(path):
                self.fail("MKCOL did not create directory %s" % (path,))

        request = SimpleRequest(self.site, "MKCOL", uri)

        return self.send(request, check_result)
Пример #10
0
    def test_MKCOL(self):
        """
        MKCOL request
        """
        path, uri = self.mkdtemp("collection")

        rmdir(path)

        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("MKCOL response %s != %s" %
                          (response.code, responsecode.CREATED))

            if not os.path.isdir(path):
                self.fail("MKCOL did not create directory %s" % (path, ))

        request = SimpleRequest(self.site, "MKCOL", uri)

        return self.send(request, check_result)
Пример #11
0
def upgradeCalendarHome(homePath, directory, cuaCache):

    errorOccurred = False

    log.debug("Upgrading calendar home: %s" % (homePath,))

    try:
        for cal in os.listdir(homePath):
            calPath = os.path.join(homePath, cal)
            if not os.path.isdir(calPath):
                # Skip non-directories; these might have been uploaded by a
                # random DAV client, they can't be calendar collections.
                continue
            if cal == 'notifications':
                # Delete the old, now obsolete, notifications directory.
                rmdir(calPath)
                continue
            log.debug("Upgrading calendar: %s" % (calPath,))
            if not upgradeCalendarCollection(calPath, directory, cuaCache):
                errorOccurred = True

            # Change the calendar-free-busy-set xattrs of the inbox to the
            # __uids__/<guid> form
            if cal == "inbox":
                try:
                    for attr, value in xattr.xattr(calPath).iteritems():
                        if attr == xattrname("{urn:ietf:params:xml:ns:caldav}calendar-free-busy-set"):
                            value = updateFreeBusySet(value, directory)
                            if value is not None:
                                # Need to write the xattr back to disk
                                xattr.setxattr(calPath, attr, value)
                except IOError, ioe:
                    if ioe.errno == errno.EOPNOTSUPP:
                        # On non-native xattr systems we cannot do this,
                        # but those systems will typically not be migrating
                        # from pre-v1
                        pass
                except:
                    raise
Пример #12
0
    def test_MKCOL_invalid_body(self):
        """
        MKCOL request with invalid request body
        (Any body at all is invalid in our implementation; there is no
        such thing as a valid body.)
        """
        path, uri = self.mkdtemp("collection")

        rmdir(path)

        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.UNSUPPORTED_MEDIA_TYPE:
                self.fail("MKCOL response %s != %s" % (response.code, responsecode.UNSUPPORTED_MEDIA_TYPE))

            if os.path.isdir(path):
                self.fail("MKCOL incorrectly created directory %s" % (path,))

        request = SimpleRequest(self.site, "MKCOL", uri)
        request.stream = MemoryStream("This is not a valid MKCOL request body.")

        return self.send(request, check_result)
Пример #13
0
    def test_make_calendar_with_props(self):
        """
        Make calendar with properties (CalDAV-access-09, section 5.3.1.2)
        """
        uri = "/calendars/users/user01/calendar_prop/"
        path = os.path.join(self.docroot, uri[1:])

        if os.path.exists(path):
            rmdir(path)

        @inlineCallbacks
        def do_test(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("MKCALENDAR failed: %s" % (response.code, ))

            resource = (yield request.locateResource(uri))
            if not resource.isCalendarCollection():
                self.fail("MKCALENDAR made non-calendar collection")

            for qname, value in (
                (davxml.DisplayName.qname(), "Lisa's Events"),
                (caldavxml.CalendarDescription.qname(),
                 "Calendar restricted to events."),
            ):
                stored = yield resource.readProperty(qname, None)
                stored = str(stored)
                if stored != value:
                    self.fail(
                        "MKCALENDAR failed to set property %s: %s != %s" %
                        (qname, stored, value))

            supported_components = yield resource.readProperty(
                caldavxml.SupportedCalendarComponentSet, None)
            supported_components = supported_components.children
            if len(supported_components) != 1:
                self.fail(
                    "MKCALENDAR failed to set property %s: len(%s) != 1" %
                    (caldavxml.SupportedCalendarComponentSet.qname(),
                     supported_components))
            if supported_components[0] != caldavxml.CalendarComponent(
                    name="VEVENT"):
                self.fail("MKCALENDAR failed to set property %s: %s != %s" %
                          (caldavxml.SupportedCalendarComponentSet.qname(),
                           supported_components[0].toxml(),
                           caldavxml.CalendarComponent(name="VEVENT").toxml()))

            tz = (yield resource.readProperty(caldavxml.CalendarTimeZone,
                                              None))
            tz = tz.calendar()
            self.failUnless(tz.resourceType() == "VTIMEZONE")
            self.failUnless(
                tuple(tz.subcomponents())[0].propertyValue("TZID") ==
                "US-Eastern")

        mk = caldavxml.MakeCalendar(
            davxml.Set(
                davxml.PropertyContainer(
                    davxml.DisplayName("Lisa's Events"),
                    caldavxml.CalendarDescription(
                        "Calendar restricted to events."),  # FIXME: lang=en
                    caldavxml.SupportedCalendarComponentSet(
                        caldavxml.CalendarComponent(name="VEVENT")),
                    caldavxml.CalendarTimeZone("""BEGIN:VCALENDAR
PRODID:-//Example Corp.//CalDAV Client//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:US-Eastern
LAST-MODIFIED:19870101T000000Z
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:Eastern Standard Time (US & Canada)
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:Eastern Daylight Time (US & Canada)
END:DAYLIGHT
END:VTIMEZONE
END:VCALENDAR
"""))))

        request = SimpleStoreRequest(self,
                                     "MKCALENDAR",
                                     uri,
                                     authPrincipal=self.authPrincipal)
        request.stream = MemoryStream(mk.toxml())
        return self.send(request, do_test)
Пример #14
0
    uid, gid = getCalendarServerIDs(config)

    if not os.path.exists(config.DataRoot):
        makeDirsUserGroup(config.DataRoot, uid=uid, gid=gid)

    if os.path.exists(docRoot):

        # Look for the /principals/ directory on disk
        oldPrincipals = os.path.join(docRoot, "principals")
        if os.path.exists(oldPrincipals):
            # First move the proxy database and rename it
            doProxyDatabaseMoveUpgrade(config, uid=uid, gid=gid)

            # Now delete the on disk representation of principals
            rmdir(oldPrincipals)
            log.debug(
                "Removed the old principal directory at '%s'."
                % (oldPrincipals,)
            )

        calRoot = os.path.join(docRoot, "calendars")
        if os.path.exists(calRoot):

            uidHomes = os.path.join(calRoot, "__uids__")

            # Move calendar homes to new location:

            log.warn("Moving calendar homes to %s" % (uidHomes,))

            if os.path.exists(uidHomes):
Пример #15
0
    def test_make_calendar_with_props(self):
        """
        Make calendar with properties (CalDAV-access-09, section 5.3.1.2)
        """
        uri = "/calendars/users/user01/calendar_prop/"
        path = os.path.join(self.docroot, uri[1:])

        if os.path.exists(path):
            rmdir(path)

        @inlineCallbacks
        def do_test(response):
            response = IResponse(response)

            if response.code != responsecode.CREATED:
                self.fail("MKCALENDAR failed: %s" % (response.code,))

            resource = (yield request.locateResource(uri))
            if not resource.isCalendarCollection():
                self.fail("MKCALENDAR made non-calendar collection")

            for qname, value in (
                (davxml.DisplayName.qname(), "Lisa's Events"),
                (caldavxml.CalendarDescription.qname(), "Calendar restricted to events."),
            ):
                stored = yield resource.readProperty(qname, None)
                stored = str(stored)
                if stored != value:
                    self.fail("MKCALENDAR failed to set property %s: %s != %s"
                              % (qname, stored, value))

            supported_components = yield resource.readProperty(caldavxml.SupportedCalendarComponentSet, None)
            supported_components = supported_components.children
            if len(supported_components) != 1:
                self.fail("MKCALENDAR failed to set property %s: len(%s) != 1"
                          % (caldavxml.SupportedCalendarComponentSet.qname(), supported_components))
            if supported_components[0] != caldavxml.CalendarComponent(name="VEVENT"):
                self.fail("MKCALENDAR failed to set property %s: %s != %s"
                          % (caldavxml.SupportedCalendarComponentSet.qname(),
                             supported_components[0].toxml(), caldavxml.CalendarComponent(name="VEVENT").toxml()))

            tz = (yield resource.readProperty(caldavxml.CalendarTimeZone, None))
            tz = tz.calendar()
            self.failUnless(tz.resourceType() == "VTIMEZONE")
            self.failUnless(tuple(tz.subcomponents())[0].propertyValue("TZID") == "US-Eastern")

        mk = caldavxml.MakeCalendar(
            davxml.Set(
                davxml.PropertyContainer(
                    davxml.DisplayName("Lisa's Events"),
                    caldavxml.CalendarDescription("Calendar restricted to events."), # FIXME: lang=en
                    caldavxml.SupportedCalendarComponentSet(caldavxml.CalendarComponent(name="VEVENT")),
                    caldavxml.CalendarTimeZone(
                        """BEGIN:VCALENDAR
PRODID:-//Example Corp.//CalDAV Client//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:US-Eastern
LAST-MODIFIED:19870101T000000Z
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:Eastern Standard Time (US & Canada)
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:Eastern Daylight Time (US & Canada)
END:DAYLIGHT
END:VTIMEZONE
END:VCALENDAR
"""
                    )
                )
            )
        )

        request = SimpleStoreRequest(self, "MKCALENDAR", uri, authPrincipal=self.authPrincipal)
        request.stream = MemoryStream(mk.toxml())
        return self.send(request, do_test)
    def test_calendarHomeURLs(self):
        """
        DirectoryPrincipalResource.calendarHomeURLs(),
        DirectoryPrincipalResource.scheduleInboxURL(),
        DirectoryPrincipalResource.scheduleOutboxURL()
        """
        # No calendar home provisioner should result in no calendar homes.
        for provisioningResource, _ignore_recordType, recordResource, record in self._allRecords():
            if record.enabledForCalendaring:
                self.failIf(tuple(recordResource.calendarHomeURLs()))
                self.failIf(recordResource.scheduleInboxURL())
                self.failIf(recordResource.scheduleOutboxURL())

        # Need to create a calendar home provisioner for each service.
        calendarRootResources = {}

        for directory in self.directoryServices:
            path = os.path.join(self.docroot, directory.__class__.__name__)

            if os.path.exists(path):
                rmdir(path)
            os.mkdir(path)

            # Need a data store
            _newStore = CommonDataStore(path, None, None, True, False)

            provisioningResource = DirectoryCalendarHomeProvisioningResource(
                directory,
                "/calendars/",
                _newStore
            )

            calendarRootResources[directory.__class__.__name__] = provisioningResource

        # Calendar home provisioners should result in calendar homes.
        for provisioningResource, _ignore_recordType, recordResource, record in self._allRecords():
            if record.enabledForCalendaring:
                homeURLs = tuple(recordResource.calendarHomeURLs())
                self.failUnless(homeURLs)

                # Turn off enabledForCalendaring and calendarHomeURLs should
                # be empty
                record.enabledForCalendaring = False
                self.failIf(tuple(recordResource.calendarHomeURLs()))
                record.enabledForCalendaring = True

                calendarRootURL = calendarRootResources[record.service.__class__.__name__].url()

                inboxURL = recordResource.scheduleInboxURL()
                outboxURL = recordResource.scheduleOutboxURL()

                self.failUnless(inboxURL)
                self.failUnless(outboxURL)

                for homeURL in homeURLs:
                    self.failUnless(homeURL.startswith(calendarRootURL))

                    if inboxURL and inboxURL.startswith(homeURL):
                        self.failUnless(len(inboxURL) > len(homeURL))
                        self.failUnless(inboxURL.endswith("/"))
                        inboxURL = None

                    if outboxURL and outboxURL.startswith(homeURL):
                        self.failUnless(len(outboxURL) > len(homeURL))
                        self.failUnless(outboxURL.endswith("/"))
                        outboxURL = None

                self.failIf(inboxURL)
                self.failIf(outboxURL)
Пример #17
0
    uid, gid = getCalendarServerIDs(config)

    if not os.path.exists(config.DataRoot):
        makeDirsUserGroup(config.DataRoot, uid=uid, gid=gid)

    if os.path.exists(docRoot):

        # Look for the /principals/ directory on disk
        oldPrincipals = os.path.join(docRoot, "principals")
        if os.path.exists(oldPrincipals):
            # First move the proxy database and rename it
            doProxyDatabaseMoveUpgrade(config, uid=uid, gid=gid)

            # Now delete the on disk representation of principals
            rmdir(oldPrincipals)
            log.debug(
                "Removed the old principal directory at '%s'."
                % (oldPrincipals,)
            )

        calRoot = os.path.join(docRoot, "calendars")
        if os.path.exists(calRoot):

            uidHomes = os.path.join(calRoot, "__uids__")

            # Move calendar homes to new location:

            log.warn("Moving calendar homes to %s" % (uidHomes,))

            if os.path.exists(uidHomes):