Merge lp:~hernejj/ubuntu-qa-tools/better_hugday into lp:ubuntu-qa-tools

Proposed by Jason J. Herne
Status: Needs review
Proposed branch: lp:~hernejj/ubuntu-qa-tools/better_hugday
Merge into: lp:ubuntu-qa-tools
Diff against target: 1040 lines (+834/-56)
11 files modified
README (+19/-6)
debian/changelog (+11/-0)
hugday-tools/hugday (+113/-49)
hugday_lib/cookie_lib/ChromeCookieLoader.py (+63/-0)
hugday_lib/cookie_lib/CookieFinder.py (+149/-0)
hugday_lib/cookie_lib/CookieLoader.py (+209/-0)
hugday_lib/cookie_lib/EpiphanyCookieLoader.py (+53/-0)
hugday_lib/cookie_lib/FirefoxCookieLoader.py (+60/-0)
hugday_lib/cookie_lib/KonquerorCookieLoader.py (+111/-0)
hugday_lib/cookie_lib/SeamonkeyCookieLoader.py (+43/-0)
setup.py (+3/-1)
To merge this branch: bzr merge lp:~hernejj/ubuntu-qa-tools/better_hugday
Reviewer Review Type Date Requested Status
Markus Korn Pending
Ubuntu Bug Control Pending
Review via email: mp+23257@code.launchpad.net

Commit message

Adds code to do the following:
- Supported browsers: Firefox, Epiphany, Seamonkey, Google Chrome, Konqueror
- Automatic cookie detection for all supported browsers.
- User no longer has to close the browser to find cookies.
- Cookie file format automatically detected when --cookie is given
- User can specify a browser (--browser) and cookie is automatically found within that browser's cookie files.
- Some simple code cleanup and extra commenting in hugday tool.

Description of the change

I've been working on some improvements to the hugday tool (part of the ubuntu-qa-tools) that should make hugday easier to use. Making hugday easier to use will lower the "barrier of entry" for new comers who are interested in participating in the Ubuntu Bug Days. And anything we can do to help people help Ubuntu is a good idea in my book ;).

I've added code to allow for more robust cookie handling by the "hugday init" sub-command. Here is a list of features currently implemented in my branch:
- Supported browsers: Firefox, Epiphany, Seamonkey, Google Chrome, Konqueror
- Automatic cookie detection for all supported browsers.
- User no longer has to close the browser to find cookies.
- Cookie file format automatically detected when --cookie is given
- User can specify a browser (--browser) and cookie is automatically found within that browser's cookie files.
- Some simple code cleanup and extra commenting in hugday tool.

If this is something that bug-control is interested in I'd be happy to have these features merged back into the official ubuntu-qa-tools-branch. Although I must admit I'm not sure what the process is for officially requesting such a merge.

To post a comment you must log in.
Revision history for this message
Brian Murray (brian-murray) wrote :

This sounds really exciting! You have followed the proper process for requesting such a merge but unfortunately I don't think we can get this into Lucid since we are past feature freeze. I'm requesting that the original author look at your changes too.

Revision history for this message
Jason J. Herne (hernejj) wrote :

> This sounds really exciting! You have followed the proper process for
> requesting such a merge but unfortunately I don't think we can get this into
> Lucid since we are past feature freeze. I'm requesting that the original
> author look at your changes too.

Hi Brian. Thanks for your interest. It's not problem for me if this has to wait for Maverick Meerkat.. I understand how the schedule works :). Once code review is complete I can always put an updated package in my PPA. Then others can test the changes if they are interested.

339. By Jason J. Herne

- Added Google Chromium support

Revision history for this message
Jason J. Herne (hernejj) wrote :

One note I'd like to make for the reviewers.

The hugday code that I replaced was searching for two cookies: MOIN_SESSION and MOIN_ID. My new code only looks for MOIN_SESSION. I'm not sure what MOIN_ID is or where it comes from but I could not find any instances of it in my testing.

If there is a valid reason to continue to search for MOIN_ID as well as MOIN_SESSION then please let me know and I'll modify this branch to look for MOIN_ID if MOIN_SESSION is not found.

Revision history for this message
Jason J. Herne (hernejj) wrote :

Just a friendly poke to find out what the status is on this review. :)

Revision history for this message
Markus Korn (thekorn) wrote :

Hey Jason,
I'm sorry, I totally forgot about this merge proposal. Reviewing this huge diff will take some time, but I hope to get it done until next weekend.

Just a side note, have you ever thought about moving your cookielib into a separate project/package? Because it seems to be useful for other python scripts too, and as a side effect it would reduce the size of this diff.

Sorry again,
and thanks for the reminder,
have a nice day,
Markus

Revision history for this message
Jason J. Herne (hernejj) wrote :

On Mon, Aug 2, 2010 at 5:14 PM, Markus Korn <email address hidden> wrote:

> Hey Jason,
> I'm sorry, I totally forgot about this merge proposal. Reviewing this huge
> diff will take some time, but I hope to get it done until next weekend.
>
> Just a side note, have you ever thought about moving your cookielib into a
> separate project/package? Because it seems to be useful for other python
> scripts too, and as a side effect it would reduce the size of this diff.
>
> Sorry again,
> and thanks for the reminder,
> have a nice day,
> Markus
> --
>
> https://code.launchpad.net/~hernejj/ubuntu-qa-tools/better_hugday/+merge/23257<https://code.launchpad.net/%7Ehernejj/ubuntu-qa-tools/better_hugday/+merge/23257>
> You are the owner of lp:~hernejj/ubuntu-qa-tools/better_hugday.
>

I had considered separating out the cookielib code but I'm not sure what
other use it has at the moment. Seems preemptive to do it without another
project that can use it.
It can always be done as follow on work when another need arises. It would
not be that hard to do.

--
- Jason J. Herne (<email address hidden>)

Unmerged revisions

339. By Jason J. Herne

- Added Google Chromium support

338. By Jason J. Herne

- Fixed errors in usage information for hugday
- Added previously forgotten cookie loader file
- Updated readme and changelog

337. By Jason J. Herne

- ChromeCookieLoader.py: Fixed bug, need to check that cookies were loaded BEFORE we iterate through them ;)
- CookieFinder.py: Added missing import of os module
- CookieFinder.py: Added Konqueror support
- CookieFinder.py: Change browser string comparison to always use lower case
- CookieFinder.py: Fixed bug, In get_cookeies(), don't return if a cookie loader has no cookies, need to check ALL cookie loaders.
- KonquerorCookieLoader.py: Initial import.

336. By Jason J. Herne

- User can now specify exactly which browser to pull cookie file from: --browser=<firefox|seamonkey|chrome|epiphany>

335. By Jason J. Herne

- bug fix: Expand ~ in path names given by user
- Fixed error mesasge text
- Added print stmt to output the CookieLoader we're using

334. By jason <jason@foobarbaz>

- Fixed timestamp handling in Chrome

333. By jason <jason@foobarbaz>

- Removed unneeded comment from SeamonkeyLoader

332. By Jason J. Herne

- Properly close connection to sqlite database files

331. By Jason J. Herne

- Rewrote existing get_credentials code to use CookieFinder when the user specifies a cookie file on the command line.

330. By Jason J. Herne

- Bug fix: Check that path exists in cookier_scanner routine before scanning it.
- Bug fix: Uncomment exception handling code (originally commented for testing purposes.)
- Cookie Finder/Loader now provides a method to detect if cookie files were loaded.
- All cookie loaders have been updated to support the above method.
- hugday now uses the above method to give a proper error message if no cookie files were found.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2009-02-10 09:50:50 +0000
+++ README 2010-04-13 16:46:31 +0000
@@ -93,13 +93,26 @@
93 $ hugday list --date 20090101 (for hugday at 2009-01-01)93 $ hugday list --date 20090101 (for hugday at 2009-01-01)
94 94
95Before actually changing content of a wikipage the hugday tools needs95Before actually changing content of a wikipage the hugday tools needs
96to know the useres name and his wiki-id, 'hugday init' provides some96to know the user's Launchpad ID and wiki-id, 'hugday init' provides some
97options to get this information97options to get this information:
98 $ hugday init --user <USER> --cookie <PATH> (try to get the MOIN_ID98
99 out of the mozilla-like cookie file and use USER for entries in991) Let hugday automatically detect the cookie containing the wiki-id.
100 the 'Triager' column)100
101 $ hugday init --user <USER>
102
1032) Tell hugday which web brower you most recently used to log on to
104 wiki.ubuntu.com
105
106 $ hugday init --user <USER> --browser <firefox|seamonkey|chrome|epiphany|konqueror>
107
1083) Provide the path to a cookie file that contains a cookie for ".wiki.ubuntu.com"
109 that has the name "MOIN_SESSION".
110
111 $ hugday init --user <USER> --cookie <PATH>
112
1134) Provide the wiki-id directly.
114
101 $ hugday init --user <USER> --wiki-id <MOINID>115 $ hugday init --user <USER> --wiki-id <MOINID>
102 $ hugday init (interactive mode, not implemented yet)
103 116
104To mark a bug as DONE run:117To mark a bug as DONE run:
105 $ hugday close 123456118 $ hugday close 123456
106119
=== modified file 'debian/changelog'
--- debian/changelog 2010-03-31 19:17:37 +0000
+++ debian/changelog 2010-04-13 16:46:31 +0000
@@ -1,3 +1,14 @@
1ubuntu-qa-tools (0.1.4.4) lucid; urgency=low
2
3 * Improvements to cookie processing in hugday tool.
4 - Supported browsers: Firefox, Epiphany, Seamonkey, Google Chrome, Konqueror
5 - Automatic cookie detection for all supported browsers.
6 - user no longer has to close the browser to find cookies.
7 - Cookie file format automatically detected when --cookie is given
8 - User can specify a browser (--browser) and cookie is automatically found within that browser's cookie files.
9
10 -- Jason J. Herne <hernejj@gmail.com> Thu, 8 Apr 2010 11:54:00 -0400
11
1ubuntu-qa-tools (0.1.4.3) lucid; urgency=low12ubuntu-qa-tools (0.1.4.3) lucid; urgency=low
213
3 * Fix to work with launchpad's multi-version code.14 * Fix to work with launchpad's multi-version code.
415
=== modified file 'hugday-tools/hugday'
--- hugday-tools/hugday 2009-03-18 20:25:21 +0000
+++ hugday-tools/hugday 2010-04-13 16:46:31 +0000
@@ -19,13 +19,13 @@
19#19#
20# ##################################################################20# ##################################################################
2121
22import sys22import sys, os, shutil, time, re
23import re23import urllib, urllib2, libxml2
24import os
25import urllib
26import urllib2
27import libxml2
28import cookielib24import cookielib
25import webbrowser
26
27from hugday_lib.cookie_lib.CookieFinder import CookieFinder
28
29try:29try:
30 import sqlite3 as sqlite30 import sqlite3 as sqlite
31except ImportError:31except ImportError:
@@ -55,11 +55,13 @@
55 55
56RE_BUGS = "%s(%%s)%s" %(re.escape("https://bugs.launchpad.net/bugs/"), re.escape("|"))56RE_BUGS = "%s(%%s)%s" %(re.escape("https://bugs.launchpad.net/bugs/"), re.escape("|"))
5757
5858######################################################
59# Parses Command Line using Python's optparse module #
60######################################################
59class CmdOptions(OptionParser):61class CmdOptions(OptionParser):
60 62
61 USAGE = (63 USAGE = (
62 "\t%prog init --user <USERNAME> [--wiki-id <MOINID>] [--cookie <PATH>]\n"64 "\t%prog init --user <USERNAME> [--wiki-id <MOINID>] [--cookie <PATH>] [--browser <firefox|seamonkey|chrome|epiphany|konqueror>]\n"
63 "\t%prog current [--remember]\n"65 "\t%prog current [--remember]\n"
64 "\t%prog close <Bugs> [--day <ID>] [--kde] [--user <TRIAGER>]\n"66 "\t%prog close <Bugs> [--day <ID>] [--kde] [--user <TRIAGER>]\n"
65 "\t%prog list [--day <ID>] [--kde] [--filter <open|done>]\n"67 "\t%prog list [--day <ID>] [--kde] [--filter <open|done>]\n"
@@ -80,13 +82,15 @@
80 make_option("--wiki-id", action="store", type="string", dest="wiki_id",82 make_option("--wiki-id", action="store", type="string", dest="wiki_id",
81 help="the users MOIN-ID"),83 help="the users MOIN-ID"),
82 make_option("--cookie", action="store", type="string", dest="cookie",84 make_option("--cookie", action="store", type="string", dest="cookie",
83 help="path to users mozilla-like cookie file")85 help="path to users cookie file"),
86 make_option("--browser", action="store", type="string", dest="browser",
87 help="Web browser that will be searched for the wiki-id cookie")
84 )88 )
85 89
86 TOOLS = {90 TOOLS = {
87 "init": (91 "init": (
88 ("user", ),92 ("user", ),
89 ("wiki_id", "cookie"),93 ("wiki_id", "cookie", "browser"),
90 ),94 ),
91 "current": (95 "current": (
92 tuple(),96 tuple(),
@@ -121,7 +125,7 @@
121 else:125 else:
122 self.error("Only one sub-tool allowed")126 self.error("Only one sub-tool allowed")
123 if tool == "close" and not options.bugs:127 if tool == "close" and not options.bugs:
124 self.error("at elast one bug needed")128 self.error("at least one bug needed")
125 given_options = set(i for i, k in self.defaults.iteritems() if not getattr(options, i) == k)129 given_options = set(i for i, k in self.defaults.iteritems() if not getattr(options, i) == k)
126 needed_options = set(CmdOptions.TOOLS[tool][0]) - given_options130 needed_options = set(CmdOptions.TOOLS[tool][0]) - given_options
127 if needed_options:131 if needed_options:
@@ -250,44 +254,93 @@
250 title = b.xpathEval("td[2]")[0].content.strip()254 title = b.xpathEval("td[2]")[0].content.strip()
251 triager = b.xpathEval("td[3]")[0].content.strip() or None255 triager = b.xpathEval("td[3]")[0].content.strip() or None
252 yield (nr, title, done, triager, section)256 yield (nr, title, done, triager, section)
253 257
254def get_credentials(user, wiki_id=None, cookie=None):258################################################################################
259# Obtain the user's moin_id. This will allow us to authenticate to the wiki in #
260# order to make updates. The user may either provide the moin_id directly or #
261# the user provides their browser cookie file from which we can read the ID. #
262################################################################################
263def get_credentials(user, wiki_id=None, cookie_file_path=None, browser_str=None):
264
265 # User provided their moin_id string. Just save it in the config file.
255 if wiki_id:266 if wiki_id:
256 config = update_config(user=user, moin_id=wiki_id)267 config = update_config(user=user, moin_id=wiki_id)
257 elif cookie:268
258 # parse cookie269 # User provided their cookie file path. Attempt to read the MOIN_SESSION
259 # this includes a workaround for new cookie format270 # cookie from the cookie file.
260 result = None271 elif cookie_file_path:
261 try:272
262 cj = cookielib.MozillaCookieJar()273 cookie_file_path = os.path.expanduser(cookie_file_path)
263 cj.load(os.path.expanduser(cookie))274
264 result = [i.value for i in cj if i.domain == "wiki.ubuntu.com" \275 # Ensure cookie file exists
265 and i.name in ("MOIN_ID", "MOIN_SESSION")]276 if (not os.path.exists(cookie_file_path)):
266 except cookielib.LoadError:277 raise RuntimeError("The specified cookie file does not exist: '%s'" %cookie_file_path)
267 if not sqlite:278
268 raise TypeError(("Try to read cookiefile, cannot handle "279 # Load cookie file
269 "format of '%s'" %cookie))280 cookie_finder = CookieFinder()
270 try:281 cookie_file_valid = cookie_finder.set_cookie_file(cookie_file_path)
271 con = sqlite.connect(cookie)282
272 con.row_factory = sqlite.Row283 # Was cookie file valid?
273284 if (not cookie_file_valid):
274 cur = con.cursor()285 raise RuntimeError("The specified file is not a valid cookie file from a supported browser: '%s'. " %cookie_file_path)
275 cur.execute(("select value from moz_cookies where "286
276 "(name=? or name=?) and host=?"),287 # Get desired cookie
277 ("MOIN_SESSION", "MOIN_ID", "wiki.ubuntu.com",))288 cookie = cookie_finder.get_newest_cookie(domain=".wiki.ubuntu.com", name="MOIN_SESSION", ignore_expired=True)
278 #TODO: add check for expired cookie289
279 result = [i["value"] for i in cur]290 # Did we find a matching cookie?
280 except sqlite.Error, e:291 if (not cookie):
281 raise TypeError(("Error while trying to read cookie in "292 raise RuntimeError("Unable to find the MOIN_SESSION cookie in the given cookie file: '%s'. Please ensure you've logged in to wiki.ubuntu.com with this browser." %cookie_file_path )
282 "sql format, cannot handle "293
283 "format of '%s'" %cookie))294 # Found cookie! Update config file.
284 if not result:295 config = update_config(user=user, moin_id=cookie['value'])
285 raise ValueError("No cookie with name 'MOIN_ID' found in '%s'" %cookie)296 print "Cookie detection succeeded."
286 config = update_config(user=user, moin_id=result.pop())297
298 # User provided a string telling us which browser they wish to
299 # search to find the wiki-id cookie.
300 elif browser_str:
301
302 # See if CookieFinder supports the user's browser
303 cookie_finder = CookieFinder()
304 browser_supported = cookie_finder.set_browser(browser_str)
305
306 if (not browser_supported):
307 raise RuntimeError("unsupported browser '%s'" % browser_str)
308
309 # Get desired cookie.
310 cookie = cookie_finder.get_newest_cookie(domain=".wiki.ubuntu.com", name="MOIN_SESSION", ignore_expired=True)
311
312 # Did the cookie loader find valid files to read cookies from?
313 if (not cookie_finder.has_cookie_files()):
314 raise RuntimeError("No valid cookie files were found for the given browser.")
315
316 # Did we find a matching cookie?
317 if (not cookie):
318 raise RuntimeError("Unable to find the MOIN_SESSION cookie in the given browser's cookie files: '%s'. Please ensure you've logged in to wiki.ubuntu.com with this browser." %browser_str)
319
320 # Found cookie! Update config file.
321 config = update_config(user=user, moin_id=cookie['value'])
322 print "Cookie detection succeeded."
323
324 # Only --user option was specified (--cookie & --wiki-id were omitted)
325 # Do auto detection of cookie file.
287 else:326 else:
288 # interactive mode or openid, TBD327
289 raise NotImplementedError328 # Try and automatically find the cookie we need
290 329 cookie_finder = CookieFinder()
330 cookie = cookie_finder.get_newest_cookie(domain=".wiki.ubuntu.com", name="MOIN_SESSION", ignore_expired=True)
331
332 # Did the cookie loader find valid files to read cookies from?
333 if (not cookie_finder.has_cookie_files()):
334 raise RuntimeError("No valid cookie files were found. You do not seem to be using any supported browsers.")
335
336 # Did we find a matching cookie?
337 if (not cookie):
338 raise RuntimeError("Unable to detect the MOIN_SESSION cookie. Please ensure you've logged in to wiki.ubuntu.com with a supported browser.")
339
340 # Write the obtained moin_id to the user's configuration file
341 print "Cookie detection succeeded."
342 config = update_config(user=user, moin_id=cookie['value'])
343
291def build_request(url, moin_id, proxy=None, data=None):344def build_request(url, moin_id, proxy=None, data=None):
292 request = urllib2.Request(url, data)345 request = urllib2.Request(url, data)
293 #~ # moinmoin < 1.6346 #~ # moinmoin < 1.6
@@ -379,18 +432,27 @@
379 url = "%s/KDE" %url432 url = "%s/KDE" %url
380 return url433 return url
381434
435
436##########################
437# Main Program #
438# Execution starts here #
439##########################
382def main():440def main():
441
383 cmdoptions = CmdOptions()442 cmdoptions = CmdOptions()
384 tool, options = cmdoptions.parse_args()443 tool, options = cmdoptions.parse_args()
444
385 if tool == "list-days":445 if tool == "list-days":
386 print "list of all hugdays, latest first:"446 print "list of all hugdays, latest first:"
387 for day in parse_all_hugdays():447 for day in parse_all_hugdays():
388 print "\t* https://wiki.ubuntu.com/UbuntuBugDay/%s" %day448 print "\t* https://wiki.ubuntu.com/UbuntuBugDay/%s" %day
449
389 elif tool == "current":450 elif tool == "current":
390 current = get_current()451 current = get_current()
391 print current452 print current
392 if options.remember:453 if options.remember:
393 update_config(current=current)454 update_config(current=current)
455
394 elif tool == "list":456 elif tool == "list":
395 url = get_url(options.day, options.kde)457 url = get_url(options.day, options.kde)
396 i = None458 i = None
@@ -399,15 +461,17 @@
399 if i is not None:461 if i is not None:
400 print "="*50462 print "="*50
401 print "Total:", i + 1463 print "Total:", i + 1
464
402 elif tool == "init":465 elif tool == "init":
403 get_credentials(options.user, options.wiki_id, options.cookie)466 get_credentials(options.user, options.wiki_id, options.cookie, options.browser)
467
404 elif tool == "close":468 elif tool == "close":
405 url = get_url(options.day, options.kde)469 url = get_url(options.day, options.kde)
406 close_bugs(options.bugs, url, options.user)470 close_bugs(options.bugs, url, options.user)
471
472 # FIXME: Shouldn't this be impossible since we detect this in cmdoptions.parse_args()?
407 else:473 else:
408 raise RuntimeError("unknown tool '%s'" %tool)474 raise RuntimeError("unknown tool '%s'" %tool)
409
410
411475
412if __name__ == "__main__":476if __name__ == "__main__":
413 try:477 try:
414478
=== added directory 'hugday_lib'
=== added file 'hugday_lib/__init__.py'
=== added directory 'hugday_lib/cookie_lib'
=== added file 'hugday_lib/cookie_lib/ChromeCookieLoader.py'
--- hugday_lib/cookie_lib/ChromeCookieLoader.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/ChromeCookieLoader.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,63 @@
1#!/usr/bin/python
2
3import os, shutil
4
5from CookieLoader import CookieLoader
6
7# This is a subclass of CookieLoader. Please see CookieLoader for more details.
8class ChromeCookieLoader(CookieLoader):
9
10 # browser name
11 browser_str = "chrome"
12
13 # List of directories to search for cookie files.
14 cookie_file_search_path = [ os.path.join( "~" , ".config" , "google-chrome" ) ,
15 os.path.join( "~" , ".config" , "chromium" )
16 ]
17
18 # List of valid cookie file names.
19 cookie_file_names = [ "Cookies" ]
20
21 # attempts to load cookies from the given file.
22 # If cookie_file_path points to a valid readable cookie file that can be
23 # parsed then this function will return True. If it returns false then
24 # the specified cookie file is not readable by this cookie finder.
25 def load_cookies_from_file(self, cookie_file_path):
26
27 # If the given cookie file does not exist, give up.
28 if (not os.path.exists(cookie_file_path)):
29 return False
30
31 # If we attempt to use the cookie file while the browser is running
32 # we will get errors. Only one process is allowed to use it at a time.
33 # To get around this we can simply copy it to /tmp and then use it.
34 tmp_cookie_file_path = os.path.join( "/" , "tmp" , os.path.basename(cookie_file_path) )
35 shutil.copyfile(cookie_file_path, tmp_cookie_file_path)
36
37 # Chrome cookie files are sqlite databases
38 cookies = self.load_sqlite_cookie_file(tmp_cookie_file_path, table_name="cookies", domain_key="host_key", name_key="name", value_key="value", expire_time_key="expires_utc")
39
40 # If the load failed, then we've been given an invalid cookie file.
41 if (not cookies):
42 os.remove(tmp_cookie_file_path)
43 return False
44
45 # Fix timestamps in Google Chrome cookies!!
46 # Chrome stores cookies with a 64-bit integer that represents the number of Microseconds that have passed since 1/1/1601. So it's not quite a
47 # Unix timestamp. See top comments in this file for more info: http://src.chromium.org/svn/trunk/src/base/time_posix.cc
48 #
49 # The basic proceedure for converting a Chrome timestamp into a Unix timestap is this: unix_time = (chrome_time / 1000000) - 11644473600
50 for cookie in cookies:
51 cookie['expire_time'] = (cookie['expire_time'] / 1000000) - 11644473600
52
53 # Loop over all cookies and add them to our cookies list
54 for cookie in cookies:
55 self.cookies.append(cookie)
56
57 # Erase temporary cookie file.
58 os.remove(tmp_cookie_file_path)
59
60 # We were able to read cookies from this file.
61 self.found_valid_cookie_file = True
62 return True
63
064
=== added file 'hugday_lib/cookie_lib/CookieFinder.py'
--- hugday_lib/cookie_lib/CookieFinder.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/CookieFinder.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,149 @@
1from FirefoxCookieLoader import FirefoxCookieLoader
2from EpiphanyCookieLoader import EpiphanyCookieLoader
3from SeamonkeyCookieLoader import SeamonkeyCookieLoader
4from ChromeCookieLoader import ChromeCookieLoader
5from KonquerorCookieLoader import KonquerorCookieLoader
6
7import time, os
8from datetime import datetime
9
10# Used to find/access cookies for many different web browsers. You can point
11# CookieFinder to a specific cookie file (set_cookie_file) or you can simply
12# perform a search (get_cookies/get_newest_cookie) and CookieFinder will
13# automatically scan every cookie file it can find for every browser it supports.
14class CookieFinder:
15
16 # List of cookie loaders. Each one scans a different browser's cookie file(s).
17 cookie_loaders = []
18
19 # Creates a new CookieFinder.
20 def __init__(self):
21
22 # Populate cookie loaders, one loader for each browser we support
23 self.cookie_loaders.append( FirefoxCookieLoader() )
24 self.cookie_loaders.append( EpiphanyCookieLoader() )
25 self.cookie_loaders.append( SeamonkeyCookieLoader() )
26 self.cookie_loaders.append( ChromeCookieLoader() )
27 self.cookie_loaders.append( KonquerorCookieLoader() )
28
29 # Tells CookieFinder that you only wish to search the given browser for
30 # cookies. All CookieLoaders will be search until one is found that matches
31 # the given browser string. Once that loader is found all others will be
32 # removed from our loaders list. All subsequent operations using this CookieFiner
33 # will only invoke the one loader.
34 # Returns True if a suitable CookieLoader was found. Returns False otherwise.
35 def set_browser(self, browser_str):
36
37 # Avoid case comparison problems
38 browser_str = browser_str.lower()
39
40 # Locate a cookie loader for the browser the user specified
41 for cookie_loader in self.cookie_loaders:
42
43 if ( cookie_loader.browser_str == browser_str):
44
45 # We found a cookie loader that supports the user's browser.
46 # Throw away the rest of the loaders.
47 self.cookie_loaders = [cookie_loader]
48
49 # Return true and the caller will be most pleased :)
50 return True
51
52 # We got to the end of the list and none of our cookie loaders match.
53 return False
54
55 # Tells CookieFinder that you only want to search the given file for cookies.
56 # If cookie_file_path points to a valid readable cookie file that can be
57 # parsed by CookieFinder then this function will return True. If it returns
58 # false then the specified cookie file is not readable by CookieFinder.
59 def set_cookie_file(self, cookie_file_path):
60
61 # Ensure ~ is properly handled in the path
62 cookie_file_path = os.path.expanduser(cookie_file_path)
63
64 # Locate a cookie loader that can read this cookie file.
65 for cookie_loader in self.cookie_loaders:
66
67 if ( cookie_loader.load_cookies_from_file(cookie_file_path) ):
68
69 # Since we found a cookie loader that can read this file there is
70 # no need to keep the rest around.
71 print "Using Cookie Loader " + str(cookie_loader.__module__)
72 self.cookie_loaders = [cookie_loader]
73
74 # We found a cookie loader that will read the caller's cookie
75 # file. Return true and the caller will be most pleased :)
76 return True
77
78 # We got to the end of the list and none of our cookie loaders read the file.
79 return False
80
81 # Returns a list of cookies found by this CookieFinder that match the given criteria.
82 # If caller does not specify any of the search criteria then all cookies will be
83 # returned. An empty list is returned if no matching cookies were found.
84 def get_cookies(self, domain=None, name=None, ignore_expired=False):
85
86 cookies = []
87
88 for cookie_loader in self.cookie_loaders:
89
90 # Ensure this cookie loader has its cookies loaded.
91 found_cookies = cookie_loader.load_cookies()
92
93 # If no cookies were found go try next loader
94 if(not found_cookies): continue
95
96 # Look for cookies matching the caller's search criteria.
97 for cookie in cookie_loader.cookies:
98 # If user specified a domain, skip this cookie if its domain does not match
99 # The domain name is converted to lowercase to avoid comparison failue.
100 # Any leading '.' character is also removed from domain name to prevent comparison failure.
101 if domain and (not cookie['domain'].lower().lstrip(".") == domain.lower().lstrip(".")):
102 continue
103
104 # If user specified a name, skip this cookie if its name does not match
105 if name and (not cookie['name'].lower() == name.lower()):
106 continue
107
108 # If user wants: skip this cookie if it has expired.
109 if ignore_expired and (time.time() > cookie['expire_time']):
110 continue
111
112 # This cookie matches, add it to the list.
113 #print ( " Cookie: name=%s value=%s expires=%s" % (cookie['name'], cookie['value'], datetime.fromtimestamp(cookie['expire_time'])) )
114 cookies.append(cookie)
115
116 # Return cookie list
117 return cookies
118
119 # Returns the newest cookie found by this CookieFinder that match the given criteria.
120 # The "newest" cookie is the cookie with the latest expiration date. This is really
121 # only meaningful when comparing the same cookie but from different browser files.
122 # It is useful when you just want ONE copy (the latest and greatest) of a specific
123 # cookie but you're not sure which browser or cookie file has it.
124 # None is returned if no matching cookie is found.
125 def get_newest_cookie(self, domain=None, name=None, ignore_expired=False):
126
127 # Get list of all matching cookies
128 cookies = self.get_cookies(domain, name, ignore_expired)
129 if (len(cookies) == 0): return None
130
131 newest_cookie = cookies[0]
132
133 # Look for the one with the largest expire time.
134 for cookie in cookies:
135 if ( cookie['expire_time'] > newest_cookie['expire_time'] ):
136 newest_cookie = cookie
137
138 return newest_cookie
139
140 # Returns True if this CookieFinder was able to find/load at least one cookie file.
141 # This is useful to distinguish between thw following cases: 1) No cookie files are
142 # found to load cookies from. 2) No matching cookies were found inside the cookie file(s).
143 def has_cookie_files(self):
144
145 for cookie_loader in self.cookie_loaders:
146 if (cookie_loader.found_valid_cookie_file): return True
147
148 return False
149
0150
=== added file 'hugday_lib/cookie_lib/CookieLoader.py'
--- hugday_lib/cookie_lib/CookieLoader.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/CookieLoader.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,209 @@
1#!/usr/bin/python
2
3import os, cookielib
4
5try: import sqlite3 as sqlite
6except ImportError:
7 try: from pysqlite2 import dbapi2 as sqlite
8 except ImportError: sqlite = None
9
10# base CookieLoader class. This class is not mean to be used directly. Instead
11# child classes should be created to implement cookie loading for a specific
12# browser.
13#
14# Used to find/access cookies for some web browser. You can specify
15# a specific cookie file (load_cookies_from_file) or you can let this class
16# automatically detect cookie files and load cookies from them (load_cookies).
17class CookieLoader:
18
19 # Child classes should provide this string.
20 # all lower case String (no spaces) that represents the name of the webbrowser that
21 # this CookieLoader loads cookies for.
22 browser_str = None
23
24 # List of cookies found. This is not valid until either load_cookies_from_file
25 # has been called and has returned True or load_cookies has been called and
26 # has returned true.
27 #
28 # cookie objects on this list are dictionaries and have the following properties:
29 # 'domain' : string - Host setting the cookie
30 # 'name' : string - Cookie name
31 # 'value' : string - Cookie value
32 # 'expire_time' : integer - Expire date/time (Unix Time)
33 cookies = []
34
35 # Indicates that at least one valid cookie file was found during loading.
36 found_valid_cookie_file = False
37
38 # Child classes should provide this list.
39 # List of directories to search for cookie files (searched recursively).
40 cookie_file_search_path = []
41
42 # Child classes should provide this list.
43 # List of valid cookie file names. Files with these names will be search for cookies
44 # if they are found in the paths listed in the cookie_file_search_path.
45 cookie_file_names = []
46
47 # Child classes should provide this method.
48 # attempts to load cookies from the given file.
49 # If cookie_file_path points to a valid readable cookie file that can be
50 # parsed then this function will return True. If it returns false then
51 # the specified cookie file is not readable by this cookie finder.
52 def load_cookies_from_file(self, cookie_file_path):
53 raise NotImplementedError("This method cannot be used directly. Subclass CookieFinder and override this method.")
54
55 # Loads all cookies that are found in all cookie files found.
56 # Cookie files are searched for in the paths found in
57 # the cookie_file_search_paths list.
58 # Returns True if at least one cookie file can be loaded, False otherwise.
59 def load_cookies(self):
60
61 # If there are already cookies loaded, do not reload them, just return.
62 # This prevents reloading the cookie list on every search since load_cookies
63 # is called before every search.
64 if (self.cookies):
65 return ( len(self.cookies) > 0 )
66
67 # Initialize cookies to an empty list
68 self.cookies = []
69
70 found_cookies = False
71
72 # Find all cookie files
73 cookie_file_paths = self.find_cookie_files()
74
75 # Try to load each cookie file individually. If we can load any one of them then
76 # we can declare succcess.
77 for cookie_file_path in cookie_file_paths:
78
79 # If cookies are found, they are added to this objects cookies list.
80 found_cookies = self.load_cookies_from_file(cookie_file_path)
81
82 return found_cookies
83
84 ######################################################
85 ################# Internal Functions #################
86 ######################################################
87
88 # Searches all predefined paths for cookie files. Returns a list of fully
89 # qualified paths to cookie files found.
90 def find_cookie_files(self):
91
92 cookie_file_paths = []
93
94 # Search each directory for cookies
95 for cur_dir in self.cookie_file_search_path:
96
97 # Expand '~' in paths
98 cur_dir = os.path.expanduser(cur_dir)
99
100 cur_paths = self.cookie_file_scan(cur_dir, cookie_file_paths)
101
102 return cookie_file_paths
103
104 # Recursively scan for cookie files in the target directory and return a
105 # list of the cookie files found.
106 def cookie_file_scan(self, target_dir, cookie_file_list):
107
108 # Ensure current directory exists
109 if (not os.path.exists(target_dir)): return
110
111 # Loop over all files/dirs in the current_dir
112 for cur_file in os.listdir(target_dir):
113
114 # Full path to current file
115 cur_file_path = os.path.join(target_dir, cur_file)
116
117 # If the current file is a folder, recursively process it
118 if( os.path.isdir(cur_file_path)):
119
120 # Scan it for cookie files
121 self.cookie_file_scan(cur_file_path, cookie_file_list)
122
123 # The current file is a file (not a directory), see if it is a cookie file.
124 else:
125
126 # If the current file matches any of the names in cookie_file_names, it is a cookie file.
127 for name in self.cookie_file_names:
128 if (cur_file.lower() == name.lower()):
129 cookie_file_list.append(cur_file_path)
130
131 ####################################################################
132 ################# Generic Cookie Parsing Functions #################
133 ####################################################################
134 # These parsing functions can be used by many different browsers. #
135 # They are provided here for child classes to use. This avoid #
136 # duplicating the code in each child class that can use them. #
137 ####################################################################
138
139 # Loads cookies from a sqlite cookie file and returns the list of cookies.
140 # Returns list of cookies on success and None otherwise.
141 # The table and key names default to the ones used by Mozilla based browsers as they are the most common.
142 def load_sqlite_cookie_file(self, cookie_file_path, table_name="moz_cookies", domain_key="host", name_key="name", value_key="value", expire_time_key="expiry"):
143
144 cookies = []
145
146 # "Connect" to cookie file :)
147 try:
148 con = sqlite.connect(cookie_file_path)
149 con.row_factory = sqlite.Row
150
151 # Perform SQL query to obtain all cookies
152 cur = con.cursor().execute("select * from " + table_name)
153
154 # If query fails, this is NOT a valid sqlite cookie file.
155 except sqlite.Error, e:
156 return None
157
158 # cookie objects returned are dictionaries and have the following properties
159 # 'id' - ???
160 # 'name' - Cookie name
161 #'value' - Cookie value
162 #'host' - Host setting the cookie
163 #'path' - ???
164 #'expiry' - Expire date/time (Unix Time)
165 #'lastAccessed' - last time cookie was used.
166 #'isSecure' - ???
167 #'isHttpOnly' - ???
168
169
170 # Build and return list of cookies.
171 for cookie in cur:
172 new_cookie = {}
173 new_cookie['domain'] = cookie[domain_key]
174 new_cookie['name'] = cookie[name_key]
175 new_cookie['value'] = cookie[value_key]
176 new_cookie['expire_time'] = cookie[expire_time_key]
177 cookies.append(new_cookie)
178
179 # Close connection to database file
180 con.close()
181
182 return cookies
183
184 # Loads cookies from a plain text cookie file and returns the list of cookies.
185 # Returns list of cookies on success and None otherwise.
186 def load_txt_cookie_file(self, cookie_file_path):
187
188 cookies = []
189
190 # Load cookie file
191 try:
192 cookie_jar = cookielib.MozillaCookieJar()
193 cookie_jar.load(cookie_file_path)
194
195 # If load fails, this is NOT a valid plain text cookie file.
196 except cookielib.LoadError:
197 return None
198
199 # Loop over all cookies and all them to our cookies list
200 for cookie in cookie_jar:
201 new_cookie = {}
202 new_cookie['domain'] = cookie.domain
203 new_cookie['name'] = cookie.name
204 new_cookie['value'] = cookie.value
205 new_cookie['expire_time'] = cookie.expires # int
206 cookies.append(new_cookie)
207
208 return cookies
209
0210
=== added file 'hugday_lib/cookie_lib/EpiphanyCookieLoader.py'
--- hugday_lib/cookie_lib/EpiphanyCookieLoader.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/EpiphanyCookieLoader.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,53 @@
1#!/usr/bin/python
2
3import os, shutil
4
5from CookieLoader import CookieLoader
6
7# This is a subclass of CookieLoader. Please see CookieLoader for more details.
8class EpiphanyCookieLoader(CookieLoader):
9
10 # browser name
11 browser_str = "epiphany"
12
13 # List of directories to search for cookie files.
14 cookie_file_search_path = [ os.path.join( "~" , ".gnome2" , "epiphany" ) ]
15
16 # List of valid cookie file names.
17 cookie_file_names = [ "cookies.sqlite" ]
18
19 # attempts to load cookies from the given file.
20 # If cookie_file_path points to a valid readable cookie file that can be
21 # parsed then this function will return True. If it returns false then
22 # the specified cookie file is not readable by this cookie finder.
23 def load_cookies_from_file(self, cookie_file_path):
24
25 # If the given cookie file does not exist, give up.
26 if (not os.path.exists(cookie_file_path)):
27 return False
28
29 # If we attempt to use the cookie file while the browser is running
30 # we will get errors. Only one process is allowed to use it at a time.
31 # To get around this we can simply copy it to /tmp and then use it.
32 tmp_cookie_file_path = os.path.join( "/" , "tmp" , os.path.basename(cookie_file_path) )
33 shutil.copyfile(cookie_file_path, tmp_cookie_file_path)
34
35 # Epiphany cookie files are sqlite databases
36 cookies = self.load_sqlite_cookie_file(tmp_cookie_file_path)
37
38 # If the load failed, then we've been given an invalid cookie file.
39 if (not cookies):
40 os.remove(tmp_cookie_file_path)
41 return False
42
43 # Loop over all cookies and add them to our cookies list
44 for cookie in cookies:
45 self.cookies.append(cookie)
46
47 # Erase temporary cookie file.
48 os.remove(tmp_cookie_file_path)
49
50 # We were able to read cookies from this file.
51 self.found_valid_cookie_file = True
52 return True
53
054
=== added file 'hugday_lib/cookie_lib/FirefoxCookieLoader.py'
--- hugday_lib/cookie_lib/FirefoxCookieLoader.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/FirefoxCookieLoader.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,60 @@
1#!/usr/bin/python
2
3import os, shutil
4
5from CookieLoader import CookieLoader
6
7# This is a subclass of CookieLoader. Please see CookieLoader for more details.
8class FirefoxCookieLoader(CookieLoader):
9
10 # browser name
11 browser_str = "firefox"
12
13 # List of directories to search for cookie files.
14 cookie_file_search_path = [ os.path.join( "~" , ".mozilla" , "firefox" ) ]
15
16 # List of valid cookie file names.
17 cookie_file_names = [ "cookies.sqlite" , "cookies.txt" ]
18
19 # attempts to load cookies from the given file.
20 # If cookie_file_path points to a valid readable cookie file that can be
21 # parsed then this function will return True. If it returns false then
22 # the specified cookie file is not readable by this cookie finder.
23 def load_cookies_from_file(self, cookie_file_path):
24
25 # If the given cookie file does not exist, give up.
26 if (not os.path.exists(cookie_file_path)):
27 return False
28
29 # If we attempt to use the cookie file while the browser is running
30 # we will get errors. Only one process is allowed to use it at a time.
31 # To get around this we can simply copy it to /tmp and then use it.
32 tmp_cookie_file_path = os.path.join( "/" , "tmp" , os.path.basename(cookie_file_path) )
33 shutil.copyfile(cookie_file_path, tmp_cookie_file_path)
34
35 # Firefox cookie files can be one of two formats:
36 # old format - cookies.txt - Plain text cookie file
37 # new format - cookies.sqlite - sqlite database file
38
39 # 1st, try to read that file as if it is an sqlite cookie file.
40 cookies = self.load_sqlite_cookie_file(tmp_cookie_file_path)
41
42 # If that fails, try to read it as plain text
43 if (not cookies): cookies = self.load_txt_cookie_file(tmp_cookie_file_path)
44
45 # If they both failed, then we've been given an invalid cookie file.
46 if (not cookies):
47 os.remove(tmp_cookie_file_path)
48 return False
49
50 # Loop over all cookies and add them to our cookies list
51 for cookie in cookies:
52 self.cookies.append(cookie)
53
54 # Erase temporary cookie file.
55 os.remove(tmp_cookie_file_path)
56
57 # We were able to read cookies from this file.
58 self.found_valid_cookie_file = True
59 return True
60
061
=== added file 'hugday_lib/cookie_lib/KonquerorCookieLoader.py'
--- hugday_lib/cookie_lib/KonquerorCookieLoader.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/KonquerorCookieLoader.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,111 @@
1 #!/usr/bin/python
2
3import os, shutil
4
5from CookieLoader import CookieLoader
6
7# This is a subclass of CookieLoader. Please see CookieLoader for more details.
8class KonquerorCookieLoader(CookieLoader):
9
10 # browser name
11 browser_str = "konqueror"
12
13 # List of directories to search for cookie files.
14 cookie_file_search_path = [ os.path.join( "~" , ".kde" , "share" , "apps" , "kcookiejar") ]
15
16 # List of valid cookie file names.
17 cookie_file_names = [ "cookies" ]
18
19 # attempts to load cookies from the given file.
20 # If cookie_file_path points to a valid readable cookie file that can be
21 # parsed then this function will return True. If it returns false then
22 # the specified cookie file is not readable by this cookie finder.
23 def load_cookies_from_file(self, cookie_file_path):
24
25 # If the given cookie file does not exist, give up.
26 if (not os.path.exists(cookie_file_path)):
27 return False
28
29 # Konqueror cookie files are in plain text format
30 cookies = self.load_konqueror_cookie_file(cookie_file_path)
31
32 # If the load failed, then we've been given an invalid cookie file.
33 if (not cookies):
34 print "not cookies"
35 return False
36
37 # Loop over all cookies and add them to our cookies list
38 for cookie in cookies:
39 self.cookies.append(cookie)
40
41 # We were able to read cookies from this file.
42 return True
43
44
45
46 # Loads cookies from a Konqueror plain text cookie file and returns the list of cookies.
47 # Returns list of cookies on success and None otherwise.
48 def load_konqueror_cookie_file(self, cookie_file_path):
49
50 cookies = []
51
52 # Here is an example Konquerir cookie file:
53 # # KDE Cookie File v2
54 # #
55 # # Host Domain Path Exp.date Prot Name Sec Value
56 # [.ubuntu.com]
57 # wiki.ubuntu.com ".wiki.ubuntu.com" "/" 1286259931 0 __utmz 4 230736537.1270491931.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)
58 # wiki.ubuntu.com ".wiki.ubuntu.com" "/" 1333564241 0 __utma 4 230736537.1618083871.1270491931.1270492211.1270492242.3
59 # wiki.ubuntu.com ".wiki.ubuntu.com" "/" 1270494047 0 __utmb 4 230736537
60 # wiki.ubuntu.com ".wiki.ubuntu.com" "/" 1333564247 0 __utmv 4 230736537.UbuntuWiki
61 # wiki.ubuntu.com "" "/" 1585852247 0 MOIN_SESSION 4 249_4_7z1eln24s28t8ifido5k3cnwc_
62 # [.launchpad.net]
63 # login.launchpad.net "" "/" 1271701555 0 sessionid 5 9ebf071969502599c1d1f959d210c892
64 # [.slashdot.org]
65 # slashdot.org ".slashdot.org" "/" 1286260261 0 __utmz 4 9273847.1270492261.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
66 # slashdot.org ".slashdot.org" "/" 1333564271 0 __utma 4 9273847.870340038.1270492261.1270492261.1270492261.1
67 # slashdot.org ".slashdot.org" "/" 1270494071 0 __utmb 4 9273847.1.10.1270492261
68 #
69
70 # Open cookie file
71 cookie_file = open(cookie_file_path, "r")
72
73 # Ensure this is a Konqueror cookie file
74 first_line = cookie_file.readline()
75 if ( first_line.find("KDE Cookie File") == -1 ):
76 print "Not cookie file!"
77 return False
78
79 # Parse file line by line looking for cookies...
80 for line in cookie_file:
81
82 # Throw away comments, host headers
83 if ( line.startswith("#") ): continue
84 if ( line.startswith("[") ): continue
85
86 # Split string on whitespace (Ignore lines that do not contain enough tokens)
87 tokens = line.split()
88 if ( len(tokens) < 8): continue
89
90 # Construct cookie
91 new_cookie = {}
92 new_cookie['domain'] = tokens[0]
93 new_cookie['name'] = tokens[5]
94 new_cookie['value'] = tokens[7]
95 new_cookie['expire_time'] = tokens[3]
96
97 # Sanity check data & convert expire time to an integer
98 if (new_cookie['expire_time'].isdigit()):
99 new_cookie['expire_time'] = int(new_cookie['expire_time'])
100 else: continue
101
102 # We have a good cookie :)
103 cookies.append(new_cookie)
104
105 # Close file.
106 cookie_file.close()
107
108 # Found cookie files :)
109 self.found_valid_cookie_file = True
110 return cookies
111
0112
=== added file 'hugday_lib/cookie_lib/SeamonkeyCookieLoader.py'
--- hugday_lib/cookie_lib/SeamonkeyCookieLoader.py 1970-01-01 00:00:00 +0000
+++ hugday_lib/cookie_lib/SeamonkeyCookieLoader.py 2010-04-13 16:46:31 +0000
@@ -0,0 +1,43 @@
1#!/usr/bin/python
2
3import os, shutil
4
5from CookieLoader import CookieLoader
6
7# This is a subclass of CookieLoader. Please see CookieLoader for more details.
8class SeamonkeyCookieLoader(CookieLoader):
9
10 # browser name
11 browser_str = "seamonkey"
12
13 # List of directories to search for cookie files.
14 cookie_file_search_path = [ os.path.join( "~" , ".mozilla" , "default" ) ]
15
16 # List of valid cookie file names.
17 cookie_file_names = [ "cookies.txt" ]
18
19 # attempts to load cookies from the given file.
20 # If cookie_file_path points to a valid readable cookie file that can be
21 # parsed then this function will return True. If it returns false then
22 # the specified cookie file is not readable by this cookie finder.
23 def load_cookies_from_file(self, cookie_file_path):
24
25 # If the given cookie file does not exist, give up.
26 if (not os.path.exists(cookie_file_path)):
27 return False
28
29 # Epiphany cookie files are sqlite databases
30 cookies = self.load_txt_cookie_file(cookie_file_path)
31
32 # If the load failed, then we've been given an invalid cookie file.
33 if (not cookies):
34 return False
35
36 # Loop over all cookies and add them to our cookies list
37 for cookie in cookies:
38 self.cookies.append(cookie)
39
40 # We were able to read cookies from this file.
41 self.found_valid_cookie_file = True
42 return True
43
044
=== added file 'hugday_lib/cookie_lib/__init__.py'
=== modified file 'setup.py'
--- setup.py 2010-03-31 16:37:16 +0000
+++ setup.py 2010-04-13 16:46:31 +0000
@@ -28,5 +28,7 @@
28 'dl-ubuntu-test-iso/iso-ripper',28 'dl-ubuntu-test-iso/iso-ripper',
29 'hugday-tools/hugday',29 'hugday-tools/hugday',
30 ],30 ],
31 packages=[],31 packages=['hugday_lib',
32 'hugday_lib/cookie_lib'
33 ]
32)34)