diff options
author | Aleksander Machniak <machniak@kolabsys.com> | 2016-09-30 20:00:07 +0200 |
---|---|---|
committer | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2016-09-30 20:00:07 +0200 |
commit | efb60aa451319f372188033e8966dafd27685818 (patch) | |
tree | c419ecc482f8b87c0d22180951d4a8b1b481b536 | |
parent | 43a5cac5b3ec98344724d1727b5b7fe542bbb592 (diff) | |
download | pykolab-efb60aa451319f372188033e8966dafd27685818.tar.gz |
T1461: Convert windows timezones into Olson format in iTip
Summary:
iCalendar is used to parse iTip data, but it does not support windows tz.
Fixes T1461
Reviewers: #pykolab_developers, vanmeeuwen
Reviewed By: #pykolab_developers, vanmeeuwen
Subscribers: vanmeeuwen
Maniphest Tasks: T1461
Differential Revision: https://git.kolab.org/D219
-rw-r--r-- | pykolab/itip/__init__.py | 36 | ||||
-rw-r--r-- | tests/unit/test-011-itip.py | 7 |
2 files changed, 38 insertions, 5 deletions
diff --git a/pykolab/itip/__init__.py b/pykolab/itip/__init__.py index eda4f04..4999fad 100644 --- a/pykolab/itip/__init__.py +++ b/pykolab/itip/__init__.py @@ -2,12 +2,14 @@ import icalendar import pykolab import traceback import kolabformat +import re from pykolab.xml import to_dt from pykolab.xml import event_from_ical from pykolab.xml import todo_from_ical from pykolab.xml import participant_status_label from pykolab.translate import _ +from tzlocal import windows_tz log = pykolab.getLogger('pykolab.wallace') @@ -18,7 +20,6 @@ def events_from_message(message, methods=None): def todos_from_message(message, methods=None): return objects_from_message(message, ["VTODO"], methods) - def objects_from_message(message, objnames, methods=None): """ Obtain the iTip payload from email.message <message> @@ -51,6 +52,9 @@ def objects_from_message(message, objnames, methods=None): log.debug(_("Raw iTip payload (%r): %r") % (part.get_param('charset'), itip_payload), level=9) + # Convert unsupported timezones, etc. + itip_payload = _convert_itip_payload(itip_payload) + # Python iCalendar prior to 3.0 uses "from_string". if hasattr(icalendar.Calendar, 'from_ical'): cal = icalendar.Calendar.from_ical(itip_payload) @@ -141,7 +145,6 @@ def objects_from_message(message, objnames, methods=None): return itip_objects - def check_event_conflict(kolab_event, itip_event): """ Determine whether the given kolab event conflicts with the given itip event @@ -210,10 +213,35 @@ def check_event_conflict(kolab_event, itip_event): return conflict - def _is_transparent(event): return event.get_transparency() or event.get_status() == kolabformat.StatusCancelled +def _convert_itip_payload(itip): + matchlist = re.findall("^((DTSTART|DTEND|DUE|EXDATE|COMPLETED)[:;][^\n]+)$", itip, re.MULTILINE) + + for match in matchlist: + match = match[0] + search = re.search(";TZID=([^:;]+)", match) + + if search: + tzorig = tzdest = search.group(1).replace('"', '') + + # timezone in Olson-database format, nothing to convert + if re.match("[a-zA-Z]+/[a-zA-Z0-9_+-]+", tzorig): + continue + + # convert timezone from windows format to Olson + if tzorig in windows_tz.win_tz: + tzdest = windows_tz.win_tz[tzorig] + + # @TODO: Should be prefer server time if it has the same offset? + + # replace old with new timezone name + if tzorig != tzdest: + replace = match.replace(search.group(0), ";TZID=" + tzdest) + itip = itip.replace("\n" + match, "\n" + replace) + + return itip def check_date_conflict(_es, _ee, _is, _ie): """ @@ -238,7 +266,7 @@ def check_date_conflict(_es, _ee, _is, _ie): conflict = True else: conflict = False - + return conflict diff --git a/tests/unit/test-011-itip.py b/tests/unit/test-011-itip.py index 38e00b8..173a26e 100644 --- a/tests/unit/test-011-itip.py +++ b/tests/unit/test-011-itip.py @@ -286,7 +286,7 @@ METHOD:REQUEST BEGIN:VEVENT UID:eea25142-fb1c-4831-a02d-ac9fb4c16b70 DTSTAMP:20140213T125414Z -DTSTART;TZID=3DEurope/London:20140713T100000 +DTSTART;TZID=3D"W. Europe Standard Time":20140713T100000 DTEND;TZID=3DEurope/London:20140713T140000 SUMMARY:Testing =C3=9Cmlauts DESCRIPTION:Testing =C3=9Cmlauts @@ -375,6 +375,11 @@ class TestITip(unittest.TestCase): self.assertEqual(xml.get_summary(), "Testing Ümlauts") self.assertEqual(xml.get_location(), "Rue the Genève") + # Timezone conversion + itips = itip.events_from_message(message_from_string(itip_unicode)) + xml = itips[0]['xml'] + self.assertEqual(xml.get_start().tzinfo.__str__(), "Europe/Berlin") + def test_002_check_date_conflict(self): astart = datetime.datetime(2014, 7, 13, 10, 0, 0) aend = astart + datetime.timedelta(hours=2) |