Hash items resilient against formatting

This commit is contained in:
Markus Unterwaditzer 2014-05-17 15:20:46 +02:00
parent a80fa62927
commit 8f5fdfb2d4
4 changed files with 31 additions and 8 deletions

View file

@ -85,4 +85,6 @@ END:VCALENDAR'''
SIMPLE_TEMPLATE = u'''BEGIN:FOO
UID:{r}
X-SOMETHING:{r}
HAHA:YES
END:FOO'''

View file

@ -7,9 +7,11 @@
: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((
@ -74,3 +76,10 @@ def test_split_collection_timezones():
)
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)

View file

@ -7,7 +7,6 @@
:license: MIT, see LICENSE for more details.
'''
import hashlib
from .. import exceptions
from .. import utils
@ -35,17 +34,15 @@ class Item(object):
def __init__(self, raw):
assert isinstance(raw, utils.text_type)
raw = raw.splitlines()
for line in raw:
for line in raw.splitlines():
if line.startswith(u'UID:'):
uid = line[4:].strip()
if uid:
self.uid = uid
self.raw = u'\n'.join(raw)
self.hash = hashlib.sha256(
self.raw.strip().encode('utf-8')).hexdigest()
self.raw = raw
self.hash = utils.vobject.hash_item(raw)
self.ident = self.uid or self.hash

View file

@ -6,12 +6,27 @@
:copyright: (c) 2014 Markus Unterwaditzer
:license: MIT, see LICENSE for more details.
'''
import hashlib
import icalendar.cal
import icalendar.parser
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',),
wrap_items_with=(u'VCALENDAR',)):
'''Emits items in the order they occur in the text.'''