mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
dav: Fully move collection management into Discover
This commit is contained in:
parent
ed6a65a6ab
commit
7d41378505
2 changed files with 71 additions and 82 deletions
|
|
@ -116,9 +116,6 @@ class ServerMixin(object):
|
||||||
'collection': collection, 'unsafe_href_chars': ''}
|
'collection': collection, 'unsafe_href_chars': ''}
|
||||||
|
|
||||||
if collection is not None:
|
if collection is not None:
|
||||||
if storage_backend != 'multifilesystem':
|
|
||||||
# XXX: https://github.com/Kozea/Radicale/pull/236
|
|
||||||
rv = self.storage_class.create_collection(**rv)
|
|
||||||
s = self.storage_class(**rv)
|
s = self.storage_class(**rv)
|
||||||
s.delete(*s.upload(get_item()))
|
s.delete(*s.upload(get_item()))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ def _get_collection_from_url(url):
|
||||||
|
|
||||||
|
|
||||||
class Discover(object):
|
class Discover(object):
|
||||||
|
_namespace = None
|
||||||
_resourcetype = None
|
_resourcetype = None
|
||||||
_homeset_xml = None
|
_homeset_xml = None
|
||||||
_homeset_tag = None
|
_homeset_tag = None
|
||||||
|
|
@ -95,8 +96,17 @@ class Discover(object):
|
||||||
</d:propfind>
|
</d:propfind>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, session):
|
def __init__(self, **kwargs):
|
||||||
self.session = session
|
if kwargs.pop('collection', None) is not None:
|
||||||
|
raise TypeError('collection argument must not be given.')
|
||||||
|
|
||||||
|
discover_args, _ = utils.split_dict(kwargs, lambda key: key in (
|
||||||
|
'url', 'username', 'password', 'verify', 'auth', 'useragent',
|
||||||
|
'verify_fingerprint', 'auth_cert',
|
||||||
|
))
|
||||||
|
|
||||||
|
self.session = DavSession(**discover_args)
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
def find_dav(self):
|
def find_dav(self):
|
||||||
try:
|
try:
|
||||||
|
|
@ -113,7 +123,11 @@ class Discover(object):
|
||||||
|
|
||||||
def find_principal(self, url=None):
|
def find_principal(self, url=None):
|
||||||
if url is None:
|
if url is None:
|
||||||
url = self.find_dav()
|
try:
|
||||||
|
return self.find_principal('')
|
||||||
|
except (HTTPError, exceptions.Error):
|
||||||
|
return self.find_principal(self.find_dav())
|
||||||
|
|
||||||
headers = self.session.get_default_headers()
|
headers = self.session.get_default_headers()
|
||||||
headers['Depth'] = 0
|
headers['Depth'] = 0
|
||||||
body = """
|
body = """
|
||||||
|
|
@ -171,20 +185,60 @@ class Discover(object):
|
||||||
yield {'href': href, 'displayname': displayname}
|
yield {'href': href, 'displayname': displayname}
|
||||||
|
|
||||||
def discover(self):
|
def discover(self):
|
||||||
for x in self.find_collections():
|
for c in self.find_collections():
|
||||||
yield x
|
url = c['href']
|
||||||
|
collection = _get_collection_from_url(url)
|
||||||
|
storage_args = dict(self.kwargs)
|
||||||
|
storage_args.update({'url': url, 'collection': collection,
|
||||||
|
'collection_human': c['displayname']})
|
||||||
|
yield storage_args
|
||||||
|
|
||||||
|
def create(self, collection):
|
||||||
|
if collection is None:
|
||||||
|
collection = _get_collection_from_url(self.kwargs['url'])
|
||||||
|
|
||||||
|
for c in self.discover():
|
||||||
|
if c['collection'] == collection:
|
||||||
|
return c
|
||||||
|
|
||||||
|
home = self.find_home()
|
||||||
|
url = '{}/{}'.format(home.rstrip('/'), collection)
|
||||||
|
|
||||||
# Another one of Radicale's specialties: Discovery is broken (returning
|
|
||||||
# completely wrong URLs at every stage) as of version 0.9.
|
|
||||||
# https://github.com/Kozea/Radicale/issues/196
|
|
||||||
try:
|
try:
|
||||||
for x in self.find_collections(''):
|
url = self._create_collection_impl(url)
|
||||||
yield x
|
except HTTPError as e:
|
||||||
except (InvalidXMLResponse, HTTPError, exceptions.Error):
|
raise NotImplementedError(e)
|
||||||
pass
|
else:
|
||||||
|
rv = dict(self.kwargs)
|
||||||
|
rv['collection'] = collection
|
||||||
|
rv['url'] = url
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def _create_collection_impl(self, url):
|
||||||
|
data = '''<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<D:mkcol xmlns:D="DAV:" xmlns:C="{}">
|
||||||
|
<D:set>
|
||||||
|
<D:prop>
|
||||||
|
<D:resourcetype>
|
||||||
|
<D:collection/>
|
||||||
|
<C:{}/>
|
||||||
|
</D:resourcetype>
|
||||||
|
</D:prop>
|
||||||
|
</D:set>
|
||||||
|
</D:mkcol>
|
||||||
|
'''.format(self._namespace, self._resourcetype)
|
||||||
|
|
||||||
|
response = self.session.request(
|
||||||
|
'MKCOL',
|
||||||
|
url,
|
||||||
|
data=data,
|
||||||
|
headers=self.session.get_default_headers(),
|
||||||
|
)
|
||||||
|
return response.url
|
||||||
|
|
||||||
|
|
||||||
class CalDiscover(Discover):
|
class CalDiscover(Discover):
|
||||||
|
_namespace = 'urn:ietf:params:xml:ns:caldav'
|
||||||
_resourcetype = 'calendar'
|
_resourcetype = 'calendar'
|
||||||
_homeset_xml = """
|
_homeset_xml = """
|
||||||
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||||
|
|
@ -198,6 +252,7 @@ class CalDiscover(Discover):
|
||||||
|
|
||||||
|
|
||||||
class CardDiscover(Discover):
|
class CardDiscover(Discover):
|
||||||
|
_namespace = 'urn:ietf:params:xml:ns:carddav'
|
||||||
_resourcetype = 'addressbook'
|
_resourcetype = 'addressbook'
|
||||||
_homeset_xml = """
|
_homeset_xml = """
|
||||||
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:carddav">
|
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:carddav">
|
||||||
|
|
@ -294,74 +349,15 @@ class DavStorage(Storage):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.url = url
|
self.url = url
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _get_session(cls, **kwargs):
|
|
||||||
discover_args, _ = utils.split_dict(kwargs, lambda key: key in (
|
|
||||||
'url', 'username', 'password', 'verify', 'auth', 'useragent',
|
|
||||||
'verify_fingerprint', 'auth_cert',
|
|
||||||
))
|
|
||||||
return DavSession(**discover_args)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def discover(cls, **kwargs):
|
def discover(cls, **kwargs):
|
||||||
if kwargs.pop('collection', None) is not None:
|
d = cls.discovery_class(**kwargs)
|
||||||
raise TypeError('collection argument must not be given.')
|
return d.discover()
|
||||||
|
|
||||||
d = cls.discovery_class(cls._get_session(**kwargs))
|
|
||||||
for c in d.discover():
|
|
||||||
url = c['href']
|
|
||||||
collection = _get_collection_from_url(url)
|
|
||||||
storage_args = dict(kwargs)
|
|
||||||
storage_args.update({'url': url, 'collection': collection,
|
|
||||||
'collection_human': c['displayname']})
|
|
||||||
yield storage_args
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_collection(cls, collection, **kwargs):
|
def create_collection(cls, collection, **kwargs):
|
||||||
if collection is None:
|
d = cls.discovery_class(**kwargs)
|
||||||
collection = _get_collection_from_url(kwargs['url'])
|
return d.create(collection)
|
||||||
session = cls._get_session(**kwargs)
|
|
||||||
d = cls.discovery_class(session)
|
|
||||||
|
|
||||||
for c in cls.discover(**kwargs):
|
|
||||||
if c['collection'] == collection:
|
|
||||||
return c
|
|
||||||
|
|
||||||
home = d.find_home()
|
|
||||||
url = '{}/{}'.format(home.rstrip('/'), collection)
|
|
||||||
|
|
||||||
try:
|
|
||||||
url = cls._create_collection_impl(d, url, kwargs)
|
|
||||||
except HTTPError as e:
|
|
||||||
raise NotImplementedError(e)
|
|
||||||
else:
|
|
||||||
rv = dict(kwargs)
|
|
||||||
rv['collection'] = collection
|
|
||||||
rv['url'] = url
|
|
||||||
return rv
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _create_collection_impl(cls, d, url, kwargs):
|
|
||||||
data = '''<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<D:mkcol xmlns:D="DAV:" xmlns:C="{}">
|
|
||||||
<D:set>
|
|
||||||
<D:prop>
|
|
||||||
<D:resourcetype>
|
|
||||||
<D:collection/>
|
|
||||||
<C:{}/>
|
|
||||||
</D:resourcetype>
|
|
||||||
</D:prop>
|
|
||||||
</D:set>
|
|
||||||
</D:mkcol>
|
|
||||||
'''.format(cls._dav_namespace, cls._dav_resourcetype)
|
|
||||||
|
|
||||||
response = d.session.request(
|
|
||||||
'MKCOL',
|
|
||||||
url,
|
|
||||||
data=data,
|
|
||||||
headers=d.session.get_default_headers(),
|
|
||||||
)
|
|
||||||
return response.url
|
|
||||||
|
|
||||||
def _normalize_href(self, *args, **kwargs):
|
def _normalize_href(self, *args, **kwargs):
|
||||||
return _normalize_href(self.session.url, *args, **kwargs)
|
return _normalize_href(self.session.url, *args, **kwargs)
|
||||||
|
|
@ -588,8 +584,6 @@ class CaldavStorage(DavStorage):
|
||||||
fileext = '.ics'
|
fileext = '.ics'
|
||||||
item_mimetype = 'text/calendar'
|
item_mimetype = 'text/calendar'
|
||||||
discovery_class = CalDiscover
|
discovery_class = CalDiscover
|
||||||
_dav_namespace = 'urn:ietf:params:xml:ns:caldav'
|
|
||||||
_dav_resourcetype = 'calendar'
|
|
||||||
|
|
||||||
start_date = None
|
start_date = None
|
||||||
end_date = None
|
end_date = None
|
||||||
|
|
@ -723,6 +717,4 @@ class CarddavStorage(DavStorage):
|
||||||
{hrefs}
|
{hrefs}
|
||||||
</C:addressbook-multiget>'''
|
</C:addressbook-multiget>'''
|
||||||
|
|
||||||
_dav_namespace = 'urn:ietf:params:xml:ns:carddav'
|
|
||||||
_dav_resourcetype = 'addressbook'
|
|
||||||
get_multi_data_query = '{urn:ietf:params:xml:ns:carddav}address-data'
|
get_multi_data_query = '{urn:ietf:params:xml:ns:carddav}address-data'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue