1.1 --- a/EventAggregatorSupport/Types.py Sun Mar 30 20:04:32 2014 +0200
1.2 +++ b/EventAggregatorSupport/Types.py Sun Mar 30 20:32:50 2014 +0200
1.3 @@ -36,6 +36,15 @@
1.4 except ImportError:
1.5 libxml2dom = None
1.6
1.7 +# Import MoinMessage for decryption.
1.8 +
1.9 +try:
1.10 + import MoinMessageSupport
1.11 + import MoinMessage
1.12 +except ImportError:
1.13 + MoinMessageSupport = None
1.14 + MoinMessage = None
1.15 +
1.16 # Page parsing.
1.17
1.18 definition_list_regexp = re.compile(ur'(?P<wholeterm>^(?P<optcomment>#*)\s+(?P<term>.*?):: )(?P<desc>.*?)$', re.UNICODE | re.MULTILINE)
1.19 @@ -52,12 +61,12 @@
1.20 # Calendar-format pages are parsed directly by the iCalendar parser.
1.21
1.22 if page.getFormat() == "calendar":
1.23 - return parseEventsInCalendar(text)
1.24 + return parseEventsInCalendar(text, page.getPageURL())
1.25
1.26 # xCalendar-format pages are parsed directly by the iCalendar parser.
1.27
1.28 elif page.getFormat() == "xcalendar":
1.29 - return parseEventsInXMLCalendar(text)
1.30 + return parseEventsInXMLCalendar(text, page.getPageURL())
1.31
1.32 # Wiki-format pages are parsed region-by-region using the special markup.
1.33
1.34 @@ -66,20 +75,20 @@
1.35 # Where a page contains events, potentially in regions, identify the page
1.36 # regions and obtain the events within them.
1.37
1.38 - events = []
1.39 + events = EventResourceCollection()
1.40 for format, attributes, region in getFragments(text, True):
1.41 if format == "calendar":
1.42 - events += parseEventsInCalendar(region)
1.43 + events.append(parseEventsInCalendar(region, page.getPageURL()))
1.44 else:
1.45 - events += parseEvents(region, page, attributes.get("fragment") or fragment)
1.46 + events.append(parseEvents(region, page, attributes.get("fragment") or fragment))
1.47 return events
1.48
1.49 # Unsupported format pages return no events.
1.50
1.51 else:
1.52 - return []
1.53 + return EventResourceCollection()
1.54
1.55 -def parseEventsInCalendar(text):
1.56 +def parseEventsInCalendar(text, url=None):
1.57
1.58 """
1.59 Parse events in iCalendar format from the given 'text'.
1.60 @@ -88,10 +97,9 @@
1.61 # Fill the StringIO with encoded plain string data.
1.62
1.63 encoding = "utf-8"
1.64 - calendar = parseEventsInCalendarFromResource(StringIO(text.encode(encoding)), encoding)
1.65 - return calendar.getEvents()
1.66 + return parseEventsInCalendarFromResource(StringIO(text.encode(encoding)), encoding, url)
1.67
1.68 -def parseEventsInXMLCalendar(text):
1.69 +def parseEventsInXMLCalendar(text, url):
1.70
1.71 """
1.72 Parse events in xCalendar format from the given 'text'.
1.73 @@ -100,8 +108,30 @@
1.74 # Fill the StringIO with encoded plain string data.
1.75
1.76 encoding = "utf-8"
1.77 - calendar = parseEventsInXMLCalendarFromResource(StringIO(text.encode(encoding)), encoding)
1.78 - return calendar.getEvents()
1.79 + return parseEventsInXMLCalendarFromResource(StringIO(text.encode(encoding)), encoding, url)
1.80 +
1.81 +def parseEventsInStore(store, url=None, request=None):
1.82 +
1.83 + """
1.84 + Parse events in the given item 'store'.
1.85 + """
1.86 +
1.87 + calendar = EventResourceCollection()
1.88 + for text in store:
1.89 + calendar.append(parseEventsInMessage(text, url, request))
1.90 + return calendar
1.91 +
1.92 +def parseEventsInMessage(text, url=None, request=None):
1.93 +
1.94 + """
1.95 + Parse events in the given 'text' in MIME e-mail message format.
1.96 + """
1.97 +
1.98 + message = Parser().parsestr(text)
1.99 + return parseEventsInMessagePart(message, url=url, request=request)
1.100 +
1.101 +# Events originating from remote sources are typically made available within
1.102 +# calendar objects, with collection objects used to group multiple calendars.
1.103
1.104 def parseEventsInCalendarFromResource(f, encoding=None, url=None, metadata=None):
1.105
1.106 @@ -132,35 +162,58 @@
1.107 else:
1.108 return None
1.109
1.110 -def parseEventsInXMLCalendarsFromResource(f, encoding=None, url=None, metadata=None):
1.111 +def parseEventsInMailboxFromResource(f, encoding=None, url=None, metadata=None):
1.112
1.113 """
1.114 - Parse a collection of events in xCalendar format from the given file-like
1.115 - object 'f', with content having any specified 'encoding' and being described
1.116 - by the given 'url' and 'metadata'.
1.117 + Parse a compound message containing events in iCalendar or xCalendar format
1.118 + from the given file-like object 'f', with content having any specified
1.119 + 'encoding' and being described by the given 'url' and 'metadata'.
1.120 """
1.121
1.122 - new_url = "" # hide the IMAP URL
1.123 -
1.124 message = Parser().parse(f)
1.125 - resources = EventResourceCollection(new_url, metadata or {})
1.126 + new_url = "" # hide the IMAP URL
1.127 + return parseEventsInMessagePart(message, new_url, metadata)
1.128 +
1.129 +def parseEventsInMessagePart(part, url=None, metadata=None, request=None):
1.130
1.131 - for data in message.get_payload():
1.132 + """
1.133 + Parse events in the given message 'part'.
1.134 + """
1.135
1.136 - # Find the calendar data.
1.137 + if part.is_multipart():
1.138 + resources = EventResourceCollection()
1.139 +
1.140 + # Attempt to decrypt any encrypted message parts.
1.141
1.142 - if data.is_multipart():
1.143 - for part in data.get_payload():
1.144 - if part.get_content_type() == "application/calendar+xml":
1.145 - text = part
1.146 + if MoinMessageSupport is not None:
1.147 + try:
1.148 + if MoinMessage.is_encrypted(part):
1.149 + homedir = MoinMessageSupport.get_homedir(request)
1.150 + gpg = MoinMessage.GPG(homedir)
1.151 + text = gpg.decryptMessage(part)
1.152 + part = Parser().parsestr(text)
1.153 + except MoinMessage.MoinMessageError:
1.154 + return resources
1.155 +
1.156 + for subpart in part.get_payload():
1.157 + resources.append(parseEventsInMessagePart(subpart, url, metadata, request))
1.158 +
1.159 + return resources
1.160 +
1.161 + else:
1.162 + content_type = part.get_content_type()
1.163 + text = part.get_payload(decode=True)
1.164 +
1.165 + # Handle standard calendar formats.
1.166 +
1.167 + if content_type == "application/calendar+xml":
1.168 + return parseEventsInXMLCalendarFromResource(StringIO(text), part.get_charset(), url)
1.169 + elif content_type == "text/calendar":
1.170 + return parseEventsInCalendarFromResource(StringIO(text), part.get_charset(), url)
1.171 else:
1.172 - text = data
1.173 -
1.174 - # Obtain a calendar and merge it into the collection.
1.175 + return EventResourceCollection()
1.176
1.177 - resources.append(parseEventsInXMLCalendarFromResource(StringIO(text.get_payload(decode=True)), part.get_charset(), new_url))
1.178 -
1.179 - return resources
1.180 +# Wiki-specific event parsing.
1.181
1.182 def parseEvents(text, event_page, fragment=None):
1.183
1.184 @@ -272,10 +325,10 @@
1.185
1.186 "A resource providing event information."
1.187
1.188 - def __init__(self, url, metadata=None):
1.189 + def __init__(self, url, metadata=None, events=None):
1.190 self.url = url
1.191 self.metadata = metadata
1.192 - self.events = None
1.193 + self.events = events
1.194
1.195 def getPageURL(self):
1.196
1.197 @@ -330,10 +383,8 @@
1.198
1.199 "A collection of resources."
1.200
1.201 - def __init__(self, url, metadata=None):
1.202 - self.url = url
1.203 - self.metadata = metadata
1.204 - self.resources = []
1.205 + def __init__(self, resources=None):
1.206 + self.resources = resources or []
1.207
1.208 def append(self, resource):
1.209 self.resources.append(resource)
1.210 @@ -617,7 +668,7 @@
1.211 "Return a list of events from this page."
1.212
1.213 if self.events is None:
1.214 - self.events = parseEventsInPage(self.page.data, self)
1.215 + self.events = parseEventsInPage(self.page.data, self).getEvents()
1.216
1.217 return self.events
1.218