def _namedPropertiesForResource(request, props, resource, calendar=None, timezone=None, vcard=None, isowner=True, dataAllowed=True, forbidden=False): """ Return the specified properties on the specified resource. @param request: the L{IRequest} for the current request. @param props: a list of property elements or qname tuples for the properties of interest. @param resource: the L{CalDAVResource} for the targeted resource. @param calendar: the L{Component} for the calendar for the resource. This may be None if the calendar has not already been read in, in which case the resource will be used to get the calendar if needed. @param timezone: the L{Component} the VTIMEZONE to use for floating/all-day. @param vcard: the L{Component} for the vcard for the resource. This may be None if the vcard has not already been read in, in which case the resource will be used to get the vcard if needed. @param isowner: C{True} if the authorized principal making the request is the DAV:owner, C{False} otherwise. @param dataAllowed: C{True} if calendar/address data is allowed to be returned, C{False} otherwise. @param forbidden: if C{True} then return 403 status for all properties, C{False} otherwise. @return: a map of OK and NOT FOUND property values. """ properties_by_status = { responsecode.OK : [], responsecode.FORBIDDEN : [], responsecode.NOT_FOUND : [], } # Look for Prefer header first, then try Brief prefer = request.headers.getHeader("prefer", {}) returnMinimal = any([key == "return" and value == "minimal" for key, value, _ignore_args in prefer]) if not returnMinimal: returnMinimal = request.headers.getHeader("brief", False) for property in props: if isinstance(property, element.WebDAVElement): qname = property.qname() else: qname = property if forbidden: properties_by_status[responsecode.FORBIDDEN].append(propertyName(qname)) continue if isinstance(property, caldavxml.CalendarData): if dataAllowed: # Handle private events access restrictions if calendar is None: calendar = (yield resource.componentForUser()) filtered = HiddenInstanceFilter().filter(calendar) filtered = PrivateEventFilter(resource.accessMode, isowner).filter(filtered) filtered = CalendarDataFilter(property, timezone).filter(filtered) propvalue = CalendarData.fromCalendar(filtered, format=property.content_type) properties_by_status[responsecode.OK].append(propvalue) else: properties_by_status[responsecode.FORBIDDEN].append(propertyName(qname)) continue if isinstance(property, carddavxml.AddressData): if dataAllowed: if vcard is None: vcard = (yield resource.vCard()) filtered = AddressDataFilter(property).filter(vcard) propvalue = AddressData.fromAddress(filtered, format=property.content_type) properties_by_status[responsecode.OK].append(propvalue) else: properties_by_status[responsecode.FORBIDDEN].append(propertyName(qname)) continue has = (yield resource.hasProperty(property, request)) if has: try: prop = (yield resource.readProperty(property, request)) if prop is not None: properties_by_status[responsecode.OK].append(prop) elif not returnMinimal: properties_by_status[responsecode.NOT_FOUND].append(propertyName(qname)) except HTTPError: f = Failure() status = statusForFailure(f, "getting property: %s" % (qname,)) if status not in properties_by_status: properties_by_status[status] = [] if not returnMinimal or status != responsecode.NOT_FOUND: properties_by_status[status].append(propertyName(qname)) elif not returnMinimal: properties_by_status[responsecode.NOT_FOUND].append(propertyName(qname)) returnValue(properties_by_status)
def test_CalendarDataTextAndJSON(self): """ Text that we can both parse and generate CalendarData elements with both text and json formats. """ dataText = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] DTSTAMP:20080601T120000Z EXDATE:20080602T120000Z EXDATE:20080603T120000Z ORGANIZER;CN=User 01:mailto:[email protected] RRULE:FREQ=DAILY;COUNT=400 SUMMARY:Test END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") dataXML = """<?xml version='1.0' encoding='UTF-8'?> <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[%s]]></calendar-data>""" % ( dataText, ) jsonText = """[ "vcalendar", [ ["version", {}, "text", "2.0"], ["prodid", {}, "text", "-//CALENDARSERVER.ORG//NONSGML Version 1//EN"] ], [ ["vevent", [ ["uid", {}, "text", "12345-67890"], ["dtstart", {}, "date-time", "2008-06-01T12:00:00Z"], ["dtend", {}, "date-time", "2008-06-01T13:00:00Z"], ["attendee", {}, "cal-address", "mailto:[email protected]"], ["attendee", {}, "cal-address", "mailto:[email protected]"], ["dtstamp", {}, "date-time", "2008-06-01T12:00:00Z"], ["exdate", {}, "date-time", "2008-06-02T12:00:00Z"], ["exdate", {}, "date-time", "2008-06-03T12:00:00Z"], ["organizer", {"cn": "User 01"}, "cal-address", "mailto:[email protected]"], ["rrule", {}, "recur", {"count": 400, "freq": "DAILY"}], ["summary", {}, "text", "Test"] ], [ ] ] ] ] """ jsonXML = """<?xml version='1.0' encoding='UTF-8'?> <calendar-data content-type='application/calendar+json' xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[%s]]></calendar-data>""" % ( jsonText, ) cd = CalendarData.fromTextData(dataText) self.assertEqual( normalize_iCalStr(cd.calendar().getTextWithTimezones( True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual( normalizeJSON(cd.calendar().getTextWithTimezones( True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "text/calendar") self.assertEqual(cd.toxml(), dataXML) comp = Component.fromString(dataText) cd = CalendarData.fromCalendar(comp) self.assertEqual( normalize_iCalStr(cd.calendar().getTextWithTimezones( True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual( normalizeJSON(cd.calendar().getTextWithTimezones( True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "text/calendar") self.assertEqual(cd.toxml(), dataXML) cd = CalendarData.fromCalendar(comp, format="application/calendar+json") self.assertEqual( normalize_iCalStr(cd.calendar().getTextWithTimezones( True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual( normalizeJSON(cd.calendar().getTextWithTimezones( True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "application/calendar+json") self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML)) cd = CalendarData.fromTextData(jsonText, format="application/calendar+json") self.assertEqual( normalize_iCalStr(cd.calendar().getTextWithTimezones( True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual( normalizeJSON(cd.calendar().getTextWithTimezones( True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "application/calendar+json") self.assertEqual(cd.toxml(), jsonXML) comp = Component.fromString(jsonText, format="application/calendar+json") cd = CalendarData.fromCalendar(comp) self.assertEqual( normalize_iCalStr(cd.calendar().getTextWithTimezones( True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual( normalizeJSON(cd.calendar().getTextWithTimezones( True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "text/calendar") self.assertEqual(cd.toxml(), dataXML) cd = CalendarData.fromCalendar(comp, format="application/calendar+json") self.assertEqual( normalize_iCalStr(cd.calendar().getTextWithTimezones( True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual( normalizeJSON(cd.calendar().getTextWithTimezones( True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "application/calendar+json") self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML))
def _namedPropertiesForResource(request, props, resource, calendar=None, timezone=None, vcard=None, isowner=True): """ Return the specified properties on the specified resource. @param request: the L{IRequest} for the current request. @param props: a list of property elements or qname tuples for the properties of interest. @param resource: the L{CalDAVResource} for the targeted resource. @param calendar: the L{Component} for the calendar for the resource. This may be None if the calendar has not already been read in, in which case the resource will be used to get the calendar if needed. @param timezone: the L{Component} the VTIMEZONE to use for floating/all-day. @param vcard: the L{Component} for the vcard for the resource. This may be None if the vcard has not already been read in, in which case the resource will be used to get the vcard if needed. @param isowner: C{True} if the authorized principal making the request is the DAV:owner, C{False} otherwise. @return: a map of OK and NOT FOUND property values. """ properties_by_status = { responsecode.OK : [], responsecode.NOT_FOUND : [], } # Look for Prefer header first, then try Brief prefer = request.headers.getHeader("prefer", {}) returnMinimal = any([key == "return" and value == "minimal" for key, value, _ignore_args in prefer]) if not returnMinimal: returnMinimal = request.headers.getHeader("brief", False) for property in props: if isinstance(property, caldavxml.CalendarData): # Handle private events access restrictions if calendar is None: calendar = (yield resource.iCalendarForUser(request)) filtered = HiddenInstanceFilter().filter(calendar) filtered = PrivateEventFilter(resource.accessMode, isowner).filter(filtered) filtered = CalendarDataFilter(property, timezone).filter(filtered) propvalue = CalendarData.fromCalendar(filtered, format=property.content_type) properties_by_status[responsecode.OK].append(propvalue) continue if isinstance(property, carddavxml.AddressData): if vcard is None: vcard = (yield resource.vCard()) filtered = AddressDataFilter(property).filter(vcard) propvalue = AddressData.fromAddress(filtered, format=property.content_type) properties_by_status[responsecode.OK].append(propvalue) continue if isinstance(property, element.WebDAVElement): qname = property.qname() else: qname = property has = (yield resource.hasProperty(property, request)) if has: try: prop = (yield resource.readProperty(property, request)) if prop is not None: properties_by_status[responsecode.OK].append(prop) elif not returnMinimal: properties_by_status[responsecode.NOT_FOUND].append(propertyName(qname)) except HTTPError: f = Failure() status = statusForFailure(f, "getting property: %s" % (qname,)) if status not in properties_by_status: properties_by_status[status] = [] if not returnMinimal or status != responsecode.NOT_FOUND: properties_by_status[status].append(propertyName(qname)) elif not returnMinimal: properties_by_status[responsecode.NOT_FOUND].append(propertyName(qname)) returnValue(properties_by_status)
def test_CalendarDataTextAndJSON(self): """ Text that we can both parse and generate CalendarData elements with both text and json formats. """ dataText = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] DTSTAMP:20080601T120000Z EXDATE:20080602T120000Z EXDATE:20080603T120000Z ORGANIZER;CN=User 01:mailto:[email protected] RRULE:FREQ=DAILY SUMMARY:Test END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") dataXML = """<?xml version='1.0' encoding='UTF-8'?> <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[%s]]></calendar-data>""" % (dataText,) jsonText = """[ "vcalendar", [ ["version", {}, "text", "2.0"], ["prodid", {}, "text", "-//CALENDARSERVER.ORG//NONSGML Version 1//EN"] ], [ ["vevent", [ ["uid", {}, "text", "12345-67890"], ["dtstart", {}, "date-time", "2008-06-01T12:00:00Z"], ["dtend", {}, "date-time", "2008-06-01T13:00:00Z"], ["attendee", {}, "cal-address", "mailto:[email protected]"], ["attendee", {}, "cal-address", "mailto:[email protected]"], ["dtstamp", {}, "date-time", "2008-06-01T12:00:00Z"], ["exdate", {}, "date-time", "2008-06-02T12:00:00Z"], ["exdate", {}, "date-time", "2008-06-03T12:00:00Z"], ["organizer", {"cn": "User 01"}, "cal-address", "mailto:[email protected]"], ["rrule", {}, "recur", {"freq": "DAILY"}], ["summary", {}, "text", "Test"] ], [ ] ] ] ] """ jsonXML = """<?xml version='1.0' encoding='UTF-8'?> <calendar-data content-type='application/calendar+json' xmlns='urn:ietf:params:xml:ns:caldav'><![CDATA[%s]]></calendar-data>""" % (jsonText,) cd = CalendarData.fromTextData(dataText) self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "text/calendar") self.assertEqual(cd.toxml(), dataXML) comp = Component.fromString(dataText) cd = CalendarData.fromCalendar(comp) self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "text/calendar") self.assertEqual(cd.toxml(), dataXML) cd = CalendarData.fromCalendar(comp, format="application/calendar+json") self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "application/calendar+json") self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML)) cd = CalendarData.fromTextData(jsonText, format="application/calendar+json") self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "application/calendar+json") self.assertEqual(cd.toxml(), jsonXML) comp = Component.fromString(jsonText, format="application/calendar+json") cd = CalendarData.fromCalendar(comp) self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "text/calendar") self.assertEqual(cd.toxml(), dataXML) cd = CalendarData.fromCalendar(comp, format="application/calendar+json") self.assertEqual(normalize_iCalStr(cd.calendar().getTextWithTimezones(True, format="text/calendar")), normalize_iCalStr(dataText)) self.assertEqual(normalizeJSON(cd.calendar().getTextWithTimezones(True, format="application/calendar+json")), normalizeJSON(jsonText)) self.assertEqual(cd.content_type, "application/calendar+json") self.assertEqual(normalizeJSON(cd.toxml()), normalizeJSON(jsonXML))