예제 #1
0
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)
예제 #2
0
    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))
예제 #3
0
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)
예제 #4
0
    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))