summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Makefile.am10
-rw-r--r--src/plugins/mozjs.c189
-rw-r--r--src/plugins/networkmanager.c4
-rw-r--r--src/plugins/webkit.c209
4 files changed, 336 insertions, 76 deletions
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 5e5d18c..9a561ea 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -14,6 +14,9 @@ endif
if WITH_KDE
plugin_LTLIBRARIES += kde.la
endif
+if WITH_WEBKIT
+plugin_LTLIBRARIES += webkit.la
+endif
if WITH_MOZJS
plugin_LTLIBRARIES += mozjs.la
endif
@@ -45,6 +48,13 @@ kde_la_CFLAGS = -I$(top_srcdir)/src/lib @KDE_CFLAGS@
kde_la_LIBADD = ../lib/libproxy.la
kde_la_LDFLAGS = -module -avoid-version @KDE_LIBS@
+# WebKit (JavaScriptCore) based PAC runner
+webkit_la_SOURCES = webkit.c
+webkit_la_CFLAGS = -I$(top_srcdir)/src/lib @WEBKIT_CFLAGS@
+webkit_la_LIBADD = ../lib/libproxy.la
+webkit_la_LDFLAGS = -module -avoid-version @WEBKIT_LIBS@
+nodist_webkit_la_SOURCES = pacutils.h
+
# Mozilla (Spidermonkey) based PAC runner
mozjs_la_SOURCES = mozjs.c
mozjs_la_CFLAGS = -I$(top_srcdir)/src/lib @MOZJS_CFLAGS@
diff --git a/src/plugins/mozjs.c b/src/plugins/mozjs.c
index 5f89672..88c8180 100644
--- a/src/plugins/mozjs.c
+++ b/src/plugins/mozjs.c
@@ -36,38 +36,34 @@ static JSBool dnsResolve(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
// Get hostname argument
char *tmp = px_strdup(JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
+ // Set the default return value
+ *rval = JSVAL_NULL;
+
// Look it up
- struct addrinfo *info;
+ struct addrinfo *info = NULL;
if (getaddrinfo(tmp, NULL, NULL, &info))
- goto error;
+ goto out;
+
+ // Allocate the IP address
px_free(tmp);
+ tmp = px_malloc0(INET6_ADDRSTRLEN+1);
- // Try for IPv4
- tmp = px_malloc0(INET_ADDRSTRLEN+1);
- if (inet_ntop(info->ai_family,
+ // Try for IPv4 and IPv6
+ if (!inet_ntop(info->ai_family,
&((struct sockaddr_in *) info->ai_addr)->sin_addr,
tmp, INET_ADDRSTRLEN+1) > 0)
- {
- JSString *ip = JS_NewString(cx, tmp, strlen(tmp));
- *rval = STRING_TO_JSVAL(ip);
- return true;
- }
-
- // Try for IPv6
- px_free(tmp);
- tmp = px_malloc0(INET6_ADDRSTRLEN+1);
- if (inet_ntop(info->ai_family,
- &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr,
- tmp, INET6_ADDRSTRLEN+1) > 0)
- {
- JSString *ip = JS_NewString(cx, tmp, strlen(tmp));
- *rval = STRING_TO_JSVAL(ip);
- return true;
- }
+ if (!inet_ntop(info->ai_family,
+ &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr,
+ tmp, INET6_ADDRSTRLEN+1) > 0)
+ goto out;
+
+ // We succeeded
+ *rval = STRING_TO_JSVAL(JS_NewString(cx, tmp, strlen(tmp)));
+ tmp = NULL;
- error:
+ out:
+ if (info) freeaddrinfo(info);
px_free(tmp);
- *rval = JSVAL_NULL;
return true;
}
@@ -83,72 +79,115 @@ static JSBool myIpAddress(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return true;
}
+typedef struct {
+ JSRuntime *run;
+ JSContext *ctx;
+ JSClass *cls;
+ char *pac;
+} ctxStore;
+
+static void ctxs_free(ctxStore *self)
+{
+ if (!self) return;
+ if (self->ctx) JS_DestroyContext(self->ctx);
+ if (self->run) JS_DestroyRuntime(self->run);
+ if (self->cls) px_free(self->cls);
+ px_free(self->pac);
+ px_free(self);
+}
+
+static ctxStore *ctxs_new(pxPAC *pac)
+{
+ JSObject *global = NULL;
+ jsval rval;
+
+ // Create the basic context
+ ctxStore *self = px_malloc0(sizeof(ctxStore));
+
+ // Setup Javascript global class
+ self->cls = px_malloc0(sizeof(JSClass));
+ self->cls->name = "global";
+ self->cls->flags = 0;
+ self->cls->addProperty = JS_PropertyStub;
+ self->cls->delProperty = JS_PropertyStub;
+ self->cls->getProperty = JS_PropertyStub;
+ self->cls->setProperty = JS_PropertyStub;
+ self->cls->enumerate = JS_EnumerateStub;
+ self->cls->resolve = JS_ResolveStub;
+ self->cls->convert = JS_ConvertStub;
+ self->cls->finalize = JS_FinalizeStub;
+
+ // Initialize Javascript runtime environment
+ if (!(self->run = JS_NewRuntime(1024 * 1024))) goto error;
+ if (!(self->ctx = JS_NewContext(self->run, 1024 * 1024))) goto error;
+ if (!(global = JS_NewObject(self->ctx, self->cls, NULL, NULL))) goto error;
+ JS_InitStandardClasses(self->ctx, global);
+
+ // Define Javascript functions
+ JS_DefineFunction(self->ctx, global, "dnsResolve", dnsResolve, 1, 0);
+ JS_DefineFunction(self->ctx, global, "myIpAddress", myIpAddress, 0, 0);
+ JS_EvaluateScript(self->ctx, global, JAVASCRIPT_ROUTINES,
+ strlen(JAVASCRIPT_ROUTINES), "pacutils.js", 0, &rval);
+
+ // Add PAC to the environment
+ JS_EvaluateScript(self->ctx, global, px_pac_to_string(pac),
+ strlen(px_pac_to_string(pac)),
+ px_url_to_string((pxURL *) px_pac_get_url(pac)),
+ 0, &rval);
+
+ // Save the pac
+ self->pac = px_strdup(px_pac_to_string(pac));
+ return self;
+
+error:
+ ctxs_free(self);
+ return NULL;
+}
+
char *mozjs_pacrunner(pxProxyFactory *self, pxPAC *pac, pxURL *url)
{
- JSRuntime *runtime = NULL;
- JSContext *context = NULL;
- JSObject *global = NULL;
- jsval rval;
- char *answer = NULL;
-
// Make sure we have the pac file and url
if (!pac) return NULL;
if (!url) return NULL;
if (!px_pac_to_string(pac) && !px_pac_reload(pac)) return NULL;
-
- // Setup Javascript global class
- JSClass *global_class = px_malloc0(sizeof(JSClass));
- global_class->name = "global";
- global_class->flags = 0;
- global_class->addProperty = JS_PropertyStub;
- global_class->delProperty = JS_PropertyStub;
- global_class->getProperty = JS_PropertyStub;
- global_class->setProperty = JS_PropertyStub;
- global_class->enumerate = JS_EnumerateStub;
- global_class->resolve = JS_ResolveStub;
- global_class->convert = JS_ConvertStub;
- global_class->finalize = JS_FinalizeStub;
-
- // Initialize Javascript runtime environment
- if (!(runtime = JS_NewRuntime(1024 * 1024))) goto out;
- if (!(context = JS_NewContext(runtime, 1024 * 1024))) goto out;
- if (!(global = JS_NewObject(context, global_class, NULL, NULL))) goto out;
- JS_InitStandardClasses(context, global);
-
- // Define Javascript functions
- JS_DefineFunction(context, global, "dnsResolve", dnsResolve, 1, 0);
- JS_DefineFunction(context, global, "myIpAddress", myIpAddress, 0, 0);
- JS_EvaluateScript(context, global, JAVASCRIPT_ROUTINES,
- strlen(JAVASCRIPT_ROUTINES), "pacutils.js", 0, &rval);
-
- // Add PAC to the environment
- JS_EvaluateScript(context, JS_GetGlobalObject(context),
- px_pac_to_string(pac), strlen(px_pac_to_string(pac)),
- px_url_to_string((pxURL *) px_pac_get_url(pac)), 0, &rval);
+
+ // Get the cached context
+ ctxStore *ctxs = px_proxy_factory_misc_get(self, "mozjs");
+
+ // If there is a cached context, make sure it is the same pac
+ if (ctxs && strcmp(ctxs->pac, px_pac_to_string(pac)))
+ {
+ ctxs_free(ctxs);
+ ctxs = NULL;
+ }
+
+ // If no context exists (or if the pac was changed), create one
+ if (!ctxs)
+ {
+ if ((ctxs = ctxs_new(pac)))
+ px_proxy_factory_misc_set(self, "mozjs", ctxs);
+ else
+ return NULL;
+ }
// Build arguments to the FindProxyForURL() function
char *tmpurl = px_strdup(px_url_to_string(url));
char *tmphost = px_strdup(px_url_get_host(url));
- jsval val[2] = {
- STRING_TO_JSVAL(JS_NewString(context, tmpurl, strlen(tmpurl))),
- STRING_TO_JSVAL(JS_NewString(context, tmphost, strlen(tmphost)))
+ jsval args[2] = {
+ STRING_TO_JSVAL(JS_NewString(ctxs->ctx, tmpurl, strlen(tmpurl))),
+ STRING_TO_JSVAL(JS_NewString(ctxs->ctx, tmphost, strlen(tmphost)))
};
// Find the proxy (call FindProxyForURL())
- JSBool result = JS_CallFunctionName(context, JS_GetGlobalObject(context),
- "FindProxyForURL", 2, val, &rval);
- if (!result) goto out;
- answer = px_strdup(JS_GetStringBytes(JS_ValueToString(context, rval)));
+ jsval rval;
+ JSBool result = JS_CallFunctionName(ctxs->ctx, JS_GetGlobalObject(ctxs->ctx), "FindProxyForURL", 2, args, &rval);
+ if (!result) return NULL;
+ char *answer = px_strdup(JS_GetStringBytes(JS_ValueToString(ctxs->ctx, rval)));
if (!answer || !strcmp(answer, "undefined")) {
px_free(answer);
- answer = NULL;
+ return NULL;
}
-
- out:
- if (context) JS_DestroyContext(context);
- if (runtime) JS_DestroyRuntime(runtime);
- px_free(global_class);
- return answer;
+ return answer;
}
bool on_proxy_factory_instantiate(pxProxyFactory *self)
@@ -159,4 +198,6 @@ bool on_proxy_factory_instantiate(pxProxyFactory *self)
void on_proxy_factory_destantiate(pxProxyFactory *self)
{
px_proxy_factory_pac_runner_set(self, NULL);
+ ctxs_free(px_proxy_factory_misc_get(self, "mozjs"));
+ px_proxy_factory_misc_set(self, "mozjs", NULL);
}
diff --git a/src/plugins/networkmanager.c b/src/plugins/networkmanager.c
index fca92d6..e7c8360 100644
--- a/src/plugins/networkmanager.c
+++ b/src/plugins/networkmanager.c
@@ -84,13 +84,13 @@ nm_on_get_proxy(pxProxyFactory *self)
bool
on_proxy_factory_instantiate(pxProxyFactory *self)
{
- px_proxy_factory_on_get_proxies_add(self, nm_on_get_proxy);
+ px_proxy_factory_on_get_proxy_add(self, nm_on_get_proxy);
}
void
on_proxy_factory_destantiate(pxProxyFactory *self)
{
- px_proxy_factory_on_get_proxies_del(self, nm_on_get_proxy);
+ px_proxy_factory_on_get_proxy_del(self, nm_on_get_proxy);
DBusConnection *conn = px_proxy_factory_misc_get(self, "networkmanager");
if (conn)
{
diff --git a/src/plugins/webkit.c b/src/plugins/webkit.c
new file mode 100644
index 0000000..859c618
--- /dev/null
+++ b/src/plugins/webkit.c
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * libproxy - A library for proxy configuration
+ * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ ******************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#define __USE_BSD
+#include <unistd.h>
+
+#include <misc.h>
+#include <proxy_factory.h>
+
+#include <JavaScriptCore/JavaScript.h>
+#include "pacutils.h"
+
+static char *jstr2str(JSStringRef str, bool release)
+{
+ char *tmp = px_malloc0(JSStringGetMaximumUTF8CStringSize(str)+1);
+ JSStringGetUTF8CString(str, tmp, JSStringGetMaximumUTF8CStringSize(str)+1);
+ if (release) JSStringRelease(str);
+ return tmp;
+}
+
+static JSValueRef dnsResolve(JSContextRef ctx, JSObjectRef func, JSObjectRef self, size_t argc, const JSValueRef argv[], JSValueRef* exception)
+{
+ if (argc != 1) return NULL;
+ if (!JSValueIsString(ctx, argv[0])) return NULL;
+
+ // Get hostname argument
+ char *tmp = jstr2str(JSValueToStringCopy(ctx, argv[0], NULL), true);
+
+ // Look it up
+ struct addrinfo *info;
+ if (getaddrinfo(tmp, NULL, NULL, &info))
+ return NULL;
+ px_free(tmp);
+
+ // Try for IPv4
+ tmp = px_malloc0(INET6_ADDRSTRLEN+1);
+ if (!inet_ntop(info->ai_family,
+ &((struct sockaddr_in *) info->ai_addr)->sin_addr,
+ tmp, INET_ADDRSTRLEN+1) > 0)
+ // Try for IPv6
+ if (!inet_ntop(info->ai_family,
+ &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr,
+ tmp, INET6_ADDRSTRLEN+1) > 0)
+ {
+ freeaddrinfo(info);
+ px_free(tmp);
+ return NULL;
+ }
+ freeaddrinfo(info);
+
+ // Create the return value
+ JSStringRef str = JSStringCreateWithUTF8CString(tmp);
+ JSValueRef ret = JSValueMakeString(ctx, str);
+ JSStringRelease(str);
+ px_free(tmp);
+
+ return ret;
+}
+
+static JSValueRef myIpAddress(JSContextRef ctx, JSObjectRef func, JSObjectRef self, size_t argc, const JSValueRef argv[], JSValueRef* exception)
+{
+ char hostname[1024];
+ if (!gethostname(hostname, 1023)) {
+ JSStringRef str = JSStringCreateWithUTF8CString(hostname);
+ JSValueRef val = JSValueMakeString(ctx, str);
+ JSStringRelease(str);
+ JSValueRef ip = dnsResolve(ctx, func, self, 1, &val, NULL);
+ return ip;
+ }
+ return NULL;
+}
+
+typedef struct {
+ JSGlobalContextRef ctx;
+ char *pac;
+} ctxStore;
+
+static void ctxs_free(ctxStore *self)
+{
+ if (!self) return;
+ JSGlobalContextRelease(self->ctx);
+ JSGarbageCollect(self->ctx);
+ px_free(self->pac);
+ px_free(self);
+}
+
+static ctxStore *ctxs_new(pxPAC *pac)
+{
+ JSStringRef str = NULL;
+ JSObjectRef func = NULL;
+
+ // Create the basic context
+ ctxStore *self = px_malloc0(sizeof(ctxStore));
+ self->pac = px_strdup(px_pac_to_string(pac));
+ if (!(self->ctx = JSGlobalContextCreate(NULL))) goto error;
+
+ // Add dnsResolve into the context
+ str = JSStringCreateWithUTF8CString("dnsResolve");
+ func = JSObjectMakeFunctionWithCallback(self->ctx, str, dnsResolve);
+ JSObjectSetProperty(self->ctx, JSContextGetGlobalObject(self->ctx), str, func, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(str);
+
+ // Add myIpAddress into the context
+ str = JSStringCreateWithUTF8CString("myIpAddress");
+ func = JSObjectMakeFunctionWithCallback(self->ctx, str, myIpAddress);
+ JSObjectSetProperty(self->ctx, JSContextGetGlobalObject(self->ctx), str, func, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(str);
+
+ // Add all other routines into the context
+ str = JSStringCreateWithUTF8CString(JAVASCRIPT_ROUTINES);
+ if (!JSCheckScriptSyntax(self->ctx, str, NULL, 0, NULL)) goto error;
+ JSEvaluateScript(self->ctx, str, NULL, NULL, 1, NULL);
+ JSStringRelease(str);
+
+ // Add the PAC into the context
+ str = JSStringCreateWithUTF8CString(self->pac);
+ if (!JSCheckScriptSyntax(self->ctx, str, NULL, 0, NULL)) goto error;
+ JSEvaluateScript(self->ctx, str, NULL, NULL, 1, NULL);
+ JSStringRelease(str);
+
+ return self;
+
+error:
+ if (str) JSStringRelease(str);
+ ctxs_free(self);
+ return NULL;
+}
+
+char *webkit_pacrunner(pxProxyFactory *self, pxPAC *pac, pxURL *url)
+{
+ JSStringRef str = NULL;
+ JSValueRef val = NULL;
+ char *tmp = NULL;
+
+ // Make sure we have the pac file and url
+ if (!pac) return NULL;
+ if (!url) return NULL;
+ if (!px_pac_to_string(pac) && !px_pac_reload(pac)) return NULL;
+
+ // Get the cached context
+ ctxStore *ctxs = px_proxy_factory_misc_get(self, "webkit");
+
+ // If there is a cached context, make sure it is the same pac
+ if (ctxs && strcmp(ctxs->pac, px_pac_to_string(pac)))
+ {
+ ctxs_free(ctxs);
+ ctxs = NULL;
+ }
+
+ // If no context exists (or if the pac was changed), create one
+ if (!ctxs)
+ {
+ if ((ctxs = ctxs_new(pac)))
+ px_proxy_factory_misc_set(self, "webkit", ctxs);
+ else
+ return NULL;
+ }
+
+ // Run the PAC
+ tmp = px_strcat("FindProxyForURL(\"", px_url_to_string(url), "\", \"", px_url_get_host(url), "\");", NULL);
+ str = JSStringCreateWithUTF8CString(tmp);
+ px_free(tmp); tmp = NULL;
+ if (!JSCheckScriptSyntax(ctxs->ctx, str, NULL, 0, NULL)) goto error;
+ if (!(val = JSEvaluateScript(ctxs->ctx, str, NULL, NULL, 1, NULL))) goto error;
+ if (!JSValueIsString(ctxs->ctx, val)) goto error;
+ JSStringRelease(str);
+
+ // Convert the return value to a string
+ return jstr2str(JSValueToStringCopy(ctxs->ctx, val, NULL), true);
+
+error:
+ if (str) JSStringRelease(str);
+ ctxs_free(ctxs);
+ return tmp;
+}
+
+bool on_proxy_factory_instantiate(pxProxyFactory *self)
+{
+ return px_proxy_factory_pac_runner_set(self, webkit_pacrunner);
+}
+
+void on_proxy_factory_destantiate(pxProxyFactory *self)
+{
+ px_proxy_factory_pac_runner_set(self, NULL);
+ ctxs_free(px_proxy_factory_misc_get(self, "webkit"));
+ px_proxy_factory_misc_set(self, "webkit", NULL);
+}