Esempio n. 1
0
    async def report(
        self,
        environ,
        body,
        resources_by_hrefs,
        properties,
        base_href,
        base_resource,
        depth,
    ):
        requested = None
        filter_el = None
        limit = None
        for el in body:
            if el.tag in ("{DAV:}prop", "{DAV:}allprop", "{DAV:}propname"):
                requested = el
            elif el.tag == ("{%s}filter" % NAMESPACE):
                filter_el = el
            elif el.tag == ("{%s}limit" % NAMESPACE):
                limit = el
            else:
                raise webdav.BadRequestError("Unknown tag %s in report %s" %
                                             (el.tag, self.name))
        if limit is not None:
            try:
                [nresults_el] = list(limit)
            except ValueError:
                raise webdav.BadRequestError(
                    "Invalid number of subelements in limit")
            try:
                nresults = int(nresults_el.text)
            except ValueError:
                raise webdav.BadRequestError("nresults not a number")
        else:
            nresults = None

        i = 0
        async for (href, resource) in webdav.traverse_resource(
                base_resource, base_href, depth):
            if not apply_filter(filter_el, resource):
                continue
            if nresults is not None and i >= nresults:
                break
            propstat = davcommon.get_properties_with_data(
                self.data_property,
                href,
                resource,
                properties,
                environ,
                requested,
            )
            yield webdav.Status(href,
                                "200 OK",
                                propstat=[s async for s in propstat])
            i += 1
Esempio n. 2
0
 def report(self, environ, body, resources_by_hrefs, properties, base_href,
            base_resource, depth):
     # TODO(jelmer): Verify that resource is an addressbook
     requested = None
     filter_el = None
     tztext = None
     for el in body:
         if el.tag in ('{DAV:}prop', '{DAV:}propname', '{DAV:}allprop'):
             requested = el
         elif el.tag == '{urn:ietf:params:xml:ns:caldav}filter':
             filter_el = el
         elif el.tag == '{urn:ietf:params:xml:ns:caldav}timezone':
             tztext = el.text
         else:
             raise webdav.BadRequestError('Unknown tag %s in report %s' %
                                          (el.tag, self.name))
     if tztext is not None:
         tz = get_pytz_from_text(tztext)
     else:
         tz = get_calendar_timezone(base_resource)
     tzify = lambda dt: as_tz_aware_ts(dt, tz)
     for (href,
          resource) in webdav.traverse_resource(base_resource, base_href,
                                                depth):
         if not apply_filter(filter_el, resource, tzify):
             continue
         propstat = davcommon.get_properties_with_data(
             self.data_property, href, resource, properties, environ,
             requested)
         yield webdav.Status(href, '200 OK', propstat=list(propstat))
Esempio n. 3
0
    async def report(
        self,
        environ,
        body,
        resources_by_hrefs,
        properties,
        base_href,
        base_resource,
        depth,
    ):
        # TODO(jelmer): Verify that resource is a calendar
        requested = None
        filter_el = None
        tztext = None
        for el in body:
            if el.tag in ("{DAV:}prop", "{DAV:}propname", "{DAV:}allprop"):
                requested = el
            elif el.tag == "{urn:ietf:params:xml:ns:caldav}filter":
                filter_el = el
            elif el.tag == "{urn:ietf:params:xml:ns:caldav}timezone":
                tztext = el.text
            else:
                raise webdav.BadRequestError("Unknown tag %s in report %s" %
                                             (el.tag, self.name))
        if tztext is not None:
            tz = get_pytz_from_text(tztext)
        else:
            tz = get_calendar_timezone(base_resource)

        def filter_fn(cls):
            return parse_filter(filter_el, cls(tz))

        def members(collection):
            return itertools.chain(
                collection.calendar_query(filter_fn),
                collection.subcollections(),
            )

        async for (href,
                   resource) in webdav.traverse_resource(base_resource,
                                                         base_href,
                                                         depth,
                                                         members=members):
            # Ideally traverse_resource would only return the right things.
            if getattr(resource, "content_type", None) == "text/calendar":
                propstat = davcommon.get_properties_with_data(
                    self.data_property,
                    href,
                    resource,
                    properties,
                    environ,
                    requested,
                )
                yield webdav.Status(href,
                                    "200 OK",
                                    propstat=[s async for s in propstat])
Esempio n. 4
0
 async def handle(self, request, environ, app):
     content_type = request.content_type
     base_content_type, params = webdav.parse_type(content_type)
     if base_content_type not in (
             "text/xml",
             "application/xml",
             None,
             "text/plain",
             "application/octet-stream",
     ):
         raise webdav.UnsupportedMediaType(content_type)
     href, path, resource = app._get_resource_from_environ(request, environ)
     if resource is not None:
         return webdav._send_simple_dav_error(
             request,
             "403 Forbidden",
             error=ET.Element("{DAV:}resource-must-be-null"),
             description=("Something already exists at %r" % path),
         )
     try:
         resource = app.backend.create_collection(path)
     except FileNotFoundError:
         return webdav.Response(status="409 Conflict")
     el = ET.Element("{DAV:}resourcetype")
     await app.properties["{DAV:}resourcetype"].get_value(
         href, resource, el, environ)
     ET.SubElement(el, "{urn:ietf:params:xml:ns:caldav}calendar")
     app.properties["{DAV:}resourcetype"].set_value(href, resource, el)
     if base_content_type in ("text/xml", "application/xml"):
         et = await webdav._readXmlBody(
             request,
             "{urn:ietf:params:xml:ns:caldav}mkcalendar",
             strict=app.strict,
         )
         propstat = []
         for el in et:
             if el.tag != "{DAV:}set":
                 raise webdav.BadRequestError(
                     "Unknown tag %s in mkcalendar" % el.tag)
             propstat.extend(
                 webdav.apply_modify_prop(el, href, resource,
                                          app.properties))
             ret = ET.Element(
                 "{urn:ietf:params:xml:ns:carldav:}mkcalendar-response")
         for propstat_el in webdav.propstat_as_xml(propstat):
             ret.append(propstat_el)
         return webdav._send_xml_response("201 Created", ret,
                                          webdav.DEFAULT_ENCODING)
     else:
         return webdav.Response(status="201 Created")
Esempio n. 5
0
 def handle(self, environ, start_response, app):
     try:
         content_type = environ['CONTENT_TYPE']
     except KeyError:
         base_content_type = None
     else:
         base_content_type, params = webdav.parse_type(content_type)
     if base_content_type not in ('text/xml', 'application/xml', None,
                                  'text/plain'):
         raise webdav.UnsupportedMediaType(content_type)
     href, path, resource = app._get_resource_from_environ(environ)
     if resource is not None:
         return webdav._send_simple_dav_error(
             environ,
             start_response,
             '403 Forbidden',
             error=ET.Element('{DAV:}resource-must-be-null'),
             description=('Something already exists at %r' % path))
     try:
         resource = app.backend.create_collection(path)
     except FileNotFoundError:
         start_response('409 Conflict', [])
         return []
     el = ET.Element('{DAV:}resourcetype')
     app.properties['{DAV:}resourcetype'].get_value(href, resource, el,
                                                    environ)
     ET.SubElement(el, '{urn:ietf:params:xml:ns:caldav}calendar')
     app.properties['{DAV:}resourcetype'].set_value(href, resource, el)
     if base_content_type in ('text/xml', 'application/xml'):
         et = webdav._readXmlBody(
             environ, '{urn:ietf:params:xml:ns:caldav}mkcalendar')
         propstat = []
         for el in et:
             if el.tag != '{DAV:}set':
                 raise webdav.BadRequestError(
                     'Unknown tag %s in mkcalendar' % el.tag)
             propstat.extend(
                 webdav.apply_modify_prop(el, href, resource,
                                          app.properties))
             ret = ET.Element(
                 '{urn:ietf:params:xml:ns:carldav:}mkcalendar-response')
         for propstat_el in webdav.propstat_as_xml(propstat):
             ret.append(propstat_el)
         return webdav._send_xml_response(start_response, '201 Created',
                                          ret, webdav.DEFAULT_ENCODING)
     else:
         start_response('201 Created', [])
         return []
Esempio n. 6
0
 def report(self, environ, body, resources_by_hrefs, properties, base_href,
            resource, depth):
     # TODO(jelmer): Verify that depth == "0"
     # TODO(jelmer): Verify that resource is an the right resource type
     requested = None
     hrefs = []
     for el in body:
         if el.tag in ('{DAV:}prop', '{DAV:}allprop', '{DAV:}propname'):
             requested = el
         elif el.tag == '{DAV:}href':
             hrefs.append(webdav.read_href_element(el))
         else:
             raise webdav.BadRequestError('Unknown tag %s in report %s' %
                                          (el.tag, self.name))
     for (href, resource) in resources_by_hrefs(hrefs):
         if resource is None:
             yield webdav.Status(href, '404 Not Found', propstat=[])
         else:
             propstat = get_properties_with_data(self.data_property, href,
                                                 resource, properties,
                                                 environ, requested)
             yield webdav.Status(href, '200 OK', propstat=list(propstat))
Esempio n. 7
0
 async def report(
     self,
     environ,
     body,
     resources_by_hrefs,
     properties,
     base_href,
     resource,
     depth,
 ):
     # TODO(jelmer): Verify that depth == "0"
     # TODO(jelmer): Verify that resource is an the right resource type
     requested = None
     hrefs = []
     for el in body:
         if el.tag in ("{DAV:}prop", "{DAV:}allprop", "{DAV:}propname"):
             requested = el
         elif el.tag == "{DAV:}href":
             hrefs.append(webdav.read_href_element(el))
         else:
             raise webdav.BadRequestError("Unknown tag %s in report %s" %
                                          (el.tag, self.name))
     for (href, resource) in resources_by_hrefs(hrefs):
         if resource is None:
             yield webdav.Status(href, "404 Not Found", propstat=[])
         else:
             propstat = get_properties_with_data(
                 self.data_property,
                 href,
                 resource,
                 properties,
                 environ,
                 requested,
             )
             yield webdav.Status(href,
                                 "200 OK",
                                 propstat=[s async for s in propstat])
Esempio n. 8
0
    async def report(self, environ, request_body, resources_by_hrefs,
                     properties, href, resource, depth):
        old_token = None
        sync_level = None
        limit = None
        requested = None
        for el in request_body:
            if el.tag == '{DAV:}sync-token':
                old_token = el.text
            elif el.tag == '{DAV:}sync-level':
                sync_level = el.text
            elif el.tag == '{DAV:}limit':
                limit = el.text
            elif el.tag == '{DAV:}prop':
                requested = list(el)
            else:
                raise webdav.BadRequestError('unknown tag %s' % el.tag)
        # TODO(jelmer): Implement sync_level infinite
        if sync_level not in ("1", ):
            raise webdav.BadRequestError("sync level %r unsupported" %
                                         sync_level)

        new_token = resource.get_sync_token()
        try:
            diff_iter = resource.iter_differences_since(old_token, new_token)
        except NotImplementedError:
            yield webdav.Status(
                href,
                '403 Forbidden',
                error=ET.Element('{DAV:}sync-traversal-supported'))
            return

        if limit is not None:
            try:
                [nresults_el] = list(limit)
            except ValueError:
                raise webdav.BadRequestError(
                    'Invalid number of subelements in limit')
            try:
                nresults = int(nresults_el.text)
            except ValueError:
                raise webdav.BadRequestError('nresults not a number')
            diff_iter = itertools.islice(diff_iter, nresults)

        for (name, old_resource, new_resource) in diff_iter:
            subhref = urllib.parse.urljoin(webdav.ensure_trailing_slash(href),
                                           name)
            if new_resource is None:
                yield webdav.Status(subhref, status='404 Not Found')
            else:
                propstat = []
                for prop in requested:
                    if old_resource is not None:
                        old_propstat = webdav.get_property_from_element(
                            href, old_resource, properties, environ, prop)
                    else:
                        old_propstat = None
                    new_propstat = webdav.get_property_from_element(
                        href, new_resource, properties, environ, prop)
                    if old_propstat != new_propstat:
                        propstat.append(new_propstat)
                yield webdav.Status(subhref, propstat=propstat)
        yield SyncToken(new_token)