diff options
author | Dieter Plaetinck <dieter@plaetinck.be> | 2010-01-24 16:21:11 +0100 |
---|---|---|
committer | Dieter Plaetinck <dieter@plaetinck.be> | 2010-01-24 16:21:11 +0100 |
commit | 0cd3f65d05e7d966ff66d2aa97908332eb2d6c06 (patch) | |
tree | dfaa9b7d376cba31436e72655df018d128337187 | |
parent | c3c4d481079f2a24ea16cd49b785b6f358a28fc9 (diff) | |
parent | 67c68ee643eaef16277fa614d873dd558bfdbd04 (diff) |
merge in pawelz' authentication handler + some other fixes
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | README | 43 | ||||
-rw-r--r-- | docs/INSTALL | 2 | ||||
-rw-r--r-- | examples/config/config | 16 | ||||
-rw-r--r-- | examples/data/scripts/auth.py | 53 | ||||
-rwxr-xr-x | examples/data/scripts/uzbl-event-manager | 8 | ||||
-rw-r--r-- | src/callbacks.c | 11 | ||||
-rw-r--r-- | src/callbacks.h | 3 | ||||
-rw-r--r-- | src/uzbl-core.c | 65 | ||||
-rw-r--r-- | src/uzbl-core.h | 9 | ||||
-rw-r--r-- | tests/test-expand.c | 6 |
12 files changed, 202 insertions, 24 deletions
@@ -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 @@ -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 @@ -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)); } |