aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/callbacks.c148
-rw-r--r--src/callbacks.h5
-rw-r--r--src/cookie-jar.c26
-rw-r--r--src/cookie-jar.h1
-rw-r--r--src/events.c22
-rw-r--r--src/events.h4
-rwxr-xr-xsrc/uzbl-browser4
-rw-r--r--src/uzbl-core.c343
-rw-r--r--src/uzbl-core.h17
9 files changed, 385 insertions, 185 deletions
diff --git a/src/callbacks.c b/src/callbacks.c
index fcd7a8c..ee6cf58 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -412,6 +412,7 @@ title_change_cb (WebKitWebView* web_view, GParamSpec param_spec) {
uzbl.gui.main_title = title ? g_strdup (title) : g_strdup ("(no title)");
update_title();
send_event(TITLE_CHANGED, uzbl.gui.main_title, NULL);
+ g_setenv("UZBL_TITLE", uzbl.gui.main_title, TRUE);
}
void
@@ -437,6 +438,7 @@ load_status_change_cb (WebKitWebView* web_view, GParamSpec param_spec) {
g_free (uzbl.state.uri);
GString* newuri = g_string_new (webkit_web_frame_get_uri (frame));
uzbl.state.uri = g_string_free (newuri, FALSE);
+ g_setenv("UZBL_URI", uzbl.state.uri, TRUE);
send_event(LOAD_COMMIT, webkit_web_frame_get_uri (frame), NULL);
break;
@@ -744,41 +746,139 @@ create_web_view_cb (WebKitWebView *web_view, WebKitWebFrame *frame, gpointer us
(void) web_view;
(void) frame;
(void) user_data;
- if (uzbl.state.selected_url != NULL) {
- if (uzbl.state.verbose)
- printf("\nNew web view -> %s\n", uzbl.state.selected_url);
- if (strncmp(uzbl.state.selected_url, "javascript:", strlen("javascript:")) == 0) {
- WebKitWebView* new_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ if (uzbl.state.verbose)
+ printf("New web view -> javascript link...\n");
- g_signal_connect (new_view, "web-view-ready",
- G_CALLBACK(create_web_view_js_cb), NULL);
+ WebKitWebView* new_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- return new_view;
- }
- else
- send_event(NEW_WINDOW, uzbl.state.selected_url, NULL);
+ g_signal_connect (new_view, "web-view-ready",
+ G_CALLBACK(create_web_view_js_cb), NULL);
+ return new_view;
+}
- } else {
- if (uzbl.state.verbose)
- printf("New web view -> javascript link...\n");
+void
+download_progress_cb(WebKitDownload *download, GParamSpec *pspec, gpointer user_data) {
+ (void) pspec; (void) user_data;
+
+ gdouble progress;
+ g_object_get(download, "progress", &progress, NULL);
+
+ const gchar *dest_uri = webkit_download_get_destination_uri(download);
+ const gchar *dest_path = dest_uri + strlen("file://");
+
+ gchar *details = g_strdup_printf("%s %.2lf", dest_path, progress);
+ send_event(DOWNLOAD_PROGRESS, details, NULL);
+ g_free(details);
+}
+
+void
+download_status_cb(WebKitDownload *download, GParamSpec *pspec, gpointer user_data) {
+ (void) pspec; (void) user_data;
- WebKitWebView* new_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ WebKitDownloadStatus status;
+ g_object_get(download, "status", &status, NULL);
- g_signal_connect (new_view, "web-view-ready",
- G_CALLBACK(create_web_view_js_cb), NULL);
- return new_view;
+ switch(status) {
+ case WEBKIT_DOWNLOAD_STATUS_CREATED:
+ case WEBKIT_DOWNLOAD_STATUS_STARTED:
+ case WEBKIT_DOWNLOAD_STATUS_ERROR:
+ case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
+ return; /* these are irrelevant */
+ case WEBKIT_DOWNLOAD_STATUS_FINISHED:
+ {
+ const gchar *dest_uri = webkit_download_get_destination_uri(download);
+ const gchar *dest_path = dest_uri + strlen("file://");
+ send_event(DOWNLOAD_COMPLETE, dest_path, NULL);
+ }
}
- return NULL;
}
gboolean
-download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) {
- (void) web_view;
- (void) user_data;
+download_cb(WebKitWebView *web_view, WebKitDownload *download, gpointer user_data) {
+ (void) web_view; (void) user_data;
- send_event(DOWNLOAD_REQ, webkit_download_get_uri ((WebKitDownload*)download), NULL);
- return (FALSE);
+ /* get the URI being downloaded */
+ const gchar *uri = webkit_download_get_uri(download);
+
+ if (uzbl.state.verbose)
+ printf("Download requested -> %s\n", uri);
+
+ if (!uzbl.behave.download_handler) {
+ webkit_download_cancel(download);
+ return FALSE; /* reject downloads when there's no download handler */
+ }
+
+ /* get a reasonable suggestion for a filename */
+ const gchar *suggested_filename;
+ g_object_get(download, "suggested-filename", &suggested_filename, NULL);
+
+ /* get the mimetype of the download */
+ const gchar *content_type;
+ WebKitNetworkResponse *r = webkit_download_get_network_response(download);
+ /* downloads can be initiated from the context menu, in that case there is
+ no network response yet and trying to get one would crash. */
+ if(WEBKIT_IS_NETWORK_RESPONSE(r)) {
+ SoupMessage *m = webkit_network_response_get_message(r);
+ SoupMessageHeaders *h;
+ g_object_get(m, "response-headers", &h, NULL);
+ content_type = soup_message_headers_get_one(h, "Content-Type");
+ } else
+ content_type = "application/octet-stream";
+
+ /* get the filesize of the download, as given by the server.
+ (this may be inaccurate, there's nothing we can do about that.) */
+ unsigned int total_size = webkit_download_get_total_size(download);
+
+ gchar *ev = g_strdup_printf("'%s' '%s' '%s' %d", uri, suggested_filename,
+ content_type, total_size);
+ run_handler(uzbl.behave.download_handler, ev);
+ g_free(ev);
+
+ /* no response, cancel the download */
+ if(!uzbl.comm.sync_stdout) {
+ webkit_download_cancel(download);
+ return FALSE;
+ }
+
+ /* no response, cancel the download */
+ if(uzbl.comm.sync_stdout[0] == 0) {
+ webkit_download_cancel(download);
+ uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
+ return FALSE;
+ }
+
+ /* we got a response, it's the path we should download the file to */
+ gchar *destination_path = uzbl.comm.sync_stdout;
+ uzbl.comm.sync_stdout = NULL;
+
+ /* presumably people don't need newlines in their filenames. */
+ char *p = strchr(destination_path, '\n');
+ if ( p != NULL ) *p = '\0';
+
+ /* set up progress callbacks */
+ g_signal_connect(download, "notify::status", G_CALLBACK(download_status_cb), NULL);
+ g_signal_connect(download, "notify::progress", G_CALLBACK(download_progress_cb), NULL);
+
+ /* convert relative path to absolute path */
+ if(destination_path[0] != '/') {
+ gchar *rel_path = destination_path;
+ gchar *cwd = g_get_current_dir();
+ destination_path = g_strconcat(cwd, "/", destination_path, NULL);
+ g_free(cwd);
+ g_free(rel_path);
+ }
+
+ send_event(DOWNLOAD_STARTED, destination_path, NULL);
+
+ /* convert absolute path to file:// URI */
+ gchar *destination_uri = g_strconcat("file://", destination_path, NULL);
+ g_free(destination_path);
+
+ webkit_download_set_destination_uri(download, destination_uri);
+ g_free(destination_uri);
+
+ return TRUE;
}
gboolean
diff --git a/src/callbacks.h b/src/callbacks.h
index a4258f2..40fa80d 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -133,9 +133,6 @@ cmd_load_start();
WebKitWebSettings*
view_settings();
-gboolean
-download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data);
-
void
toggle_zoom_type (WebKitWebView* page, GArray *argv, GString *result);
@@ -197,7 +194,7 @@ request_starting_cb(WebKitWebView *web_view, WebKitWebFrame *frame, WebKitWebRes
create_web_view_cb (WebKitWebView *web_view, WebKitWebFrame *frame, gpointer user_data);
gboolean
-download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data);
+download_cb (WebKitWebView *web_view, WebKitDownload *download, gpointer user_data);
void
populate_popup_cb(WebKitWebView *v, GtkMenu *m, void *c);
diff --git a/src/cookie-jar.c b/src/cookie-jar.c
index f2e340b..626e454 100644
--- a/src/cookie-jar.c
+++ b/src/cookie-jar.c
@@ -12,6 +12,7 @@
#include "cookie-jar.h"
#include "uzbl-core.h"
+#include "events.h"
static void
uzbl_cookie_jar_session_feature_init(SoupSessionFeatureInterface *iface, gpointer user_data);
@@ -38,6 +39,8 @@ soup_cookie_jar_socket_init(UzblCookieJar *jar) {
jar->handler = NULL;
jar->socket_path = NULL;
jar->connection_fd = -1;
+ jar->in_get_callback = 0;
+ jar->in_manual_add = 0;
}
static void
@@ -141,7 +144,7 @@ request_started(SoupSessionFeature *feature, SoupSession *session,
static void
changed(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) {
- (void) old_cookie;
+ SoupCookie * cookie = new_cookie ? new_cookie : old_cookie;
UzblCookieJar *uzbl_jar = UZBL_COOKIE_JAR(jar);
@@ -155,6 +158,25 @@ changed(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) {
if(uzbl_jar->in_get_callback)
return;
+ gchar *scheme = cookie->secure ? "https" : "http";
+
+ /* send a ADD or DELETE -_COOKIE event depending on what have changed */
+ if(!uzbl_jar->in_manual_add) {
+ gchar *expires = NULL;
+ if(cookie->expires)
+ expires = g_strdup_printf ("%d", soup_date_to_time_t (cookie->expires));
+
+ gchar * eventstr = g_strdup_printf ("'%s' '%s' '%s' '%s' '%s' '%s'",
+ cookie->domain, cookie->path, cookie->name, cookie->value, scheme, expires?expires:"");
+ if(new_cookie)
+ send_event(ADD_COOKIE, eventstr, NULL);
+ else
+ send_event(DELETE_COOKIE, eventstr, NULL);
+ g_free(eventstr);
+ if(expires)
+ g_free(expires);
+ }
+
/* the cookie daemon is only interested in new cookies and changed
ones, it can take care of deleting expired cookies on its own. */
if(!new_cookie)
@@ -162,8 +184,6 @@ changed(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) {
GString *s = g_string_new ("PUT");
- gchar *scheme = new_cookie->secure ? "https" : "http";
-
if(has_socket_handler(uzbl_jar)) {
g_string_append_c(s, 0); /* null-terminate the PUT */
g_string_append_len(s, scheme, strlen(scheme)+1);
diff --git a/src/cookie-jar.h b/src/cookie-jar.h
index 80af00e..f3e3733 100644
--- a/src/cookie-jar.h
+++ b/src/cookie-jar.h
@@ -16,6 +16,7 @@ typedef struct {
int connection_fd;
gboolean in_get_callback;
+ gboolean in_manual_add;
} UzblCookieJar;
typedef struct {
diff --git a/src/events.c b/src/events.c
index 20e3675..baaf8f3 100644
--- a/src/events.c
+++ b/src/events.c
@@ -22,7 +22,6 @@ const char *event_table[LAST_EVENT] = {
"REQUEST_STARTING" ,
"KEY_PRESS" ,
"KEY_RELEASE" ,
- "DOWNLOAD_REQUEST" ,
"COMMAND_EXECUTED" ,
"LINK_HOVER" ,
"TITLE_CHANGED" ,
@@ -45,10 +44,14 @@ const char *event_table[LAST_EVENT] = {
"PLUG_CREATED" ,
"COMMAND_ERROR" ,
"BUILTINS" ,
- "PTR_MOVE"
"PTR_MOVE" ,
"SCROLL_VERT" ,
- "SCROLL_HORIZ"
+ "SCROLL_HORIZ" ,
+ "DOWNLOAD_STARTED" ,
+ "DOWNLOAD_PROGRESS",
+ "DOWNLOAD_COMPLETE",
+ "ADD_COOKIE" ,
+ "DELETE_COOKIE"
};
void
@@ -136,24 +139,16 @@ send_event_stdout(GString *msg) {
void
send_event(int type, const gchar *details, const gchar *custom_event) {
GString *event_message = g_string_new("");
- gchar *buf, *p_val = NULL;
-
- /* expand shell vars */
- if(details) {
- buf = g_strdup(details);
- p_val = parseenv(buf ? g_strchug(buf) : " ");
- g_free(buf);
- }
/* check for custom events */
if(custom_event) {
g_string_printf(event_message, "EVENT [%s] %s %s\n",
- uzbl.state.instance_name, custom_event, p_val);
+ uzbl.state.instance_name, custom_event, details);
}
/* check wether we support the internal event */
else if(type < LAST_EVENT) {
g_string_printf(event_message, "EVENT [%s] %s %s\n",
- uzbl.state.instance_name, event_table[type], p_val);
+ uzbl.state.instance_name, event_table[type], details);
}
if(event_message->str) {
@@ -163,7 +158,6 @@ send_event(int type, const gchar *details, const gchar *custom_event) {
g_string_free(event_message, TRUE);
}
- g_free(p_val);
}
/* Transform gdk key events to our own events */
diff --git a/src/events.h b/src/events.h
index bc7960d..3c7b933 100644
--- a/src/events.h
+++ b/src/events.h
@@ -7,7 +7,7 @@
enum event_type {
LOAD_START, LOAD_COMMIT, LOAD_FINISH, LOAD_ERROR,
REQUEST_STARTING,
- KEY_PRESS, KEY_RELEASE, DOWNLOAD_REQ, COMMAND_EXECUTED,
+ KEY_PRESS, KEY_RELEASE, COMMAND_EXECUTED,
LINK_HOVER, TITLE_CHANGED, GEOMETRY_CHANGED,
WEBINSPECTOR, NEW_WINDOW, SELECTION_CHANGED,
VARIABLE_SET, FIFO_SET, SOCKET_SET,
@@ -16,6 +16,8 @@ enum event_type {
FOCUS_LOST, FOCUS_GAINED, FILE_INCLUDED,
PLUG_CREATED, COMMAND_ERROR, BUILTINS,
PTR_MOVE, SCROLL_VERT, SCROLL_HORIZ,
+ DOWNLOAD_STARTED, DOWNLOAD_PROGRESS, DOWNLOAD_COMPLETE,
+ ADD_COOKIE, DELETE_COOKIE,
/* must be last entry */
LAST_EVENT
diff --git a/src/uzbl-browser b/src/uzbl-browser
index 88d3742..faa2829 100755
--- a/src/uzbl-browser
+++ b/src/uzbl-browser
@@ -8,6 +8,8 @@
# to your $XDG_DATA_HOME/uzbl/scripts/ and edit them
PREFIX=/usr/local
+export PREFIX
+
EXAMPLES=$PREFIX/share/uzbl/examples
XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
@@ -66,7 +68,7 @@ fi
# we could also check if its pid file exists to avoid having to spawn it.
#if [ ! -f "$XDG_CACHE_HOME"/uzbl/cookie_daemon_socket.pid ]
#then
- ${UZBL_COOKIE_DAEMON:-uzbl-cookie-manager}
+# ${UZBL_COOKIE_DAEMON:-uzbl-cookie-manager}
#fi
# uzbl-event-manager will exit if one is already running.
diff --git a/src/uzbl-core.c b/src/uzbl-core.c
index 9a9af23..cc680c2 100644
--- a/src/uzbl-core.c
+++ b/src/uzbl-core.c
@@ -93,6 +93,7 @@ const struct var_name_to_ptr_t {
{ "cookie_handler", PTR_V_STR(uzbl.behave.cookie_handler, 1, cmd_set_cookie_handler)},
{ "authentication_handler", PTR_V_STR(uzbl.behave.authentication_handler, 1, set_authentication_handler)},
{ "scheme_handler", PTR_V_STR(uzbl.behave.scheme_handler, 1, NULL)},
+ { "download_handler", PTR_V_STR(uzbl.behave.download_handler, 1, NULL)},
{ "fifo_dir", PTR_V_STR(uzbl.behave.fifo_dir, 1, cmd_fifo_dir)},
{ "socket_dir", PTR_V_STR(uzbl.behave.socket_dir, 1, cmd_socket_dir)},
{ "http_debug", PTR_V_INT(uzbl.behave.http_debug, 1, cmd_http_debug)},
@@ -414,36 +415,6 @@ find_existing_file(gchar* path_list) {
return NULL;
}
-
-/* Returns a new string with environment $variables expanded */
-gchar*
-parseenv (gchar* string) {
- extern char** environ;
- gchar* tmpstr = NULL, * out;
- int i = 0;
-
- if(!string)
- return NULL;
-
- out = g_strdup(string);
- while (environ[i] != NULL) {
- gchar** env = g_strsplit (environ[i], "=", 2);
- gchar* envname = g_strconcat ("$", env[0], NULL);
-
- if (g_strrstr (string, envname) != NULL) {
- tmpstr = out;
- out = str_replace(envname, env[1], out);
- g_free (tmpstr);
- }
-
- g_free (envname);
- g_strfreev (env); // somebody said this breaks uzbl
- i++;
- }
-
- return out;
-}
-
void
clean_up(void) {
if(uzbl.info.pid_str) {
@@ -496,8 +467,6 @@ get_click_context() {
}
/* --- SIGNALS --- */
-int sigs[] = {SIGTERM, SIGINT, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGALRM, 0};
-
sigfunc*
setup_signal(int signr, sigfunc *shandler) {
struct sigaction nh, oh;
@@ -513,21 +482,9 @@ setup_signal(int signr, sigfunc *shandler) {
}
void
-catch_signal(int s) {
- if(s == SIGTERM ||
- s == SIGINT ||
- s == SIGILL ||
- s == SIGFPE ||
- s == SIGQUIT) {
- clean_up();
- exit(EXIT_SUCCESS);
- }
- else if(s == SIGSEGV) {
- clean_up();
- fprintf(stderr, "Program aborted, segmentation fault!\nAttempting to clean up...\n");
- exit(EXIT_FAILURE);
- }
- else if(s == SIGALRM && uzbl.state.event_buffer) {
+empty_event_buffer(int s) {
+ (void) s;
+ if(uzbl.state.event_buffer) {
g_ptr_array_free(uzbl.state.event_buffer, TRUE);
uzbl.state.event_buffer = NULL;
}
@@ -626,9 +583,10 @@ struct {const char *key; CommandInfo value;} cmdlist[] =
{ "js", {run_js, TRUE} },
{ "script", {run_external_js, 0} },
{ "toggle_status", {toggle_status_cb, 0} },
- { "spawn", {spawn, 0} },
+ { "spawn", {spawn_async, 0} },
{ "sync_spawn", {spawn_sync, 0} }, // needed for cookie handler
- { "sh", {spawn_sh, 0} },
+ { "sync_spawn_exec", {spawn_sync_exec, 0} }, // needed for load_cookies.sh :(
+ { "sh", {spawn_sh_async, 0} },
{ "sync_sh", {spawn_sh_sync, 0} }, // needed for cookie handler
{ "exit", {close_uzbl, 0} },
{ "search", {search_forward_text, TRUE} },
@@ -656,7 +614,9 @@ struct {const char *key; CommandInfo value;} cmdlist[] =
{ "menu_editable_remove", {menu_remove_edit, TRUE} },
{ "hardcopy", {hardcopy, TRUE} },
{ "include", {include, TRUE} },
- { "show_inspector", {show_inspector, 0} }
+ { "show_inspector", {show_inspector, 0} },
+ { "add_cookie", {add_cookie, 0} },
+ { "delete_cookie", {delete_cookie, 0} }
};
void
@@ -695,9 +655,8 @@ set_var(WebKitWebView *page, GArray *argv, GString *result) {
gchar **split = g_strsplit(argv_idx(argv, 0), "=", 2);
if (split[0] != NULL) {
- gchar *value = parseenv(split[1] ? g_strchug(split[1]) : " ");
+ gchar *value = split[1] ? g_strchug(split[1]) : " ";
set_var_value(g_strstrip(split[0]), value);
- g_free(value);
}
g_strfreev(split);
}
@@ -927,14 +886,12 @@ void
include(WebKitWebView *page, GArray *argv, GString *result) {
(void) page;
(void) result;
- gchar *pe = NULL,
- *path = NULL;
+ gchar *path = argv_idx(argv, 0);
- if(!argv_idx(argv, 0))
+ if(!path)
return;
- pe = parseenv(argv_idx(argv, 0));
- if((path = find_existing_file(pe))) {
+ if((path = find_existing_file(path))) {
if(!for_each_line_in_file(path, parse_cmd_line_cb, NULL)) {
gchar *tmp = g_strdup_printf("File %s can not be read.", path);
send_event(COMMAND_ERROR, tmp, NULL);
@@ -944,7 +901,6 @@ include(WebKitWebView *page, GArray *argv, GString *result) {
send_event(FILE_INCLUDED, path, NULL);
g_free(path);
}
- g_free(pe);
}
void
@@ -955,6 +911,57 @@ show_inspector(WebKitWebView *page, GArray *argv, GString *result) {
}
void
+add_cookie(WebKitWebView *page, GArray *argv, GString *result) {
+ (void) page; (void) result;
+ gchar *host, *path, *name, *value;
+ gboolean secure = 0;
+ SoupDate *expires = NULL;
+
+ if(argv->len != 6)
+ return;
+
+ // Parse with same syntax as ADD_COOKIE event
+ host = argv_idx (argv, 0);
+ path = argv_idx (argv, 1);
+ name = argv_idx (argv, 2);
+ value = argv_idx (argv, 3);
+ secure = strcmp (argv_idx (argv, 4), "https") == 0;
+ if (strlen (argv_idx (argv, 5)) != 0)
+ expires = soup_date_new_from_time_t (
+ strtoul (argv_idx (argv, 5), NULL, 10));
+
+ // Create new cookie
+ SoupCookie * cookie = soup_cookie_new (name, value, host, path, -1);
+ soup_cookie_set_secure (cookie, secure);
+ if (expires)
+ soup_cookie_set_expires (cookie, expires);
+
+ // Add cookie to jar
+ uzbl.net.soup_cookie_jar->in_manual_add = 1;
+ soup_cookie_jar_add_cookie (SOUP_COOKIE_JAR (uzbl.net.soup_cookie_jar), cookie);
+ uzbl.net.soup_cookie_jar->in_manual_add = 0;
+}
+
+void
+delete_cookie(WebKitWebView *page, GArray *argv, GString *result) {
+ (void) page; (void) result;
+
+ if(argv->len < 4)
+ return;
+
+ SoupCookie * cookie = soup_cookie_new (
+ argv_idx (argv, 2),
+ argv_idx (argv, 3),
+ argv_idx (argv, 0),
+ argv_idx (argv, 1),
+ 0);
+
+ uzbl.net.soup_cookie_jar->in_manual_add = 1;
+ soup_cookie_jar_delete_cookie (SOUP_COOKIE_JAR (uzbl.net.soup_cookie_jar), cookie);
+ uzbl.net.soup_cookie_jar->in_manual_add = 0;
+}
+
+void
act_dump_config() {
dump_config();
}
@@ -1271,7 +1278,7 @@ run_command (const gchar *command, const guint npre, const gchar **args,
/*@null@*/ gchar**
split_quoted(const gchar* src, const gboolean unquote) {
- /* split on unquoted space, return array of strings;
+ /* split on unquoted space or tab, return array of strings;
remove a layer of quotes and backslashes if unquote */
if (!src) return NULL;
@@ -1292,7 +1299,7 @@ split_quoted(const gchar* src, const gboolean unquote) {
else if ((*p == '\'') && unquote && !dq) sq = !sq;
else if (*p == '\'' && !dq) { g_string_append_c(s, *p);
sq = ! sq; }
- else if ((*p == ' ') && !dq && !sq) {
+ else if ((*p == ' ' || *p == '\t') && !dq && !sq) {
dup = g_strdup(s->str);
g_array_append_val(a, dup);
g_string_truncate(s, 0);
@@ -1307,37 +1314,51 @@ split_quoted(const gchar* src, const gboolean unquote) {
}
void
-spawn(WebKitWebView *web_view, GArray *argv, GString *result) {
- (void)web_view; (void)result;
+spawn(GArray *argv, gboolean sync, gboolean exec) {
gchar *path = NULL;
//TODO: allow more control over argument order so that users can have some arguments before the default ones from run_command, and some after
if (argv_idx(argv, 0) &&
((path = find_existing_file(argv_idx(argv, 0)))) ) {
+ if (uzbl.comm.sync_stdout)
+ uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
run_command(path, 0,
- ((const gchar **) (argv->data + sizeof(gchar*))),
- FALSE, NULL);
+ ((const gchar **) (argv->data + sizeof(gchar*))),
+ sync, sync?&uzbl.comm.sync_stdout:NULL);
+ // run each line of output from the program as a command
+ if (sync && exec && uzbl.comm.sync_stdout) {
+ gchar *head = uzbl.comm.sync_stdout;
+ gchar *tail;
+ while ((tail = strchr (head, '\n'))) {
+ *tail = '\0';
+ parse_cmd_line(head, NULL);
+ head = tail + 1;
+ }
+ }
g_free(path);
}
}
void
-spawn_sync(WebKitWebView *web_view, GArray *argv, GString *result) {
+spawn_async(WebKitWebView *web_view, GArray *argv, GString *result) {
(void)web_view; (void)result;
- gchar *path = NULL;
+ spawn(argv, FALSE, FALSE);
+}
- if (argv_idx(argv, 0) &&
- ((path = find_existing_file(argv_idx(argv, 0)))) ) {
- run_command(path, 0,
- ((const gchar **) (argv->data + sizeof(gchar*))),
- TRUE, &uzbl.comm.sync_stdout);
- g_free(path);
- }
+void
+spawn_sync(WebKitWebView *web_view, GArray *argv, GString *result) {
+ (void)web_view; (void)result;
+ spawn(argv, TRUE, FALSE);
}
void
-spawn_sh(WebKitWebView *web_view, GArray *argv, GString *result) {
+spawn_sync_exec(WebKitWebView *web_view, GArray *argv, GString *result) {
(void)web_view; (void)result;
+ spawn(argv, TRUE, TRUE);
+}
+
+void
+spawn_sh(GArray *argv, gboolean sync) {
if (!uzbl.behave.shell_cmd) {
g_printerr ("spawn_sh: shell_cmd is not set!\n");
return;
@@ -1351,31 +1372,28 @@ spawn_sh(WebKitWebView *web_view, GArray *argv, GString *result) {
for (i = 1; i < g_strv_length(cmd); i++)
g_array_prepend_val(argv, cmd[i]);
- if (cmd) run_command(cmd[0], g_strv_length(cmd) + 1, (const gchar **) argv->data, FALSE, NULL);
+ if (cmd) {
+ if (uzbl.comm.sync_stdout)
+ uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
+
+ run_command(cmd[0], g_strv_length(cmd) + 1,
+ (const gchar **) argv->data,
+ sync, sync?&uzbl.comm.sync_stdout:NULL);
+ }
g_free (spacer);
g_strfreev (cmd);
}
void
-spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) {
+spawn_sh_async(WebKitWebView *web_view, GArray *argv, GString *result) {
(void)web_view; (void)result;
- if (!uzbl.behave.shell_cmd) {
- g_printerr ("spawn_sh_sync: shell_cmd is not set!\n");
- return;
- }
-
- guint i;
- gchar *spacer = g_strdup("");
- g_array_insert_val(argv, 1, spacer);
- gchar **cmd = split_quoted(uzbl.behave.shell_cmd, TRUE);
-
- for (i = 1; i < g_strv_length(cmd); i++)
- g_array_prepend_val(argv, cmd[i]);
+ spawn_sh(argv, FALSE);
+}
- if (cmd) run_command(cmd[0], g_strv_length(cmd) + 1, (const gchar **) argv->data,
- TRUE, &uzbl.comm.sync_stdout);
- g_free (spacer);
- g_strfreev (cmd);
+void
+spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) {
+ (void)web_view; (void)result;
+ spawn_sh(argv, TRUE);
}
void
@@ -1592,6 +1610,28 @@ control_fifo(GIOChannel *gio, GIOCondition condition) {
return TRUE;
}
+gboolean
+attach_fifo(gchar *path) {
+ GError *error = NULL;
+ /* we don't really need to write to the file, but if we open the
+ * file as 'r' we will block here, waiting for a writer to open
+ * the file. */
+ GIOChannel *chan = g_io_channel_new_file(path, "r+", &error);
+ if (chan) {
+ if (g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_fifo, NULL)) {
+ if (uzbl.state.verbose)
+ printf ("attach_fifo: created successfully as %s\n", path);
+ send_event(FIFO_SET, path, NULL);
+ uzbl.comm.fifo_path = path;
+ g_setenv("UZBL_FIFO", uzbl.comm.fifo_path, TRUE);
+ return TRUE;
+ } else g_warning ("attach_fifo: could not add watch on %s\n", path);
+ } else g_warning ("attach_fifo: can't open: %s\n", error->message);
+
+ if (error) g_error_free (error);
+ return FALSE;
+}
+
/*@null@*/ gchar*
init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */
if (uzbl.comm.fifo_path) { /* get rid of the old fifo if one exists */
@@ -1601,28 +1641,31 @@ init_fifo(gchar *dir) { /* return dir or, on error, free dir and return NULL */
uzbl.comm.fifo_path = NULL;
}
- GIOChannel *chan = NULL;
- GError *error = NULL;
gchar *path = build_stream_name(FIFO, dir);
if (!file_exists(path)) {
- if (mkfifo (path, 0666) == 0) {
- // we don't really need to write to the file, but if we open the file as 'r' we will block here, waiting for a writer to open the file.
- chan = g_io_channel_new_file(path, "r+", &error);
- if (chan) {
- if (g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_fifo, NULL)) {
- if (uzbl.state.verbose)
- printf ("init_fifo: created successfully as %s\n", path);
- send_event(FIFO_SET, path, NULL);
- uzbl.comm.fifo_path = path;
- return dir;
- } else g_warning ("init_fifo: could not add watch on %s\n", path);
- } else g_warning ("init_fifo: can't open: %s\n", error->message);
+ if (mkfifo (path, 0666) == 0 && attach_fifo(path)) {
+ return dir;
} else g_warning ("init_fifo: can't create %s: %s\n", path, strerror(errno));
- } else g_warning ("init_fifo: can't create %s: file exists\n", path);
+ } else {
+ /* the fifo exists. but is anybody home? */
+ int fd = open(path, O_WRONLY|O_NONBLOCK);
+ if(fd < 0) {
+ /* some error occurred, presumably nobody's on the read end.
+ * we can attach ourselves to it. */
+ if(attach_fifo(path))
+ return dir;
+ else
+ g_warning("init_fifo: can't attach to %s: %s\n", path, strerror(errno));
+ } else {
+ /* somebody's there, we can't use that fifo. */
+ close(fd);
+ /* whatever, this instance can live without a fifo. */
+ g_warning ("init_fifo: can't create %s: file exists and is occupied\n", path);
+ }
+ }
/* if we got this far, there was an error; cleanup */
- if (error) g_error_free (error);
g_free(dir);
g_free(path);
return NULL;
@@ -1773,6 +1816,32 @@ control_client_socket(GIOChannel *clientchan) {
return TRUE;
}
+
+gboolean
+attach_socket(gchar *path, struct sockaddr_un *local) {
+ GIOChannel *chan = NULL;
+ int sock = socket (AF_UNIX, SOCK_STREAM, 0);
+
+ if (bind (sock, (struct sockaddr *) local, sizeof(*local)) != -1) {
+ if (uzbl.state.verbose)
+ printf ("init_socket: opened in %s\n", path);
+
+ if(listen (sock, 5) < 0)
+ g_warning ("attach_socket: could not listen on %s: %s\n", path, strerror(errno));
+
+ if( (chan = g_io_channel_unix_new(sock)) ) {
+ g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_socket, chan);
+ uzbl.comm.socket_path = path;
+ send_event(SOCKET_SET, path, NULL);
+ g_setenv("UZBL_SOCKET", uzbl.comm.socket_path, TRUE);
+ return TRUE;
+ }
+ } else g_warning ("attach_socket: could not bind to %s: %s\n", path, strerror(errno));
+
+ return FALSE;
+}
+
+
/*@null@*/ gchar*
init_socket(gchar *dir) { /* return dir or, on error, free dir and return NULL */
if (uzbl.comm.socket_path) { /* remove an existing socket should one exist */
@@ -1787,30 +1856,33 @@ init_socket(gchar *dir) { /* return dir or, on error, free dir and return NULL *
return NULL;
}
- GIOChannel *chan = NULL;
- int sock, len;
struct sockaddr_un local;
gchar *path = build_stream_name(SOCKET, dir);
- sock = socket (AF_UNIX, SOCK_STREAM, 0);
-
local.sun_family = AF_UNIX;
strcpy (local.sun_path, path);
- unlink (local.sun_path);
- len = strlen (local.sun_path) + sizeof (local.sun_family);
- if (bind (sock, (struct sockaddr *) &local, len) != -1) {
- if (uzbl.state.verbose)
- printf ("init_socket: opened in %s\n", path);
- listen (sock, 5);
-
- if( (chan = g_io_channel_unix_new(sock)) ) {
- g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc) control_socket, chan);
- uzbl.comm.socket_path = path;
- send_event(SOCKET_SET, path, NULL);
- return dir;
+ if(!file_exists(path) && attach_socket(path, &local)) {
+ /* it's free for the taking. */
+ return dir;
+ } else {
+ /* see if anybody's listening on the socket path we want. */
+ int sock = socket (AF_UNIX, SOCK_STREAM, 0);
+ if(connect(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
+ /* some error occurred, presumably nobody's listening.
+ * we can attach ourselves to it. */
+ unlink(path);
+ if(attach_socket(path, &local))
+ return dir;
+ else
+ g_warning("init_socket: can't attach to existing socket %s: %s\n", path, strerror(errno));
+ } else {
+ /* somebody's there, we can't use that socket path. */
+ close(sock);
+ /* whatever, this instance can live without a socket. */
+ g_warning ("init_socket: can't create %s: socket exists and is occupied\n", path);
}
- } else g_warning ("init_socket: could not open in %s: %s\n", path, strerror(errno));
+ }
/* if we got this far, there was an error; cleanup */
g_free(path);
@@ -2075,6 +2147,7 @@ settings_init () {
send_event(COMMAND_ERROR, tmp, NULL);
g_free(tmp);
}
+ g_setenv("UZBL_CONFIG", s->config_file, TRUE);
} else if (uzbl.state.verbose)
printf ("No configuration file loaded.\n");
@@ -2241,10 +2314,10 @@ initialize(int argc, char *argv[]) {
uzbl.net.soup_cookie_jar = uzbl_cookie_jar_new();
soup_session_add_feature(uzbl.net.soup_session, SOUP_SESSION_FEATURE(uzbl.net.soup_cookie_jar));
- for(i=0; sigs[i]; i++) {
- if(setup_signal(sigs[i], catch_signal) == SIG_ERR)
- fprintf(stderr, "uzbl: error hooking %d: %s\n", sigs[i], strerror(errno));
- }
+ /* TODO: move the handler setup to event_buffer_timeout and disarm the
+ * handler in empty_event_buffer? */
+ if(setup_signal(SIGALRM, empty_event_buffer) == SIG_ERR)
+ fprintf(stderr, "uzbl: error hooking %d: %s\n", SIGALRM, strerror(errno));
event_buffer_timeout(10);
uzbl.info.webkit_major = webkit_major_version();
@@ -2358,12 +2431,16 @@ main (int argc, char* argv[]) {
"signal::changed", (GCallback)scroll_horiz_cb, NULL,
NULL);
+ gchar *xwin = g_strdup_printf("%d", (int)uzbl.xwin);
+ g_setenv("UZBL_XID", xwin, TRUE);
+
if(!uzbl.state.instance_name)
- uzbl.state.instance_name = itos((int)uzbl.xwin);
+ uzbl.state.instance_name = g_strdup(xwin);
- GString *tmp = g_string_new("");
- g_string_printf(tmp, "%d", getpid());
- uzbl.info.pid_str = g_string_free(tmp, FALSE);
+ g_free(xwin);
+
+ uzbl.info.pid_str = g_strdup_printf("%d", getpid());
+ g_setenv("UZBL_PID", uzbl.info.pid_str, TRUE);
send_event(INSTANCE_START, uzbl.info.pid_str, NULL);
if(uzbl.state.plug_mode) {
diff --git a/src/uzbl-core.h b/src/uzbl-core.h
index b5a502e..98ae342 100644
--- a/src/uzbl-core.h
+++ b/src/uzbl-core.h
@@ -133,6 +133,7 @@ typedef struct {
gchar* fantasy_font_family;
gchar* cursive_font_family;
gchar* scheme_handler;
+ gchar* download_handler;
gboolean show_status;
gboolean forward_keys;
gboolean status_top;
@@ -228,9 +229,6 @@ itos(int val);
gchar*
strfree(gchar *str);
-gchar*
-parseenv (gchar* string);
-
void
clean_up(void);
@@ -266,10 +264,10 @@ run_command(const gchar *command, const guint npre,
const gchar **args, const gboolean sync, char **output_stdout);
void
-spawn(WebKitWebView *web_view, GArray *argv, GString *result);
+spawn_async(WebKitWebView *web_view, GArray *argv, GString *result);
void
-spawn_sh(WebKitWebView *web_view, GArray *argv, GString *result);
+spawn_sh_async(WebKitWebView *web_view, GArray *argv, GString *result);
void
spawn_sync(WebKitWebView *web_view, GArray *argv, GString *result);
@@ -278,6 +276,9 @@ void
spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result);
void
+spawn_sync_exec(WebKitWebView *web_view, GArray *argv, GString *result);
+
+void
parse_command(const char *cmd, const char *param, GString *result);
void
@@ -454,6 +455,12 @@ void
show_inspector(WebKitWebView *page, GArray *argv, GString *result);
void
+add_cookie(WebKitWebView *page, GArray *argv, GString *result);
+
+void
+delete_cookie(WebKitWebView *page, GArray *argv, GString *result);
+
+void
builtins();
typedef void (*Command)(WebKitWebView*, GArray *argv, GString *result);