summaryrefslogtreecommitdiff
path: root/src/backend/plugins/config-kde/config-kde.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/plugins/config-kde/config-kde.c')
-rw-r--r--src/backend/plugins/config-kde/config-kde.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/backend/plugins/config-kde/config-kde.c b/src/backend/plugins/config-kde/config-kde.c
new file mode 100644
index 0000000..ccec002
--- /dev/null
+++ b/src/backend/plugins/config-kde/config-kde.c
@@ -0,0 +1,303 @@
+/* config-kde.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 "config-kde.h"
+
+#include "px-plugin-config.h"
+#include "px-manager.h"
+
+static void px_config_iface_init (PxConfigInterface *iface);
+
+typedef enum {
+ KDE_PROXY_TYPE_NONE = 0,
+ KDE_PROXY_TYPE_MANUAL,
+ KDE_PROXY_TYPE_PAC,
+ KDE_PROXY_TYPE_WPAD,
+ KDE_PROXY_TYPE_SYSTEM,
+} KdeProxyType;
+
+struct _PxConfigKde {
+ GObject parent_instance;
+
+ char *config_file;
+ gboolean available;
+ GFileMonitor *monitor;
+
+ GStrv no_proxy;
+ char *http_proxy;
+ char *https_proxy;
+ char *ftp_proxy;
+ char *socks_proxy;
+ KdeProxyType proxy_type;
+ char *pac_script;
+};
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (PxConfigKde,
+ px_config_kde,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (PX_TYPE_CONFIG, px_config_iface_init))
+
+enum {
+ PROP_0,
+ PROP_CONFIG_OPTION
+};
+
+static void px_config_kde_set_config_file (PxConfigKde *self,
+ char *proxy_file);
+
+static void
+on_file_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ PxConfigKde *self = PX_CONFIG_KDE (user_data);
+
+ g_debug ("%s: Reloading configuration\n", __FUNCTION__);
+ px_config_kde_set_config_file (self, g_file_get_path (file));
+}
+
+static void
+px_config_kde_set_config_file (PxConfigKde *self,
+ char *proxy_file)
+{
+ g_autoptr (GError) error = NULL;
+ g_autofree char *line = NULL;
+ g_autoptr (GFile) file = NULL;
+ g_autoptr (GFileInputStream) istr = NULL;
+ g_autoptr (GDataInputStream) dstr = NULL;
+ const char *desktops;
+
+ self->available = FALSE;
+
+ desktops = getenv ("XDG_CURRENT_DESKTOP");
+ if (!desktops)
+ return;
+
+ /* Remember that XDG_CURRENT_DESKTOP is a list of strings. */
+ if (strstr (desktops, "KDE") == NULL)
+ return;
+
+ g_clear_pointer (&self->config_file, g_free);
+ self->config_file = proxy_file ? g_strdup (proxy_file) : g_build_filename (g_get_user_config_dir (), "kioslaverc", NULL);
+
+ file = g_file_new_for_path (self->config_file);
+ if (!file) {
+ g_debug ("%s: Could not create file for %s", __FUNCTION__, self->config_file);
+ return;
+ }
+
+ istr = g_file_read (file, NULL, NULL);
+ if (!istr) {
+ g_debug ("%s: Could not read file %s", __FUNCTION__, self->config_file);
+ return;
+ }
+
+ dstr = g_data_input_stream_new (G_INPUT_STREAM (istr));
+ if (!dstr)
+ return;
+
+ g_clear_object (&self->monitor);
+ self->monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, &error);
+ if (!self->monitor)
+ g_warning ("Could not add a file monitor for %s, error: %s", g_file_get_uri (file), error->message);
+ else
+ g_signal_connect_object (G_OBJECT (self->monitor), "changed", G_CALLBACK (on_file_changed), self, 0);
+
+ do {
+ g_clear_pointer (&line, g_free);
+
+ line = g_data_input_stream_read_line (dstr, NULL, NULL, &error);
+ if (line) {
+ g_auto (GStrv) kv = NULL;
+ g_autoptr (GString) value = NULL;
+ kv = g_strsplit (line, "=", 2);
+
+ if (g_strv_length (kv) != 2)
+ continue;
+
+ value = g_string_new (kv[1]);
+ g_string_replace (value, "\"", "", 0);
+ g_string_replace (value, " ", ":", 0);
+
+ if (strcmp (kv[0], "httpsProxy") == 0) {
+ self->https_proxy = g_strdup (value->str);
+ } else if (strcmp (kv[0], "httpProxy") == 0) {
+ self->http_proxy = g_strdup (value->str);
+ } else if (strcmp (kv[0], "ftpProxy") == 0) {
+ self->ftp_proxy = g_strdup (value->str);
+ } else if (strcmp (kv[0], "socksProxy") == 0) {
+ self->socks_proxy = g_strdup (value->str);
+ } else if (strcmp (kv[0], "NoProxyFor") == 0) {
+ self->no_proxy = g_strsplit (value->str, ",", -1);
+ } else if (strcmp (kv[0], "Proxy Config Script") == 0) {
+ self->pac_script = g_strdup (value->str);
+ } else if (strcmp (kv[0], "ProxyType") == 0) {
+ self->proxy_type = atoi (value->str);
+ }
+ }
+ } while (line);
+
+ self->available = TRUE;
+}
+
+
+static void
+px_config_kde_init (PxConfigKde *self)
+{
+ px_config_kde_set_config_file (self, NULL);
+}
+
+static void
+px_config_kde_dispose (GObject *object)
+{
+ PxConfigKde *self = PX_CONFIG_KDE (object);
+
+ g_clear_pointer (&self->config_file, g_free);
+ g_clear_object (&self->monitor);
+ g_clear_pointer (&self->no_proxy, g_strfreev);
+ g_clear_pointer (&self->http_proxy, g_free);
+ g_clear_pointer (&self->https_proxy, g_free);
+ g_clear_pointer (&self->ftp_proxy, g_free);
+ g_clear_pointer (&self->socks_proxy, g_free);
+ g_clear_pointer (&self->pac_script, g_free);
+
+ G_OBJECT_CLASS (px_config_kde_parent_class)->dispose (object);
+}
+
+static void
+px_config_kde_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PxConfigKde *config = PX_CONFIG_KDE (object);
+
+ switch (prop_id) {
+ case PROP_CONFIG_OPTION:
+ px_config_kde_set_config_file (config, g_value_dup_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+px_config_kde_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PxConfigKde *config = PX_CONFIG_KDE (object);
+
+ switch (prop_id) {
+ case PROP_CONFIG_OPTION:
+ g_value_set_string (value, config->config_file);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+px_config_kde_class_init (PxConfigKdeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = px_config_kde_dispose;
+ object_class->set_property = px_config_kde_set_property;
+ object_class->get_property = px_config_kde_get_property;
+
+ g_object_class_override_property (object_class, PROP_CONFIG_OPTION, "config-option");
+}
+
+static gboolean
+px_config_kde_is_available (PxConfig *config)
+{
+ PxConfigKde *self = PX_CONFIG_KDE (config);
+
+ return self->available;
+}
+
+static void
+px_config_kde_get_config (PxConfig *config,
+ GUri *uri,
+ GStrvBuilder *builder)
+{
+ PxConfigKde *self = PX_CONFIG_KDE (config);
+ const char *scheme = g_uri_get_scheme (uri);
+ g_autofree char *proxy = NULL;
+
+ if (!self->available)
+ return;
+
+ if (!self->proxy_type)
+ return;
+
+ if (px_manager_is_ignore (uri, self->no_proxy))
+ return;
+
+ switch (self->proxy_type) {
+ case KDE_PROXY_TYPE_MANUAL:
+ case KDE_PROXY_TYPE_SYSTEM:
+ /* System is the same as manual, except that a button for auto dection
+ * is shown. Based on this manual fields are set.
+ */
+ if (g_strcmp0 (scheme, "ftp") == 0) {
+ proxy = g_strdup (self->ftp_proxy);
+ } else if (g_strcmp0 (scheme, "https") == 0) {
+ proxy = g_strdup (self->https_proxy);
+ } else if (g_strcmp0 (scheme, "http") == 0) {
+ proxy = g_strdup (self->http_proxy);
+ } else if (self->socks_proxy && strlen (self->socks_proxy) > 0) {
+ proxy = g_strdup (self->socks_proxy);
+ }
+ break;
+ case KDE_PROXY_TYPE_WPAD:
+ proxy = g_strdup ("wpad://");
+ break;
+ case KDE_PROXY_TYPE_PAC:
+ proxy = g_strdup_printf ("pac+%s", self->pac_script);
+ break;
+ case KDE_PROXY_TYPE_NONE:
+ default:
+ break;
+ }
+
+ if (proxy)
+ px_strv_builder_add_proxy (builder, proxy);
+}
+
+static void
+px_config_iface_init (PxConfigInterface *iface)
+{
+ iface->name = "config-kde";
+ iface->priority = PX_CONFIG_PRIORITY_DEFAULT;
+ iface->is_available = px_config_kde_is_available;
+ iface->get_config = px_config_kde_get_config;
+}