about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMarco Peereboom <marco@conformal.com>2011-11-05 17:26:58 -0500
committerMarco Peereboom <marco@conformal.com>2011-11-05 17:26:58 -0500
commit06e4023aef80e8d5fe4bc5aa220f223ee6f21185 (patch)
treecd1f1ceb457bfec973ca89191909365d7fa73f14
parent4712843c14c43c806b12e8f3017e004f0740cbeb (diff)
downloadxombrero-06e4023aef80e8d5fe4bc5aa220f223ee6f21185.tar.gz
Add autorun JavaScript after page loads
It tries to open a default.js file followed by host.domain.js.  If the
host.domain.js file does not exist it tries to open domain.js.

It reads the content of the default AND host/domain file and executes
it.

All scripts go in the ~/.xxxterm/js/ directory.
-rw-r--r--settings.c2
-rw-r--r--xxxterm.c178
-rw-r--r--xxxterm.conf1
-rw-r--r--xxxterm.h1
4 files changed, 182 insertions, 0 deletions
diff --git a/settings.c b/settings.c
index 5d6494f..6bae81e 100644
--- a/settings.c
+++ b/settings.c
@@ -85,6 +85,7 @@ char		search_file[PATH_MAX];
 char		command_file[PATH_MAX];
 char		*encoding = NULL;
 int		autofocus_onload = 0;
+int		js_autorun_enabled = 1;
 
 char		*cmd_font_name = NULL;
 char		*oops_font_name = NULL;
@@ -254,6 +255,7 @@ struct settings		rs[] = {
 	{ "home",			XT_S_STR, 0, NULL,	&home, NULL },
 	{ "http_proxy",			XT_S_STR, 0, NULL,	&http_proxy, NULL, NULL, set_http_proxy },
 	{ "icon_size",			XT_S_INT, 0,		&icon_size, NULL, NULL },
+	{ "js_autorun_enabled",		XT_S_INT, 0,		&js_autorun_enabled, NULL, NULL },
 	{ "max_connections",		XT_S_INT, XT_SF_RESTART,&max_connections, NULL, NULL },
 	{ "max_host_connections",	XT_S_INT, XT_SF_RESTART,&max_host_connections, NULL, NULL },
 	{ "read_only_cookies",		XT_S_INT, 0,		&read_only_cookies, NULL, NULL },
diff --git a/xxxterm.c b/xxxterm.c
index 1baf5c2..03aa39b 100644
--- a/xxxterm.c
+++ b/xxxterm.c
@@ -81,6 +81,7 @@ TAILQ_HEAD(command_list, command_entry);
 #define XT_DIR			(".xxxterm")
 #define XT_CACHE_DIR		("cache")
 #define XT_CERT_DIR		("certs/")
+#define XT_JS_DIR		("js/")
 #define XT_SESSIONS_DIR		("sessions/")
 #define XT_CONF_FILE		("xxxterm.conf")
 #define XT_QMARKS_FILE		("quickmarks")
@@ -637,6 +638,7 @@ show_oops(struct tab *at, const char *fmt, ...)
 
 char			work_dir[PATH_MAX];
 char			certs_dir[PATH_MAX];
+char			js_dir[PATH_MAX];
 char			cache_dir[PATH_MAX];
 char			sessions_dir[PATH_MAX];
 char			cookie_file[PATH_MAX];
@@ -3845,9 +3847,181 @@ notify_title_cb(WebKitWebView* wview, GParamSpec* pspec, struct tab *t)
 		gtk_window_set_title(GTK_WINDOW(main_window), win_title);
 }
 
+char *
+get_domain(const gchar *host)
+{
+	size_t		x;
+	int		silly_domain = 0;
+	char		*p;
+
+	/* handle silly domains like .co.uk */
+
+	if ((x = strlen(host)) <= 6)
+		return (g_strdup(host));
+
+	if (host[x - 3] == '.' && host[x - 6] == '.') {
+		silly_domain = 1;
+		x = x - 7;
+		while (x > 0)
+			if (host[x] != '.')
+				x--;
+			else
+				return (g_strdup(&host[x + 1]));
+	}
+
+	/* find first . */
+	p = g_strrstr(host, ".");
+	if (p == NULL)
+		return (g_strdup(""));
+	p--;
+	while (p > host)
+		if (*p != '.')
+			p--;
+		else
+			return (g_strdup(p + 1));
+
+	return (g_strdup(host));
+}
+
+void
+js_autorun(struct tab *t)
+{
+	SoupURI			*su = NULL;
+	const gchar		*uri;
+	size_t			got_default = 0, got_host = 0;
+	struct stat		sb;
+	char			deff[PATH_MAX], hostf[PATH_MAX];
+	char			*js = NULL, *jsat, *domain = NULL;
+	FILE			*deffile = NULL, *hostfile = NULL;
+	JSGlobalContextRef	ctx;
+	WebKitWebFrame		*frame;
+	JSStringRef		str;
+	JSValueRef		val, exception;
+	char			*es;
+
+	if (js_autorun_enabled == 0)
+		return;
+
+	uri = get_uri(t);
+	if (uri &&
+	    !(g_str_has_prefix(uri, "http://") ||
+	    g_str_has_prefix(uri, "https://"))) {
+		show_oops(t, "invalid uri");
+		goto done;
+	}
+
+	su = soup_uri_new(uri);
+	if (su == NULL) {
+		show_oops(t, "invalid soup URI");
+		goto done;
+	}
+	if (!SOUP_URI_VALID_FOR_HTTP(su)) {
+		show_oops(t, "invalid HTTPS URI");
+		goto done;
+	}
+
+	DNPRINTF(XT_D_JS, "%s: host: %s domain: %s\n", __func__,
+	    su->host, domain);
+	domain = get_domain(su->host);
+
+	snprintf(deff, sizeof deff, "%s/default.js", js_dir);
+	if ((deffile = fopen(deff, "r")) != NULL) {
+		if (fstat(fileno(deffile), &sb) == -1) {
+			show_oops(t, "can't stat default JS file");
+			goto done;
+		}
+		got_default = sb.st_size;
+	}
+
+	/* try host first followed by domain */
+	snprintf(hostf, sizeof hostf, "%s/%s.js", js_dir, su->host);
+	DNPRINTF(XT_D_JS, "trying file: %s\n", hostf);
+	if ((hostfile = fopen(hostf, "r")) == NULL) {
+		snprintf(hostf, sizeof hostf, "%s/%s.js", js_dir, domain);
+		DNPRINTF(XT_D_JS, "trying file: %s\n", hostf);
+		if ((hostfile = fopen(hostf, "r")) == NULL)
+			goto nofile;
+	}
+	DNPRINTF(XT_D_JS, "file: %s\n", hostf);
+	if (fstat(fileno(hostfile), &sb) == -1) {
+		show_oops(t, "can't stat %s JS file", hostf);
+		goto done;
+	}
+	got_host = sb.st_size;
+
+nofile:
+	if (got_default + got_host == 0)
+		goto done;
+
+	js = g_malloc0(got_default + got_host + 1);
+	jsat = js;
+
+	if (got_default) {
+		if (fread(js, got_default, 1, deffile) != 1) {
+			show_oops(t, "default file read error");
+			goto done;
+		}
+		jsat = js + got_default;
+	}
+
+	if (got_host) {
+		if (fread(jsat, got_host, 1, hostfile) != 1) {
+			show_oops(t, "host file read error");
+			goto done;
+		}
+	}
+
+	/* this code needs to be redone */
+	frame = webkit_web_view_get_main_frame(t->wv);
+	ctx = webkit_web_frame_get_global_context(frame);
+
+	str = JSStringCreateWithUTF8CString(js);
+	val = JSEvaluateScript(ctx, str, JSContextGetGlobalObject(ctx),
+	    NULL, 0, &exception);
+	JSStringRelease(str);
+
+	DNPRINTF(XT_D_JS, "run_script: val %p\n", val);
+	if (val == NULL) {
+		es = js_ref_to_string(ctx, exception);
+		if (es) {
+			show_oops(t, "script exception: %s", es);
+			g_free(es);
+		}
+		goto done;
+	} else {
+		es = js_ref_to_string(ctx, val);
+#if 0
+		/* return values */
+		if (!strncmp(es, XT_JS_DONE, XT_JS_DONE_LEN))
+			; /* do nothing */
+		if (!strncmp(es, XT_JS_INSERT, XT_JS_INSERT_LEN))
+			; /* do nothing */
+#endif
+		if (es) {
+			show_oops(t, "script complete return value: '%s'", es);
+			g_free(es);
+		} else
+			show_oops(t, "script complete: without a return value");
+	}
+done:
+	if (su)
+		soup_uri_free(su);
+	if (js)
+		g_free(js);
+	if (deffile)
+		fclose(deffile);
+	if (hostfile)
+		fclose(hostfile);
+	if (domain)
+		g_free(domain);
+}
+
 void
 webview_load_finished_cb(WebKitWebView *wv, WebKitWebFrame *wf, struct tab *t)
 {
+	/* autorun some js if enabled */
+	js_autorun(t);
+
 	run_script(t, JS_HINTING);
 	if (autofocus_onload &&
 	    t->tab_id == gtk_notebook_get_current_page(notebook))
@@ -7047,6 +7221,10 @@ main(int argc, char *argv[])
 	    work_dir, XT_SESSIONS_DIR);
 	xxx_dir(sessions_dir);
 
+	/* js dir */
+	snprintf(js_dir, sizeof js_dir, "%s/%s", work_dir, XT_JS_DIR);
+	xxx_dir(js_dir);
+
 	/* runtime settings that can override config file */
 	if (runtime_settings[0] != '\0')
 		config_parse(runtime_settings, 1);
diff --git a/xxxterm.conf b/xxxterm.conf
index a5dc359..839c3bd 100644
--- a/xxxterm.conf
+++ b/xxxterm.conf
@@ -35,6 +35,7 @@
 # history_autosave	= 1
 # autofocus_onload	= 1
 # encoding		= UTF-8
+# js_autorun_enabled	= 0
 
 #
 # default_script points to a script executed by the run_script command.
diff --git a/xxxterm.h b/xxxterm.h
index 28bdfbd..8d5f1bd 100644
--- a/xxxterm.h
+++ b/xxxterm.h
@@ -511,6 +511,7 @@ extern char	search_file[PATH_MAX];
 extern char	command_file[PATH_MAX];
 extern char	*encoding;
 extern int	autofocus_onload;
+extern int	js_autorun_enabled;
 extern char	*cmd_font_name;
 extern char	*oops_font_name;
 extern char	*statusbar_font_name;