コード例 #1
0
    def test_calendar_query_bogus_timezone_id(self):
        """
        Partial retrieval of events by time range.
        (CalDAV-access-09, section 7.6.1)
        """
        TimezoneCache.create()
        self.addCleanup(TimezoneCache.clear)

        calendar_properties = (
            davxml.GETETag(),
            caldavxml.CalendarData(),
        )

        query_timerange = caldavxml.TimeRange(
            start="%04d1001T000000Z" % (DateTime.getToday().getYear(), ),
            end="%04d1101T000000Z" % (DateTime.getToday().getYear(), ),
        )

        query = caldavxml.CalendarQuery(
            davxml.PropertyContainer(*calendar_properties),
            caldavxml.Filter(
                caldavxml.ComponentFilter(
                    caldavxml.ComponentFilter(
                        query_timerange,
                        name="VEVENT",
                    ),
                    name="VCALENDAR",
                ), ),
            caldavxml.TimeZoneID.fromString("bogus"),
        )

        result = yield self.calendar_query(
            query, got_xml=None, expected_code=responsecode.FORBIDDEN)
        self.assertTrue("valid-timezone" in result)
コード例 #2
0
    def readProperty(self, property, request):

        if type(property) is tuple:
            qname = property
        else:
            qname = property.qname()
        namespace, name = qname

        if namespace == dav_namespace:
            if name == "resourcetype":
                result = davxml.ResourceType.empty  # @UndefinedVariable
                return result
            elif name == "getetag":
                result = davxml.GETETag(
                    ETag(hashlib.md5(self.vCardText()).hexdigest()).generate())
                return result
            elif name == "getcontenttype":
                mimeType = MimeType('text', 'vcard', {})
                result = davxml.GETContentType(generateContentType(mimeType))
                return result
            elif name == "getcontentlength":
                result = davxml.GETContentLength.fromString(
                    str(len(self.vCardText())))
                return result
            elif name == "getlastmodified":
                if self.vCard().hasProperty("REV"):
                    modDatetime = parse_date(self.vCard().propertyValue("REV"))
                else:
                    modDatetime = datetime.datetime.utcnow()

                # strip time zone because time zones are unimplemented in davxml.GETLastModified.fromDate
                d = modDatetime.date()
                t = modDatetime.time()
                modDatetimeNoTZ = datetime.datetime(d.year, d.month, d.day,
                                                    t.hour, t.minute, t.second,
                                                    t.microsecond, None)
                result = davxml.GETLastModified.fromDate(modDatetimeNoTZ)
                return result
            elif name == "creationdate":
                if self.vCard().hasProperty(
                        "REV"):  # use modification date property if it exists
                    creationDatetime = parse_date(
                        self.vCard().propertyValue("REV"))
                else:
                    creationDatetime = datetime.datetime.utcnow()
                result = davxml.CreationDate.fromDate(creationDatetime)
                return result
            elif name == "displayname":
                # AddressBook.app uses N. Use FN or UID instead?
                result = davxml.DisplayName.fromString(
                    self.vCard().propertyValue("N"))
                return result

        elif namespace == twisted_dav_namespace:
            return super(ABDirectoryQueryResult,
                         self).readProperty(property, request)

        return self._directoryBackedAddressBook.readProperty(property, request)
コード例 #3
0
    def test_calendar_query_timezone(self):
        """
        Partial retrieval of events by time range.
        (CalDAV-access-09, section 7.6.1)
        """
        TimezoneCache.create()
        self.addCleanup(TimezoneCache.clear)

        tzid1 = "Etc/GMT+1"
        tz1 = Component(None, pycalendar=readVTZ(tzid1))

        calendar_properties = (
            davxml.GETETag(),
            caldavxml.CalendarData(),
        )

        query_timerange = caldavxml.TimeRange(
            start="%04d1001T000000Z" % (DateTime.getToday().getYear(), ),
            end="%04d1101T000000Z" % (DateTime.getToday().getYear(), ),
        )

        query = caldavxml.CalendarQuery(
            davxml.PropertyContainer(*calendar_properties),
            caldavxml.Filter(
                caldavxml.ComponentFilter(
                    caldavxml.ComponentFilter(
                        query_timerange,
                        name="VEVENT",
                    ),
                    name="VCALENDAR",
                ), ),
            caldavxml.TimeZone.fromCalendar(tz1),
        )

        def got_xml(doc):
            if not isinstance(doc.root_element, davxml.MultiStatus):
                self.fail(
                    "REPORT response XML root element is not multistatus: %r" %
                    (doc.root_element, ))

        return self.calendar_query(query, got_xml)
コード例 #4
0
    def test_calendar_query_wrong_timezone_elements(self):
        """
        Partial retrieval of events by time range.
        (CalDAV-access-09, section 7.6.1)
        """
        TimezoneCache.create()
        self.addCleanup(TimezoneCache.clear)

        tzid1 = "Etc/GMT+1"
        tz1 = Component(None, pycalendar=readVTZ(tzid1))

        calendar_properties = (
            davxml.GETETag(),
            caldavxml.CalendarData(),
        )

        query_timerange = caldavxml.TimeRange(
            start="%04d1001T000000Z" % (DateTime.getToday().getYear(), ),
            end="%04d1101T000000Z" % (DateTime.getToday().getYear(), ),
        )

        query = caldavxml.CalendarQuery(
            davxml.PropertyContainer(*calendar_properties),
            caldavxml.Filter(
                caldavxml.ComponentFilter(
                    caldavxml.ComponentFilter(
                        query_timerange,
                        name="VEVENT",
                    ),
                    name="VCALENDAR",
                ), ),
            caldavxml.TimeZone.fromCalendar(tz1),
        )
        query.children += (caldavxml.TimeZoneID.fromString(tzid1), )

        result = yield self.calendar_query(
            query, got_xml=None, expected_code=responsecode.BAD_REQUEST)
        self.assertTrue("Only one of" in result)
コード例 #5
0
    def simple_event_multiget(self,
                              cal_uri,
                              okuids,
                              baduids,
                              data=None,
                              no_init=False,
                              withData=True):

        cal_uri = joinURL("/calendars/users/wsanchez", cal_uri)
        props = (davxml.GETETag(), )
        if withData:
            props += (caldavxml.CalendarData(), )
        children = []
        children.append(davxml.PropertyContainer(*props))

        okhrefs = [joinURL(cal_uri, x + ".ics") for x in okuids]
        badhrefs = [joinURL(cal_uri, x + ".ics") for x in baduids]
        for href in okhrefs + badhrefs:
            children.append(davxml.HRef.fromString(href))

        query = caldavxml.CalendarMultiGet(*children)

        def got_xml(doc):
            if not isinstance(doc.root_element, davxml.MultiStatus):
                self.fail(
                    "REPORT response XML root element is not multistatus: %r" %
                    (doc.root_element, ))

            for response in doc.root_element.childrenOfType(
                    davxml.PropertyStatusResponse):
                href = str(response.childOfType(davxml.HRef))
                for propstat in response.childrenOfType(davxml.PropertyStatus):
                    status = propstat.childOfType(davxml.Status)

                    if status.code != responsecode.OK:
                        self.fail(
                            "REPORT failed (status %s) to locate properties: %r"
                            % (status.code, href))

                    properties = propstat.childOfType(
                        davxml.PropertyContainer).children

                    for property in properties:
                        qname = property.qname()
                        if qname == (davxml.dav_namespace, "getetag"):
                            continue
                        if qname != (caldavxml.caldav_namespace,
                                     "calendar-data"):
                            self.fail(
                                "Response included unexpected property %r" %
                                (property, ))

                        result_calendar = property.calendar()

                        if result_calendar is None:
                            self.fail(
                                "Invalid response CalDAV:calendar-data: %r" %
                                (property, ))

                        uid = result_calendar.resourceUID()

                        if uid in okuids:
                            okuids.remove(uid)
                        else:
                            self.fail("Got calendar for unexpected UID %r" %
                                      (uid, ))

                        if data:
                            original_calendar = ical.Component.fromString(
                                data[uid])
                        else:
                            original_filename = file(
                                os.path.join(self.holidays_dir, uid + ".ics"))
                            original_calendar = ical.Component.fromStream(
                                original_filename)

                        self.assertEqual(result_calendar, original_calendar)

            for response in doc.root_element.childrenOfType(
                    davxml.StatusResponse):
                href = str(response.childOfType(davxml.HRef))
                propstatus = response.childOfType(davxml.PropertyStatus)
                if propstatus is not None:
                    status = propstatus.childOfType(davxml.Status)
                else:
                    status = response.childOfType(davxml.Status)
                if status.code != responsecode.OK:
                    if href in okhrefs:
                        self.fail(
                            "REPORT failed (status %s) to locate properties: %r"
                            % (status.code, href))
                    else:
                        if href in badhrefs:
                            badhrefs.remove(href)
                            continue
                        else:
                            self.fail("Got unexpected href %r" % (href, ))

            if withData and (len(okuids) + len(badhrefs)):
                self.fail("Some components were not returned: %r, %r" %
                          (okuids, badhrefs))

        return self.calendar_query(cal_uri, query, got_xml, data, no_init)
コード例 #6
0
    def simple_vcard_query(self, vcard_uri, vcard_filter, uids, withData=True, limit=None):

        vcard_uri = joinURL("/addressbooks/users/wsanchez", vcard_uri)

        props = (
            davxml.GETETag(),
        )
        if withData:
            props += (
                carddavxml.AddressData(),
            )
        query = carddavxml.AddressBookQuery(
            davxml.PropertyContainer(*props),
            carddavxml.Filter(
                vcard_filter,
            ),
        )

        def got_xml(doc):
            if not isinstance(doc.root_element, davxml.MultiStatus):
                self.fail("REPORT response XML root element is not multistatus: %r" % (doc.root_element,))

            count = 0
            for response in doc.root_element.childrenOfType(davxml.PropertyStatusResponse):
                for propstat in response.childrenOfType(davxml.PropertyStatus):
                    status = propstat.childOfType(davxml.Status)

                    if status.code == responsecode.INSUFFICIENT_STORAGE_SPACE and limit is not None:
                        continue
                    if status.code != responsecode.OK:
                        self.fail("REPORT failed (status %s) to locate properties: %r"
                                  % (status.code, propstat))
                    elif limit is not None:
                        count += 1
                        continue

                    properties = propstat.childOfType(davxml.PropertyContainer).children

                    for property in properties:
                        qname = property.qname()
                        if qname == (davxml.dav_namespace, "getetag"):
                            continue
                        if qname != (carddavxml.carddav_namespace, "address-data"):
                            self.fail("Response included unexpected property %r" % (property,))

                        result_addressbook = property.address()

                        if result_addressbook is None:
                            self.fail("Invalid response CardDAV:address-data: %r" % (property,))

                        uid = result_addressbook.resourceUID()

                        if uid in uids:
                            uids.remove(uid)
                        else:
                            self.fail("Got addressbook for unexpected UID %r" % (uid,))

                        original_filename = file(os.path.join(self.vcards_dir, uid + ".vcf"))
                        original_addressbook = vcard.Component.fromStream(original_filename)

                        self.assertEqual(result_addressbook, original_addressbook)

                if limit is not None and count != limit:
                    self.fail("Wrong number of limited results: %d" % (count,))

        return self.addressbook_query(vcard_uri, query, got_xml)
コード例 #7
0
    def test_calendar_query_time_range(self):
        """
        Partial retrieval of events by time range.
        (CalDAV-access-09, section 7.6.1)
        """
        calendar_properties = (
            davxml.GETETag(),
            caldavxml.CalendarData(
                caldavxml.CalendarComponent(
                    caldavxml.AllProperties(),
                    caldavxml.CalendarComponent(
                        caldavxml.Property(name="X-ABC-GUID"),
                        caldavxml.Property(name="UID"),
                        caldavxml.Property(name="DTSTART"),
                        caldavxml.Property(name="DTEND"),
                        caldavxml.Property(name="DURATION"),
                        caldavxml.Property(name="EXDATE"),
                        caldavxml.Property(name="EXRULE"),
                        caldavxml.Property(name="RDATE"),
                        caldavxml.Property(name="RRULE"),
                        caldavxml.Property(name="LOCATION"),
                        caldavxml.Property(name="SUMMARY"),
                        name="VEVENT",
                    ),
                    caldavxml.CalendarComponent(
                        caldavxml.AllProperties(),
                        caldavxml.AllComponents(),
                        name="VTIMEZONE",
                    ),
                    name="VCALENDAR",
                ), ),
        )

        query_timerange = caldavxml.TimeRange(
            start="%04d1001T000000Z" % (DateTime.getToday().getYear(), ),
            end="%04d1101T000000Z" % (DateTime.getToday().getYear(), ),
        )

        query = caldavxml.CalendarQuery(
            davxml.PropertyContainer(*calendar_properties),
            caldavxml.Filter(
                caldavxml.ComponentFilter(
                    caldavxml.ComponentFilter(
                        query_timerange,
                        name="VEVENT",
                    ),
                    name="VCALENDAR",
                ), ),
        )

        def got_xml(doc):
            if not isinstance(doc.root_element, davxml.MultiStatus):
                self.fail(
                    "REPORT response XML root element is not multistatus: %r" %
                    (doc.root_element, ))

            for response in doc.root_element.childrenOfType(
                    davxml.PropertyStatusResponse):
                properties_to_find = [p.qname() for p in calendar_properties]

                for propstat in response.childrenOfType(davxml.PropertyStatus):
                    status = propstat.childOfType(davxml.Status)
                    properties = propstat.childOfType(
                        davxml.PropertyContainer).children

                    if status.code != responsecode.OK:
                        self.fail(
                            "REPORT failed (status %s) to locate properties: %r"
                            % (status.code, properties))

                    for property in properties:
                        qname = property.qname()
                        if qname in properties_to_find:
                            properties_to_find.remove(qname)
                        else:
                            self.fail(
                                "REPORT found property we didn't ask for: %r" %
                                (property, ))

                        if isinstance(property, caldavxml.CalendarData):
                            cal = property.calendar()
                            instances = cal.expandTimeRanges(
                                query_timerange.end)
                            vevents = [
                                x for x in cal.subcomponents()
                                if x.name() == "VEVENT"
                            ]
                            if not TimeRange(query_timerange).matchinstance(
                                    vevents[0], instances):
                                self.fail(
                                    "REPORT property %r returned calendar %s outside of request time range %r"
                                    % (property, property.calendar,
                                       query_timerange))

        return self.calendar_query(query, got_xml)
コード例 #8
0
    def simple_event_query(self, event_filter, uids, withData=True):
        props = (davxml.GETETag(), )
        if withData:
            props += (caldavxml.CalendarData(), )
        query = caldavxml.CalendarQuery(
            davxml.PropertyContainer(*props),
            caldavxml.Filter(
                caldavxml.ComponentFilter(
                    caldavxml.ComponentFilter(
                        event_filter,
                        name="VEVENT",
                    ),
                    name="VCALENDAR",
                ), ),
        )

        def got_xml(doc):
            if not isinstance(doc.root_element, davxml.MultiStatus):
                self.fail(
                    "REPORT response XML root element is not multistatus: %r" %
                    (doc.root_element, ))

            for response in doc.root_element.childrenOfType(
                    davxml.PropertyStatusResponse):
                for propstat in response.childrenOfType(davxml.PropertyStatus):
                    status = propstat.childOfType(davxml.Status)

                    if status.code != responsecode.OK:
                        self.fail(
                            "REPORT failed (status %s) to locate properties: %r"
                            % (status.code, propstat))

                    properties = propstat.childOfType(
                        davxml.PropertyContainer).children

                    for property in properties:
                        qname = property.qname()
                        if qname == (davxml.dav_namespace, "getetag"):
                            continue
                        if qname != (caldavxml.caldav_namespace,
                                     "calendar-data"):
                            self.fail(
                                "Response included unexpected property %r" %
                                (property, ))

                        result_calendar = property.calendar()

                        if result_calendar is None:
                            self.fail(
                                "Invalid response CalDAV:calendar-data: %r" %
                                (property, ))

                        uid = result_calendar.resourceUID()

                        if uid in uids:
                            uids.remove(uid)
                        else:
                            self.fail("Got calendar for unexpected UID %r" %
                                      (uid, ))

                        original_filename = file(
                            os.path.join(self.holidays_dir, uid + ".ics"))
                        original_calendar = ical.Component.fromStream(
                            original_filename)

                        self.assertEqual(result_calendar, original_calendar)

        return self.calendar_query(query, got_xml)