aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/config/config28
-rw-r--r--examples/config/cookies22
-rwxr-xr-xexamples/data/scripts/download.sh4
-rw-r--r--examples/data/scripts/follow.js11
-rwxr-xr-xexamples/data/scripts/follow.sh21
-rwxr-xr-xexamples/data/scripts/formfiller.sh13
-rw-r--r--examples/data/scripts/go_input.js27
-rwxr-xr-xexamples/data/scripts/go_input.sh20
-rwxr-xr-xexamples/data/scripts/history.sh2
-rwxr-xr-xexamples/data/scripts/insert_bookmark.sh6
-rwxr-xr-xexamples/data/scripts/instance-select-wmii.sh4
-rwxr-xr-xexamples/data/scripts/load_url_from_bookmarks.sh6
-rwxr-xr-xexamples/data/scripts/load_url_from_history.sh6
-rwxr-xr-xexamples/data/scripts/userscript.sh40
-rwxr-xr-xexamples/data/scripts/userscripts.sh8
-rw-r--r--examples/data/scripts/util/dmenu.sh2
-rwxr-xr-xexamples/data/scripts/uzbl-cookie-daemon44
-rwxr-xr-xexamples/data/scripts/uzbl-event-manager2
-rwxr-xr-xexamples/data/scripts/uzbl-tabbed25
-rw-r--r--examples/uzbl-cookie-manager.c381
20 files changed, 588 insertions, 84 deletions
diff --git a/examples/config/config b/examples/config/config
index 1457c71..8189479 100644
--- a/examples/config/config
+++ b/examples/config/config
@@ -64,6 +64,9 @@ set authentication_handler = sync_spawn @scripts_dir/auth.py
# Load commit handlers
@on_event LOAD_COMMIT @set_status <span foreground="green">recv</span>
+# Userscript support. Add all scripts to $XDG_DATA_HOME/uzbl/userscripts
+#@on_event LOAD_COMMIT spawn @scripts_dir/userscripts.sh
+
# Load finish handlers
@on_event LOAD_FINISH @set_status <span foreground="gold">done</span>
@on_event LOAD_FINISH spawn @scripts_dir/history.sh
@@ -76,6 +79,9 @@ set authentication_handler = sync_spawn @scripts_dir/auth.py
# Example CONFIG_CHANGED event handler
#@on_event CONFIG_CHANGED print Config changed: %1 = %2
+# Scroll percentage calculation
+@on_event SCROLL_VERT set scroll_message = \@<(function(){var a='%1'.split(' ');var p='--';if(a[2]!=a[1]){p=(a[0]/(a[2]-a[3]));p=Math.round(10000*p)/100;};return p+'%';})()>\@
+
# === Behaviour and appearance ===============================================
set show_status = 1
@@ -121,6 +127,7 @@ set useragent = Uzbl (Webkit @{WEBKIT_MAJOR}.@{WEBKIT_MINOR}.@{WEBKIT_MI
@modmap <Control> <Ctrl>
@modmap <ISO_Left_Tab> <Shift-Tab>
@modmap <space> <Space>
+@modmap <KP_Enter> <Enter>
#modkey_addition <Key1> <Key2> <Result>
@modkey_addition <Shift> <Ctrl> <Meta>
@@ -130,6 +137,7 @@ set useragent = Uzbl (Webkit @{WEBKIT_MAJOR}.@{WEBKIT_MINOR}.@{WEBKIT_MI
#ignore_key <glob>
@ignore_key <ISO_*>
@ignore_key <Shift>
+@ignore_key <Multi_key>
# --- Bind aliases -----------------------------------------------------------
@@ -188,8 +196,12 @@ set ebind = @mode_bind global,-insert
@cbind l = scroll horizontal 20
@cbind <Page_Up> = scroll vertical -100%
@cbind <Page_Down> = scroll vertical 100%
+@cbind <Ctrl>f = scroll vertical 100%
+@cbind <Ctrl>b = scroll vertical -100%
@cbind << = scroll vertical begin
@cbind >> = scroll vertical end
+@cbind <Home> = scroll vertical begin
+@cbind <End> = scroll vertical end
@cbind ^ = scroll horizontal begin
@cbind $ = scroll horizontal end
@cbind <Space> = scroll vertical end
@@ -253,8 +265,12 @@ set ebind = @mode_bind global,-insert
# Yanking & pasting binds
@cbind yu = sh 'echo -n $6 | xclip'
+@cbind yU = sh 'echo -n $8 | xclip' \@SELECTED_URI
@cbind yy = sh 'echo -n $7 | xclip'
+@cbind yY = sh 'echo -n $8 | xclip' \@SELECTED_URI
+# Clone current window
+@cbind c = sh 'uzbl-browser -u $6'
# Go the page from primary selection
@cbind p = sh 'echo "uri `xclip -selection primary -o | sed s/\\\@/%40/g`" > $4'
# Go to the page in clipboard
@@ -265,7 +281,7 @@ set ebind = @mode_bind global,-insert
@bind <Shift-Insert> = sh 'echo "event INJECT_KEYCMD `xclip -o | sed s/\\\@/%40/g`" > $4'
# Bookmark inserting binds
-@cbind <Ctrl>b<tags:>_ = sh 'echo -e "$6 %s" >> $XDG_DATA_HOME/uzbl/bookmarks'
+@cbind <Ctrl>b<tags:>_ = sh 'echo `printf "$6 %s"` >> $XDG_DATA_HOME/uzbl/bookmarks'
# Or use a script to insert a bookmark.
@cbind B = spawn @scripts_dir/insert_bookmark.sh
@@ -279,7 +295,8 @@ set follow_hint_keys = 0123456789
#set follow_hint_keys = qwerty
#set follow_hint_keys = asdfghjkl;
#set follow_hint_keys = thsnd-rcgmvwb/;789aefijkopquxyz234
-@cbind fl* = script @scripts_dir/follow.js '@follow_hint_keys %s'
+@cbind fl* = spawn @scripts_dir/follow.sh "%s"
+@cbind gi = spawn @scripts_dir/go_input.sh
# Form filler binds
# This script allows you to configure (per domain) values to fill in form
@@ -299,7 +316,12 @@ set formfiller = spawn @scripts_dir/formfiller.sh
@cbind gN = event NEW_TAB_NEXT
@cbind go<uri:>_ = event NEW_TAB %s
@cbind gO<uri:>_ = event NEW_TAB_NEXT %s
-@cbind gY = sh 'echo "event NEW_TAB `xclip -selection primary -o | sed s/\\\@/%40/g`" > $4'
+@cbind gy = sh 'echo "event NEW_TAB `xclip -selection primary -o | sed s/\\\@/%40/g`" > $4'
+@cbind gY = sh 'echo "event NEW_TAB_NEXT `xclip -selection primary -o | sed s/\\\@/%40/g`" > $4'
+
+# Clone current tab
+@cbind gd = sh 'echo "event NEW_TAB $6" > $4'
+@cbind gD = sh 'echo "event NEW_TAB_NEXT $6" > $4'
# Closing / resting
@cbind gC = exit
diff --git a/examples/config/cookies b/examples/config/cookies
deleted file mode 100644
index 9b7374a..0000000
--- a/examples/config/cookies
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file demonstrates how one *could* manage his cookies. this file is used by the example cookie handler script.
-# stick to this format.
-# trusted -> always store what we get, send what we have (TODO: by default, or when requested?)
-# deny -> deny storing + sending
-
-# if you don't like to edit this file manually, you could even write a script that adds/removes entries using sed, and call the script from uzbl with a keybind...
-
-
-TRUSTED
-bbs.archlinux.org
-archlinux.org
-linux.com
-
-
-
-
-DENY
-www.icanhascheezburger.com
-
-
-
-# rest -> ask \ No newline at end of file
diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh
index 7375535..606aa62 100755
--- a/examples/data/scripts/download.sh
+++ b/examples/data/scripts/download.sh
@@ -2,8 +2,8 @@
# just an example of how you could handle your downloads
# try some pattern matching on the uri to determine what we should do
-source $UZBL_UTIL_DIR/uzbl-args.sh
-source $UZBL_UTIL_DIR/uzbl-dir.sh
+. $UZBL_UTIL_DIR/uzbl-args.sh
+. $UZBL_UTIL_DIR/uzbl-dir.sh
# Some sites block the default wget --user-agent..
GET="wget --user-agent=Firefox --content-disposition --load-cookies=$UZBL_COOKIE_JAR"
diff --git a/examples/data/scripts/follow.js b/examples/data/scripts/follow.js
index bcceb74..3a18b1b 100644
--- a/examples/data/scripts/follow.js
+++ b/examples/data/scripts/follow.js
@@ -127,12 +127,11 @@ function clickElem(item) {
removeAllHints();
if (item) {
var name = item.tagName;
- if (name == 'A') {
+ if (name == 'BUTTON') {
item.click();
- window.location = item.href;
} else if (name == 'INPUT') {
- var type = item.getAttribute('type').toUpperCase();
- if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
+ var type = item.type.toUpperCase();
+ if (type == 'TEXT' || type == 'SEARCH' || type == 'PASSWORD') {
item.focus();
item.select();
} else {
@@ -166,7 +165,7 @@ function addFormElems() {
for (var f = 0; f < forms.length; f++) {
for (var e = 0; e < forms[f].elements.length; e++) {
var el = forms[f].elements[e];
- if (el && ['INPUT', 'TEXTAREA', 'SELECT'].indexOf(el.tagName) + 1 && isVisible(el) && elementInViewport(el)) {
+ if (el && ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'].indexOf(el.tagName) + 1 && isVisible(el) && elementInViewport(el)) {
res[0].push(el);
}
}
@@ -242,7 +241,7 @@ function followLinks(follow) {
var oldDiv = doc.getElementById(uzbldivid);
var leftover = [[], []];
if (s.length == len && linknr < elems[0].length && linknr >= 0) {
- clickElem(elems[0][linknr]);
+ return clickElem(elems[0][linknr]);
} else {
for (var j = 0; j < elems[0].length; j++) {
var b = true;
diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh
new file mode 100755
index 0000000..ba59575
--- /dev/null
+++ b/examples/data/scripts/follow.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+config=$1;
+shift
+pid=$1;
+shift
+xid=$1;
+shift
+fifo=$1;
+shift
+socket=$1;
+shift
+url=$1;
+shift
+title=$1;
+shift
+
+case $(echo 'script @scripts_dir/follow.js "@{follow_hint_keys} '$1'"' | socat - unix-connect:$socket) in
+ *XXXEMIT_FORM_ACTIVEXXX*) echo 'event FORM_ACTIVE' | socat - unix-connect:$socket ;;
+ *XXXRESET_MODEXXX*) echo 'set mode=' | socat - unix-connect:$socket ;;
+esac
diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh
index 19147a8..b2e61ec 100755
--- a/examples/data/scripts/formfiller.sh
+++ b/examples/data/scripts/formfiller.sh
@@ -43,11 +43,12 @@ DMENU_LINES="3"
DMENU_PROMPT="Choose profile"
DMENU_OPTIONS="vertical resize"
-source $UZBL_UTIL_DIR/dmenu.sh
-source $UZBL_UTIL_DIR/editor.sh
-source $UZBL_UTIL_DIR/uzbl-args.sh
-source $UZBL_UTIL_DIR/uzbl-dir.sh
+. $UZBL_UTIL_DIR/dmenu.sh
+. $UZBL_UTIL_DIR/editor.sh
+. $UZBL_UTIL_DIR/uzbl-args.sh
+. $UZBL_UTIL_DIR/uzbl-dir.sh
+RAND=$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c 1-5)
MODELINE="> vim:ft=formfiller"
[ -d "$(dirname $UZBL_FORMS_DIR)" ] || exit 1
@@ -125,7 +126,7 @@ if [ "$action" = 'load' ]; then
if [ $(cat $UZBL_FORMS_DIR/$domain | grep "!profile" | wc -l) -gt 1 ]; then
menu=$(cat $UZBL_FORMS_DIR/$domain | \
sed -n 's/^!profile=\([^[:blank:]]\+\)/\1/p')
- option=$(echo -e -n "$menu" | $DMENU)
+ option=$(printf "$menu" | $DMENU)
fi
# Remove comments
@@ -174,7 +175,7 @@ elif [ "$action" = "once" ]; then
else
if [ "$action" = 'new' -o "$action" = 'add' ]; then
[ "$action" = 'new' ] && echo "$MODELINE" > $UZBL_FORMS_DIR/$domain
- echo "!profile=NAME_THIS_PROFILE$RANDOM" >> $UZBL_FORMS_DIR/$domain
+ echo "!profile=NAME_THIS_PROFILE$RAND" >> $UZBL_FORMS_DIR/$domain
#
# 2. and 3. line (tr -d and sed) are because, on gmail login for example,
# <input > tag is splited into lines
diff --git a/examples/data/scripts/go_input.js b/examples/data/scripts/go_input.js
new file mode 100644
index 0000000..557671f
--- /dev/null
+++ b/examples/data/scripts/go_input.js
@@ -0,0 +1,27 @@
+var elements = document.querySelectorAll("textarea, input" + [
+ ":not([type='button'])",
+ ":not([type='checkbox'])",
+ ":not([type='hidden'])",
+ ":not([type='image'])",
+ ":not([type='radio'])",
+ ":not([type='reset'])",
+ ":not([type='submit'])"].join(""));
+function gi() {
+ if (elements) {
+ var el, i = 0;
+ while((el = elements[i++])) {
+ var style=getComputedStyle(el, null);
+ if (style.display !== 'none' && style.visibility === 'visible') {
+ if (el.type === "file") {
+ el.click();
+ }
+ else {
+ el.focus();
+ }
+ return "XXXEMIT_FORM_ACTIVEXXX";
+ }
+ }
+ }
+}
+
+gi();
diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh
new file mode 100755
index 0000000..c873dd8
--- /dev/null
+++ b/examples/data/scripts/go_input.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+config=$1;
+shift
+pid=$1;
+shift
+xid=$1;
+shift
+fifo=$1;
+shift
+socket=$1;
+shift
+url=$1;
+shift
+title=$1;
+shift
+
+case $(echo 'script @scripts_dir/go_input.js' | socat - unix-connect:$socket) in
+ *XXXEMIT_FORM_ACTIVEXXX*) echo 'event FORM_ACTIVE' | socat - unix-connect:$socket ;;
+esac
diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh
index 0cd2218..0561fe9 100755
--- a/examples/data/scripts/history.sh
+++ b/examples/data/scripts/history.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-source $UZBL_UTIL_DIR/uzbl-dir.sh
+. $UZBL_UTIL_DIR/uzbl-dir.sh
[ -w "$UZBL_HISTORY_FILE" ] || [ ! -a "$UZBL_HISTORY_FILE" ] || exit 1
diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh
index 9303b85..d99ff31 100755
--- a/examples/data/scripts/insert_bookmark.sh
+++ b/examples/data/scripts/insert_bookmark.sh
@@ -1,12 +1,12 @@
#!/bin/sh
-source $UZBL_UTIL_DIR/uzbl-args.sh
-source $UZBL_UTIL_DIR/uzbl-dir.sh
+. "$UZBL_UTIL_DIR"/uzbl-args.sh
+. "$UZBL_UTIL_DIR"/uzbl-dir.sh
[ -d "$UZBL_DATA_DIR" ] || exit 1
[ -w "$UZBL_BOOKMARKS_FILE" ] || [ ! -a "$UZBL_BOOKMARKS_FILE" ] || exit 1
-which zenity &>/dev/null || exit 2
+which zenity 2>&1 >/dev/null || exit 2
tags=$(zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URL:")
exitstatus=$?
diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh
index 967d7ad..19d04e8 100755
--- a/examples/data/scripts/instance-select-wmii.sh
+++ b/examples/data/scripts/instance-select-wmii.sh
@@ -13,7 +13,7 @@
DMENU_SCHEME="wmii"
-source $UZBL_UTIL_DIR/dmenu.sh
+. $UZBL_UTIL_DIR/dmenu.sh
case "$1" in
"list" )
@@ -23,7 +23,7 @@ case "$1" in
label=$(wmiir read /client/$i/label)
list="$list$i : $label\n"
done
- window=$(echo -e "$list" | $DMENU | cut -d ' ' -f1)
+ window=$(printf "$list\n" | $DMENU | cut -d ' ' -f1)
wmiir xwrite /tag/sel/ctl "select client $window"
;;
"next" )
diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh
index ed1e2e8..9346526 100755
--- a/examples/data/scripts/load_url_from_bookmarks.sh
+++ b/examples/data/scripts/load_url_from_bookmarks.sh
@@ -5,9 +5,9 @@
DMENU_SCHEME="bookmarks"
DMENU_OPTIONS="xmms vertical resize"
-source "$UZBL_UTIL_DIR"/dmenu.sh
-source "$UZBL_UTIL_DIR"/uzbl-args.sh
-source "$UZBL_UTIL_DIR"/uzbl-dir.sh
+. "$UZBL_UTIL_DIR"/dmenu.sh
+. "$UZBL_UTIL_DIR"/uzbl-args.sh
+. "$UZBL_UTIL_DIR"/uzbl-dir.sh
[ -r "$UZBL_BOOKMARKS_FILE" ] || exit 1
diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh
index 8582bc3..4499e7f 100755
--- a/examples/data/scripts/load_url_from_history.sh
+++ b/examples/data/scripts/load_url_from_history.sh
@@ -3,9 +3,9 @@
DMENU_SCHEME="history"
DMENU_OPTIONS="xmms vertical resize"
-source "$UZBL_UTIL_DIR"/dmenu.sh
-source "$UZBL_UTIL_DIR"/uzbl-args.sh
-source "$UZBL_UTIL_DIR"/uzbl-dir.sh
+. "$UZBL_UTIL_DIR"/dmenu.sh
+. "$UZBL_UTIL_DIR"/uzbl-args.sh
+. "$UZBL_UTIL_DIR"/uzbl-dir.sh
[ -r "$UZBL_HISTORY_FILE" ] || exit 1
diff --git a/examples/data/scripts/userscript.sh b/examples/data/scripts/userscript.sh
new file mode 100755
index 0000000..33a24ae
--- /dev/null
+++ b/examples/data/scripts/userscript.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+if [ $# = "3" ]
+then
+ fifo="$1"
+ url="$2"
+ SCRIPT="$3"
+else
+ fifo="$4"
+ url="$6"
+ SCRIPT="$8"
+fi
+
+# Extract metadata chunk
+META="`sed -ne '/^\s*\/\/\s*==UserScript==\s*$/,/^\s*\/\/\s*==\/UserScript==\s*$/p' "$SCRIPT"`"
+SHOULD_RUN=false # Assume this script will not be included
+# Loop over all include rules
+for INCLUDE in `echo "$META" | grep "^\s*\/\/\s*@include"`; do
+ # Munge into grep pattern
+ INCLUDE="`echo "$INCLUDE" | sed -e 's/^\s*\/\/\s*@include\s*//' -e 's/\./\\\\./g' -e 's/\*/.*/g' -e 's/[\r\n]//g'`"
+ if echo "$url" | grep -x "$INCLUDE"; then
+ SHOULD_RUN=true
+ break
+ fi
+done
+
+# Loop over all exclude rules
+for EXCLUDE in `echo "$META" | grep "^\s*\/\/\s*@exclude"`; do
+ # Munge into grep pattern
+ EXCLUDE="`echo "$EXCLUDE" | sed -e 's/^\s*\/\/\s*@exclude\s*//' -e 's/\./\\\\./g' -e 's/\*/.*/g' -e 's/[\r\n]//g'`"
+ if echo "$url" | grep -x "$EXCLUDE"; then
+ SHOULD_RUN=false
+ break
+ fi
+done
+
+# Run the script
+if [ $SHOULD_RUN = true ]; then
+ echo "script '$SCRIPT'" > "$fifo"
+fi
diff --git a/examples/data/scripts/userscripts.sh b/examples/data/scripts/userscripts.sh
new file mode 100755
index 0000000..8896224
--- /dev/null
+++ b/examples/data/scripts/userscripts.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+scripts_dir="$XDG_DATA_HOME/uzbl/userscripts"
+
+for SCRIPT in $(grep -rlx "\s*//\s*==UserScript==\s*" "$scripts_dir")
+do
+ $XDG_DATA_HOME/uzbl/scripts/userscript.sh "$4" "$6" "$SCRIPT"
+done
diff --git a/examples/data/scripts/util/dmenu.sh b/examples/data/scripts/util/dmenu.sh
index 757e5cd..f789178 100644
--- a/examples/data/scripts/util/dmenu.sh
+++ b/examples/data/scripts/util/dmenu.sh
@@ -12,7 +12,7 @@ case "$DMENU_SCHEME" in
# Formfiller
"formfiller" )
NB="#0f0f0f"
- NF="4e7093"
+ NF="#4e7093"
SB="#003d7c"
SF="#3a9bff"
;;
diff --git a/examples/data/scripts/uzbl-cookie-daemon b/examples/data/scripts/uzbl-cookie-daemon
index ed88de4..0b9bef9 100755
--- a/examples/data/scripts/uzbl-cookie-daemon
+++ b/examples/data/scripts/uzbl-cookie-daemon
@@ -436,18 +436,26 @@ class CookieMonster:
daemon_timeout = config['daemon_timeout']
echo("listening on %r" % config['cookie_socket'])
+ connections = []
+
while self._running:
# This line tells the socket how many pending incoming connections
# to enqueue at once. Raising this number may or may not increase
# performance.
self.server_socket.listen(1)
- if bool(select.select([self.server_socket], [], [], 1)[0]):
- client_socket, _ = self.server_socket.accept()
- self.handle_request(client_socket)
+ r, w, x = select.select([self.server_socket]+connections, [], [], 1)
+
+ for socket in r:
+ if self.server_socket == socket:
+ client_socket, _ = socket.accept()
+ connections.append(client_socket)
+ else:
+ if not self.handle_request(socket):
+ # connection was closed, forget about the client socket
+ connections.remove(socket)
+
self.last_request = time.time()
- client_socket.close()
- continue
if daemon_timeout:
# Checks if the daemon has been idling for too long.
@@ -462,7 +470,7 @@ class CookieMonster:
# Receive cookie request from client.
data = client_socket.recv(8192)
if not data:
- return
+ return False
# Cookie argument list in packet is null separated.
argv = data.split("\0")
@@ -471,17 +479,17 @@ class CookieMonster:
# Catch the EXIT command sent to kill running daemons.
if action == "EXIT":
self._running = False
- return
+ return False
# Catch whitelist RELOAD command.
elif action == "RELOAD":
self.reload_whitelist()
- return
+ return True
# Return if command unknown.
elif action not in ['GET', 'PUT']:
error("unknown command %r." % argv)
- return
+ return True
# Determine whether or not to print cookie data to terminal.
print_cookie = (config['verbose'] and not config['daemon_mode'])
@@ -499,13 +507,14 @@ class CookieMonster:
req = urllib2.Request(uri)
if action == "GET":
- self.jar.add_cookie_header(req)
- if req.has_header('Cookie'):
- cookie = req.get_header('Cookie')
- client_socket.send(cookie)
- if print_cookie:
- print cookie
-
+ self.jar._policy._now = self._now = int(time.time())
+ cookies = self.jar._cookies_for_request(req)
+ attrs = self.jar._cookie_attrs(cookies)
+ if attrs:
+ cookie = "; ".join(attrs)
+ client_socket.send(cookie)
+ if print_cookie:
+ print cookie
else:
client_socket.send("\0")
@@ -515,10 +524,13 @@ class CookieMonster:
print cookie
self.put_cookie(req, cookie)
+ client_socket.send("\0")
if print_cookie:
print
+ return True
+
def put_cookie(self, req, cookie=None):
'''Put a cookie in the cookie jar.'''
diff --git a/examples/data/scripts/uzbl-event-manager b/examples/data/scripts/uzbl-event-manager
index ab13fbb..8ad3af7 100755
--- a/examples/data/scripts/uzbl-event-manager
+++ b/examples/data/scripts/uzbl-event-manager
@@ -825,7 +825,7 @@ if __name__ == "__main__":
add('-n', '--no-daemon',
dest='daemon_mode', action='store_false', default=True,
- help='daemonize the process')
+ help='do not daemonize the process')
add('-a', '--auto-close',
dest='auto_close', action='store_true', default=False,
diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed
index 5bf802a..9e5d715 100755
--- a/examples/data/scripts/uzbl-tabbed
+++ b/examples/data/scripts/uzbl-tabbed
@@ -158,7 +158,7 @@ import atexit
import types
from gobject import io_add_watch, source_remove, timeout_add, IO_IN, IO_HUP
-from signal import signal, SIGTERM, SIGINT, SIGCHLD
+from signal import signal, SIGTERM, SIGINT
from optparse import OptionParser, OptionGroup
from traceback import print_exc
@@ -536,7 +536,6 @@ class UzblTabbed:
self._timers = {}
self._buffer = ""
self._killed = False
- self._processes = []
# A list of the recently closed tabs
self._closed = []
@@ -656,9 +655,6 @@ class UzblTabbed:
# Catch keyboard interrupts
signal(SIGINT, lambda signum, stack_frame: self.terminate(SIGINT))
- # Catch SIGCHLD
- signal(SIGCHLD, lambda signum, stack_frame: self.join_children())
-
try:
gtk.main()
@@ -678,15 +674,6 @@ class UzblTabbed:
raise
-
- def join_children(self):
- '''Find and remove zombie children processes.'''
-
- for p in self._processes:
- if p.poll() is not None:
- self._processes.remove(p)
-
-
def terminate(self, termsig=None):
'''Handle termination signals and exit safely and cleanly.'''
@@ -847,6 +834,8 @@ class UzblTabbed:
# Commands ( [] = optional, {} = required )
# new [uri]
# open new tab and head to optional uri.
+ # newbg [uri]
+ # open a new tab in the background
# close [tab-num]
# close current tab or close via tab id.
# next [n-tabs]
@@ -875,6 +864,12 @@ class UzblTabbed:
else:
self.new_tab()
+ elif cmd[0] == "newbg":
+ if len(cmd) == 2:
+ self.new_tab(cmd[1], switch=False)
+ else:
+ self.new_tab(switch=False)
+
elif cmd[0] == "newfromclip":
uri = subprocess.Popen(['xclip','-selection','clipboard','-o'],\
stdout=subprocess.PIPE).communicate()[0]
@@ -1009,7 +1004,7 @@ class UzblTabbed:
cmd = ['uzbl-browser', '-n', name, '-s', str(sid),
'--connect-socket', self.socket_path, '--uri', uri]
- self._processes += [subprocess.Popen(cmd)] # TODO: do i need close_fds=True ?
+ gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH)
uzbl = UzblInstance(self, tab, name, uri, title, switch)
SocketClient.instances_queue[name] = uzbl
diff --git a/examples/uzbl-cookie-manager.c b/examples/uzbl-cookie-manager.c
new file mode 100644
index 0000000..70addf3
--- /dev/null
+++ b/examples/uzbl-cookie-manager.c
@@ -0,0 +1,381 @@
+#define _POSIX_SOURCE
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/unistd.h>
+
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include <libsoup/soup-cookie.h>
+#include <libsoup/soup-cookie-jar-text.h>
+#include <libsoup/soup-uri.h>
+
+#include "../src/util.h"
+
+extern const XDG_Var XDG[];
+
+int verbose = 0;
+
+#define SOCK_BACKLOG 10
+#define MAX_COOKIE_LENGTH 4096
+
+char cookie_buffer[MAX_COOKIE_LENGTH];
+
+int setup_socket(const char *cookied_socket_path) {
+ /* delete the cookie socket if it was left behind on a previous run */
+ unlink(cookied_socket_path);
+
+ int socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+
+ if(socket_fd < 0) {
+ fprintf(stderr, "socket failed (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ struct sockaddr_un sa;
+ sa.sun_family = AF_UNIX;
+ strcpy(sa.sun_path, cookied_socket_path);
+
+ if(bind(socket_fd, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
+ fprintf(stderr, "bind failed (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ if(listen(socket_fd, SOCK_BACKLOG) < 0) {
+ fprintf(stderr, "listen failed (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ return socket_fd;
+}
+
+const char *whitelist_path = NULL;
+GPtrArray *whitelisted_hosts = NULL;
+time_t whitelist_update_time = 0;
+
+void whitelist_line_cb(const gchar* line, void *user_data) {
+ (void) user_data;
+
+ gchar *norm_host;
+
+ const gchar *p = line;
+ while(isspace(*p))
+ p++;
+
+ if(p[0] == '#' || !p[0]) /* ignore comments and blank lines */
+ return;
+
+ if(p[0] == '.')
+ norm_host = g_strdup(p);
+ else
+ norm_host = g_strconcat(".", p, NULL);
+
+ g_ptr_array_add(whitelisted_hosts, g_strchomp(norm_host));
+}
+
+gboolean load_whitelist(const char *whitelist_path) {
+ if(!file_exists(whitelist_path))
+ return FALSE;
+
+ /* check if the whitelist file was updated */
+ struct stat f;
+ if(stat(whitelist_path, &f) < 0)
+ return FALSE;
+
+ if(whitelisted_hosts == NULL)
+ whitelisted_hosts = g_ptr_array_new();
+
+ if(f.st_mtime > whitelist_update_time) {
+ /* the file was updated, reload the whitelist */
+ if(verbose) puts("reloading whitelist");
+ while(whitelisted_hosts->len > 0) {
+ g_free(g_ptr_array_index(whitelisted_hosts, 0));
+ g_ptr_array_remove_index_fast(whitelisted_hosts, 0);
+ }
+ for_each_line_in_file(whitelist_path, whitelist_line_cb, NULL);
+ whitelist_update_time = f.st_mtime;
+ }
+
+ return TRUE;
+}
+
+gboolean should_save_cookie(const char *host) {
+ if(!load_whitelist(whitelist_path))
+ return TRUE; /* some error with the file, assume no whitelist */
+
+ /* we normalize the hostname so it has a . in front like the whitelist entries */
+ gchar *test_host = (host[0] == '.') ? g_strdup(host) : g_strconcat(".", host, NULL);
+ int hl = strlen(test_host);
+
+ /* test against each entry in the whitelist */
+ gboolean result = FALSE;
+ guint i;
+ for(i = 0; i < whitelisted_hosts->len; i++) {
+ /* a match means the host ends with (or is equal to) the whitelist entry */
+ const gchar *entry = g_ptr_array_index(whitelisted_hosts, i);
+ int el = strlen(entry);
+ result = (el <= hl) && !strcmp(test_host + (hl - el), entry);
+
+ if(result)
+ break;
+ }
+
+ g_free(test_host);
+
+ return result;
+}
+
+void handle_request(SoupCookieJar *j, const char *buff, int len, int fd) {
+ const char *command = buff;
+
+ const char *scheme = command + strlen(command) + 1;
+ if((scheme - buff) > len) {
+ fprintf(stderr, "got malformed or partial request\n");
+ return;
+ }
+
+ const char *host = scheme + strlen(scheme) + 1;
+ if((host - buff) > len) {
+ fprintf(stderr, "got malformed or partial request\n");
+ return;
+ }
+
+ const char *path = host + strlen(host) + 1;
+ if((path - buff) > len) {
+ fprintf(stderr, "got malformed or partial request\n");
+ return;
+ }
+
+ /* glue the parts back together into a SoupURI */
+ char *u = g_strconcat(scheme, "://", host, path, NULL);
+ if(verbose) printf("%s %s\n", command, u);
+ SoupURI *uri = soup_uri_new(u);
+ g_free(u);
+
+ if(!strcmp(command, "GET")) {
+ char *result = soup_cookie_jar_get_cookies(j, uri, TRUE);
+ if(result) {
+ if(verbose) puts(result);
+ if(write(fd, result, strlen(result)+1) < 0)
+ fprintf(stderr, "write failed (%s)", strerror(errno));
+
+ g_free(result);
+ } else {
+ if(verbose) puts("-");
+ if(write(fd, "", 1) < 0)
+ fprintf(stderr, "write failed (%s)", strerror(errno));
+ }
+ } else if(!strcmp(command, "PUT")) {
+ const char *name_and_val = path + strlen(path) + 1;
+ if((name_and_val - buff) > len) {
+ fprintf(stderr, "got malformed or partial request\n");
+ return;
+ }
+
+ if(verbose) puts(name_and_val);
+
+ if(should_save_cookie(host)) {
+ char *eql = strchr(name_and_val, '=');
+ eql[0] = 0;
+
+ const char *name = name_and_val;
+ const char *value = eql + 1;
+
+ SoupCookie *cookie = soup_cookie_new(name, value, host, path, SOUP_COOKIE_MAX_AGE_ONE_YEAR);
+
+ soup_cookie_jar_add_cookie(j, cookie);
+ } else if(verbose)
+ puts("no, blacklisted.");
+
+ if(write(fd, "", 1) < 0)
+ fprintf(stderr, "write failed (%s)", strerror(errno));
+ }
+
+ soup_uri_free(uri);
+}
+
+void
+wait_for_things_to_happen_and_then_do_things(SoupCookieJar* j, int cookie_socket) {
+ GArray *connections = g_array_new (FALSE, FALSE, sizeof (int));
+
+ while(1) {
+ unsigned int i;
+ int r;
+ fd_set fs;
+
+ int maxfd = cookie_socket;
+ FD_ZERO(&fs);
+ FD_SET(maxfd, &fs);
+
+ for(i = 0; i < connections->len; i++) {
+ int fd = g_array_index(connections, int, i);
+ if(fd > maxfd) maxfd = fd;
+ FD_SET(fd, &fs);
+ }
+
+ r = select(maxfd+1, &fs, NULL, NULL, NULL);
+ if(r < 0) {
+ fprintf(stderr, "select failed (%s)\n", strerror(errno));
+ continue;
+ }
+
+ if(FD_ISSET(cookie_socket, &fs)) {
+ /* handle new connection */
+ int fd = accept(cookie_socket, NULL, NULL);
+ g_array_append_val(connections, fd);
+ if(verbose) puts("got connection.");
+ }
+
+ for(i = 0; i < connections->len; i++) {
+ /* handle activity on a connection */
+ int fd = g_array_index(connections, int, i);
+ if(FD_ISSET(fd, &fs)) {
+ r = read(fd, cookie_buffer, MAX_COOKIE_LENGTH);
+ if(r < 0) {
+ fprintf(stderr, "read failed (%s)\n", strerror(errno));
+ continue;
+ } else if(r == 0) {
+ if(verbose) puts("client hung up.");
+ g_array_remove_index(connections, i);
+ i--; /* other elements in the array are moved down to fill the gap */
+ continue;
+ }
+ cookie_buffer[r] = 0;
+
+ handle_request(j, cookie_buffer, r, fd);
+ }
+ }
+ }
+}
+
+void usage(const char *progname) {
+ printf("%s [-s socket-path] [-f cookies.txt] [-w whitelist-file] [-n] [-v]\n", progname);
+ puts("\t-n\tdon't daemonise the process");
+ puts("\t-v\tbe verbose");
+}
+
+void daemonise() {
+ int r = fork();
+
+ if(r < 0) {
+ fprintf(stderr, "fork failed (%s)", strerror(errno));
+ exit(1);
+ } else if (r > 0) {
+ /* this is the parent, which has done its job */
+ exit(0);
+ }
+
+ if(setsid() < 0) {
+ fprintf(stderr, "setsid failed (%s)", strerror(errno));
+ exit(1);
+ }
+}
+
+const char *pid_file_path = NULL;
+const char *cookied_socket_path = NULL;
+
+void cleanup_after_signal(int signal) {
+ (void) signal;
+ unlink(pid_file_path);
+ unlink(cookied_socket_path);
+ exit(0);
+}
+
+int main(int argc, char *argv[]) {
+ int i;
+
+ const char *cookies_txt_path = NULL;
+ gboolean foreground = FALSE;
+
+ for(i = 1; i < argc && argv[i][0] == '-'; i++) {
+ switch(argv[i][1]) {
+ case 's':
+ cookied_socket_path = argv[++i];
+ break;
+ case 'f':
+ cookies_txt_path = argv[++i];
+ break;
+ case 'w':
+ whitelist_path = argv[++i];
+ break;
+ case 'n':
+ foreground = TRUE;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ if(!foreground)
+ daemonise();
+
+ if(!cookies_txt_path)
+ cookies_txt_path = g_strconcat(get_xdg_var(XDG[1]), "/uzbl/cookies.txt", NULL);
+
+ if(!cookied_socket_path)
+ cookied_socket_path = g_strconcat(get_xdg_var(XDG[2]), "/uzbl/cookie_daemon_socket", NULL);
+
+ if(!whitelist_path)
+ whitelist_path = g_strconcat(get_xdg_var(XDG[0]), "/uzbl/cookie_whitelist", NULL);
+
+ /* write out and lock the pid file.
+ * this ensures that only one uzbl-cookie-manager is running per-socket.
+ * (we should probably also lock the cookies.txt to prevent accidents...) */
+ pid_file_path = g_strconcat(cookied_socket_path, ".pid", NULL);
+ int lockfd = open(pid_file_path, O_RDWR|O_CREAT, 0600);
+ if(lockfd < 0) {
+ fprintf(stderr, "couldn't open pid file %s (%s)\n", pid_file_path, strerror(errno));
+ return 1;
+ }
+
+ if(flock(lockfd, LOCK_EX|LOCK_NB) < 0) {
+ fprintf(stderr, "couldn't lock pid file %s (%s)\n", pid_file_path, strerror(errno));
+ fprintf(stderr, "uzbl-cookie-manager is probably already running\n");
+ return 1;
+ }
+
+ gchar* pids = g_strdup_printf("%d\n", getpid());
+ write(lockfd, pids, strlen(pids));
+ g_free(pids);
+
+ struct sigaction sa;
+ sa.sa_handler = cleanup_after_signal;
+ if(sigaction(SIGINT, &sa, NULL) || sigaction(SIGTERM, &sa, NULL)) {
+ fprintf(stderr, "sigaction failed (%s)\n", strerror(errno));
+ return 1;
+ }
+
+ if(!foreground) {
+ /* close STDIO */
+ close(0);
+ close(1);
+ close(2);
+ }
+
+ g_type_init();
+
+ SoupCookieJar *j = soup_cookie_jar_text_new(cookies_txt_path, FALSE);
+
+ int cookie_socket = setup_socket(cookied_socket_path);
+ if(cookie_socket < 0)
+ return 1;
+
+ wait_for_things_to_happen_and_then_do_things(j, cookie_socket);
+
+ return 0;
+}