Exemplo n.º 1
0
Arquivo: app.py Projeto: linkdd/9cal
    def delete(self, path, collections, request_body, environ):
        """
            Manage DELETE request.

            The URL contains the element to delete :

                /path/to/calendar/element-uid.ics : delete an item
                /path/to/calendar/ : delete the whole calendar
        """

        collection = collections[0]

        if collection.path == path.strip('/'):
            # Path match the collection, delete the whole collection
            item = collection

        else:
            # Path match an item, delete the item
            item = collection.get_item(self.wsgi_name_from_path(path, collection))

        if item and environ.get('HTTP_IF_MATCH', item.etag) == item.etag:
            # No ETag precondition, or precondition verified

            if item is collection:
                collection.delete()

            else:
                collection.remove(item.name)

            # Write response body

            multistatus = ET.Element(xmlutils.tag('D', 'multistatus'))
            response = ET.Element(xmlutils.tag('D', 'response'))
            multistatus.append(response)

            href = ET.Element(xmlutils.tag('D', 'href'))
            href.text = path
            response.append(href)

            status = ET.Element(xmlutils.tag('D', 'status'))
            status.text = util.http_response(200)
            response.append(status)

            return 204, {}, [xmlutils.render(multistatus)]

        # No item or ETag precondition not verified
        return 412, {}, []
Exemplo n.º 2
0
Arquivo: app.py Projeto: linkdd/9cal
    def report(self, path, collections, request_body, environ):
        """
            Manage REPORT request.

            According to [RFC 3253], it should return 207 Multi-Status.
            The request body contains :

                <C:calendar-multiget / calendar-query>
                    <D:href>...</D:href>
                    <D:prop>
                        ...
                    </D:prop>
                </C:calendar-multiget / calendar-query>

            It should returns the following content :

                <D:multistatus>
                    <D:response>
                        <D:href>
                        <D:propstat>
                            <D:prop>
                                ...
                            </D:prop>
                            <D:status>...</D:status>
                        </D:propstat>
                    </D:response>
                    ...
                </D:multistatus>
        """

        headers = {
            'Content-Type': 'text/xml',
        }

        collection = collections[0]

        # Parse request body
        dom = ET.fromstring(request_body)

        dprop = dom.find(xmlutils.tag('D', 'prop'))
        properties = [prop.tag for prop in dprop]

        if collection:
            if dom.tag == xmlutils.tag('C', 'calendar-multiget'):
                hrefs = set(href.text for href in dom.findall(xmlutils.tag('D', 'href')))

            else:
                hrefs = (path,)
        else:
            hrefs = ()

        # Write response body
        multistatus = ET.Element(xmlutils.tag('D', 'multistatus'))

        for href in hrefs:
            name = self.wsgi_name_from_path(href, collection)

            if name:
                # The reference is an item

                path = '/'.join(href.split('/')[:-1]) + '/'
                items = (item for item in collection.items if item.name == name)

            else:
                # The reference is a collection
                path = href
                items = collection.components

            # Create a response element for all items
            for item in items:
                response = ET.Element(xmlutils.tag('D', 'response'))
                multistatus.append(response)

                xmlhref = ET.Element(xmlutils.tag('D', 'href'))
                xmlhref.text = '/'.join([path.rstrip('/'), item.name]) + '.ics'
                response.append(xmlhref)

                propstat = ET.Element(xmlutils.tag('D', 'propstat'))
                response.append(propstat)

                prop = ET.Element(xmlutils.tag('D', 'prop'))
                propstat.append(prop)

                for tag in properties:
                    element = ET.Element(tag)

                    if tag == xmlutils.tag('D', 'getetag'):
                        element.text = item.etag

                    elif tag == xmlutils.tag('C', 'calendar-data'):
                        if isinstance(item, ical.Component):
                            element.text = item.to_ical()

                    prop.append(element)

                status = ET.Element(xmlutils.tag('D', 'status'))
                status.text = util.http_response(200)
                propstat.append(status)

        return 207, headers, [xmlutils.render(multistatus)]
Exemplo n.º 3
0
def propfind_response(path, item, props):
    """ Perform a PROPFIND on ``item`` """

    is_collection = isinstance(item, ical.Collection)

    if is_collection:
        with item.props as properties:
            collection_props = properties

    response = ET.Element(tag('D', 'response'))

    href = ET.Element(tag('D', 'href'))
    href.text = item.name
    response.append(href)

    propstat404 = ET.Element(tag('D', 'propstat'))
    propstat200 = ET.Element(tag('D', 'propstat'))
    response.append(propstat200)

    prop404 = ET.Element(tag('D', 'prop'))
    propstat404.append(prop404)

    prop200 = ET.Element(tag('D', 'prop'))
    propstat200.append(prop200)

    for xmltag in props:
        element = ET.Element(xmltag)
        tag_not_found = False

        if xmltag == tag('D', 'getetag'):
            element.text = item.etag

        elif xmltag == tag('D', 'principal-URL'):
            xmltag = ET.Element(tag('D', 'href'))
            xmltag.text = path
            element.append(xmltag)

        elif xmltag in (
                tag('D', 'principal-collection-set'),
                tag('C', 'calendar-user-address-set'),
                tag('C', 'calendar-home-set')
                ):
            xmltag = ET.Element(tag('D', 'href'))
            xmltag.text = path
            element.append(xmltag)

        elif xmltag == tag('C', 'supported-calendar-component-set'):
            for component in ("VTODO", "VEVENT", "VJOURNAL"):
                comp = ET.Element(tag('C', 'comp'))
                comp.set('name', component)
                element.append(comp)

        elif xmltag == tag('D', 'current-user-principal'):
            xmltag = ET.Element(tag('D', 'href'))
            xmltag.text = path
            element.append(xmltag)

        elif xmltag == tag('D', 'current-user-privilege-set'):
            privilege = ET.Element(tag('D', 'privilege'))
            privilege.append(ET.Element(tag('D', 'all')))
            element.append(privilege)

        elif xmltag == tag('D', 'supported-report-set'):
            for report_name in (
                    'principal-property-search',
                    'sync-collection',
                    'expand-property',
                    'principal-search-property-set'
                    ):
                supported = ET.Element(tag('D', 'supported-report'))
                report_tag = ET.Element(tag('D', 'report'))
                report_tag.text = report_name
                supported.append(report_tag)
                element.append(supported)

        elif is_collection:
            # Only for collections
            if xmltag == tag('D', 'getcontenttype'):
                element.text = item.mimetype

            elif xmltag == tag('D', 'resourcetype'):
                xmltag = ET.Element(tag('C', item.resource_type))
                element.append(xmltag)

                xmltag = ET.Element(tag('D', 'collection'))
                element.append(xmltag)

            elif xmltag == tag('D', 'owner'):
                element.text = os.path.dirname(path)

            elif xmltag == tag('CS', 'getctag'):
                element.text = item.etag

            elif xmltag == tag('C', 'calendar-timezone'):
                element.text = item.timezones.to_ical()

            else:
                tagname = tag_clark(xmltag)

                if tagname in collection_props:
                    element.text = collection_props[tagname]
                else:
                    tag_not_found = True

        # Not for collections
        elif xmltag == tag('D', 'getcontenttype'):
            element.text = '{0}; component={1}'.format(item.mimetype, item.tag.lower())

        elif xmltag == tag('D', 'resourcetype'):
            # Must be empty for non-collection element
            pass

        else:
            tag_not_found = True

        if tag_not_found:
            prop404.append(element)
        else:
            prop200.append(element)

    status200 = ET.Element(tag('D', 'status'))
    status200.text = http_response(200)
    propstat200.append(status200)

    status404 = ET.Element(tag('D', 'status'))
    status404.text = http_response(404)
    propstat404.append(status404)

    if len(prop404):
        response.append(propstat404)

    return response