summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2014-10-23 07:37:49 -0400
committerThomas Bruederli <bruederli@kolabsys.com>2014-10-23 07:37:49 -0400
commitbdf46e31d5713e2ee216f6a96ecdab2f6fa60ada (patch)
treec615d297131916cc90823344742306122e0bf59e
parente5ed7a38f7683069795a0fcdc38818e0cc3a7bf8 (diff)
downloadpykolab-bdf46e31d5713e2ee216f6a96ecdab2f6fa60ada.tar.gz
Convert unicode strings to utf-8 encoded strings when parsing iCal messages + add unit test for this
-rw-r--r--pykolab/xml/event.py28
-rw-r--r--tests/unit/test-011-itip.py57
2 files changed, 78 insertions, 7 deletions
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index 30b754f..2eb1155 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -21,6 +21,20 @@ from recurrence_rule import RecurrenceRule
log = pykolab.getLogger('pykolab.xml_event')
+def ustr(s):
+ if not isinstance(s, unicode):
+ for cs in ['utf-8','latin-1']:
+ try:
+ s = unicode(s, cs)
+ break
+ except:
+ pass
+
+ if isinstance(s, unicode):
+ return s.encode('utf-8')
+
+ return s
+
def event_from_ical(string):
return Event(from_ical=string)
@@ -130,7 +144,7 @@ class Event(object):
self.event.setAttendees(self._attendees)
def add_category(self, category):
- self._categories.append(str(category))
+ self._categories.append(ustr(category))
self.event.setCategories(self._categories)
def add_exception_date(self, _datetime):
@@ -628,11 +642,11 @@ class Event(object):
self.event.setCreated(xmlutils.to_cdatetime(_datetime, False, True))
def set_description(self, description):
- self.event.setDescription(str(description))
+ self.event.setDescription(ustr(description))
def set_comment(self, comment):
if hasattr(self.event, 'setComment'):
- self.event.setComment(str(comment))
+ self.event.setComment(ustr(comment))
def set_dtstamp(self, _datetime):
self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True))
@@ -697,7 +711,7 @@ class Event(object):
params = {}
if params.has_key('CN'):
- name = str(params['CN'])
+ name = ustr(params['CN'])
else:
name = None
@@ -756,7 +770,7 @@ class Event(object):
params = {}
if params.has_key('CN'):
- cn = str(params['CN'])
+ cn = ustr(params['CN'])
self.set_organizer(str(address), name=cn)
@@ -767,7 +781,7 @@ class Event(object):
self.set_sequence(sequence)
def set_ical_summary(self, summary):
- self.set_summary(str(summary))
+ self.set_summary(ustr(summary))
def set_ical_uid(self, uid):
self.set_uid(str(uid))
@@ -790,7 +804,7 @@ class Event(object):
self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True))
def set_location(self, location):
- self.event.setLocation(str(location))
+ self.event.setLocation(ustr(location))
def set_organizer(self, email, name=None):
contactreference = ContactReference(email)
diff --git a/tests/unit/test-011-itip.py b/tests/unit/test-011-itip.py
index a08d05f..cb1b760 100644
--- a/tests/unit/test-011-itip.py
+++ b/tests/unit/test-011-itip.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
import pykolab
import datetime
import pytz
@@ -253,6 +255,54 @@ END:VEVENT
END:VCALENDAR
"""
+itip_unicode = """MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_c8894dbdb8baeedacae836230e3436fd"
+From: "Doe, John" <john.doe@example.org>
+Date: Tue, 25 Feb 2014 13:54:14 +0100
+Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org>
+User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0
+To: resource-car-audia4@example.org
+Subject: "test"
+
+--=_c8894dbdb8baeedacae836230e3436fd
+Content-Type: text/plain; charset=UTF-8; format=flowed
+Content-Transfer-Encoding: quoted-printable
+
+*test*
+
+--=_c8894dbdb8baeedacae836230e3436fd
+Content-Type: text/calendar; charset=UTF-8; method=REQUEST; name=event.ics
+Content-Disposition: attachment; filename=event.ics
+Content-Transfer-Encoding: quoted-printable
+
+
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Roundcube=20Webmail=200.9-0.3.el6.kolab_3.0//NONSGML=20Calendar//=
+EN
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:eea25142-fb1c-4831-a02d-ac9fb4c16b70
+DTSTAMP:20140213T125414Z
+DTSTART;TZID=3DEurope/London:20140713T100000
+DTEND;TZID=3DEurope/London:20140713T140000
+SUMMARY:Testing =C3=9Cmlauts
+DESCRIPTION:Testing =C3=9Cmlauts
+LOCATION:Rue the Gen=C3=A8ve
+ORGANIZER;CN=3D"D=C3=BE,=20John":mailto:john.doe@example.org
+ATTENDEE;ROLE=3DREQ-PARTICIPANT;CUTYPE=3DRESOURCE;PARTSTAT=3DNEEDS-ACTION;R=
+SVP=3DTRUE:mailto:resource-car-audia4@example.org
+ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DTENTATIVE;CN=3DSomebody=20Else:m=
+ailto:somebody@else.com
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
+--=_c8894dbdb8baeedacae836230e3436fd--
+"""
+
itip_empty = """MIME-Version: 1.0
Date: Fri, 17 Jan 2014 13:51:50 +0100
From: <john.doe@example.org>
@@ -318,6 +368,13 @@ class TestITip(unittest.TestCase):
itips7 = itip.events_from_message(message_from_string(itip_non_multipart.replace("METHOD:REQUEST", "METHOD:PUBLISH").replace("method=REQUEST", "method=PUBLISH")))
self.assertEqual(len(itips7), 0, "Invalid METHOD")
+ # iTips with unicode data
+ itips8 = itip.events_from_message(message_from_string(itip_unicode))
+ self.assertEqual(len(itips8), 1)
+ xml = itips8[0]['xml']
+ self.assertEqual(xml.get_summary(), "Testing Ümlauts")
+ self.assertEqual(xml.get_location(), "Rue the Genève")
+
def test_002_check_date_conflict(self):
astart = datetime.datetime(2014,7,13, 10,0,0)