Example #1
0
    def propfind(self, request, path, xbody=None, *args, **kwargs):
        if not self.has_access(self.resource, 'read'):
            return HttpResponseForbidden()

        if not self.resource.exists:
            return HttpResponseNotFound()

        if not self.get_access(self.resource):
            return HttpResponseForbidden()

        get_all_props, get_prop, get_prop_names = True, False, False
        if xbody:
            get_prop = [p.xpath('local-name()') for p in xbody('/D:propfind/D:prop/*')]
            get_all_props = xbody('/D:propfind/D:allprop')
            get_prop_names = xbody('/D:propfind/D:propname')
            if int(bool(get_prop)) + int(bool(get_all_props)) + int(bool(get_prop_names)) != 1:
                return HttpResponseBadRequest()

        children = self.resource.get_descendants(depth=self.get_depth(), include_self=True)

        if get_prop_names:
            responses = [
                D.response(
                    D.href(url_join(self.base_url, child.get_escaped_path())),
                    D.propstat(
                        D.prop(*[
                            D(name) for name in child.ALL_PROPS
                        ]),
                        D.status('HTTP/1.1 200 OK'),
                    ),
                )
                for child in children
            ]
        else:
            responses = [
                D.response(
                    D.href(url_join(self.base_url, child.get_escaped_path())),
                    D.propstat(
                        D.prop(
                            *get_property_tag_list(child, *(get_prop if get_prop else child.ALL_PROPS))
                        ),
                        D.status('HTTP/1.1 200 OK'),
                    ),
                )
                for child in children
            ]

        body = D.multistatus(*responses)
        response = HttpResponseMultiStatus(etree.tostring(body, pretty_print=True, xml_declaration=True, encoding='utf-8'))
        return response
Example #2
0
    def propfind(self, request, path, xbody=None, *args, **kwargs):
        if not self.has_access(self.resource, 'read'):
            return self.no_access()

        if not self.resource.exists:
            raise Http404("Resource doesn't exists")

        if not self.get_access(self.resource):
            return self.no_access()

        get_all_props, get_prop, get_prop_names = True, False, False
        if xbody:
            get_prop = [p.xpath('local-name()') for p in xbody('/D:propfind/D:prop/*')]
            get_all_props = xbody('/D:propfind/D:allprop')
            get_prop_names = xbody('/D:propfind/D:propname')
            if int(bool(get_prop)) + int(bool(get_all_props)) + int(bool(get_prop_names)) != 1:
                return HttpResponseBadRequest()

        children = self.resource.get_descendants(depth=self.get_depth())

        if get_prop_names:
            responses = [
                D.response(
                    D.href(url_join(self.base_url, child.get_escaped_path())),
                    D.propstat(
                        D.prop(*[
                            D(name) for name in child.ALL_PROPS
                        ]),
                        D.status('HTTP/1.1 200 OK'),
                    ),
                )
                for child in children
            ]
        else:
            responses = [
                D.response(
                    D.href(url_join(self.base_url, child.get_escaped_path())),
                    D.propstat(
                        D.prop(
                            *get_property_tag_list(child, *(get_prop if get_prop else child.ALL_PROPS))
                        ),
                        D.status('HTTP/1.1 200 OK'),
                    ),
                )
                for child in children
            ]

        body = D.multistatus(*responses)
        return self.build_xml_response(body, HttpResponseMultiStatus)
Example #3
0
    def propfind(self, request, path, xbody=None, *args, **kwargs):
        if not self.has_access(self.resource, 'read'):
            return self.no_access()

        if not self.resource.exists:
            raise Http404("Resource doesn't exists")

        if not self.get_access(self.resource):
            return self.no_access()

        get_all_props, get_prop, get_prop_names = True, False, False
        if xbody:
            get_prop = [
                p.xpath('local-name()') for p in xbody('/D:propfind/D:prop/*')
            ]
            get_all_props = xbody('/D:propfind/D:allprop')
            get_prop_names = xbody('/D:propfind/D:propname')
            if int(bool(get_prop)) + int(bool(get_all_props)) + int(
                    bool(get_prop_names)) != 1:
                return HttpResponseBadRequest()

        children = self.resource.get_descendants(depth=self.get_depth())

        if get_prop_names:
            responses = [
                D.response(
                    D.href(url_join(self.base_url, child.get_escaped_path())),
                    D.propstat(
                        D.prop(*[D(name) for name in child.ALL_PROPS]),
                        D.status('HTTP/1.1 200 OK'),
                    ),
                ) for child in children
            ]
        else:
            responses = [
                D.response(
                    D.href(url_join(self.base_url, child.get_escaped_path())),
                    D.propstat(
                        D.prop(*get_property_tag_list(
                            child, *(
                                get_prop if get_prop else child.ALL_PROPS))),
                        D.status('HTTP/1.1 200 OK'),
                    ),
                ) for child in children
            ]

        body = D.multistatus(*responses)
        return self.build_xml_response(body, HttpResponseMultiStatus)
Example #4
0
    def get_children(self):
        """Return an iterator of all direct children of this resource."""
        if not self.exists or isinstance(self.obj, self.object_model):
            return

        models = [[
            self.collection_model, self.collection_select_related,
            self.collection_prefetch_related
        ],
                  [
                      self.object_model, self.object_select_related,
                      self.object_prefetch_related
                  ]]
        for model, select_related, prefetch_related in models:
            qs = model.objects
            if select_related:
                qs = qs.select_related(*select_related)
            if prefetch_related:
                qs = qs.prefetch_related(*prefetch_related)
            kwargs = self.get_model_lookup_kwargs(
                **{self.collection_attribute: self.obj})
            for child in qs.filter(**kwargs):
                yield self.clone(
                    url_join(*(self.path + [child.name])),
                    obj=child  # Sending ready object to reduce db requests
                )
Example #5
0
 def read(self):
     response = HttpResponse()
     response['X-Accel-Redirect'] = url_join(self.prefix, self.get_path().encode('utf-8'))
     response['X-Accel-Charset'] = 'utf-8'
     response['Content-Type'] = mimetypes.guess_type(self.displayname)
     response['Content-Length'] = self.getcontentlength
     response['Last-Modified'] = http_date(self.getlastmodified)
     response['ETag'] = self.getetag
     raise ResponseException(response)
Example #6
0
 def read(self):
     response = HttpResponse()
     response['X-Accel-Redirect'] = url_join(self.prefix, self.get_path().encode('utf-8'))
     response['X-Accel-Charset'] = 'utf-8'
     response['Content-Type'] = mimetypes.guess_type(self.displayname)
     response['Content-Length'] = self.getcontentlength
     response['Last-Modified'] = http_date(self.getlastmodified)
     response['ETag'] = self.getetag
     raise ResponseException(response)
Example #7
0
 def get_children(self):
     """Return an iterator of all direct children of this resource."""
     for child in os.listdir(self.get_abs_path()):
         try:
             is_unicode = isinstance(child, unicode)
         except NameError:  # Python 3 fix
             is_unicode = isinstance(child, str)
         if not is_unicode:
             child = child.decode(fs_encoding)
         yield self.clone(url_join(*(self.path + [child])))
Example #8
0
 def get_children(self):
     """Return an iterator of all direct children of this resource."""
     for child in os.listdir(self.get_abs_path()):
         try:
             is_unicode = isinstance(child, unicode)
         except NameError:  # Python 3 fix
             is_unicode = isinstance(child, str)
         if not is_unicode:
             child = child.decode(fs_encoding)
         yield self.clone(url_join(*(self.path + [child])))
Example #9
0
    def get_children(self):
        """Return an iterator of all direct children of this resource."""
        if not self.exists or isinstance(self.obj, self.object_model):
            return

        for model in [self.collection_model, self.object_model]:
            kwargs = self.get_model_kwargs(**{self.collection_attribute: self.obj})
            for child in model.objects.filter(**kwargs):
                yield self.clone(
                    url_join(*(self.path + [child.name])),
                    obj=child    # Sending ready object to reduce db requests
                )
Example #10
0
    def get_children(self):
        """Return an iterator of all direct children of this resource."""
        # make sure the current object is a directory
        path = self.get_abs_path()

        if os.path.isdir(path):
            for child in os.listdir(path):
                try:
                    is_unicode = isinstance(child, str)
                except NameError:  # Python 3 fix
                    is_unicode = isinstance(child, str)
                if not is_unicode:
                    child = child.decode(fs_encoding)
                yield self.clone(url_join(*(self.path + [child])))
Example #11
0
    def get_children(self):
        """Return an iterator of all direct children of this resource."""
        if not self.exists or isinstance(self.obj, self.object_model):
            return

        querysets = [self.collection_model_qs, self.object_model_qs]
        for qs in querysets:
            # get kwargs for this model
            kwargs = self.get_model_lookup_kwargs(
                **{self.collection_attribute: self.obj})

            # wtf?
            for child in qs.filter(**kwargs):
                yield self.clone(
                    url_join(*(self.path + [child.name])),
                    obj=child  # Sending ready object to reduce db requests
                )
Example #12
0
 def get(self, request, path, head=False, *args, **kwargs):
     if not self.resource.exists:
         raise Http404("Resource doesn't exists")
     if not path.endswith("/") and self.resource.is_collection:
         return HttpResponseRedirect(request.build_absolute_uri() + "/")
     if path.endswith("/") and self.resource.is_object:
         return HttpResponseRedirect(
             request.build_absolute_uri().rstrip("/"))
     response = HttpResponse()
     if head:
         response['Content-Length'] = 0
     if not self.has_access(self.resource, 'read'):
         return self.no_access()
     if self.resource.is_object:
         response['Content-Type'] = self.resource.content_type
         response['ETag'] = self.resource.getetag
         if not head:
             response['Content-Length'] = self.resource.getcontentlength
             try:
                 response.content = self.resource.read()
             except AsSendFileFS:
                 assert sendfile is not None, "django-sendfile is not installed."
                 full_path = self.resource.get_abs_path()
                 if self.resource.quote:
                     full_path = urllib.quote(full_path)
                 response = sendfile.sendfile(request, full_path)
                 return response
             except RedirectFSException:
                 response = HttpResponse()
                 response['X-Accel-Redirect'] = url_join(
                     self.resource.prefix,
                     self.resource.get_path().encode('utf-8'))
                 response['X-Accel-Charset'] = 'utf-8'
                 response['Content-Type'] = mimetypes.guess_type(
                     self.resource.displayname)
                 response['Content-Length'] = self.resource.getcontentlength
                 response['Last-Modified'] = http_date(
                     self.resource.getlastmodified)
                 response['ETag'] = self.resource.getetag
                 raise ResponseException(response)
     elif not head:
         response = super(DavView, self).get(request, *args, **kwargs)
     response['Last-Modified'] = self.resource.getlastmodified
     return response
Example #13
0
 def proppatch(self, request, path, xbody, *args, **kwargs):
     if not self.resource.exists:
         raise Http404("Resource doesn't exists")
     if not self.has_access(self.resource, 'write'):
         return self.no_access()
     depth = self.get_depth(default="0")
     if depth != 0:
         return HttpResponseBadRequest('Invalid depth header value %s' %
                                       depth)
     props = xbody('/D:propertyupdate/D:set/D:prop/*')
     body = D.multistatus(
         D.response(
             D.href(
                 url_join(self.base_url,
                          self.resource.get_escaped_path())), *[
                              D.propstat(D.status('HTTP/1.1 200 OK'),
                                         D.prop(el.tag)) for el in props
                          ]))
     return self.build_xml_response(body, HttpResponseMultiStatus)
Example #14
0
 def proppatch(self, request, path, xbody, *args, **kwargs):
     if not self.resource.exists:
         return HttpResponseNotFound()
     if not self.has_access(self.resource, 'write'):
         return HttpResponseForbidden()
     depth = self.get_depth(default="0")
     if depth != 0:
         return HttpResponseBadRequest('Invalid depth header value %s' % depth)
     props = xbody('/D:propertyupdate/D:set/D:prop/*')
     body = D.multistatus(
         D.response(
             D.href(url_join(self.base_url, self.resource.get_escaped_path())),
             *[D.propstat(
                 D.status('HTTP/1.1 200 OK'),
                 D.prop(el.tag)
             ) for el in props]
         )
     )
     return self.build_xml_response(body, HttpResponseMultiStatus)
Example #15
0
    def get_children(self):
        """Return an iterator of all direct children of this resource."""
        if not self.exists or isinstance(self.obj, self.object_model):
            return

        models = [
            [self.collection_model, self.collection_select_related, self.collection_prefetch_related],
            [self.object_model, self.object_select_related, self.object_prefetch_related]
        ]
        for model, select_related, prefetch_related in models:
            qs = model.objects
            if select_related:
                qs = qs.select_related(*select_related)
            if prefetch_related:
                qs = qs.prefetch_related(*prefetch_related)
            kwargs = self.get_model_lookup_kwargs(**{self.collection_attribute: self.obj})
            for child in qs.filter(**kwargs):
                yield self.clone(
                    url_join(*(self.path + [child.name])),
                    obj=child    # Sending ready object to reduce db requests
                )
Example #16
0
    def get(self, request, path, head=False, *args, **kwargs):
        """
        GET a resource

        If head=True, only the headers are returned

        This method also handles X-Accel-Redirect headers

        :param request:
        :param path:
        :param head:
        :param args:
        :param kwargs:
        :return:
        """
        if not self.resource.exists:
            # Resource does not exist
            if head:
                return HttpResponse(content='', status=404)
            raise Http404("Resource doesn't exists")
        if not path.endswith("/") and self.resource.is_collection:
            # make sure collections always end with a slash
            return HttpResponseRedirect(request.build_absolute_uri() + "/")
        if path.endswith("/") and self.resource.is_object:
            # make sure files do not end with a slash
            return HttpResponseRedirect(
                request.build_absolute_uri().rstrip("/"))

        # make sure the user has access
        if not self.has_access(self.resource, 'read'):
            return self.no_access()

        # construct a response
        response = FileResponse()

        # set default content length to 0 - we can still overwrite it later
        response['Content-Length'] = 0

        # it's either an object or a collection
        if self.resource.is_object:
            # is an object
            response['Content-Type'] = self.resource.content_type
            response['ETag'] = self.resource.etag
            response['Content-Length'] = self.resource.getcontentlength
            response['Accept-Ranges'] = 'bytes'
            response['Cache-Control'] = 'must-revalidate'

            etags = request.META.get('HTTP_IF_NONE_MATCH', None)
            if etags \
                and (self.resource.etag in (e.strip(' ').strip('"') for e in etags.split(','))):
                response.status_code = 304
                return response
            if not head:
                # not a head request, so we can actually return a response
                if DJANGODAV_X_REDIRECT:
                    # Using X-Accel-Redirect
                    # create a new response that handles x-accel-redirect
                    response = HttpResponse()

                    # get the path to the requested file
                    current_path_to_file = self.resource.read().name

                    # make sure the path is relative
                    if current_path_to_file.startswith("/"):
                        # absolute path - convert it into a path relative to the resources root path
                        relpath = os.path.relpath(self.resource.read().name,
                                                  self.resource.root)
                    else:
                        # it's already a relative path, everything is fine
                        relpath = self.resource.read().name

                    # we are not allowed to send utf8 headers, so we need to make sure to quote it
                    response['X-Accel-Redirect'] = urlquote(
                        # join url with the DAV prefix
                        url_join(DJANGODAV_X_REDIRECT_PREFIX, relpath))
                    # set the display name as the content disposition header, acting as the download name of the file
                    response[
                        'Content-Disposition'] = rfc5987_content_disposition(
                            self.resource.displayname)
                    response['Content-Type'] = self.resource.content_type

                    # Unfortunately, setting content-length, last-modified and etag does not work with nginx, as those
                    # are overwritten by nginx, see https://forum.nginx.org/read.php?2,205636,205665#msg-205665
                    # Therefore we need to set them with a prefix, e.g., X-Accel-, and handle it with nginx
                    # add_header and $upstream_http_*
                    response[
                        'X-Accel-Content-Length'] = self.resource.getcontentlength
                    response[
                        'X-Accel-Last-Modified'] = self.resource.get_modified(
                        ).ctime()
                    response['X-Accel-ETag'] = self.resource.etag

                    return response
                else:
                    # try to read the resource and return it in response
                    response.streaming_content = self.resource.read()
        elif not head:
            # not a head request, and not an object -> render index.html
            response = super(DavView, self).get(request, *args, **kwargs)

        # set last modified field of response, so browsers and other tools can properly handle caching
        response['Last-Modified'] = self.resource.getlastmodified

        return response
Example #17
0
 def get_children(self):
     """Return an iterator of all direct children of this resource."""
     for child in os.listdir(self.get_abs_path()):
         yield self.clone(url_join(*(self.path + [child])))
Example #18
0
 def get_children(self):
     """Return an iterator of all direct children of this resource."""
     for child in os.listdir(self.get_abs_path()):
         if not isinstance(child, unicode):
             child = child.decode(fs_encoding)
         yield self.clone(url_join(*(self.path + [child])))