1.1 --- a/MoinShare.py Wed Apr 02 00:41:37 2014 +0200
1.2 +++ b/MoinShare.py Wed Apr 02 23:57:59 2014 +0200
1.3 @@ -202,10 +202,16 @@
1.4 if feed_url.startswith("file:"):
1.5 raise FeedMissingError
1.6
1.7 + elif feed_url.startswith("imap"):
1.8 + reader = imapreader
1.9 +
1.10 + else:
1.11 + reader = None
1.12 +
1.13 # Obtain the resource, using a cached version if appropriate.
1.14
1.15 max_cache_age = int(getattr(request.cfg, "moin_share_max_cache_age", "300"))
1.16 - data = getCachedResource(request, feed_url, "MoinShare", "wiki", max_cache_age)
1.17 + data = getCachedResource(request, feed_url, "MoinShare", "wiki", max_cache_age, reader)
1.18 if not data:
1.19 raise FeedMissingError
1.20
1.21 @@ -217,6 +223,10 @@
1.22
1.23 if content_type in ("application/atom+xml", "application/rss+xml", "application/xml"):
1.24 return getUpdatesFromFeed(f, max_entries, show_content)
1.25 +
1.26 + elif content_type == "multipart/mixed":
1.27 + return getUpdatesFromMailbox(f, max_entries, show_content, request)
1.28 +
1.29 else:
1.30 raise FeedContentTypeError
1.31
1.32 @@ -240,117 +250,150 @@
1.33
1.34 feed_updates = []
1.35
1.36 - try:
1.37 - # Parse each node from the feed.
1.38 + # Parse each node from the feed.
1.39
1.40 - channel_title = channel_link = None
1.41 + channel_title = channel_link = None
1.42
1.43 - feed_type = None
1.44 - update = None
1.45 - in_source = False
1.46 + feed_type = None
1.47 + update = None
1.48 + in_source = False
1.49
1.50 - events = xml.dom.pulldom.parse(feed)
1.51 + events = xml.dom.pulldom.parse(feed)
1.52
1.53 - for event, value in events:
1.54 + for event, value in events:
1.55
1.56 - if not in_source and event == xml.dom.pulldom.START_ELEMENT:
1.57 - tagname = value.localName
1.58 + if not in_source and event == xml.dom.pulldom.START_ELEMENT:
1.59 + tagname = value.localName
1.60
1.61 - # Detect the feed type and items.
1.62 + # Detect the feed type and items.
1.63
1.64 - if tagname == "feed" and value.namespaceURI == ATOM_NS:
1.65 - feed_type = "atom"
1.66 + if tagname == "feed" and value.namespaceURI == ATOM_NS:
1.67 + feed_type = "atom"
1.68
1.69 - elif tagname == "rss":
1.70 - feed_type = "rss"
1.71 + elif tagname == "rss":
1.72 + feed_type = "rss"
1.73
1.74 - # Detect items.
1.75 + # Detect items.
1.76
1.77 - elif feed_type == "rss" and tagname == "item" or \
1.78 - feed_type == "atom" and tagname == "entry":
1.79 + elif feed_type == "rss" and tagname == "item" or \
1.80 + feed_type == "atom" and tagname == "entry":
1.81
1.82 - update = Update()
1.83 + update = Update()
1.84
1.85 - # Detect source declarations.
1.86 + # Detect source declarations.
1.87
1.88 - elif feed_type == "atom" and tagname == "source":
1.89 - in_source = True
1.90 + elif feed_type == "atom" and tagname == "source":
1.91 + in_source = True
1.92
1.93 - # Handle item elements.
1.94 + # Handle item elements.
1.95
1.96 - elif tagname == "title":
1.97 - events.expandNode(value)
1.98 - if update:
1.99 - update.title = text(value)
1.100 - else:
1.101 - channel_title = text(value)
1.102 + elif tagname == "title":
1.103 + events.expandNode(value)
1.104 + if update:
1.105 + update.title = text(value)
1.106 + else:
1.107 + channel_title = text(value)
1.108
1.109 - elif tagname == "link":
1.110 - events.expandNode(value)
1.111 - if update:
1.112 - update.link = linktext(value, feed_type)
1.113 - else:
1.114 - channel_link = linktext(value, feed_type)
1.115 + elif tagname == "link":
1.116 + events.expandNode(value)
1.117 + if update:
1.118 + update.link = linktext(value, feed_type)
1.119 + else:
1.120 + channel_link = linktext(value, feed_type)
1.121
1.122 - elif show_content and (
1.123 - feed_type == "atom" and tagname in ("content", "summary") or
1.124 - feed_type == "rss" and tagname == "description"):
1.125 -
1.126 - events.expandNode(value)
1.127 + elif show_content and (
1.128 + feed_type == "atom" and tagname in ("content", "summary") or
1.129 + feed_type == "rss" and tagname == "description"):
1.130
1.131 - # Obtain content where requested or, failing that, a
1.132 - # summary.
1.133 + events.expandNode(value)
1.134
1.135 - if update and (need_content(show_content, tagname) or tagname == "summary" and not update.content):
1.136 - if feed_type == "atom":
1.137 - update.content_type = value.getAttribute("type") or "text"
1.138 + # Obtain content where requested or, failing that, a
1.139 + # summary.
1.140
1.141 - # Normalise the content types and extract the
1.142 - # content.
1.143 + if update and (need_content(show_content, tagname) or tagname == "summary" and not update.content):
1.144 + if feed_type == "atom":
1.145 + update.content_type = value.getAttribute("type") or "text"
1.146 +
1.147 + # Normalise the content types and extract the
1.148 + # content.
1.149
1.150 - if update.content_type in ("xhtml", "application/xhtml+xml", "application/xml"):
1.151 - update.content = children(value)
1.152 - update.content_type = "application/xhtml+xml"
1.153 - elif update.content_type in ("html", "text/html"):
1.154 - update.content = text(value)
1.155 - update.content_type = "text/html"
1.156 - else:
1.157 - update.content = text(value)
1.158 - update.content_type = "text/plain"
1.159 + if update.content_type in ("xhtml", "application/xhtml+xml", "application/xml"):
1.160 + update.content = children(value)
1.161 + update.content_type = "application/xhtml+xml"
1.162 + elif update.content_type in ("html", "text/html"):
1.163 + update.content = text(value)
1.164 + update.content_type = "text/html"
1.165 else:
1.166 - update.content_type = "text/html"
1.167 update.content = text(value)
1.168 -
1.169 - elif feed_type == "atom" and tagname == "updated" or \
1.170 - feed_type == "rss" and tagname == "pubDate":
1.171 -
1.172 - events.expandNode(value)
1.173 + update.content_type = "text/plain"
1.174 + else:
1.175 + update.content_type = "text/html"
1.176 + update.content = text(value)
1.177
1.178 - if update:
1.179 - if feed_type == "atom":
1.180 - value = getDateTimeFromISO8601(text(value))
1.181 - else:
1.182 - value = DateTime(parsedate(text(value)))
1.183 - update.updated = value
1.184 + elif feed_type == "atom" and tagname == "updated" or \
1.185 + feed_type == "rss" and tagname == "pubDate":
1.186 +
1.187 + events.expandNode(value)
1.188
1.189 - elif event == xml.dom.pulldom.END_ELEMENT:
1.190 - tagname = value.localName
1.191 + if update:
1.192 + if feed_type == "atom":
1.193 + value = getDateTimeFromISO8601(text(value))
1.194 + else:
1.195 + value = DateTime(parsedate(text(value)))
1.196 + update.updated = value
1.197
1.198 - if feed_type == "rss" and tagname == "item" or \
1.199 - feed_type == "atom" and tagname == "entry":
1.200 -
1.201 - feed_updates.append(update)
1.202 + elif event == xml.dom.pulldom.END_ELEMENT:
1.203 + tagname = value.localName
1.204
1.205 - update = None
1.206 + if feed_type == "rss" and tagname == "item" or \
1.207 + feed_type == "atom" and tagname == "entry":
1.208 +
1.209 + feed_updates.append(update)
1.210
1.211 - elif feed_type == "atom" and tagname == "source":
1.212 - in_source = False
1.213 + update = None
1.214
1.215 - finally:
1.216 - feed.close()
1.217 + elif feed_type == "atom" and tagname == "source":
1.218 + in_source = False
1.219
1.220 return (feed_type, channel_title, channel_link), feed_updates
1.221
1.222 +# Update retrieval from mailboxes and multipart messages.
1.223 +
1.224 +def getUpdatesFromMailbox(feed, max_entries, show_content, request):
1.225 +
1.226 + """
1.227 + Retrieve from 'feed' up to the given number 'max_entries' of update entries.
1.228 + The 'show_content' parameter can indicate that a "summary" is to be obtained
1.229 + for each update, that the "content" of each update is to be obtained
1.230 + (falling back to a summary if no content is provided), or no content
1.231 + (indicated by a false value) is to be obtained.
1.232 +
1.233 + A tuple of the form ((feed_type, channel_title, channel_link), updates) is
1.234 + returned.
1.235 + """
1.236 +
1.237 + mailbox = Parser().parse(feed)
1.238 +
1.239 + feed_updates = []
1.240 +
1.241 + # Parse each message from the feed as a separate update.
1.242 +
1.243 + for message_number, part in enumerate(mailbox.get_payload()):
1.244 + update = Update()
1.245 + update.fragment = update.updated = getDateTimeFromRFC2822(part.get("date"))
1.246 + update.title = part.get("subject", "Update #%d" % message_number)
1.247 + update.message_number = message_number
1.248 +
1.249 + update.content, update.content_type, update.parts, actual_author = \
1.250 + getUpdateContentFromPart(part, request)
1.251 +
1.252 + if actual_author:
1.253 + update.author = actual_author
1.254 +
1.255 + feed_updates.append(update)
1.256 +
1.257 + return ("mbox", None, None), feed_updates
1.258 +
1.259 # Update retrieval from pages.
1.260
1.261 def getUpdatesFromPage(page, request):