3 from rss_sqlite import Listing
7 from htmlentitydefs import name2codepoint
8 from gconf import client_get_default
9 from urllib2 import ProxyHandler
10 from threading import Thread
11 from os.path import isfile, isdir, exists
12 from os import mkdir, remove, stat
14 CONFIGDIR = "/home/user/.feedingit/"
17 #commands = [("addFeed","httpwww"), ("openFeed", "xxxx"), ("openArticle", ("feedid","artid"))]
27 return unichr(int(text[3:-1], 16))
29 return unichr(int(text[2:-1]))
35 text = unichr(name2codepoint[text[1:-1]])
38 return text # leave as is
39 return sub("&#?\w+;", fixup, text)
42 from cgi import escape
43 return escape(text).encode('ascii', 'xmlcharrefreplace')
47 listing = Listing(CONFIGDIR)
48 httpd = BaseHTTPServer.HTTPServer(("127.0.0.1", PORT), Handler)
52 def addFeed(self, url):
53 commands.append(("addFeed",url))
58 def openFeed(self, key):
59 commands.append( ("openFeed", key) )
61 def openArticle(self, key, id):
62 commands.append( ("openArticle", key, id) )
64 def automaticUpdate(self):
65 commands.append(("updateAll",))
66 # for cat in listing.getListOfCategories():
67 # for feed in listing.getSortedListOfKeys("Manual", category=cat):
69 # download = Download(listing, feeds)
72 class Download(Thread):
73 def __init__(self, listing, keys):
75 self.listing = listing
79 updateDbusHandler.UpdateStarted()
81 print "Start update: %s" % key
82 updatingFeeds.append(key)
83 (use_proxy, proxy) = config.getProxy()
86 self.listing.updateFeed(key, proxy=proxy, imageCache=config.getImageCache() )
88 self.listing.updateFeed(key, imageCache=config.getImageCache() )
90 print "Error updating feed: %s" %key
91 updatingFeeds.remove(key)
92 print "End update: %s" % key
93 updateDbusHandler.UpdateFinished()
95 class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
98 for cat in listing.getListOfCategories():
99 for feed in listing.getSortedListOfKeys("Manual", category=cat):
101 download = Download(listing, feeds)
104 def openTaskSwitch(self):
106 subprocess.Popen("dbus-send /com/nokia/hildon_desktop com.nokia.hildon_desktop.exit_app_view", shell=True)
108 def getCommands(self):
109 commandXml = "<commands>"
110 for item in commands:
111 if item[0]=="addFeed":
112 commandXml += "<command c='addFeed'>%s</command>" %(sanitize(item[1]))
113 if item[0]=="openFeed":
115 cat = str(listing.getFeedCategory(key))
116 commandXml += "<command c='openFeed' cat='%s'>%s</command>" % (sanitize(cat), sanitize(key) )
117 if item[0]=="openArticle":
119 cat = str(listing.getFeedCategory(key))
121 commandXml += "<command c='openArticle' cat='%s' key='%s'>%s</command>" %(sanitize(cat), sanitize(key), sanitize(articleid) )
122 if item[0]=="updateAll":
124 commands.remove(item)
125 commandXml += "</commands>"
128 def getConfigXml(self):
129 xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
130 xml += "<hideReadFeed>True</hideReadFeed>"
131 xml += "<hideReadArticles>True</hideReadArticles>"
135 def generateCategoryXml(self):
136 xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
137 for cat in listing.getListOfCategories():
139 xml += "<catname>%s</catname>" %sanitize(listing.getCategoryTitle(cat))
140 xml += "<catid>%s</catid>" % cat
145 def fix_title(self, title):
146 return escape(unescape(title).replace("<em>","").replace("</em>","").replace("<nobr>","").replace("</nobr>","").replace("<wbr>","").replace("—","-"))
148 def generateFeedsXml(self, catid):
149 xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
150 for key in listing.getSortedListOfKeys("Manual", category=catid):
152 xml += "<feedname>%s</feedname>" %sanitize(listing.getFeedTitle(key))
153 xml += "<feedid>%s</feedid>" %key
154 xml += "<unread>%s</unread>" %listing.getFeedNumberOfUnreadItems(key)
155 xml += "<updatedDate>%s</updatedDate>" %listing.getFeedUpdateTime(key)
156 xml += "<icon>%s</icon>" %listing.getFavicon(key)
157 if key in updatingFeeds:
158 xml += "<updating>True</updating>"
160 xml += "<updating>False</updating>"
165 def generateArticlesXml(self, key, onlyUnread, markAllAsRead):
166 feed = listing.getFeed(key)
167 if markAllAsRead=="True":
169 listing.updateUnread(key)
170 updateDbusHandler.ArticleCountUpdated()
171 xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
172 if onlyUnread == "False":
174 for id in feed.getIds(onlyUnread):
176 xml += "<title>%s</title>" %self.fix_title(feed.getTitle(id))
177 xml += "<articleid>%s</articleid>" %id
178 xml += "<unread>%s</unread>" %str(feed.isEntryRead(id))
179 xml += "<updatedDate>%s</updatedDate>" %feed.getDateStamp(id)
180 xml += "<path>%s</path>" %feed.getContentLink(id)
186 (req, sep, arg) = self.path.partition("?")
187 request = req.split("/")
190 args = arg.split("&")
193 arguments[ele[0]] = ele[1]
194 if request[1] == "categories":
195 xml = self.generateCategoryXml()
196 elif request[1] == "feeds":
198 xml = self.generateFeedsXml(catid)
199 elif request[1] == "articles":
201 onlyUnread = arguments.get("onlyUnread","False")
202 markAllAsRead = arguments.get("markAllAsRead", "False")
203 xml = self.generateArticlesXml(key, onlyUnread, markAllAsRead)
204 elif request[1] == "html":
207 feed = listing.getFeed(key)
209 file = open(feed.getContentLink(article))
210 html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
213 html = "<html><body>Error retrieving article</body></html>"
214 self.send_response(200)
215 self.send_header("Content-type", "text/html")
217 self.wfile.write(html)
218 #listing.updateUnread(key)
220 elif request[1] == "isUpdating":
223 if (key in updatingFeeds) or ((key=="") and (len(updatingFeeds)>0)):
224 xml += "<updating>True</updating>"
226 xml += "<updating>False</updating>"
227 xml += self.getCommands()
229 elif request[1] == "read":
232 feed = listing.getFeed(key)
233 feed.setEntryRead(article)
234 listing.updateUnread(key)
235 updateDbusHandler.ArticleCountUpdated()
236 self.send_response(200)
237 self.send_header("Content-type", "text/html")
239 self.wfile.write("OK")
241 elif request[1] == "config":
242 xml = self.getConfigXml()
243 elif request[1] == "home":
244 file = open(self.path)
245 self.send_response(200)
246 self.send_header("Content-type", "text/html")
248 self.wfile.write(file.read())
251 elif request[1] == "task":
252 self.openTaskSwitch()
253 xml = "<xml>OK</xml>"
254 elif request[1] == "deleteCat":
256 listing.removeCategory(key)
257 xml = "<xml>OK</xml>"
258 elif request[1] == "deleteFeed":
260 listing.removeFeed(key)
261 xml = "<xml>OK</xml>"
262 elif request[1] == "addFeed":
265 url = arguments.get("url","")
266 listing.addFeed(name, url, category=cat)
267 xml = "<xml>OK</xml>"
268 elif request[1] == "updateFeed":
270 download = Download(listing, [key,])
272 xml = "<xml>OK</xml>"
273 elif request[1]=="updateAll":
274 #app.automaticUpdate()
276 updateDbusHandler.ArticleCountUpdated()
277 xml = "<xml>OK</xml>"
278 elif request[1] == "addCat":
280 listing.addCategory(catName)
281 xml = "<xml>OK</xml>"
283 self.send_error(404, "File not found")
285 self.send_response(200)
286 self.send_header("Content-type", "text/xml")
288 self.wfile.write(xml.encode("utf-8"))
292 if not isdir(CONFIGDIR):
296 print "Error: Can't create configuration directory"
300 from config import Config
301 config = Config(None,CONFIGDIR+"config.ini")
307 # Start the HTTP server in a new thread
308 thread.start_new_thread(start_server, ())
310 # Initialize the glib mainloop, for dbus purposes
311 from feedingitdbus import ServerObject
312 from updatedbus import UpdateServerObject, get_lock
315 gobject.threads_init()
316 import dbus.mainloop.glib
317 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
319 global updateDbusHandler, dbusHandler
321 dbusHandler = ServerObject(app)
322 updateDbusHandler = UpdateServerObject(app)
324 mainloop = gobject.MainLoop()