mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
Hash items resilient against formatting
This commit is contained in:
parent
a80fa62927
commit
8f5fdfb2d4
4 changed files with 31 additions and 8 deletions
|
|
@ -85,4 +85,6 @@ END:VCALENDAR'''
|
||||||
|
|
||||||
SIMPLE_TEMPLATE = u'''BEGIN:FOO
|
SIMPLE_TEMPLATE = u'''BEGIN:FOO
|
||||||
UID:{r}
|
UID:{r}
|
||||||
|
X-SOMETHING:{r}
|
||||||
|
HAHA:YES
|
||||||
END:FOO'''
|
END:FOO'''
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from vdirsyncer.utils.vobject import split_collection, join_collection
|
from vdirsyncer.utils.vobject import split_collection, join_collection, \
|
||||||
|
hash_item
|
||||||
|
|
||||||
from .. import normalize_item, SIMPLE_TEMPLATE, BARE_EVENT_TEMPLATE
|
from .. import normalize_item, SIMPLE_TEMPLATE, BARE_EVENT_TEMPLATE, \
|
||||||
|
EVENT_TEMPLATE
|
||||||
|
|
||||||
|
|
||||||
_simple_joined = u'\r\n'.join((
|
_simple_joined = u'\r\n'.join((
|
||||||
|
|
@ -74,3 +76,10 @@ def test_split_collection_timezones():
|
||||||
)
|
)
|
||||||
|
|
||||||
assert given == expected
|
assert given == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_hash_item():
|
||||||
|
a = EVENT_TEMPLATE.format(r=1)
|
||||||
|
b = u'\n'.join(line for line in a.splitlines()
|
||||||
|
if u'PRODID' not in line and u'VERSION' not in line)
|
||||||
|
assert hash_item(a) == hash_item(b)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
from .. import exceptions
|
from .. import exceptions
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
|
@ -35,17 +34,15 @@ class Item(object):
|
||||||
|
|
||||||
def __init__(self, raw):
|
def __init__(self, raw):
|
||||||
assert isinstance(raw, utils.text_type)
|
assert isinstance(raw, utils.text_type)
|
||||||
raw = raw.splitlines()
|
|
||||||
|
|
||||||
for line in raw:
|
for line in raw.splitlines():
|
||||||
if line.startswith(u'UID:'):
|
if line.startswith(u'UID:'):
|
||||||
uid = line[4:].strip()
|
uid = line[4:].strip()
|
||||||
if uid:
|
if uid:
|
||||||
self.uid = uid
|
self.uid = uid
|
||||||
|
|
||||||
self.raw = u'\n'.join(raw)
|
self.raw = raw
|
||||||
self.hash = hashlib.sha256(
|
self.hash = utils.vobject.hash_item(raw)
|
||||||
self.raw.strip().encode('utf-8')).hexdigest()
|
|
||||||
self.ident = self.uid or self.hash
|
self.ident = self.uid or self.hash
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,27 @@
|
||||||
:copyright: (c) 2014 Markus Unterwaditzer
|
:copyright: (c) 2014 Markus Unterwaditzer
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
'''
|
'''
|
||||||
|
import hashlib
|
||||||
|
|
||||||
import icalendar.cal
|
import icalendar.cal
|
||||||
import icalendar.parser
|
import icalendar.parser
|
||||||
|
|
||||||
from . import text_type, itervalues
|
from . import text_type, itervalues
|
||||||
|
|
||||||
|
|
||||||
|
def hash_item(text):
|
||||||
|
try:
|
||||||
|
lines = to_unicode_lines(icalendar.cal.Component.from_ical(text))
|
||||||
|
except Exception:
|
||||||
|
lines = sorted(text.splitlines())
|
||||||
|
|
||||||
|
hashable = u'\r\n'.join(line.strip() for line in lines
|
||||||
|
if line.strip() and
|
||||||
|
u'PRODID' not in line and
|
||||||
|
u'VERSION' not in line)
|
||||||
|
return hashlib.sha256(hashable.encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def split_collection(text, inline=(u'VTIMEZONE',),
|
def split_collection(text, inline=(u'VTIMEZONE',),
|
||||||
wrap_items_with=(u'VCALENDAR',)):
|
wrap_items_with=(u'VCALENDAR',)):
|
||||||
'''Emits items in the order they occur in the text.'''
|
'''Emits items in the order they occur in the text.'''
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue