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
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)
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)
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 )
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)
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])))
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 )
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])))
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 )
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
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)
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)
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 )
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
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])))
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])))