From 5ab073d90e3c66a53e116c78299c657a13847d5c Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Fri, 3 Dec 2010 14:55:47 -0700 Subject: display active downloads in the status bar --- examples/data/plugins/downloads.py | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 examples/data/plugins/downloads.py (limited to 'examples/data/plugins') diff --git a/examples/data/plugins/downloads.py b/examples/data/plugins/downloads.py new file mode 100644 index 0000000..7bf32d7 --- /dev/null +++ b/examples/data/plugins/downloads.py @@ -0,0 +1,69 @@ +# this plugin does a very simple display of download progress. to use it, add +# @downloads to your status_format. + +import os +ACTIVE_DOWNLOADS = {} + +# after a download's status has changed this is called to update the status bar +def update_download_section(uzbl): + global ACTIVE_DOWNLOADS + + if len(ACTIVE_DOWNLOADS): + # add a newline before we list downloads + result = ' downloads:' + for path in ACTIVE_DOWNLOADS: + # add each download + fn = os.path.basename(path) + progress, = ACTIVE_DOWNLOADS[path] + + dl = " %s (%d%%)" % (fn, progress * 100) + + # replace entities to make sure we don't break our markup + # (this could be done with an @[]@ expansion in uzbl, but then we + # can't use the above to make a new line) + dl = dl.replace("&", "&").replace("<", "<") + result += dl + else: + result = '' + + # and the result gets saved to an uzbl variable that can be used in + # status_format + if uzbl.config.get('downloads', '') != result: + uzbl.config['downloads'] = result + +def download_started(uzbl, destination_path): + # add to the list of active downloads + global ACTIVE_DOWNLOADS + ACTIVE_DOWNLOADS[destination_path] = (0.0,) + + # update the progress + update_download_section(uzbl) + +def download_progress(uzbl, args): + # parse the arguments + s = args.rindex(' ') + destination_path = args[:s] + progress = float(args[s+1:]) + + # update the progress + global ACTIVE_DOWNLOADS + ACTIVE_DOWNLOADS[destination_path] = (progress,) + + # update the status bar variable + update_download_section(uzbl) + +def download_complete(uzbl, destination_path): + # remove from the list of active downloads + global ACTIVE_DOWNLOADS + del ACTIVE_DOWNLOADS[destination_path] + + # update the status bar variable + update_download_section(uzbl) + +# plugin init hook +def init(uzbl): + connect_dict(uzbl, { + 'DOWNLOAD_STARTED': download_started, + 'DOWNLOAD_PROGRESS': download_progress, + 'DOWNLOAD_COMPLETE': download_complete, + }) -- cgit v1.2.3 From a172410534b4048d621fd6a6f2f3da5f6565feec Mon Sep 17 00:00:00 2001 From: keis Date: Wed, 1 Dec 2010 00:22:29 +0100 Subject: cookie forwarder as EM plugin persistance to mozilla cookies.txt format --- examples/data/plugins/cookies.py | 116 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 examples/data/plugins/cookies.py (limited to 'examples/data/plugins') diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py new file mode 100644 index 0000000..80c9ab0 --- /dev/null +++ b/examples/data/plugins/cookies.py @@ -0,0 +1,116 @@ +""" Basic cookie manager + forwards cookies to all other instances connected to the event manager""" + +from collections import defaultdict +import os, re + +_splitquoted = re.compile("( |\\\".*?\\\"|'.*?')") +def splitquoted(text): + return [str(p.strip('\'"')) for p in _splitquoted.split(text) if p.strip()] + +# allows for partial cookies +# ? allow wildcard in key +def match(key, cookie): + for k,c in zip(key,cookie): + if k != c: + return False + return True + +class NullStore(object): + def add_cookie(self, rawcookie, cookie): + pass + + def delete_cookie(self, rkey, key): + pass + +class TextStore(object): + def __init__(self, filename): + self.filename = filename + + def as_event(self, cookie): + if cookie[0].startswith("#HttpOnly_"): + domain = cookie[0][len("#HttpOnly_"):] + elif cookie[0].startswith('#'): + return None + else: + domain = cookie[0] + return (domain, + cookie[2], + cookie[5], + cookie[6], + 'https' if cookie[3] == 'TRUE' else 'http', + cookie[4]) + + def as_file(self, cookie): + return (cookie[0], + 'TRUE' if cookie[0].startswith('.') else 'FALSE', + cookie[1], + 'TRUE' if cookie[4] == 'https' else 'FALSE', + cookie[5], + cookie[2], + cookie[3]) + + def add_cookie(self, rawcookie, cookie): + assert len(cookie) == 6 + + # Skip cookies limited to this session + if len(cookie[-1]) == 0: + return + + # delete equal cookies (ignoring expire time, value and secure flag) + self.delete_cookie(None, cookie[:-3]) + + first = not os.path.exists(self.filename) + with open(self.filename, 'a') as f: + if first: + print >> f, "# HTTP Cookie File" + print >> f, '\t'.join(self.as_file(cookie)) + + def delete_cookie(self, rkey, key): + if not os.path.exists(self.filename): + return + + # read all cookies + with open(self.filename, 'r') as f: + cookies = f.readlines() + + # write those that don't match the cookie to delete + with open(self.filename, 'w') as f: + for l in cookies: + c = self.as_event(l.split('\t')) + if c is None or not match(key, c): + print >> f, l, + +xdg_data_home = os.environ.get('XDG_DATA_HOME', os.path.join(os.environ['HOME'], '.local/share')) +DefaultStore = TextStore(os.path.join(xdg_data_home, 'uzbl/cookies.txt')) + +def expires_with_session(cookie): + return cookie[5] == '' + +def get_recipents(uzbl): + """ get a list of Uzbl instances to send the cookie too. """ + # This could be a lot more interesting + return [u for u in uzbl.parent.uzbls.values() if u is not uzbl] + +def get_store(uzbl): + return DefaultStore + +def add_cookie(uzbl, cookie): + for u in get_recipents(uzbl): + u.send('add_cookie %s' % cookie) + + splitted = splitquoted(cookie) + get_store(uzbl).add_cookie(cookie, splitted) + +def delete_cookie(uzbl, cookie): + for u in get_recipents(uzbl): + u.send('delete_cookie %s' % cookie) + + splitted = splitquoted(cookie) + get_store(uzbl).delete_cookie(cookie, splitted) + +def init(uzbl): + connect_dict(uzbl, { + 'ADD_COOKIE': add_cookie, + 'DELETE_COOKIE': delete_cookie, + }) -- cgit v1.2.3 From bf1bc5b562e1013706a903311df0bfb105d5464b Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 3 Dec 2010 13:31:26 +0100 Subject: keep session cookies in em plugin --- examples/data/plugins/cookies.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'examples/data/plugins') diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index 80c9ab0..225a6af 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -23,6 +23,13 @@ class NullStore(object): def delete_cookie(self, rkey, key): pass +class ListStore(list): + def add_cookie(self, rawcookie, cookie): + self.append(rawcookie) + + def delete_cookie(self, rkey, key): + self[:] = [x for x in self if not match(key, splitquoted(x))] + class TextStore(object): def __init__(self, filename): self.filename = filename @@ -53,10 +60,6 @@ class TextStore(object): def add_cookie(self, rawcookie, cookie): assert len(cookie) == 6 - # Skip cookies limited to this session - if len(cookie[-1]) == 0: - return - # delete equal cookies (ignoring expire time, value and secure flag) self.delete_cookie(None, cookie[:-3]) @@ -83,6 +86,7 @@ class TextStore(object): xdg_data_home = os.environ.get('XDG_DATA_HOME', os.path.join(os.environ['HOME'], '.local/share')) DefaultStore = TextStore(os.path.join(xdg_data_home, 'uzbl/cookies.txt')) +SessionStore = ListStore() def expires_with_session(cookie): return cookie[5] == '' @@ -92,7 +96,9 @@ def get_recipents(uzbl): # This could be a lot more interesting return [u for u in uzbl.parent.uzbls.values() if u is not uzbl] -def get_store(uzbl): +def get_store(uzbl, session=False): + if session: + return SessionStore return DefaultStore def add_cookie(uzbl, cookie): @@ -100,17 +106,24 @@ def add_cookie(uzbl, cookie): u.send('add_cookie %s' % cookie) splitted = splitquoted(cookie) - get_store(uzbl).add_cookie(cookie, splitted) + get_store(uzbl, expires_with_session(splitted)).add_cookie(cookie, splitted) def delete_cookie(uzbl, cookie): for u in get_recipents(uzbl): u.send('delete_cookie %s' % cookie) splitted = splitquoted(cookie) - get_store(uzbl).delete_cookie(cookie, splitted) + if len(splitted) == 6: + get_store(uzbl, expires_with_session(splitted)).delete_cookie(cookie, splitted) + else: + for store in set([get_store(uzbl, session) for session in (True, False)]): + store.delete_cookie(cookie, splitted) def init(uzbl): connect_dict(uzbl, { 'ADD_COOKIE': add_cookie, 'DELETE_COOKIE': delete_cookie, }) + + for cookie in get_store(uzbl, True): + uzbl.send('add_cookie %s' % cookie) -- cgit v1.2.3 From 46ddb58bcd2c0e7e3be27ed903ddce91eb14cc85 Mon Sep 17 00:00:00 2001 From: keis Date: Sun, 12 Dec 2010 16:52:38 +0100 Subject: basic blacklisting in cookies plugin --- examples/config/config | 4 ++++ examples/data/plugins/cookies.py | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'examples/data/plugins') diff --git a/examples/config/config b/examples/config/config index 213bb88..29f5fbc 100644 --- a/examples/config/config +++ b/examples/config/config @@ -122,6 +122,10 @@ set progress.pending = set useragent = Uzbl (Webkit @{WEBKIT_MAJOR}.@{WEBKIT_MINOR}.@{WEBKIT_MICRO}) (@(+uname -sm)@ [@ARCH_UZBL]) (Commit @COMMIT) +# === Configure cookie blacklist ======================================================== +# Drop google analytics tracking cookies +#request BLACKLIST_COOKIE name '^__utm.$' + # === Key binding configuration ============================================== # --- Internal modmapping and ignoring --------------------------------------- diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index 225a6af..0264471 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -4,6 +4,8 @@ from collections import defaultdict import os, re +symbolic = {'domain': 0, 'path':1, 'name':2, 'value':3, 'scheme':4, 'expires':5} + _splitquoted = re.compile("( |\\\".*?\\\"|'.*?')") def splitquoted(text): return [str(p.strip('\'"')) for p in _splitquoted.split(text) if p.strip()] @@ -88,7 +90,13 @@ xdg_data_home = os.environ.get('XDG_DATA_HOME', os.path.join(os.environ['HOME'], DefaultStore = TextStore(os.path.join(xdg_data_home, 'uzbl/cookies.txt')) SessionStore = ListStore() -def expires_with_session(cookie): +def accept_cookie(uzbl, cookie): + for component, match in uzbl.cookie_blacklist: + if match(cookie[component]) is not None: + return False + return True + +def expires_with_session(uzbl, cookie): return cookie[5] == '' def get_recipents(uzbl): @@ -102,11 +110,14 @@ def get_store(uzbl, session=False): return DefaultStore def add_cookie(uzbl, cookie): - for u in get_recipents(uzbl): - u.send('add_cookie %s' % cookie) - splitted = splitquoted(cookie) - get_store(uzbl, expires_with_session(splitted)).add_cookie(cookie, splitted) + if accept_cookie(uzbl, splitted): + for u in get_recipents(uzbl): + u.send('add_cookie %s' % cookie) + + get_store(uzbl, expires_with_session(uzbl, splitted)).add_cookie(cookie, splitted) + else: + uzbl.send('delete_cookie %s' % cookie) def delete_cookie(uzbl, cookie): for u in get_recipents(uzbl): @@ -114,15 +125,28 @@ def delete_cookie(uzbl, cookie): splitted = splitquoted(cookie) if len(splitted) == 6: - get_store(uzbl, expires_with_session(splitted)).delete_cookie(cookie, splitted) + get_store(uzbl, expires_with_session(uzbl, splitted)).delete_cookie(cookie, splitted) else: for store in set([get_store(uzbl, session) for session in (True, False)]): store.delete_cookie(cookie, splitted) +def blacklist(uzbl, arg): + component, regexp = splitquoted(arg) + try: + component = symbolic[component] + except KeyError: + component = int(component) + assert component <= 5 + uzbl.cookie_blacklist.append((component, re.compile(regexp).match)) + def init(uzbl): connect_dict(uzbl, { 'ADD_COOKIE': add_cookie, 'DELETE_COOKIE': delete_cookie, + 'BLACKLIST_COOKIE': blacklist + }) + export_dict(uzbl, { + 'cookie_blacklist' : [] }) for cookie in get_store(uzbl, True): -- cgit v1.2.3 From c294dc43176f384a7a7c2a3be25eebefb3698315 Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 17 Dec 2010 23:40:59 +0100 Subject: should open file with a+ when writing cookies --- examples/data/plugins/cookies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/data/plugins') diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index 0264471..a4ae530 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -66,7 +66,7 @@ class TextStore(object): self.delete_cookie(None, cookie[:-3]) first = not os.path.exists(self.filename) - with open(self.filename, 'a') as f: + with open(self.filename, 'a+') as f: if first: print >> f, "# HTTP Cookie File" print >> f, '\t'.join(self.as_file(cookie)) -- cgit v1.2.3 From 6ade80cd01d0473dc1268d35a9db89dc03b1b9e9 Mon Sep 17 00:00:00 2001 From: keis Date: Sat, 18 Dec 2010 23:07:33 +0100 Subject: put session cookies in file --- examples/config/config | 1 + examples/data/plugins/cookies.py | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'examples/data/plugins') diff --git a/examples/config/config b/examples/config/config index caf68a1..e755be1 100644 --- a/examples/config/config +++ b/examples/config/config @@ -396,6 +396,7 @@ set default_mode = command # === Post-load misc commands ================================================ sync_spawn_exec @scripts_dir/load_cookies.sh +sync_spawn_exec @scripts_dir/load_cookies.sh @data_home/uzbl/session-cookies.txt # Set the "home" page. set uri = uzbl.org/doesitwork/@COMMIT diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index a4ae530..8fb9b32 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -88,7 +88,7 @@ class TextStore(object): xdg_data_home = os.environ.get('XDG_DATA_HOME', os.path.join(os.environ['HOME'], '.local/share')) DefaultStore = TextStore(os.path.join(xdg_data_home, 'uzbl/cookies.txt')) -SessionStore = ListStore() +SessionStore = TextStore(os.path.join(xdg_data_home, 'uzbl/session-cookies.txt')) def accept_cookie(uzbl, cookie): for component, match in uzbl.cookie_blacklist: @@ -148,6 +148,3 @@ def init(uzbl): export_dict(uzbl, { 'cookie_blacklist' : [] }) - - for cookie in get_store(uzbl, True): - uzbl.send('add_cookie %s' % cookie) -- cgit v1.2.3 From 186668a01883127447f1b6042ea84c8f3cd7536b Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Wed, 22 Dec 2010 21:08:18 -0700 Subject: add cookie whitelisting, document BLACKLIST_COOKIE and WHITELIST_COOKIE events --- README | 10 ++++++++- examples/data/plugins/cookies.py | 44 ++++++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 10 deletions(-) (limited to 'examples/data/plugins') diff --git a/README b/README index e0d9dc9..35492da 100644 --- a/README +++ b/README @@ -719,7 +719,6 @@ Events have this format: be a unix-timestamp or empty * `EVENT [uzbl_instance_name] DELETE_COOKIE domain path name value scheme expire`: When a cookie was deleted. arguments as ADD_COOKIE - Events/requests which the EM and its plugins listens for @@ -794,6 +793,15 @@ Events/requests which the EM and its plugins listens for `` is `+`, advance the cursor by one character, and if it is `-`, move the cursor back by one character. * `START_COMPLETION`: TODO explain completion +* `BLACKLIST_COOKIE`: add a rule for blacklisting cookies + - `request BLACKLIST_COOKIE `: Blacklist cookies where + `` matches ``. `` is one of `domain`, + `path`, `name`, `value`, `scheme` or `expires`. +* `WHITELIST_COOKIE`: add a rule for whitelisting cookies (if any whitelist is + set then only cookies that are whitelisted cookies will be used) + - `request WHITELIST_COOKIE `: Whitelist cookies where + `` matches ``. `` is one of `domain`, + `path`, `name`, `value`, `scheme` or `expires`. ### COMMAND LINE ARGUMENTS diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index 8fb9b32..387e820 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -4,6 +4,7 @@ from collections import defaultdict import os, re +# these are symbolic names for the components of the cookie tuple symbolic = {'domain': 0, 'path':1, 'name':2, 'value':3, 'scheme':4, 'expires':5} _splitquoted = re.compile("( |\\\".*?\\\"|'.*?')") @@ -90,11 +91,22 @@ xdg_data_home = os.environ.get('XDG_DATA_HOME', os.path.join(os.environ['HOME'], DefaultStore = TextStore(os.path.join(xdg_data_home, 'uzbl/cookies.txt')) SessionStore = TextStore(os.path.join(xdg_data_home, 'uzbl/session-cookies.txt')) -def accept_cookie(uzbl, cookie): - for component, match in uzbl.cookie_blacklist: +def match_list(_list, cookie): + for component, match in _list: if match(cookie[component]) is not None: - return False - return True + return True + return False + +# accept a cookie only when: +# a. there is no whitelist and the cookie is in the blacklist +# b. the cookie is in the whitelist and not in the blacklist +def accept_cookie(uzbl, cookie): + if uzbl.cookie_whitelist: + if match_list(uzbl.cookie_whitelist, cookie): + return not match_list(uzbl.cookie_blacklist, cookie) + return False + + return not match_list(uzbl.cookie_blacklist, cookie) def expires_with_session(uzbl, cookie): return cookie[5] == '' @@ -114,9 +126,10 @@ def add_cookie(uzbl, cookie): if accept_cookie(uzbl, splitted): for u in get_recipents(uzbl): u.send('add_cookie %s' % cookie) - + get_store(uzbl, expires_with_session(uzbl, splitted)).add_cookie(cookie, splitted) else: + logger.debug('cookie %r is blacklisted' % splitted) uzbl.send('delete_cookie %s' % cookie) def delete_cookie(uzbl, cookie): @@ -130,21 +143,34 @@ def delete_cookie(uzbl, cookie): for store in set([get_store(uzbl, session) for session in (True, False)]): store.delete_cookie(cookie, splitted) -def blacklist(uzbl, arg): +# add a cookie matcher to a whitelist or a blacklist. +# a matcher is a (component, re) tuple that matches a cookie when the +# "component" part of the cookie matches the regular expression "re". +# "component" is one of the keys defined in the variable "symbolic" above, +# or the index of a component of a cookie tuple. +def add_cookie_matcher(_list, arg): component, regexp = splitquoted(arg) try: component = symbolic[component] except KeyError: component = int(component) assert component <= 5 - uzbl.cookie_blacklist.append((component, re.compile(regexp).match)) + _list.append((component, re.compile(regexp).match)) + +def blacklist(uzbl, arg): + add_cookie_matcher(uzbl.cookie_blacklist, arg) + +def whitelist(uzbl, arg): + add_cookie_matcher(uzbl.cookie_whitelist, arg) def init(uzbl): connect_dict(uzbl, { 'ADD_COOKIE': add_cookie, 'DELETE_COOKIE': delete_cookie, - 'BLACKLIST_COOKIE': blacklist + 'BLACKLIST_COOKIE': blacklist, + 'WHITELIST_COOKIE': whitelist }) export_dict(uzbl, { - 'cookie_blacklist' : [] + 'cookie_blacklist' : [], + 'cookie_whitelist' : [] }) -- cgit v1.2.3 From 7c87ebed095a50fb7bd0de60c7cabb859e483535 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Fri, 24 Dec 2010 07:21:54 -0700 Subject: WHITE/BLACKLIST_COOKIE regexp matches anywhere in the string (instead of only from start) --- examples/data/plugins/cookies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/data/plugins') diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index 387e820..c507fd6 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -155,7 +155,7 @@ def add_cookie_matcher(_list, arg): except KeyError: component = int(component) assert component <= 5 - _list.append((component, re.compile(regexp).match)) + _list.append((component, re.compile(regexp).search)) def blacklist(uzbl, arg): add_cookie_matcher(uzbl.cookie_blacklist, arg) -- cgit v1.2.3 From 1bfd9730057b4f272a93dc820a5f9b92c6c22385 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Tue, 28 Dec 2010 10:41:54 -0700 Subject: change open mode for writing cookies to 'a' --- examples/data/plugins/cookies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/data/plugins') diff --git a/examples/data/plugins/cookies.py b/examples/data/plugins/cookies.py index c507fd6..c9fe2c3 100644 --- a/examples/data/plugins/cookies.py +++ b/examples/data/plugins/cookies.py @@ -67,7 +67,7 @@ class TextStore(object): self.delete_cookie(None, cookie[:-3]) first = not os.path.exists(self.filename) - with open(self.filename, 'a+') as f: + with open(self.filename, 'a') as f: if first: print >> f, "# HTTP Cookie File" print >> f, '\t'.join(self.as_file(cookie)) -- cgit v1.2.3