aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar keis <keijser@gmail.com>2010-11-30 14:21:18 +0100
committerGravatar keis <keijser@gmail.com>2010-11-30 14:21:18 +0100
commit0d6e2be4c835a2460cfebcc165ade7272e16466a (patch)
treeb89a1922a03c28c89cee9defa6856eb80da356ff /src
parentd7af40c7c462a148c51c8f20f455df3859551e2e (diff)
parent518004933b6d110d2a6d140f86c759dd4e713607 (diff)
Merge branch 'master' of git://github.com/Dieterbe/uzbl into gtk3
Conflicts: Makefile
Diffstat (limited to 'src')
-rw-r--r--src/callbacks.c173
-rw-r--r--src/callbacks.h25
-rw-r--r--src/cookie-jar.c306
-rw-r--r--src/cookie-jar.h33
-rw-r--r--src/events.c104
-rw-r--r--src/events.h2
-rw-r--r--src/util.c110
-rw-r--r--src/util.h18
-rwxr-xr-xsrc/uzbl-browser90
-rw-r--r--src/uzbl-core.c436
-rw-r--r--src/uzbl-core.h34
11 files changed, 769 insertions, 562 deletions
diff --git a/src/callbacks.c b/src/callbacks.c
index 85653be..d763fa9 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -6,7 +6,7 @@
#include "uzbl-core.h"
#include "callbacks.h"
#include "events.h"
-
+#include "util.h"
void
set_proxy_url() {
@@ -46,6 +46,19 @@ set_authentication_handler() {
}
void
+set_status_background() {
+ GdkColor color;
+ gdk_color_parse (uzbl.behave.status_background, &color);
+ /* labels and hboxes do not draw their own background. applying this
+ * on the vbox/main_window is ok as the statusbar is the only affected
+ * widget. (if not, we could also use GtkEventBox) */
+ if (uzbl.gui.main_window)
+ gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color);
+ else if (uzbl.gui.plug)
+ gtk_widget_modify_bg (GTK_WIDGET(uzbl.gui.plug), GTK_STATE_NORMAL, &color);
+}
+
+void
set_icon() {
if(file_exists(uzbl.gui.icon)) {
if (uzbl.gui.main_window)
@@ -182,6 +195,12 @@ cmd_zoom_level() {
}
void
+cmd_enable_pagecache() {
+ g_object_set (G_OBJECT(view_settings()), "enable-page-cache",
+ uzbl.behave.enable_pagecache, NULL);
+}
+
+void
cmd_disable_plugins() {
g_object_set (G_OBJECT(view_settings()), "enable-plugins",
!uzbl.behave.disable_plugins, NULL);
@@ -395,17 +414,43 @@ title_change_cb (WebKitWebView* web_view, GParamSpec param_spec) {
}
void
-progress_change_cb (WebKitWebView* page, gint progress, gpointer data) {
- (void) page;
- (void) data;
- gchar *prg_str;
-
- prg_str = itos(progress);
+progress_change_cb (WebKitWebView* web_view, GParamSpec param_spec) {
+ (void) param_spec;
+ int progress = webkit_web_view_get_progress(web_view) * 100;
+ gchar *prg_str = itos(progress);
send_event(LOAD_PROGRESS, prg_str, NULL);
g_free(prg_str);
}
void
+load_status_change_cb (WebKitWebView* web_view, GParamSpec param_spec) {
+ (void) param_spec;
+
+ WebKitWebFrame *frame = webkit_web_view_get_main_frame(web_view);
+ WebKitLoadStatus status = webkit_web_view_get_load_status(web_view);
+ switch(status) {
+ case WEBKIT_LOAD_PROVISIONAL:
+ send_event(LOAD_START, uzbl.state.uri, NULL);
+ break;
+ case WEBKIT_LOAD_COMMITTED:
+ g_free (uzbl.state.uri);
+ GString* newuri = g_string_new (webkit_web_frame_get_uri (frame));
+ uzbl.state.uri = g_string_free (newuri, FALSE);
+
+ send_event(LOAD_COMMIT, webkit_web_frame_get_uri (frame), NULL);
+ break;
+ case WEBKIT_LOAD_FINISHED:
+ send_event(LOAD_FINISH, webkit_web_frame_get_uri(frame), NULL);
+ break;
+ case WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT:
+ break; /* we don't do anything with this (yet) */
+ case WEBKIT_LOAD_FAILED:
+ break; /* load_error_cb will handle this case */
+ }
+
+}
+
+void
selection_changed_cb(WebKitWebView *webkitwebview, gpointer ud) {
(void)ud;
gchar *tmp;
@@ -417,23 +462,6 @@ selection_changed_cb(WebKitWebView *webkitwebview, gpointer ud) {
}
void
-load_finish_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
- (void) page;
- (void) data;
-
- send_event(LOAD_FINISH, webkit_web_frame_get_uri(frame), NULL);
-}
-
-void
-load_start_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
- (void) page;
- (void) frame;
- (void) data;
-
- send_event(LOAD_START, uzbl.state.uri, NULL);
-}
-
-void
load_error_cb (WebKitWebView* page, WebKitWebFrame* frame, gchar *uri, gpointer web_err, gpointer ud) {
(void) page;
(void) frame;
@@ -447,17 +475,6 @@ load_error_cb (WebKitWebView* page, WebKitWebFrame* frame, gchar *uri, gpointer
}
void
-load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) {
- (void) page;
- (void) data;
- g_free (uzbl.state.uri);
- GString* newuri = g_string_new (webkit_web_frame_get_uri (frame));
- uzbl.state.uri = g_string_free (newuri, FALSE);
-
- send_event(LOAD_COMMIT, webkit_web_frame_get_uri (frame), NULL);
-}
-
-void
destroy_cb (GtkWidget* widget, gpointer data) {
(void) widget;
(void) data;
@@ -589,9 +606,9 @@ motion_notify_cb(GtkWidget* window, GdkEventMotion* event, gpointer user_data) {
(void) event;
(void) user_data;
- gchar *details;
- details = g_strdup_printf("%.0lf %.0lf %u", event->x, event->y, event->state);
+ gchar *details = g_strdup_printf("%.0lf %.0lf %u", event->x, event->y, event->state);
send_event(PTR_MOVE, details, NULL);
+ g_free(details);
return FALSE;
}
@@ -703,11 +720,10 @@ create_web_view_js2_cb (WebKitWebView* web_view, GParamSpec param_spec) {
if (strncmp(uri, "javascript:", strlen("javascript:")) == 0) {
eval_js(uzbl.gui.web_view, (gchar*) uri + strlen("javascript:"), NULL, "javascript:");
+ gtk_widget_destroy(GTK_WIDGET(web_view));
}
else
send_event(NEW_WINDOW, uri, NULL);
-
- gtk_widget_destroy(GTK_WIDGET(web_view));
}
@@ -717,7 +733,7 @@ create_web_view_js_cb (WebKitWebView* web_view, gpointer user_data) {
(void) user_data;
g_object_connect (web_view, "signal::notify::uri",
- G_CALLBACK(create_web_view_js2_cb), NULL);
+ G_CALLBACK(create_web_view_js2_cb), NULL, NULL);
return TRUE;
}
@@ -764,6 +780,44 @@ download_cb (WebKitWebView *web_view, GObject *download, gpointer user_data) {
return (FALSE);
}
+gboolean
+scroll_vert_cb(GtkAdjustment *adjust, void *w)
+{
+ (void) w;
+
+ gdouble value = gtk_adjustment_get_value(adjust);
+ gdouble min = gtk_adjustment_get_lower(adjust);
+ gdouble max = gtk_adjustment_get_upper(adjust);
+ gdouble page = gtk_adjustment_get_page_size(adjust);
+ gchar* details;
+ details = g_strdup_printf("%g %g %g %g", value, min, max, page);
+
+ send_event(SCROLL_VERT, details, NULL);
+
+ g_free(details);
+
+ return (FALSE);
+}
+
+gboolean
+scroll_horiz_cb(GtkAdjustment *adjust, void *w)
+{
+ (void) w;
+
+ gdouble value = gtk_adjustment_get_value(adjust);
+ gdouble min = gtk_adjustment_get_lower(adjust);
+ gdouble max = gtk_adjustment_get_upper(adjust);
+ gdouble page = gtk_adjustment_get_page_size(adjust);
+ gchar* details;
+ details = g_strdup_printf("%g %g %g %g", value, min, max, page);
+
+ send_event(SCROLL_HORIZ, details, NULL);
+
+ g_free(details);
+
+ return (FALSE);
+}
+
void
run_menu_command(GtkWidget *menu, const char *line) {
(void) menu;
@@ -831,38 +885,11 @@ populate_popup_cb(WebKitWebView *v, GtkMenu *m, void *c) {
}
void
-save_cookies_js(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie, gpointer user_data) {
- (void) jar;
- (void) user_data;
- (void) old_cookie;
- char *scheme;
- GString *s;
-
- if(new_cookie != NULL) {
- scheme = (new_cookie->secure == TRUE) ? "https" : "http";
-
- s = g_string_new("");
- g_string_printf(s, "PUT '%s' '%s' '%s' '%s=%s'", scheme, new_cookie->domain, new_cookie->path, new_cookie->name, new_cookie->value);
- run_handler(uzbl.behave.cookie_handler, s->str);
- g_string_free(s, TRUE);
- }
-}
-
-void
-save_cookies_http(SoupMessage *msg, gpointer user_data) {
- (void) user_data;
- GSList *ck;
- char *cookie;
-
- for(ck = soup_cookies_from_response(msg); ck; ck = ck->next){
- cookie = soup_cookie_to_set_cookie_header(ck->data);
- SoupURI *soup_uri = soup_message_get_uri(msg);
- GString *s = g_string_new("");
- g_string_printf(s, "PUT '%s' '%s' '%s' '%s'", soup_uri->scheme, soup_uri->host, soup_uri->path, cookie);
- run_handler(uzbl.behave.cookie_handler, s->str);
- g_free (cookie);
- g_string_free(s, TRUE);
- }
+cmd_set_cookie_handler() {
+ if(uzbl.behave.cookie_handler[0] == 0) {
+ g_free(uzbl.behave.cookie_handler);
+ uzbl.behave.cookie_handler = NULL;
+ }
- g_slist_free(ck);
+ uzbl_cookie_jar_set_handler(uzbl.net.soup_cookie_jar, uzbl.behave.cookie_handler);
}
diff --git a/src/callbacks.h b/src/callbacks.h
index fdd08e4..a4258f2 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -16,6 +16,9 @@ void
set_authentication_handler();
void
+set_status_background();
+
+void
set_icon();
void
@@ -59,6 +62,9 @@ void
cmd_set_zoom_type();
void
+cmd_enable_pagecache();
+
+void
cmd_disable_plugins();
void
@@ -143,16 +149,10 @@ void
title_change_cb (WebKitWebView* web_view, GParamSpec param_spec);
void
-progress_change_cb (WebKitWebView* page, gint progress, gpointer data);
-
-void
-load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data);
+progress_change_cb (WebKitWebView* web_view, GParamSpec param_spec);
void
-load_start_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data);
-
-void
-load_finish_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data);
+load_status_change_cb (WebKitWebView* web_view, GParamSpec param_spec);
void
load_error_cb (WebKitWebView* page, WebKitWebFrame* frame, gchar *uri, gpointer web_err, gpointer ud);
@@ -211,8 +211,11 @@ button_release_cb (GtkWidget* window, GdkEventButton* event);
gboolean
focus_cb(GtkWidget* window, GdkEventFocus* event, void *ud);
-void
-save_cookies_js(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie, gpointer user_data);
+gboolean
+scroll_vert_cb(GtkAdjustment *adjust, void *w);
+
+gboolean
+scroll_horiz_cb(GtkAdjustment *adjust, void *w);
void
-save_cookies_http(SoupMessage *msg, gpointer user_data);
+cmd_set_cookie_handler();
diff --git a/src/cookie-jar.c b/src/cookie-jar.c
new file mode 100644
index 0000000..f2e340b
--- /dev/null
+++ b/src/cookie-jar.c
@@ -0,0 +1,306 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <poll.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libsoup/soup-uri.h>
+#include <libsoup/soup-cookie.h>
+
+#include "cookie-jar.h"
+#include "uzbl-core.h"
+
+static void
+uzbl_cookie_jar_session_feature_init(SoupSessionFeatureInterface *iface, gpointer user_data);
+
+G_DEFINE_TYPE_WITH_CODE (UzblCookieJar, soup_cookie_jar_socket, SOUP_TYPE_COOKIE_JAR,
+ G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, uzbl_cookie_jar_session_feature_init))
+
+static void request_started (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg, SoupSocket *socket);
+static void changed(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie);
+
+static void setup_handler(UzblCookieJar *jar);
+
+static void connect_cookie_socket(UzblCookieJar *jar);
+static void disconnect_cookie_socket(UzblCookieJar *jar);
+
+static gchar *do_socket_request(UzblCookieJar *jar, gchar *request, int request_len);
+
+static bool has_socket_handler(UzblCookieJar *jar) {
+ return jar->socket_path != NULL;
+}
+
+static void
+soup_cookie_jar_socket_init(UzblCookieJar *jar) {
+ jar->handler = NULL;
+ jar->socket_path = NULL;
+ jar->connection_fd = -1;
+}
+
+static void
+finalize(GObject *object) {
+ disconnect_cookie_socket(UZBL_COOKIE_JAR(object));
+ G_OBJECT_CLASS(soup_cookie_jar_socket_parent_class)->finalize(object);
+}
+
+static void
+soup_cookie_jar_socket_class_init(UzblCookieJarClass *socket_class) {
+ G_OBJECT_CLASS(socket_class)->finalize = finalize;
+ SOUP_COOKIE_JAR_CLASS(socket_class)->changed = changed;
+}
+
+/* override SoupCookieJar's request_started handler */
+static void
+uzbl_cookie_jar_session_feature_init(SoupSessionFeatureInterface *iface, gpointer user_data) {
+ (void) user_data;
+ iface->request_started = request_started;
+}
+
+UzblCookieJar *uzbl_cookie_jar_new() {
+ return g_object_new(UZBL_TYPE_COOKIE_JAR, NULL);
+}
+
+void
+uzbl_cookie_jar_set_handler(UzblCookieJar *jar, const gchar* handler) {
+ jar->handler = handler;
+ setup_handler(jar);
+}
+
+char *get_cookies(UzblCookieJar *jar, SoupURI *uri) {
+ gchar *result, *path;
+ GString *s = g_string_new ("GET");
+
+ path = uri->path[0] ? uri->path : "/";
+
+ if(has_socket_handler(jar)) {
+ g_string_append_c(s, 0); /* null-terminate the GET */
+ g_string_append_len(s, uri->scheme, strlen(uri->scheme)+1);
+ g_string_append_len(s, uri->host, strlen(uri->host)+1 );
+ g_string_append_len(s, path, strlen(path)+1 );
+
+ result = do_socket_request(jar, s->str, s->len);
+ /* try it again; older cookie daemons closed the connection after each request */
+ if(result == NULL)
+ result = do_socket_request(jar, s->str, s->len);
+ } else {
+ g_string_append_printf(s, " '%s' '%s' '%s'", uri->scheme, uri->host, uri->path);
+
+ run_handler(jar->handler, s->str);
+ result = g_strdup(uzbl.comm.sync_stdout);
+ }
+ g_string_free(s, TRUE);
+ return result;
+}
+
+/* this is a duplicate of SoupCookieJar's request_started that uses our get_cookies instead */
+static void
+request_started(SoupSessionFeature *feature, SoupSession *session,
+ SoupMessage *msg, SoupSocket *socket) {
+ (void) session; (void) socket;
+ gchar *cookies;
+
+ UzblCookieJar *jar = UZBL_COOKIE_JAR (feature);
+ SoupURI *uri = soup_message_get_uri(msg);
+ gboolean add_to_internal_jar = false;
+
+ if(jar->handler) {
+ cookies = get_cookies(jar, uri);
+ } else {
+ /* no handler is set, fall back to the internal soup cookie jar */
+ cookies = soup_cookie_jar_get_cookies(SOUP_COOKIE_JAR(jar), soup_message_get_uri (msg), TRUE);
+ }
+
+ if (cookies && cookies[0] != 0) {
+ const gchar *next_cookie_start = cookies;
+
+ if (add_to_internal_jar) {
+ /* add the cookie data that we just obtained from the cookie handler
+ to the cookie jar so that javascript has access to them.
+ we set this flag so that we don't trigger the PUT handler. */
+ jar->in_get_callback = true;
+ do {
+ SoupCookie *soup_cookie = soup_cookie_parse(next_cookie_start, uri);
+ if(soup_cookie)
+ soup_cookie_jar_add_cookie(SOUP_COOKIE_JAR(uzbl.net.soup_cookie_jar), soup_cookie);
+ next_cookie_start = strchr(next_cookie_start, ';');
+ } while(next_cookie_start++ != NULL);
+ jar->in_get_callback = false;
+ }
+
+ soup_message_headers_replace (msg->request_headers, "Cookie", cookies);
+ } else {
+ soup_message_headers_remove (msg->request_headers, "Cookie");
+ }
+
+ if(cookies)
+ g_free (cookies);
+}
+
+static void
+changed(SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) {
+ (void) old_cookie;
+
+ UzblCookieJar *uzbl_jar = UZBL_COOKIE_JAR(jar);
+
+ /* when Uzbl begins an HTTP request, it GETs cookies from the handler
+ and then adds them to the cookie jar so that javascript can access
+ these cookies. this causes a 'changed' callback, which we don't want
+ to do anything, so we just return.
+
+ (if SoupCookieJar let us override soup_cookie_jar_get_cookies we
+ wouldn't have to do this.) */
+ if(uzbl_jar->in_get_callback)
+ return;
+
+ /* 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)
+ return;
+
+ 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);
+ g_string_append_len(s, new_cookie->domain, strlen(new_cookie->domain)+1 );
+ g_string_append_len(s, new_cookie->path, strlen(new_cookie->path)+1 );
+ g_string_append_printf(s, "%s=%s", new_cookie->name, new_cookie->value);
+
+ gchar *result = do_socket_request(uzbl_jar, s->str, s->len+1);
+ /* try it again; older cookie daemons closed the connection after each request */
+ if(!result)
+ result = do_socket_request(uzbl_jar, s->str, s->len+1);
+
+ g_free(result);
+ } else {
+ g_string_append_printf(s, " '%s' '%s' '%s' '%s=%s'", scheme, new_cookie->domain, new_cookie->path, new_cookie->name, new_cookie->value);
+
+ run_handler(uzbl_jar->handler, s->str);
+ }
+
+ g_string_free(s, TRUE);
+}
+
+static void
+setup_handler(UzblCookieJar *jar) {
+ if(jar->handler && strncmp(jar->handler, "talk_to_socket", strlen("talk_to_socket")) == 0) {
+ /* extract the socket path from the handler. */
+ jar->socket_path = jar->handler + strlen("talk_to_socket");
+ while(isspace(*jar->socket_path))
+ jar->socket_path++;
+ if(*jar->socket_path == 0)
+ return; /* there was no path specified. */
+ disconnect_cookie_socket(jar);
+ connect_cookie_socket(jar);
+ } else {
+ jar->socket_path = NULL;
+ }
+}
+
+static void
+connect_cookie_socket(UzblCookieJar *jar) {
+ struct sockaddr_un sa;
+ int fd;
+
+ g_strlcpy(sa.sun_path, jar->socket_path, sizeof(sa.sun_path));
+ sa.sun_family = AF_UNIX;
+
+ /* create socket file descriptor and connect it to path */
+ fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ if(fd == -1) {
+ g_printerr("connect_cookie_socket: creating socket failed (%s)\n", strerror(errno));
+ return;
+ }
+
+ if(connect(fd, (struct sockaddr*)&sa, sizeof(sa))) {
+ g_printerr("connect_cookie_socket: connect failed (%s)\n", strerror(errno));
+ close(fd);
+ return;
+ }
+
+ /* successful connection! */
+ jar->connection_fd = fd;
+}
+
+static void
+disconnect_cookie_socket(UzblCookieJar *jar) {
+ if(jar->connection_fd > 0) {
+ close(jar->connection_fd);
+ jar->connection_fd = -1;
+ }
+}
+
+static gchar *do_socket_request(UzblCookieJar *jar, gchar *request, int request_length) {
+ int len;
+ ssize_t ret;
+ struct pollfd pfd;
+ gchar *result = NULL;
+
+ if(jar->connection_fd < 0)
+ connect_cookie_socket(jar); /* connection was lost, reconnect */
+
+ /* write request */
+ ret = write(jar->connection_fd, request, request_length);
+ if(ret == -1) {
+ g_printerr("talk_to_socket: write failed (%s)\n", strerror(errno));
+ disconnect_cookie_socket(jar);
+ return NULL;
+ }
+
+ /* wait for a response, with a 500ms timeout */
+ pfd.fd = jar->connection_fd;
+ pfd.events = POLLIN;
+ while(1) {
+ ret = poll(&pfd, 1, 500);
+ if(ret == 1) break;
+ if(ret == 0) errno = ETIMEDOUT;
+ if(errno == EINTR) continue;
+ g_printerr("talk_to_socket: poll failed while waiting for input (%s)\n",
+ strerror(errno));
+ if(errno != ETIMEDOUT)
+ disconnect_cookie_socket(jar);
+ return NULL;
+ }
+
+ /* get length of response */
+ if(ioctl(jar->connection_fd, FIONREAD, &len) == -1) {
+ g_printerr("talk_to_socket: cannot find daemon response length, "
+ "ioctl failed (%s)\n", strerror(errno));
+ disconnect_cookie_socket(jar);
+ return NULL;
+ }
+
+ /* there was an empty response. */
+ if(len == 0)
+ return g_strdup("");
+
+ /* there is a response, read it */
+ result = g_malloc(len + 1);
+ if(!result) {
+ g_printerr("talk_to_socket: failed to allocate %d bytes\n", len);
+ return NULL;
+ }
+ result[len] = 0; /* ensure result is null terminated */
+
+ gchar *p = result;
+ while(len > 0) {
+ ret = read(jar->connection_fd, p, len);
+ if(ret == -1) {
+ g_printerr("talk_to_socket: failed to read from socket (%s)\n",
+ strerror(errno));
+ disconnect_cookie_socket(jar);
+ g_free(result);
+ return NULL;
+ } else {
+ len -= ret;
+ p += ret;
+ }
+ }
+
+ return result;
+}
diff --git a/src/cookie-jar.h b/src/cookie-jar.h
new file mode 100644
index 0000000..80af00e
--- /dev/null
+++ b/src/cookie-jar.h
@@ -0,0 +1,33 @@
+#ifndef UZBL_COOKIE_JAR_H
+#define UZBL_COOKIE_JAR_H
+
+#include <libsoup/soup-cookie-jar.h>
+
+#define UZBL_TYPE_COOKIE_JAR (soup_cookie_jar_socket_get_type ())
+#define UZBL_COOKIE_JAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UZBL_TYPE_COOKIE_JAR, UzblCookieJar))
+#define UZBL_COOKIE_JAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UZBL_TYPE_COOKIE_JAR, UzblCookieJarClass))
+
+typedef struct {
+ SoupCookieJar parent;
+
+ const gchar *handler;
+
+ const gchar *socket_path;
+ int connection_fd;
+
+ gboolean in_get_callback;
+} UzblCookieJar;
+
+typedef struct {
+ SoupCookieJarClass parent_class;
+} UzblCookieJarClass;
+
+UzblCookieJar *uzbl_cookie_jar_new();
+
+void
+uzbl_cookie_jar_set_handler(UzblCookieJar *jar, const gchar *handler);
+
+char
+*get_cookies(UzblCookieJar *jar, SoupURI *uri);
+
+#endif
diff --git a/src/events.c b/src/events.c
index c209550..20e3675 100644
--- a/src/events.c
+++ b/src/events.c
@@ -46,6 +46,9 @@ const char *event_table[LAST_EVENT] = {
"COMMAND_ERROR" ,
"BUILTINS" ,
"PTR_MOVE"
+ "PTR_MOVE" ,
+ "SCROLL_VERT" ,
+ "SCROLL_HORIZ"
};
void
@@ -57,56 +60,53 @@ event_buffer_timeout(guint sec) {
setitimer(ITIMER_REAL, &t, NULL);
}
-
-void
-send_event_socket(GString *msg) {
+static void
+send_event_sockets(GPtrArray *sockets, GString *msg) {
GError *error = NULL;
- GString *tmp;
- GIOChannel *gio = NULL;
GIOStatus ret;
gsize len;
- guint i=0, j=0;
+ guint i=0;
+
+ while(i < sockets->len) {
+ GIOChannel *gio = g_ptr_array_index(sockets, i++);
+
+ if(gio && gio->is_writeable && msg) {
+ ret = g_io_channel_write_chars (gio,
+ msg->str, msg->len,
+ &len, &error);
+
+ if (ret == G_IO_STATUS_ERROR)
+ g_warning ("Error sending event to socket: %s", error->message);
+ else
+ g_io_channel_flush(gio, &error);
+ }
+ }
+}
+
+static void
+replay_buffered_events() {
+ guint i = 0;
+ event_buffer_timeout(0);
+
+ /* replay buffered events */
+ while(i < uzbl.state.event_buffer->len) {
+ GString *tmp = g_ptr_array_index(uzbl.state.event_buffer, i++);
+ send_event_sockets(uzbl.comm.connect_chan, tmp);
+ g_string_free(tmp, TRUE);
+ }
+
+ g_ptr_array_free(uzbl.state.event_buffer, TRUE);
+ uzbl.state.event_buffer = NULL;
+}
+
+void
+send_event_socket(GString *msg) {
/* write to all --connect-socket sockets */
if(uzbl.comm.connect_chan) {
- while(i < uzbl.comm.connect_chan->len) {
- gio = g_ptr_array_index(uzbl.comm.connect_chan, i++);
- j=0;
-
- if(gio && gio->is_writeable) {
- if(uzbl.state.event_buffer) {
- event_buffer_timeout(0);
-
- /* replay buffered events */
- while(j < uzbl.state.event_buffer->len) {
- tmp = g_ptr_array_index(uzbl.state.event_buffer, j++);
- ret = g_io_channel_write_chars (gio,
- tmp->str, tmp->len,
- &len, &error);
-
- if (ret == G_IO_STATUS_ERROR)
- g_warning ("Error sending event to socket: %s", error->message);
- else
- g_io_channel_flush(gio, &error);
- }
- }
-
- if(msg) {
- ret = g_io_channel_write_chars (gio,
- msg->str, msg->len,
- &len, &error);
-
- if (ret == G_IO_STATUS_ERROR)
- g_warning ("Error sending event to socket: %s", error->message);
- else
- g_io_channel_flush(gio, &error);
- }
- }
- }
- if(uzbl.state.event_buffer) {
- g_ptr_array_free(uzbl.state.event_buffer, TRUE);
- uzbl.state.event_buffer = NULL;
- }
+ send_event_sockets(uzbl.comm.connect_chan, msg);
+ if(uzbl.state.event_buffer)
+ replay_buffered_events();
}
/* buffer events until a socket is set and connected
* or a timeout is encountered
@@ -118,22 +118,8 @@ send_event_socket(GString *msg) {
}
/* write to all client sockets */
- i=0;
if(msg && uzbl.comm.client_chan) {
- while(i < uzbl.comm.client_chan->len) {
- gio = g_ptr_array_index(uzbl.comm.client_chan, i++);
-
- if(gio && gio->is_writeable && msg) {
- ret = g_io_channel_write_chars (gio,
- msg->str, msg->len,
- &len, &error);
-
- if (ret == G_IO_STATUS_ERROR)
- g_warning ("Error sending event to socket: %s", error->message);
- else
- g_io_channel_flush(gio, &error);
- }
- }
+ send_event_sockets(uzbl.comm.client_chan, msg);
}
}
diff --git a/src/events.h b/src/events.h
index 1bd8804..bc7960d 100644
--- a/src/events.h
+++ b/src/events.h
@@ -15,7 +15,7 @@ enum event_type {
LINK_UNHOVER, FORM_ACTIVE, ROOT_ACTIVE,
FOCUS_LOST, FOCUS_GAINED, FILE_INCLUDED,
PLUG_CREATED, COMMAND_ERROR, BUILTINS,
- PTR_MOVE,
+ PTR_MOVE, SCROLL_VERT, SCROLL_HORIZ,
/* must be last entry */
LAST_EVENT
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..c9c728e
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,110 @@
+#define _POSIX_SOURCE
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "util.h"
+
+const XDG_Var XDG[] =
+{
+ { "XDG_CONFIG_HOME", "~/.config" },
+ { "XDG_DATA_HOME", "~/.local/share" },
+ { "XDG_CACHE_HOME", "~/.cache" },
+ { "XDG_CONFIG_DIRS", "/etc/xdg" },
+ { "XDG_DATA_DIRS", "/usr/local/share/:/usr/share/" },
+};
+
+/*@null@*/ gchar*
+get_xdg_var (XDG_Var xdg) {
+ const gchar* actual_value = getenv (xdg.environmental);
+ const gchar* home = getenv ("HOME");
+ gchar* return_value;
+
+ if (! actual_value || strcmp (actual_value, "") == 0) {
+ if (xdg.default_value) {
+ return_value = str_replace ("~", home, xdg.default_value);
+ } else {
+ return_value = NULL;
+ }
+ } else {
+ return_value = str_replace("~", home, actual_value);
+ }
+
+ return return_value;
+}
+
+/*@null@*/ gchar*
+find_xdg_file (int xdg_type, const char* filename) {
+ /* xdg_type = 0 => config
+ xdg_type = 1 => data
+ xdg_type = 2 => cache*/
+
+ gchar* xdgv = get_xdg_var (XDG[xdg_type]);
+ gchar* temporary_file = g_strconcat (xdgv, filename, NULL);
+ g_free (xdgv);
+
+ gchar* temporary_string;
+ char* saveptr;
+ char* buf;
+
+ if (! file_exists (temporary_file) && xdg_type != 2) {
+ buf = get_xdg_var (XDG[3 + xdg_type]);
+ temporary_string = (char *) strtok_r (buf, ":", &saveptr);
+ g_free(buf);
+
+ while ((temporary_string = (char * ) strtok_r (NULL, ":", &saveptr)) && ! file_exists (temporary_file)) {
+ g_free (temporary_file);
+ temporary_file = g_strconcat (temporary_string, filename, NULL);
+ }
+ }
+
+ //g_free (temporary_string); - segfaults.
+
+ if (file_exists (temporary_file)) {
+ return temporary_file;
+ } else {
+ g_free(temporary_file);
+ return NULL;
+ }
+}
+
+gboolean
+file_exists (const char * filename) {
+ return (access(filename, F_OK) == 0);
+}
+
+char *
+str_replace (const char* search, const char* replace, const char* string) {
+ gchar **buf;
+ char *ret;
+
+ if(!string)
+ return NULL;
+
+ buf = g_strsplit (string, search, -1);
+ ret = g_strjoinv (replace, buf);
+ g_strfreev(buf);
+
+ return ret;
+}
+
+gboolean
+for_each_line_in_file(const gchar *path, void (*callback)(const gchar *l, void *c), void *user_data) {
+ gchar *line = NULL;
+ gsize len;
+
+ GIOChannel *chan = g_io_channel_new_file(path, "r", NULL);
+
+ if (chan) {
+ while (g_io_channel_read_line(chan, &line, &len, NULL, NULL) == G_IO_STATUS_NORMAL) {
+ callback(line, user_data);
+ g_free(line);
+ }
+ g_io_channel_unref (chan);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..f03f13e
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,18 @@
+#include <glib.h>
+
+typedef struct {
+ gchar* environmental;
+ gchar* default_value;
+} XDG_Var;
+
+gchar* get_xdg_var (XDG_Var xdg);
+
+gchar* find_xdg_file (int xdg_type, const char* filename);
+
+gboolean file_exists(const char* filename);
+
+char *
+str_replace (const char* search, const char* replace, const char* string);
+
+gboolean
+for_each_line_in_file(const gchar *path, void (*callback)(const gchar *l, void *c), void *user_data);
diff --git a/src/uzbl-browser b/src/uzbl-browser
index de4f7af..88d3742 100755
--- a/src/uzbl-browser
+++ b/src/uzbl-browser
@@ -1,66 +1,80 @@
#!/bin/sh
-# this script implements a more useful out-of-the-box "browsing experience".
-# it does so by combining uzbl-core with a set of "recommended" tools and practices.
-# see docs for more info
-# If you want to customize the behavior of the cookie-daemon or similar helper tools,
-# copy them to your $XDG_DATA_HOME/uzbl/scripts/, edit them and update $PATH
-
-# Also, we assume existence of fifo/socket == correctly functioning cookie_daemon/event_manager.
-# Checking correct functioning of the daemons here would be too complex here, and it's not implemented in uzbl-core either.
-# But this shouldn't cause much problems..
+#
+# This script implements a more useful out-of-the-box "browsing experience".
+# It does so by combining uzbl-core with a set of "recommended" tools and
+# practices. See docs for more info.
+#
+# If you want to customize the behavior any of the helper tools, copy them
+# to your $XDG_DATA_HOME/uzbl/scripts/ and edit them
PREFIX=/usr/local
-if [ -z "$XDG_DATA_HOME" ]
-then
- export XDG_DATA_HOME=$HOME/.local/share
-fi
+EXAMPLES=$PREFIX/share/uzbl/examples
-if [ -z "$XDG_CACHE_HOME" ]
-then
- export XDG_CACHE_HOME=$HOME/.cache
-fi
+XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
+export XDG_DATA_HOME
-if [ -z "$XDG_CONFIG_HOME" ]
-then
- export XDG_CONFIG_HOME=$HOME/.config
-fi
+XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
+export XDG_CACHE_HOME
+
+XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
+export XDG_CONFIG_HOME
# assure the relevant directories exist.
-for dir in $XDG_CACHE_HOME/uzbl $XDG_DATA_HOME/uzbl $XDG_CONFIG_HOME/uzbl
+for dir in "$XDG_CACHE_HOME"/uzbl "$XDG_DATA_HOME"/uzbl "$XDG_CONFIG_HOME"/uzbl
do
- if [ ! -d $dir ]
+ if [ ! -d "$dir" ]
then
- if ! mkdir -p $dir
+ if ! mkdir -p "$dir"
then
echo "could not create $dir" >&2
exit 2
fi
fi
done
+
# if no config exists yet in the recommended location, put the default (recommended) config there
-if [ ! -f $XDG_CONFIG_HOME/uzbl/config ]
+if [ ! -f "$XDG_CONFIG_HOME"/uzbl/config ]
then
- if ! cp $PREFIX/share/uzbl/examples/config/config $XDG_CONFIG_HOME/uzbl/config
+ if [ ! -r "$EXAMPLES"/config/config ]
then
- echo "Could not copy default config to $XDG_CONFIG_HOME/uzbl/config" >&2
+ echo "Error: Global config not found; please check if your distribution ships them separately"
exit 3
fi
+ if ! cp "$EXAMPLES"/config/config "$XDG_CONFIG_HOME"/uzbl/config
+ then
+ echo "Could not copy default config to $XDG_CONFIG_HOME/uzbl/config" >&2
+ # Run with the global config as a last resort
+ config_file=$EXAMPLES/config/config
+ fi
+fi
+
+# this variable is used by the default helper scripts as a location to
+# load shared code from
+if [ -z "$UZBL_UTIL_DIR" ]
+then
+ if [ -d "$XDG_DATA_HOME"/uzbl/scripts/util ]
+ then
+ UZBL_UTIL_DIR=$XDG_DATA_HOME/uzbl/scripts/util
+ elif [ -d $EXAMPLES/data/scripts/util ]
+ then
+ UZBL_UTIL_DIR=$EXAMPLES/data/scripts/util
+ fi
+ export UZBL_UTIL_DIR
fi
-# Uncomment this for a slight speedup at the expense of not having
-# stale cookie daemon sockets cleaned up.
-#if [ ! -S $XDG_CACHE_HOME/uzbl/cookie_daemon_socket ]
+# uzbl-cookie-manager will exit if another instance is already running.
+# 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
- # if you want to customize it, copy to your $XDG_DATA_HOME/uzbl/scripts/ and update $PATH
- uzbl-cookie-daemon -v start
+ ${UZBL_COOKIE_DAEMON:-uzbl-cookie-manager}
#fi
-DAEMON_SOCKET=$XDG_CACHE_HOME/uzbl/event_daemon
-DAEMON_PID=${DAEMON_SOCKET}.pid
-
-#if [ -f "$DAEMON_PID" ]
+# uzbl-event-manager will exit if one is already running.
+# we could also check if its pid file exists to avoid having to spawn it.
+DAEMON_SOCKET="$XDG_CACHE_HOME"/uzbl/event_daemon
+#if [ ! -f "$DAEMON_SOCKET".pid ]
#then
- uzbl-event-manager -va start
+ ${UZBL_EVENT_MANAGER:-uzbl-event-manager -va start}
#fi
-exec uzbl-core "$@" --connect-socket $DAEMON_SOCKET
+exec uzbl-core "$@" ${config_file:+--config "$config_file"} --connect-socket $DAEMON_SOCKET
diff --git a/src/uzbl-core.c b/src/uzbl-core.c
index 42412ef..794257f 100644
--- a/src/uzbl-core.c
+++ b/src/uzbl-core.c
@@ -34,6 +34,7 @@
#include "events.h"
#include "inspector.h"
#include "config.h"
+#include "util.h"
UzblCore uzbl;
@@ -62,15 +63,6 @@ GOptionEntry entries[] =
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
-XDG_Var XDG[] =
-{
- { "XDG_CONFIG_HOME", "~/.config" },
- { "XDG_DATA_HOME", "~/.local/share" },
- { "XDG_CACHE_HOME", "~/.cache" },
- { "XDG_CONFIG_DIRS", "/etc/xdg" },
- { "XDG_DATA_DIRS", "/usr/local/share/:/usr/share/" },
-};
-
/* abbreviations to help keep the table's width humane */
#define PTR_V_STR(var, d, fun) { .ptr.s = &(var), .type = TYPE_STR, .dump = d, .writeable = 1, .func = fun }
#define PTR_V_INT(var, d, fun) { .ptr.i = (int*)&(var), .type = TYPE_INT, .dump = d, .writeable = 1, .func = fun }
@@ -93,12 +85,12 @@ const struct var_name_to_ptr_t {
{ "show_status", PTR_V_INT(uzbl.behave.show_status, 1, cmd_set_status)},
{ "status_top", PTR_V_INT(uzbl.behave.status_top, 1, move_statusbar)},
{ "status_format", PTR_V_STR(uzbl.behave.status_format, 1, NULL)},
- { "status_background", PTR_V_STR(uzbl.behave.status_background, 1, NULL)},
+ { "status_background", PTR_V_STR(uzbl.behave.status_background, 1, set_status_background)},
{ "title_format_long", PTR_V_STR(uzbl.behave.title_format_long, 1, NULL)},
{ "title_format_short", PTR_V_STR(uzbl.behave.title_format_short, 1, NULL)},
{ "icon", PTR_V_STR(uzbl.gui.icon, 1, set_icon)},
{ "forward_keys", PTR_V_INT(uzbl.behave.forward_keys, 1, NULL)},
- { "cookie_handler", PTR_V_STR(uzbl.behave.cookie_handler, 1, NULL)},
+ { "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)},
{ "fifo_dir", PTR_V_STR(uzbl.behave.fifo_dir, 1, cmd_fifo_dir)},
@@ -125,6 +117,7 @@ const struct var_name_to_ptr_t {
{ "fantasy_font_family", PTR_V_STR(uzbl.behave.fantasy_font_family, 1, cmd_fantasy_font_family)},
{ "monospace_size", PTR_V_INT(uzbl.behave.monospace_size, 1, cmd_font_size)},
{ "minimum_font_size", PTR_V_INT(uzbl.behave.minimum_font_size, 1, cmd_minimum_font_size)},
+ { "enable_pagecache", PTR_V_INT(uzbl.behave.enable_pagecache, 1, cmd_enable_pagecache)},
{ "disable_plugins", PTR_V_INT(uzbl.behave.disable_plugins, 1, cmd_disable_plugins)},
{ "disable_scripts", PTR_V_INT(uzbl.behave.disable_scripts, 1, cmd_disable_scripts)},
{ "autoload_images", PTR_V_INT(uzbl.behave.autoload_img, 1, cmd_autoload_img)},
@@ -372,48 +365,6 @@ strfree(gchar *str) {
gchar*
argv_idx(const GArray *a, const guint idx) { return g_array_index(a, gchar*, idx); }
-char *
-str_replace (const char* search, const char* replace, const char* string) {
- gchar **buf;
- char *ret;
-
- if(!string)
- return NULL;
-
- buf = g_strsplit (string, search, -1);
- ret = g_strjoinv (replace, buf);
- g_strfreev(buf);
-
- return ret;
-}
-
-GArray*
-read_file_by_line (const gchar *path) {
- GIOChannel *chan = NULL;
- gchar *readbuf = NULL;
- gsize len;
- GArray *lines = g_array_new(TRUE, FALSE, sizeof(gchar*));
- int i = 0;
-
- chan = g_io_channel_new_file(path, "r", NULL);
- if (chan) {
- while (g_io_channel_read_line(chan, &readbuf, &len, NULL, NULL) == G_IO_STATUS_NORMAL) {
- const gchar* val = g_strdup (readbuf);
- g_array_append_val (lines, val);
- g_free (readbuf);
- i ++;
- }
-
- g_io_channel_unref (chan);
- } else {
- gchar *tmp = g_strdup_printf("File %s can not be read.", path);
- send_event(COMMAND_ERROR, tmp, NULL);
- g_free(tmp);
- }
-
- return lines;
-}
-
/* search a PATH style string for an existing file+path combination */
gchar*
find_existing_file(gchar* path_list) {
@@ -679,7 +630,6 @@ struct {const char *key; CommandInfo value;} cmdlist[] =
{ "sync_spawn", {spawn_sync, 0} }, // needed for cookie handler
{ "sh", {spawn_sh, 0} },
{ "sync_sh", {spawn_sh_sync, 0} }, // needed for cookie handler
- { "talk_to_socket", {talk_to_socket, 0} },
{ "exit", {close_uzbl, 0} },
{ "search", {search_forward_text, TRUE} },
{ "search_reverse", {search_reverse_text, TRUE} },
@@ -705,7 +655,8 @@ struct {const char *key; CommandInfo value;} cmdlist[] =
{ "menu_image_remove", {menu_remove_image, TRUE} },
{ "menu_editable_remove", {menu_remove_edit, TRUE} },
{ "hardcopy", {hardcopy, TRUE} },
- { "include", {include, TRUE} }
+ { "include", {include, TRUE} },
+ { "show_inspector", {show_inspector, 0} }
};
void
@@ -735,11 +686,6 @@ builtins() {
/* -- CORE FUNCTIONS -- */
-bool
-file_exists (const char * filename) {
- return (access(filename, F_OK) == 0);
-}
-
void
set_var(WebKitWebView *page, GArray *argv, GString *result) {
(void) page; (void) result;
@@ -970,28 +916,30 @@ hardcopy(WebKitWebView *page, GArray *argv, GString *result) {
webkit_web_frame_print(webkit_web_view_get_main_frame(page));
}
+/* just a wrapper so parse_cmd_line can be used with for_each_line_in_file */
+static void
+parse_cmd_line_cb(const char *line, void *user_data) {
+ (void) user_data;
+ parse_cmd_line(line, NULL);
+}
+
void
include(WebKitWebView *page, GArray *argv, GString *result) {
(void) page;
(void) result;
gchar *pe = NULL,
- *path = NULL,
- *line;
- int i=0;
+ *path = NULL;
if(!argv_idx(argv, 0))
return;
pe = parseenv(argv_idx(argv, 0));
if((path = find_existing_file(pe))) {
- GArray* lines = read_file_by_line(path);
-
- while ((line = g_array_index(lines, gchar*, i))) {
- parse_cmd_line (line, NULL);
- i++;
- g_free (line);
+ 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);
+ g_free(tmp);
}
- g_array_free (lines, TRUE);
send_event(FILE_INCLUDED, path, NULL);
g_free(path);
@@ -1000,6 +948,13 @@ include(WebKitWebView *page, GArray *argv, GString *result) {
}
void
+show_inspector(WebKitWebView *page, GArray *argv, GString *result) {
+ (void) page; (void) argv; (void) result;
+
+ webkit_web_inspector_show(uzbl.gui.inspector);
+}
+
+void
act_dump_config() {
dump_config();
}
@@ -1156,32 +1111,23 @@ run_external_js (WebKitWebView * web_view, GArray *argv, GString *result) {
if (argv_idx(argv, 0) &&
((path = find_existing_file(argv_idx(argv, 0)))) ) {
- GArray* lines = read_file_by_line (path);
- gchar* js = NULL;
- int i = 0;
- gchar* line;
-
- while ((line = g_array_index(lines, gchar*, i))) {
- if (js == NULL) {
- js = g_strdup (line);
- } else {
- gchar* newjs = g_strconcat (js, line, NULL);
- js = newjs;
- }
- i ++;
- g_free (line);
+ gchar *file_contents = NULL;
+
+ GIOChannel *chan = g_io_channel_new_file(path, "r", NULL);
+ if (chan) {
+ gsize len;
+ g_io_channel_read_to_end(chan, &file_contents, &len, NULL);
+ g_io_channel_unref (chan);
}
if (uzbl.state.verbose)
printf ("External JavaScript file %s loaded\n", argv_idx(argv, 0));
- gchar* newjs = str_replace("%s", argv_idx (argv, 1)?argv_idx (argv, 1):"", js);
- g_free (js);
- js = newjs;
+ gchar *js = str_replace("%s", argv_idx (argv, 1) ? argv_idx (argv, 1) : "", file_contents);
+ g_free (file_contents);
eval_js (web_view, js, result, path);
g_free (js);
- g_array_free (lines, TRUE);
g_free(path);
}
}
@@ -1274,6 +1220,7 @@ run_command (const gchar *command, const guint npre, const gchar **args,
gchar *pid = itos(getpid());
gchar *xwin = itos(uzbl.xwin);
guint i;
+
sharg_append(a, command);
for (i = 0; i < npre; i++) /* add n args before the default vars */
sharg_append(a, args[i]);
@@ -1432,118 +1379,6 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) {
}
void
-talk_to_socket(WebKitWebView *web_view, GArray *argv, GString *result) {
- (void)web_view; (void)result;
-
- int fd, len;
- struct sockaddr_un sa;
- char* sockpath;
- ssize_t ret;
- struct pollfd pfd;
- struct iovec* iov;
- guint i;
-
- if(uzbl.comm.sync_stdout) uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
-
- /* This function could be optimised by storing a hash table of socket paths
- and associated connected file descriptors rather than closing and
- re-opening for every call. Also we could launch a script if socket connect
- fails. */
-
- /* First element argv[0] is path to socket. Following elements are tokens to
- write to the socket. We write them as a single packet with each token
- separated by an ASCII nul (\0). */
- if(argv->len < 2) {
- g_printerr("talk_to_socket called with only %d args (need at least two).\n",
- (int)argv->len);
- return;
- }
-
- /* copy socket path, null terminate result */
- sockpath = g_array_index(argv, char*, 0);
- g_strlcpy(sa.sun_path, sockpath, sizeof(sa.sun_path));
- sa.sun_family = AF_UNIX;
-
- /* create socket file descriptor and connect it to path */
- fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
- if(fd == -1) {
- g_printerr("talk_to_socket: creating socket failed (%s)\n", strerror(errno));
- return;
- }
- if(connect(fd, (struct sockaddr*)&sa, sizeof(sa))) {
- g_printerr("talk_to_socket: connect failed (%s)\n", strerror(errno));
- close(fd);
- return;
- }
-
- /* build request vector */
- iov = g_malloc(sizeof(struct iovec) * (argv->len - 1));
- if(!iov) {
- g_printerr("talk_to_socket: unable to allocated memory for token vector\n");
- close(fd);
- return;
- }
- for(i = 1; i < argv->len; ++i) {
- iov[i - 1].iov_base = g_array_index(argv, char*, i);
- iov[i - 1].iov_len = strlen(iov[i - 1].iov_base) + 1; /* string plus \0 */
- }
-
- /* write request */
- ret = writev(fd, iov, argv->len - 1);
- g_free(iov);
- if(ret == -1) {
- g_printerr("talk_to_socket: write failed (%s)\n", strerror(errno));
- close(fd);
- return;
- }
-
- /* wait for a response, with a 500ms timeout */
- pfd.fd = fd;
- pfd.events = POLLIN;
- while(1) {
- ret = poll(&pfd, 1, 500);
- if(ret == 1) break;
- if(ret == 0) errno = ETIMEDOUT;
- if(errno == EINTR) continue;
- g_printerr("talk_to_socket: poll failed while waiting for input (%s)\n",
- strerror(errno));
- close(fd);
- return;
- }
-
- /* get length of response */
- if(ioctl(fd, FIONREAD, &len) == -1) {
- g_printerr("talk_to_socket: cannot find daemon response length, "
- "ioctl failed (%s)\n", strerror(errno));
- close(fd);
- return;
- }
-
- /* if there is a response, read it */
- if(len) {
- uzbl.comm.sync_stdout = g_malloc(len + 1);
- if(!uzbl.comm.sync_stdout) {
- g_printerr("talk_to_socket: failed to allocate %d bytes\n", len);
- close(fd);
- return;
- }
- uzbl.comm.sync_stdout[len] = 0; /* ensure result is null terminated */
-
- ret = read(fd, uzbl.comm.sync_stdout, len);
- if(ret == -1) {
- g_printerr("talk_to_socket: failed to read from socket (%s)\n",
- strerror(errno));
- close(fd);
- return;
- }
- }
-
- /* clean up */
- close(fd);
- return;
-}
-
-void
parse_command(const char *cmd, const char *param, GString *result) {
CommandInfo *c;
GString *tmp = g_string_new("");
@@ -1716,7 +1551,6 @@ parse_cmd_line(const char *ctl_line, GString *result) {
g_free(ctlstrip);
}
-
/*@null@*/ gchar*
build_stream_name(int type, const gchar* dir) {
State *s = &uzbl.state;
@@ -1993,32 +1827,29 @@ void
update_title (void) {
Behaviour *b = &uzbl.behave;
gchar *parsed;
+ const gchar *current_title;
+ /* this check is here because if we're starting up or shutting down it might not be a window */
+ gboolean have_main_window = !uzbl.state.plug_mode && GTK_IS_WINDOW(uzbl.gui.main_window);
+
+ if(have_main_window)
+ current_title = gtk_window_get_title (GTK_WINDOW(uzbl.gui.main_window));
if (b->show_status) {
- if (b->title_format_short) {
+ if (b->title_format_short && have_main_window) {
parsed = expand(b->title_format_short, 0);
- if (uzbl.gui.main_window)
+ if(!current_title || strcmp(current_title, parsed))
gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
g_free(parsed);
}
- if (b->status_format) {
+ if (b->status_format && GTK_IS_LABEL(uzbl.gui.mainbar_label)) {
parsed = expand(b->status_format, 0);
gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), parsed);
g_free(parsed);
}
- if (b->status_background) {
- GdkColor color;
- gdk_color_parse (b->status_background, &color);
- //labels and hboxes do not draw their own background. applying this on the vbox/main_window is ok as the statusbar is the only affected widget. (if not, we could also use GtkEventBox)
- if (uzbl.gui.main_window)
- gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color);
- else if (uzbl.gui.plug)
- gtk_widget_modify_bg (GTK_WIDGET(uzbl.gui.plug), GTK_STATE_NORMAL, &color);
- }
} else {
- if (b->title_format_long) {
+ if (b->title_format_long && have_main_window) {
parsed = expand(b->title_format_long, 0);
- if (uzbl.gui.main_window)
+ if(!current_title || strcmp(current_title, parsed))
gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
g_free(parsed);
}
@@ -2037,12 +1868,10 @@ create_browser () {
"signal::button-press-event", (GCallback)button_press_cb, NULL,
"signal::button-release-event", (GCallback)button_release_cb, NULL,
"signal::motion-notify-event", (GCallback)motion_notify_cb, NULL,
- "signal::title-changed", (GCallback)title_change_cb, NULL,
+ "signal::notify::title", (GCallback)title_change_cb, NULL,
"signal::selection-changed", (GCallback)selection_changed_cb, NULL,
- "signal::load-progress-changed", (GCallback)progress_change_cb, NULL,
- "signal::load-committed", (GCallback)load_commit_cb, NULL,
- "signal::load-started", (GCallback)load_start_cb, NULL,
- "signal::load-finished", (GCallback)load_finish_cb, NULL,
+ "signal::notify::progress", (GCallback)progress_change_cb, NULL,
+ "signal::notify::load-status", (GCallback)load_status_change_cb, NULL,
"signal::load-error", (GCallback)load_error_cb, NULL,
"signal::hovering-over-link", (GCallback)link_hover_cb, NULL,
"signal::navigation-policy-decision-requested", (GCallback)navigation_decision_cb, NULL,
@@ -2125,8 +1954,7 @@ inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *ne
if ((g_strcmp0(actname, "spawn") == 0) ||
(g_strcmp0(actname, "sh") == 0) ||
(g_strcmp0(actname, "sync_spawn") == 0) ||
- (g_strcmp0(actname, "sync_sh") == 0) ||
- (g_strcmp0(actname, "talk_to_socket") == 0)) {
+ (g_strcmp0(actname, "sync_sh") == 0)) {
guint i;
GString *a = g_string_new("");
gchar **spawnparts = split_quoted(origargs, FALSE);
@@ -2222,59 +2050,6 @@ run_handler (const gchar *act, const gchar *args) {
g_strfreev(parts);
}
-/*@null@*/ gchar*
-get_xdg_var (XDG_Var xdg) {
- const gchar* actual_value = getenv (xdg.environmental);
- const gchar* home = getenv ("HOME");
- gchar* return_value;
-
- if (! actual_value || strcmp (actual_value, "") == 0) {
- if (xdg.default_value) {
- return_value = str_replace ("~", home, xdg.default_value);
- } else {
- return_value = NULL;
- }
- } else {
- return_value = str_replace("~", home, actual_value);
- }
-
- return return_value;
-}
-
-/*@null@*/ gchar*
-find_xdg_file (int xdg_type, const char* filename) {
- /* xdg_type = 0 => config
- xdg_type = 1 => data
- xdg_type = 2 => cache*/
-
- gchar* xdgv = get_xdg_var (XDG[xdg_type]);
- gchar* temporary_file = g_strconcat (xdgv, filename, NULL);
- g_free (xdgv);
-
- gchar* temporary_string;
- char* saveptr;
- char* buf;
-
- if (! file_exists (temporary_file) && xdg_type != 2) {
- buf = get_xdg_var (XDG[3 + xdg_type]);
- temporary_string = (char *) strtok_r (buf, ":", &saveptr);
- g_free(buf);
-
- while ((temporary_string = (char * ) strtok_r (NULL, ":", &saveptr)) && ! file_exists (temporary_file)) {
- g_free (temporary_file);
- temporary_file = g_strconcat (temporary_string, filename, NULL);
- }
- }
-
- //g_free (temporary_string); - segfaults.
-
- if (file_exists (temporary_file)) {
- return temporary_file;
- } else {
- g_free(temporary_file);
- return NULL;
- }
-}
void
settings_init () {
State *s = &uzbl.state;
@@ -2295,25 +2070,17 @@ settings_init () {
}
if (s->config_file) {
- GArray* lines = read_file_by_line (s->config_file);
- int i = 0;
- gchar* line;
-
- while ((line = g_array_index(lines, gchar*, i))) {
- parse_cmd_line (line, NULL);
- i ++;
- g_free (line);
+ if(!for_each_line_in_file(s->config_file, parse_cmd_line_cb, NULL)) {
+ gchar *tmp = g_strdup_printf("File %s can not be read.", s->config_file);
+ send_event(COMMAND_ERROR, tmp, NULL);
+ g_free(tmp);
}
- g_array_free (lines, TRUE);
- } else {
- if (uzbl.state.verbose)
- printf ("No configuration file loaded.\n");
- }
+ } else if (uzbl.state.verbose)
+ printf ("No configuration file loaded.\n");
if(s->connect_socket_names)
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);
}
@@ -2373,57 +2140,6 @@ void handle_authentication (SoupSession *session, SoupMessage *msg, SoupAuth *au
}
}
-void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data) {
- (void) session;
- (void) user_data;
-
- soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies_http), NULL);
- GString *s = g_string_new ("");
- SoupURI * soup_uri = soup_message_get_uri(msg);
- g_string_printf(s, "GET '%s' '%s' '%s'", soup_uri->scheme, soup_uri->host, soup_uri->path);
-
- if(uzbl.behave.cookie_handler)
- run_handler(uzbl.behave.cookie_handler, s->str);
-
- if(uzbl.behave.cookie_handler &&
- uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) {
- char *p = strchr(uzbl.comm.sync_stdout, '\n' );
- if ( p != NULL ) *p = '\0';
- soup_message_headers_replace (msg->request_headers, "Cookie", (const char *) uzbl.comm.sync_stdout);
-
- int len = strlen(uzbl.comm.sync_stdout);
-
- if(len > 0) {
- SoupCookie *soup_cookie;
- char *cookies = (char *) g_malloc(len+1);
- strncpy(cookies, uzbl.comm.sync_stdout, len+1);
-
- /* Disconnect to avoid recursion */
- g_object_disconnect(G_OBJECT(uzbl.net.soup_cookie_jar), "any_signal", G_CALLBACK(save_cookies_js), NULL, NULL);
-
- p = cookies - 1;
- while(p != NULL) {
- p = p + 1;
- soup_cookie = soup_cookie_parse((const char *) p, soup_uri);
- if (soup_cookie) {
- if(soup_cookie->domain == NULL)
- soup_cookie->domain = soup_uri->host;
- soup_cookie_jar_add_cookie(uzbl.net.soup_cookie_jar, soup_cookie);
- }
- p = strchr(p, ';');
- }
-
- g_object_connect(G_OBJECT(uzbl.net.soup_cookie_jar), "signal::changed", G_CALLBACK(save_cookies_js), NULL, NULL);
- g_free(cookies);
- }
- }
-
- if (uzbl.comm.sync_stdout)
- uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
-
- g_string_free(s, TRUE);
-}
-
void
dump_var_hash(gpointer k, gpointer v, gpointer ud) {
(void) ud;
@@ -2522,9 +2238,8 @@ initialize(int argc, char *argv[]) {
uzbl.net.soup_session = webkit_get_default_session();
- uzbl.net.soup_cookie_jar = soup_cookie_jar_new();
+ 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));
- g_object_connect(G_OBJECT(uzbl.net.soup_cookie_jar), "signal::changed", G_CALLBACK(save_cookies_js), NULL, NULL);
for(i=0; sigs[i]; i++) {
if(setup_signal(sigs[i], catch_signal) == SIG_ERR)
@@ -2548,6 +2263,7 @@ initialize(int argc, char *argv[]) {
void
load_uri_imp(gchar *uri) {
GString* newuri;
+ SoupURI* soup_uri;
/* Strip leading whitespaces */
while (*uri) {
@@ -2559,26 +2275,28 @@ load_uri_imp(gchar *uri) {
eval_js(uzbl.gui.web_view, uri, NULL, "javascript:");
return;
}
+
newuri = g_string_new (uri);
- if (!soup_uri_new(uri)) {
- GString* fullpath = g_string_new ("");
+ soup_uri = soup_uri_new(uri);
+
+ if (!soup_uri) {
+ gchar* fullpath;
if (g_path_is_absolute (newuri->str))
- g_string_assign (fullpath, newuri->str);
+ fullpath = newuri->str;
else {
- gchar* wd;
- wd = g_get_current_dir ();
- g_string_assign (fullpath, g_build_filename (wd, newuri->str, NULL));
- free(wd);
+ gchar* wd = g_get_current_dir ();
+ fullpath = g_build_filename (wd, newuri->str, NULL);
+ g_free(wd);
}
struct stat stat_result;
- if (! g_stat(fullpath->str, &stat_result)) {
- g_string_prepend (fullpath, "file://");
- g_string_assign (newuri, fullpath->str);
- }
+ if (! g_stat(fullpath, &stat_result))
+ g_string_printf (newuri, "file://%s", fullpath);
else
g_string_prepend (newuri, "http://");
- g_string_free (fullpath, TRUE);
+ } else {
+ soup_uri_free(soup_uri);
}
+
/* if we do handle cookies, ask our handler for them */
webkit_web_view_load_uri (uzbl.gui.web_view, newuri->str);
g_string_free (newuri, TRUE);
@@ -2629,6 +2347,16 @@ main (int argc, char* argv[]) {
uzbl.gui.bar_h = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_h);
gtk_widget_set_scroll_adjustments ((GtkWidget*) uzbl.gui.web_view, uzbl.gui.bar_h, uzbl.gui.bar_v);
+ g_object_connect((GObject*)uzbl.gui.bar_v,
+ "signal::value-changed", (GCallback)scroll_vert_cb, NULL,
+ "signal::changed", (GCallback)scroll_vert_cb, NULL,
+ NULL);
+
+ g_object_connect((GObject*)uzbl.gui.bar_h,
+ "signal::value-changed", (GCallback)scroll_horiz_cb, NULL,
+ "signal::changed", (GCallback)scroll_horiz_cb, NULL,
+ NULL);
+
if(!uzbl.state.instance_name)
uzbl.state.instance_name = itos((int)uzbl.xwin);
diff --git a/src/uzbl-core.h b/src/uzbl-core.h
index 5760423..b5a502e 100644
--- a/src/uzbl-core.h
+++ b/src/uzbl-core.h
@@ -40,6 +40,8 @@
#include <sys/ioctl.h>
#include <assert.h>
+#include "cookie-jar.h"
+
#define LENGTH(x) (sizeof x / sizeof x[0])
/* gui elements */
@@ -104,8 +106,8 @@ typedef struct {
/* networking */
typedef struct {
- SoupSession *soup_session;
- SoupCookieJar *soup_cookie_jar;
+ SoupSession *soup_session;
+ UzblCookieJar *soup_cookie_jar;
SoupLogger *soup_logger;
char *proxy_url;
char *useragent;
@@ -144,6 +146,7 @@ typedef struct {
guint minimum_font_size;
gfloat zoom_level;
gboolean zoom_type;
+ guint enable_pagecache;
guint disable_plugins;
guint disable_scripts;
guint autoload_img;
@@ -204,12 +207,6 @@ extern UzblCore uzbl;
typedef void sigfunc(int);
-/* XDG Stuff */
-typedef struct {
- gchar* environmental;
- gchar* default_value;
-} XDG_Var;
-
/* uzbl variables */
enum ptr_type {TYPE_INT, TYPE_STR, TYPE_FLOAT};
typedef struct {
@@ -228,15 +225,9 @@ typedef struct {
char *
itos(int val);
-char *
-str_replace (const char* search, const char* replace, const char* string);
-
gchar*
strfree(gchar *str);
-GArray*
-read_file_by_line (const gchar *path);
-
gchar*
parseenv (gchar* string);
@@ -261,9 +252,6 @@ print(WebKitWebView *page, GArray *argv, GString *result);
void
commands_hash(void);
-bool
-file_exists (const char * filename);
-
void
load_uri (WebKitWebView * web_view, GArray *argv, GString *result);
@@ -278,9 +266,6 @@ run_command(const gchar *command, const guint npre,
const gchar **args, const gboolean sync, char **output_stdout);
void
-talk_to_socket(WebKitWebView *web_view, GArray *argv, GString *result);
-
-void
spawn(WebKitWebView *web_view, GArray *argv, GString *result);
void
@@ -349,12 +334,6 @@ create_plug ();
void
run_handler (const gchar *act, const gchar *args);
-/*@null@*/ gchar*
-get_xdg_var (XDG_Var xdg);
-
-/*@null@*/ gchar*
-find_xdg_file (int xdg_type, const char* filename);
-
void
settings_init ();
@@ -472,6 +451,9 @@ void
include(WebKitWebView *page, GArray *argv, GString *result);
void
+show_inspector(WebKitWebView *page, GArray *argv, GString *result);
+
+void
builtins();
typedef void (*Command)(WebKitWebView*, GArray *argv, GString *result);