aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Dieter Plaetinck <dieter@plaetinck.be>2010-01-24 16:21:11 +0100
committerGravatar Dieter Plaetinck <dieter@plaetinck.be>2010-01-24 16:21:11 +0100
commit0cd3f65d05e7d966ff66d2aa97908332eb2d6c06 (patch)
treedfaa9b7d376cba31436e72655df018d128337187
parentc3c4d481079f2a24ea16cd49b785b6f358a28fc9 (diff)
parent67c68ee643eaef16277fa614d873dd558bfdbd04 (diff)
merge in pawelz' authentication handler + some other fixes
-rw-r--r--AUTHORS2
-rw-r--r--Makefile8
-rw-r--r--README43
-rw-r--r--docs/INSTALL2
-rw-r--r--examples/config/config16
-rw-r--r--examples/data/scripts/auth.py53
-rwxr-xr-xexamples/data/scripts/uzbl-event-manager8
-rw-r--r--src/callbacks.c11
-rw-r--r--src/callbacks.h3
-rw-r--r--src/uzbl-core.c65
-rw-r--r--src/uzbl-core.h9
-rw-r--r--tests/test-expand.c6
12 files changed, 202 insertions, 24 deletions
diff --git a/AUTHORS b/AUTHORS
index 165eae0..8e1602c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -50,7 +50,7 @@ In alphabetical order:
Moritz Lenz - small doc fix
Nicolas Pouillard - refactored scroll command
Olivier Schwander - auto file:// prepend
- Paweł Zuzelski (pawelz) - download handler proxy patch
+ Paweł Zuzelski (pawelz) - http auth handler, misc patches
Peter Suschlik - backwards searching
Přemysl Hrubý (anydot) <email is dfenze AT gmail.com> - several C contributions and cleanups
Robert Manea (robm) <email is rob DOT manea AT gmail DOT com> - C code all over the place
diff --git a/Makefile b/Makefile
index 626d21e..eeb2622 100644
--- a/Makefile
+++ b/Makefile
@@ -34,9 +34,6 @@ uzbl-core: ${TOBJ} # why doesn't ${OBJ} work?
@echo LINKING object files
@${CC} -o $@ ${OBJ} ${LDFLAGS}
@echo ... done.
- @echo Stripping binary
- @strip $@
- @echo ... done.
uzbl-browser: uzbl-core
@@ -92,6 +89,11 @@ clean:
cd ./tests/; $(MAKE) clean
rm -rf ./sandbox/{examples,usr}/
+strip:
+ @echo Stripping binary
+ @strip uzbl-core
+ @echo ... done.
+
install: install-uzbl-core install-uzbl-browser install-uzbl-tabbed
install-uzbl-core: all
diff --git a/README b/README
index 0a22b55..56e5842 100644
--- a/README
+++ b/README
@@ -513,9 +513,52 @@ The script specific arguments are:
- `$8 URI` of the page to be navigated to
+* authentication handler:
+
+ $8 authentication zone unique identifier
+ $9 domain part of URL that requests authentication
+ $10 authentication realm
+ $11 FALSE if this is the first attempt to authenticate, TRUE otherwise
+
Custom, userdefined scripts (`spawn foo bar`) get first the arguments as
specified in the config and then the above 7 are added at the end.
+### HTTP/BASIC AUTHENTICATION ###
+
+If authentication_handler variable is not set, http authentication is handled
+internally by WebKit. If you want to use custom script for http authentication,
+set authentication_handler. For example:
+
+ set authentication_handler = sync_spawn /patch/to/your/script
+
+Script will be executed on each authentication request.
+It will receive four auth-related parameters:
+
+ $8 authentication zone unique identifier (may be used as 'key')
+ $9 domain part of URL that requests authentication
+ $10 authentication realm
+ $11 FALSE if this is the first attempt to authenticate, TRUE otherwise
+
+Script is expected to print exactly two lines of text on stdout (that means
+its output must contain exactly two '\n' bytes).
+The first line contains username, the second one - password.
+If authentication fails, script will be executed again (with $11 = TRUE).
+Non-interactive scripts should handle this case and do not try to
+authenticate again to avoid loops. If number of '\n' characters in scripts
+output does not equal 2, authentication will fail.
+That means 401 error will be displayed and uzbl won't try to authenticate anymore.
+
+The simplest example of authentication handler script is:
+
+#!/bin/sh
+[ "$11" == "TRUE ] && exit
+echo alice
+echo wonderland
+
+This script tries to authenticate as user alice with password wonderland once
+and never retries authentication.
+See examples for more sofisticated, interactive authentication handler.
+
### JAVASCRIPT HELPER OBJECT DISABLED BECAUSE OF SECURITY LEAK
JavaScript code run from `uzbl` is given a special object in the global
diff --git a/docs/INSTALL b/docs/INSTALL
index 711ea97..c795502 100644
--- a/docs/INSTALL
+++ b/docs/INSTALL
@@ -9,8 +9,8 @@ From source
You can pull the code from git or get a tagged tarball.
$ git clone git://github.com/Dieterbe/uzbl.git
- [ $ git checkout origin/experimental ] # optional. see below
$ cd uzbl
+ [ $ git checkout origin/experimental ] # optional. see below
$ make
$ sudo make install
If you want to remove uzbl again, you can issue:
diff --git a/examples/config/config b/examples/config/config
index d58d0a5..929397d 100644
--- a/examples/config/config
+++ b/examples/config/config
@@ -35,7 +35,7 @@ set shell_cmd = sh -c
set scripts_dir = $XDG_DATA_HOME/uzbl:@prefix/share/uzbl/examples/data:scripts
# Javascipt helpers.
-set jsh = js var run=Uzbl.run; function get(k){return run("print \\\@"+k)}; function set(k, v) {run("set "+k+" = "+v)};
+#set jsh = js var run=Uzbl.run; function get(k){return run("print \\\@"+k)}; function set(k, v) {run("set "+k+" = "+v)};
# === Handlers ===============================================================
@@ -45,6 +45,7 @@ set jsh = js var run=Uzbl.run; function get(k){return run("print \\\@"+k)}; func
# support events that can wait for a response from a script.
set cookie_handler = talk_to_socket $XDG_CACHE_HOME/uzbl/cookie_daemon_socket
set scheme_handler = sync_spawn @scripts_dir/scheme.py
+set authentication_handler = sync_spawn @scripts_dir/auth.py
# Open in the same window.
#set new_window = sh 'echo uri "$8" > $4'
@@ -71,7 +72,7 @@ set new_window = sh 'uzbl-browser -u $8'
# Generate a FORM_ACTIVE event if an editable
# element on the loaded site has initial focus
-@on_event LOAD_FINISH js if(document.activeElement.type == 'text') {Uzbl.run("event FORM_ACTIVE");}
+#@on_event LOAD_FINISH js if(document.activeElement.type == 'text') {Uzbl.run("event FORM_ACTIVE");}
# Switch to insert mode if a (editable) html form is clicked
@on_event FORM_ACTIVE @set_mode insert
@@ -189,12 +190,8 @@ set ebind = @mode_bind global,-insert
# === Mouse bindings =========================================================
-# Middle click
-# if clicked on a link open the link in a new uzbl window
-# otherwise open the selection in the current window
-set load_from_xclip = sh 'echo "uri $(xclip -o)" > $4'
-set open_new_window = sh 'uzbl-browser -u \@SELECTED_URI'
-@bind <Button2> = @jsh if(get("SELECTED_URI")) { run("\@open_new_window"); } else { run("\\\@load_from_xclip"); }
+# Middle click open in new window
+@bind <Button2> = sh 'uzbl-browser -u \@SELECTED_URI'
# === Keyboard bindings ======================================================
@@ -276,7 +273,8 @@ set toggle_cmd_ins = @toggle_modes command insert
@cbind gh = uri http://www.uzbl.org
# --- Yanking & pasting binds ---
-@cbind y<Yank (t)itle or (u)rl:>* = @jsh if('%s' == 'u') { run("sh 'echo -n $6 | xclip'"); } else if('%s' == 't') { run("sh 'echo -n $7 | xclip'"); }; run('event SET_KEYCMD');
+@cbind yu = sh 'echo -n $6 | xclip'
+@cbind yy = sh 'echo -n $7 | xclip'
# Go the page from primary selection
@cbind p = sh 'echo "uri `xclip -selection primary -o`" > $4'
diff --git a/examples/data/scripts/auth.py b/examples/data/scripts/auth.py
new file mode 100644
index 0000000..4feb90b
--- /dev/null
+++ b/examples/data/scripts/auth.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+import gtk
+import sys
+
+def responseToDialog(entry, dialog, response):
+ dialog.response(response)
+
+def getText(authInfo, authHost, authRealm):
+ dialog = gtk.MessageDialog(
+ None,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_QUESTION,
+ gtk.BUTTONS_OK_CANCEL,
+ None)
+ dialog.set_markup('%s at %s' % (authRealm, authHost))
+
+ login = gtk.Entry()
+ password = gtk.Entry()
+ password.set_visibility(False)
+
+ login.connect("activate", responseToDialog, dialog, gtk.RESPONSE_OK)
+ password.connect("activate", responseToDialog, dialog, gtk.RESPONSE_OK)
+
+ hbox = gtk.HBox();
+
+ vbox_entries = gtk.VBox();
+ vbox_labels = gtk.VBox();
+
+ vbox_labels.pack_start(gtk.Label("Login:"), False, 5, 5)
+ vbox_labels.pack_end(gtk.Label("Password:"), False, 5, 5)
+
+ vbox_entries.pack_start(login)
+ vbox_entries.pack_end(password)
+
+ dialog.format_secondary_markup("Please enter username and password:")
+ hbox.pack_start(vbox_labels, True, True, 0)
+ hbox.pack_end(vbox_entries, True, True, 0)
+
+ dialog.vbox.pack_start(hbox)
+ dialog.show_all()
+ rv = dialog.run()
+
+ output = login.get_text() + "\n" + password.get_text()
+ dialog.destroy()
+ return rv, output
+
+if __name__ == '__main__':
+ rv, output = getText(sys.argv[8], sys.argv[9], sys.argv[10])
+ if (rv == gtk.RESPONSE_OK):
+ print output;
+ else:
+ exit(1)
diff --git a/examples/data/scripts/uzbl-event-manager b/examples/data/scripts/uzbl-event-manager
index 99b215a..a92485f 100755
--- a/examples/data/scripts/uzbl-event-manager
+++ b/examples/data/scripts/uzbl-event-manager
@@ -295,7 +295,7 @@ def parse_msg(uzbl, msg):
cmd = FINDSPACES.split(msg, 3)
if not cmd or cmd[0] != 'EVENT':
# Not an event message.
- print '---', msg
+ print '---', msg.encode('utf-8')
return
while len(cmd) < 4:
@@ -374,11 +374,11 @@ class UzblInstance(object):
msg = msg.strip()
if self.client_socket:
- print '%s<-- %s' % (' ' * self.depth, msg)
+ print (u'%s<-- %s' % (' ' * self.depth, msg)).encode('utf-8')
self.client_socket.send(("%s\n" % msg).encode('utf-8'))
else:
- print '%s!-- %s' % (' ' * self.depth, msg)
+ print (u'%s!-- %s' % (' ' * self.depth, msg)).encode('utf-8')
def export(self, name, function):
@@ -466,7 +466,7 @@ class UzblInstance(object):
elems = [event,]
if args: elems.append(unicode(args))
if kargs: elems.append(unicode(kargs))
- print "%s--> %s" % (' ' * self.depth, ' '.join(elems))
+ print (u'%s--> %s' % (' ' * self.depth, ' '.join(elems))).encode('utf-8')
if event == "INSTANCE_START" and args:
self.pid = int(args[0])
diff --git a/src/callbacks.c b/src/callbacks.c
index 9130f5f..80846e3 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -27,6 +27,17 @@ set_proxy_url() {
}
void
+set_authentication_handler() {
+ if (uzbl.behave.authentication_handler)
+ soup_session_remove_feature_by_type
+ (uzbl.net.soup_session, (GType) WEBKIT_TYPE_SOUP_AUTH_DIALOG);
+ else
+ soup_session_add_feature_by_type
+ (uzbl.net.soup_session, (GType) WEBKIT_TYPE_SOUP_AUTH_DIALOG);
+ return;
+}
+
+void
set_icon() {
if(file_exists(uzbl.gui.icon)) {
if (uzbl.gui.main_window)
diff --git a/src/callbacks.h b/src/callbacks.h
index 882ffa4..242c510 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -13,6 +13,9 @@ void
set_proxy_url();
void
+set_authentication_handler();
+
+void
set_icon();
void
diff --git a/src/uzbl-core.c b/src/uzbl-core.c
index da61093..1558882 100644
--- a/src/uzbl-core.c
+++ b/src/uzbl-core.c
@@ -101,6 +101,7 @@ const struct var_name_to_ptr_t {
{ "forward_keys", PTR_V_INT(uzbl.behave.forward_keys, 1, NULL)},
{ "download_handler", PTR_V_STR(uzbl.behave.download_handler, 1, NULL)},
{ "cookie_handler", PTR_V_STR(uzbl.behave.cookie_handler, 1, NULL)},
+ { "authentication_handler", PTR_V_STR(uzbl.behave.authentication_handler, 1, set_authentication_handler)},
{ "new_window", PTR_V_STR(uzbl.behave.new_window, 1, NULL)},
{ "scheme_handler", PTR_V_STR(uzbl.behave.scheme_handler, 1, NULL)},
{ "fifo_dir", PTR_V_STR(uzbl.behave.fifo_dir, 1, cmd_fifo_dir)},
@@ -2317,6 +2318,57 @@ settings_init () {
init_connect_socket();
g_signal_connect_after(n->soup_session, "request-started", G_CALLBACK(handle_cookies), NULL);
+ g_signal_connect(n->soup_session, "authenticate", G_CALLBACK(handle_authentication), NULL);
+}
+
+void handle_authentication (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data) {
+
+ (void) user_data;
+
+ if(uzbl.behave.authentication_handler) {
+ char *username, *password;
+ gchar *info, *host, *realm;
+ int number_of_endls=0;
+ gchar *p;
+
+ soup_session_pause_message(session, msg);
+
+ /* Sanitize strings */
+ info = g_strdup(soup_auth_get_info(auth));
+ host = g_strdup(soup_auth_get_host(auth));
+ realm = g_strdup(soup_auth_get_realm(auth));
+ for (p = info; *p; p++) if (*p == '\'') *p = '\"';
+ for (p = host; *p; p++) if (*p == '\'') *p = '\"';
+ for (p = realm; *p; p++) if (*p == '\'') *p = '\"';
+
+ GString *s = g_string_new ("");
+ g_string_printf(s, "'%s' '%s' '%s' '%s'",
+ info, host, realm, retrying?"TRUE":"FALSE");
+
+ run_handler(uzbl.behave.authentication_handler, s->str);
+
+ username = uzbl.comm.sync_stdout;
+
+ for (p = uzbl.comm.sync_stdout; *p; p++) {
+ if (*p == '\n') {
+ *p = '\0';
+ if (++number_of_endls == 1)
+ password = p + 1;
+ }
+ }
+
+ /* If stdout was correct (contains exactly two lines of text) do
+ * authenticate. */
+ if (number_of_endls == 2)
+ soup_auth_authenticate(auth, username, password);
+
+ soup_session_unpause_message(session, msg);
+
+ g_string_free(s, TRUE);
+ g_free(info);
+ g_free(host);
+ g_free(realm);
+ }
}
void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
@@ -2467,9 +2519,9 @@ initialize(int argc, char *argv[]) {
}
event_buffer_timeout(10);
- uzbl.info.webkit_major = WEBKIT_MAJOR_VERSION;
- uzbl.info.webkit_minor = WEBKIT_MINOR_VERSION;
- uzbl.info.webkit_micro = WEBKIT_MICRO_VERSION;
+ uzbl.info.webkit_major = webkit_major_version();
+ uzbl.info.webkit_minor = webkit_minor_version();
+ uzbl.info.webkit_micro = webkit_micro_version();
uzbl.info.arch = ARCH;
uzbl.info.commit = COMMIT;
@@ -2483,6 +2535,13 @@ initialize(int argc, char *argv[]) {
void
load_uri_imp(gchar *uri) {
GString* newuri;
+
+ /* Strip leading whitespaces */
+ while (*uri) {
+ if (!isspace(*uri)) break;
+ uri++;
+ }
+
if (g_strstr_len (uri, 11, "javascript:") != NULL) {
eval_js(uzbl.gui.web_view, uri, NULL);
return;
diff --git a/src/uzbl-core.h b/src/uzbl-core.h
index 70a383c..e05fcdb 100644
--- a/src/uzbl-core.h
+++ b/src/uzbl-core.h
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
@@ -123,6 +124,7 @@ typedef struct {
gchar* socket_dir;
gchar* download_handler;
gchar* cookie_handler;
+ gchar* authentication_handler;
gchar* new_window;
gchar* default_font_family;
gchar* monospace_font_family;
@@ -390,6 +392,13 @@ run_external_js (WebKitWebView * web_view, GArray *argv, GString *result);
void
eval_js(WebKitWebView * web_view, gchar *script, GString *result);
+void
+handle_authentication (SoupSession *session,
+ SoupMessage *msg,
+ SoupAuth *auth,
+ gboolean retrying,
+ gpointer user_data);
+
void handle_cookies (SoupSession *session,
SoupMessage *msg,
gpointer user_data);
diff --git a/tests/test-expand.c b/tests/test-expand.c
index 4dcd82d..7ea3d61 100644
--- a/tests/test-expand.c
+++ b/tests/test-expand.c
@@ -72,11 +72,11 @@ test_useragent (void) {
void
test_WEBKIT_VERSION (void) {
GString* expected = g_string_new("");
- g_string_append(expected, itos(WEBKIT_MAJOR_VERSION));
+ g_string_append(expected, itos(webkit_major_version()));
g_string_append(expected, " ");
- g_string_append(expected, itos(WEBKIT_MINOR_VERSION));
+ g_string_append(expected, itos(webkit_minor_version()));
g_string_append(expected, " ");
- g_string_append(expected, itos(WEBKIT_MICRO_VERSION));
+ g_string_append(expected, itos(webkit_micro_version()));
g_assert_cmpstr(expand("@WEBKIT_MAJOR @WEBKIT_MINOR @WEBKIT_MICRO", 0), ==, g_string_free(expected, FALSE));
}