Skip to content
Snippets Groups Projects
Verified Commit dfb4cfea authored by Eliot Berriot's avatar Eliot Berriot
Browse files

WIP

parent 9d7cd006
Branches webdav
No related tags found
No related merge requests found
......@@ -13,6 +13,7 @@ urlpatterns = [
# Django Admin, use {% url 'admin:index' %}
url(settings.ADMIN_URL, admin.site.urls),
url(r"^api/", include(("config.api_urls", "api"), namespace="api")),
url(r"^dav/", include(("funkwhale_api.webdav.urls", "webdav"), namespace="webdav")),
url(
r"^",
include(
......
......@@ -9,7 +9,7 @@ from django import urls
from . import preferences
from . import utils
EXCLUDED_PATHS = ["/api", "/federation", "/.well-known"]
EXCLUDED_PATHS = ["/api", "/federation", "/.well-known", "/dav", "/rest"]
def should_fallback_to_spa(path):
......
from __future__ import unicode_literals
from django.utils import six
from django.utils.xmlutils import SimplerXMLGenerator
from django.utils.six.moves import StringIO
from django.utils.encoding import smart_text
from rest_framework.renderers import BaseRenderer
DATA = """<?xml version="1.0" encoding="utf-8"?>
<d:multistatus xmlns:d="DAV:">
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype>
<d:collection />
</d:resourcetype>
<d:displayname>Products</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:quota-available-bytes>102312153088</d:quota-available-bytes>
<d:quota-used-bytes>26520371200</d:quota-used-bytes>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:getcontenttype />
<d:getcontentlength />
<d:checked-in />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.doc</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype />
<d:displayname>General.doc</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:getcontenttype>application/msword</d:getcontenttype>
<d:getcontentlength>10752</d:getcontentlength>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:checked-in>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.doc?version=1</d:href>
</d:checked-in>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:quota-available-bytes />
<d:quota-used-bytes />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.vsd</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype />
<d:displayname>General.vsd</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:getcontenttype>application/x-visio</d:getcontenttype>
<d:getcontentlength>0</d:getcontentlength>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:checked-in>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/General.vsd?version=1</d:href>
</d:checked-in>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:quota-available-bytes />
<d:quota-used-bytes />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
<d:response>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/Product.mpp</d:href>
<d:propstat>
<d:status>HTTP/1.1 200 OK</d:status>
<d:prop>
<d:resourcetype />
<d:displayname>Product.mpp</d:displayname>
<d:creationdate>2019-02-22T14:36:36Z</d:creationdate>
<d:getlastmodified>Fri, 22 Feb 2019 14:36:36 GMT</d:getlastmodified>
<d:getcontenttype>application/vnd.ms-project</d:getcontenttype>
<d:getcontentlength>114176</d:getcontentlength>
<d:supportedlock>
<d:lockentry>
<d:lockscope>
<d:exclusive />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
<d:lockentry>
<d:lockscope>
<d:shared />
</d:lockscope>
<d:locktype>
<d:write />
</d:locktype>
</d:lockentry>
</d:supportedlock>
<d:lockdiscovery />
<d:checked-in>
<d:href>https://www.ajaxbrowser.com:443/Userc97c746/Products/Product.mpp?version=1</d:href>
</d:checked-in>
</d:prop>
</d:propstat>
<d:propstat>
<d:status>HTTP/1.1 404 Not Found</d:status>
<d:prop>
<d:quota-available-bytes />
<d:quota-used-bytes />
<d:checked-out />
</d:prop>
<d:responsedescription>Property was not found</d:responsedescription>
</d:propstat>
</d:response>
</d:multistatus>
"""
class WebDAVXMLRenderer(BaseRenderer):
"""
Renders WebDAV-compliant XML
"""
media_type = "application/xml"
format = "xml"
charset = "utf-8"
item_tag_name = "list-item"
root_tag_name = "multistatus"
def render(self, data, accepted_media_type=None, renderer_context=None):
"""
Renders `data` into serialized XML.
"""
return DATA.encode("utf-8")
if data is None:
return ""
stream = StringIO()
xml = SimplerXMLGenerator(stream, self.charset)
xml.startDocument()
xml.startElement(self.root_tag_name, {})
self._to_xml(xml, data)
xml.endElement(self.root_tag_name)
xml.endDocument()
return stream.getvalue()
def _to_xml(self, xml, data):
if isinstance(data, (list, tuple)):
for item in data:
self._to_xml(xml, item)
elif isinstance(data, dict):
for key, value in six.iteritems(data):
if isinstance(value, ElementList):
for innerval in value:
xml.startElement(key, {})
self._to_xml(xml, innerval)
xml.endElement(key)
if isinstance(value, ElementGroup):
for innerkey, innerval in value.items():
xml.startElement(key, {}) # key=<propstat>
self._to_xml(xml, innerval)
xml.startElement(innerkey[0], {})
self._to_xml(xml, innerkey[1])
xml.endElement(innerkey[0])
xml.endElement(key)
else:
xml.startElement(key, {})
self._to_xml(xml, value)
xml.endElement(key)
elif data is None:
# Don't output any value
pass
else:
xml.characters(smart_text(data))
from django.conf.urls import url
from . import views
urlpatterns = [url(r"^libraries/(?P<path>.*)$", views.LibraryViewSet.as_view())]
from rest_framework import response, mixins, viewsets
from . import renderers
WEBDAV_METHODS = [
"get",
"put",
"lock",
"unlock",
"propfind",
"proppatch",
"delete",
"head",
"options",
"mkcol",
"copy",
"move",
]
ACTIONS = {m: "action_{}".format(m) for m in WEBDAV_METHODS}
class WebDAVViewSet(viewsets.GenericViewSet):
http_method_names = WEBDAV_METHODS
renderer_classes = (renderers.WebDAVXMLRenderer,)
def dispatch(self, request, *args, **kwargs):
print("BODY", request.body)
response = super().dispatch(request, *args, **kwargs)
response["DAV"] = "1"
return response
@classmethod
def as_view(cls, *args, **kwargs):
actions = {}
for method in WEBDAV_METHODS:
handler_name = "action_{}".format(method)
if hasattr(cls, handler_name):
actions[method] = handler_name
kwargs["actions"] = actions
return super().as_view(*args, **kwargs)
class LibraryViewSet(WebDAVViewSet):
authentication_classes = []
permission_classes = []
def action_propfind(self, request, *args, **kwargs):
return response.Response({})
def action_options(self, request, *args, **kwargs):
return response.Response({})
def action_get(self, request, *args, **kwargs):
return response.Response({})
def action_put(self, request, *args, **kwargs):
return response.Response({})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment