Create always safe hrefs

The set of safe characters was inspired by the set of safe characters in
URLs.

Fixes #229
This commit is contained in:
Markus Unterwaditzer 2015-07-12 23:18:38 +02:00
parent 04b3379172
commit 73e2ccf46a
6 changed files with 16 additions and 16 deletions

View file

@ -14,7 +14,7 @@ from .. import EVENT_TEMPLATE, TASK_TEMPLATE, VCARD_TEMPLATE, \
def format_item(item_template, uid=None):
# assert that special chars are handled correctly.
r = '{}@vdirsyncer'.format(random.random())
r = random.random()
return Item(item_template.format(r=r, uid=uid or r))

View file

@ -113,7 +113,7 @@ class ServerMixin(object):
url = url.rstrip('/') + '/' + collection
rv = {'url': url, 'username': 'bob', 'password': 'bob',
'collection': collection, 'unsafe_href_chars': ''}
'collection': collection}
if collection is not None:
s = self.storage_class(**rv)

View file

@ -44,7 +44,7 @@ class TestFilesystemStorage(StorageTests):
s = self.storage_class(str(tmpdir), '.txt')
s.upload(Item(u'UID:a/b/c'))
item_file, = tmpdir.listdir()
assert str(item_file).endswith('a_b_c.txt')
assert '/' not in item_file.basename and item_file.isfile()
def test_too_long_uid(self, tmpdir):
s = self.storage_class(str(tmpdir), '.txt')

View file

@ -341,15 +341,14 @@ class DavStorage(Storage):
}
def __init__(self, url, username='', password='', verify=True, auth=None,
useragent=USERAGENT, unsafe_href_chars='@',
verify_fingerprint=None, auth_cert=None, **kwargs):
useragent=USERAGENT, verify_fingerprint=None, auth_cert=None,
**kwargs):
super(DavStorage, self).__init__(**kwargs)
url = url.rstrip('/') + '/'
self.session = DavSession(url, username, password, verify, auth,
useragent, verify_fingerprint,
auth_cert)
self.unsafe_href_chars = unsafe_href_chars
# defined for _repr_attributes
self.username = username
@ -369,7 +368,7 @@ class DavStorage(Storage):
return _normalize_href(self.session.url, *args, **kwargs)
def _get_href(self, item):
href = utils.generate_href(item.ident, unsafe=self.unsafe_href_chars)
href = utils.generate_href(item.ident)
return self._normalize_href(href + self.fileext)
def _is_item_mimetype(self, mimetype):

View file

@ -87,9 +87,7 @@ class FilesystemStorage(Storage):
return os.path.join(self.path, to_native(href, self.encoding))
def _get_href(self, ident):
# XXX: POSIX only defines / and \0 as invalid chars, but we should make
# this work crossplatform.
return generate_href(ident, '/') + self.fileext
return generate_href(ident) + self.fileext
def list(self):
for fname in os.listdir(self.path):

View file

@ -8,6 +8,11 @@ from .compat import iteritems, to_unicode
from .. import exceptions
SAFE_UID_CHARS = ('abcdefghijklmnopqrstuvwxyz'
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'0123456789_.-+')
_missing = object()
@ -159,10 +164,8 @@ class cached_property(object):
return result
def generate_href(ident=None, unsafe=''):
if ident and \
ident.encode('ascii', 'ignore').decode('ascii') == ident:
for char in unsafe:
ident = ident.replace(char, '_')
def generate_href(ident=None, safe=SAFE_UID_CHARS):
if not ident or set(ident) - set(safe):
return to_unicode(uuid.uuid4().hex)
else:
return ident
return to_unicode(uuid.uuid4().hex)