summaryrefslogtreecommitdiff
path: root/src/backend/plugins/pacrunner-duktape/pacrunner-duktape.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/plugins/pacrunner-duktape/pacrunner-duktape.c')
-rw-r--r--src/backend/plugins/pacrunner-duktape/pacrunner-duktape.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/backend/plugins/pacrunner-duktape/pacrunner-duktape.c b/src/backend/plugins/pacrunner-duktape/pacrunner-duktape.c
new file mode 100644
index 0000000..3676e48
--- /dev/null
+++ b/src/backend/plugins/pacrunner-duktape/pacrunner-duktape.c
@@ -0,0 +1,201 @@
+/* pacrunner-duktape.c
+ *
+ * Copyright 2022-2023 The Libproxy Team
+ *
+ * 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
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <gio/gio.h>
+
+#include <unistd.h>
+#ifdef __WIN32__
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#endif
+
+#include "pacrunner-duktape.h"
+#include "pacutils.h"
+#include "px-plugin-pacrunner.h"
+
+#include "duktape.h"
+
+struct _PxPacRunnerDuktape {
+ GObject parent_instance;
+ duk_context *ctx;
+};
+
+static void px_pacrunner_iface_init (PxPacRunnerInterface *iface);
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (PxPacRunnerDuktape,
+ px_pacrunner_duktape,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (PX_TYPE_PACRUNNER, px_pacrunner_iface_init))
+
+
+static duk_ret_t
+dns_resolve (duk_context *ctx)
+{
+ const char *hostname = NULL;
+ struct addrinfo *info;
+ char tmp[INET6_ADDRSTRLEN + 1];
+
+ if (duk_get_top (ctx) != 1) {
+ /* Invalid number of arguments */
+ return 0;
+ }
+
+ /* We do not need to free the string - It's managed by Duktape. */
+ hostname = duk_get_string (ctx, 0);
+ if (!hostname)
+ return 0;
+
+ /* Look it up */
+ if (getaddrinfo (hostname, NULL, NULL, &info))
+ return 0;
+
+ /* Try for IPv4 */
+ if (getnameinfo (info->ai_addr,
+ info->ai_addrlen,
+ tmp,
+ INET6_ADDRSTRLEN + 1,
+ NULL,
+ 0,
+ NI_NUMERICHOST)) {
+ freeaddrinfo (info);
+ duk_push_null (ctx);
+ return 1;
+ }
+ freeaddrinfo (info);
+
+ /* Create the return value */
+ duk_push_string (ctx, tmp);
+
+ return 1;
+}
+
+static duk_ret_t
+my_ip_address (duk_context *ctx)
+{
+ char hostname[1024];
+
+ hostname[sizeof (hostname) - 1] = '\0';
+
+ if (!gethostname (hostname, sizeof (hostname) - 1)) {
+ duk_push_string (ctx, hostname);
+ return dns_resolve (ctx);
+ }
+
+ return duk_error (ctx, DUK_ERR_ERROR, "Unable to find hostname!");
+}
+
+static void
+px_pacrunner_duktape_init (PxPacRunnerDuktape *self)
+{
+ self->ctx = duk_create_heap_default ();
+ if (!self->ctx)
+ return;
+
+ duk_push_c_function (self->ctx, dns_resolve, 1);
+ duk_put_global_string (self->ctx, "dnsResolve");
+
+ duk_push_c_function (self->ctx, my_ip_address, 1);
+ duk_put_global_string (self->ctx, "myIpAddress");
+
+ duk_push_string (self->ctx, JAVASCRIPT_ROUTINES);
+ if (duk_peval_noresult (self->ctx))
+ goto error;
+
+ return;
+
+error:
+ duk_destroy_heap (self->ctx);
+}
+
+static void
+px_pacrunner_duktape_dispose (GObject *object)
+{
+ PxPacRunnerDuktape *self = PX_PACRUNNER_DUKTAPE (object);
+
+ g_clear_pointer (&self->ctx, duk_destroy_heap);
+
+ G_OBJECT_CLASS (px_pacrunner_duktape_parent_class)->dispose (object);
+}
+
+static void
+px_pacrunner_duktape_class_init (PxPacRunnerDuktapeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = px_pacrunner_duktape_dispose;
+}
+
+static gboolean
+px_pacrunner_duktape_set_pac (PxPacRunner *pacrunner,
+ GBytes *pac_data)
+{
+ PxPacRunnerDuktape *self = PX_PACRUNNER_DUKTAPE (pacrunner);
+ gsize len;
+ gconstpointer content = g_bytes_get_data (pac_data, &len);
+
+ duk_push_lstring (self->ctx, content, len);
+
+ if (duk_peval_noresult (self->ctx)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static char *
+px_pacrunner_duktape_run (PxPacRunner *pacrunner,
+ GUri *uri)
+{
+ PxPacRunnerDuktape *self = PX_PACRUNNER_DUKTAPE (pacrunner);
+ duk_int_t result;
+
+ duk_get_global_string (self->ctx, "FindProxyForURL");
+ duk_push_string (self->ctx, g_uri_to_string (uri));
+ duk_push_string (self->ctx, g_uri_get_host (uri));
+ result = duk_pcall (self->ctx, 2);
+
+ if (result == 0) {
+ const char *proxy = duk_get_string (self->ctx, 0);
+ char *proxy_string;
+
+ if (!proxy) {
+ duk_pop (self->ctx);
+ return g_strdup ("");
+ }
+
+ proxy_string = g_strdup (proxy);
+
+ duk_pop (self->ctx);
+
+ return proxy_string;
+ }
+
+ duk_pop (self->ctx);
+ return g_strdup ("");
+}
+
+static void
+px_pacrunner_iface_init (PxPacRunnerInterface *iface)
+{
+ iface->set_pac = px_pacrunner_duktape_set_pac;
+ iface->run = px_pacrunner_duktape_run;
+}