diff options
author | Jan-Michael Brummer <jan.brummer@tabos.org> | 2023-01-30 11:29:18 +0100 |
---|---|---|
committer | Jan-Michael Brummer <jan.brummer@tabos.org> | 2023-03-27 16:31:58 +0200 |
commit | 6118d7947b9463783cfadbb08acc77ad67d19379 (patch) | |
tree | 5a37d526a67347a76327c883fa942bc3a9654e96 | |
parent | 7c3ab7b3ab2afde645c1eb135f2ef8dbae5774d3 (diff) | |
download | libproxy-git-6118d7947b9463783cfadbb08acc77ad67d19379.tar.gz |
Add initial KDE plugin (#19)
-rw-r--r-- | meson_options.txt | 7 | ||||
-rw-r--r-- | src/backend/plugins/config-kde/config-kde.c | 214 | ||||
-rw-r--r-- | src/backend/plugins/config-kde/config-kde.h | 35 | ||||
-rw-r--r-- | src/backend/plugins/config-kde/config-kde.plugin | 6 | ||||
-rw-r--r-- | src/backend/plugins/config-kde/meson.build | 33 | ||||
-rw-r--r-- | src/backend/plugins/meson.build | 2 | ||||
-rw-r--r-- | src/tests/config-kde-test.c | 209 | ||||
-rw-r--r-- | src/tests/data/sample-kde-proxy-disabled | 11 | ||||
-rw-r--r-- | src/tests/data/sample-kde-proxy-manual | 11 | ||||
-rw-r--r-- | src/tests/data/sample-kde-proxy-pac | 11 | ||||
-rw-r--r-- | src/tests/data/sample-kde-proxy-wpad | 11 | ||||
-rw-r--r-- | src/tests/meson.build | 12 |
12 files changed, 562 insertions, 0 deletions
diff --git a/meson_options.txt b/meson_options.txt index f35387a..a82890c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -55,6 +55,13 @@ option( ) option( + 'config-kde', + type: 'boolean', + value: true, + description: 'Whether to build plugin for KDE System Settings' +) + +option( 'pacrunner-duktape', type: 'boolean', value: true, 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..519a2d5 --- /dev/null +++ b/src/backend/plugins/config-kde/config-kde.c @@ -0,0 +1,214 @@ +/* config-kde.c + * + * Copyright 2022-2023 Jan-Michael Brummer + * + * 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 <libpeas/peas.h> + +#include "config-kde.h" + +#include "px-plugin-config.h" +#include "px-manager.h" + +static void px_config_iface_init (PxConfigInterface *iface); +G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module); + +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; + + gboolean available; + + char *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)) + +static void +px_config_kde_read_config (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; + + + file = g_file_new_for_path (proxy_file); + if (!file) { + g_print ("Could not create file\n"); + return; + } + + istr = g_file_read (file, NULL, NULL); + if (!istr) { + g_print ("Could not read file\n"); + return; + } + + dstr = g_data_input_stream_new (G_INPUT_STREAM (istr)); + if (!dstr) + return; + + 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, "=", -1); + + if (g_strv_length (kv) != 2) + continue; + + value = g_string_new (kv[1]); + g_string_replace (value, "\"", "", 0); + g_string_replace (value, "\r", "", 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_strdup (value->str); + } 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); +} + +static void +px_config_kde_init (PxConfigKde *self) +{ + const char *test_file = g_getenv ("PX_CONFIG_KDE"); + g_autofree char *config = test_file ? g_strdup (test_file) : g_build_filename (g_get_user_config_dir (), "kioslaverc", NULL); + + self->available = g_file_test (config, G_FILE_TEST_EXISTS); + if (self->available) + px_config_kde_read_config (self, config); +} + +static void +px_config_kde_dispose (GObject *object) +{ + G_OBJECT_CLASS (px_config_kde_parent_class)->dispose (object); +} + +static void +px_config_kde_class_init (PxConfigKdeClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = px_config_kde_dispose; +} + +static gboolean +px_config_kde_is_available (PxConfig *config) +{ + PxConfigKde *self = PX_CONFIG_KDE (config); + + return self->available && g_getenv ("KDE_FULL_SESSION") != NULL; +} + +static gboolean +px_config_kde_get_config (PxConfig *config, + GUri *uri, + GStrvBuilder *builder, + GError **error) +{ + PxConfigKde *self = PX_CONFIG_KDE (config); + const char *scheme = g_uri_get_scheme (uri); + g_autofree char *proxy = NULL; + + if (!self->proxy_type) + return TRUE; + + if (self->no_proxy && strstr (self->no_proxy, g_uri_get_host (uri))) + return TRUE; + + switch (self->proxy_type) { + case KDE_PROXY_TYPE_MANUAL: + case KDE_PROXY_TYPE_SYSTEM: + 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 (g_strcmp0 (scheme, "socks") == 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) + g_strv_builder_add (builder, proxy); + + return TRUE; +} + +static void +px_config_iface_init (PxConfigInterface *iface) +{ + iface->is_available = px_config_kde_is_available; + iface->get_config = px_config_kde_get_config; +} + +G_MODULE_EXPORT void +peas_register_types (PeasObjectModule *module) +{ + peas_object_module_register_extension_type (module, + PX_TYPE_CONFIG, + PX_CONFIG_TYPE_KDE); +} diff --git a/src/backend/plugins/config-kde/config-kde.h b/src/backend/plugins/config-kde/config-kde.h new file mode 100644 index 0000000..408b28a --- /dev/null +++ b/src/backend/plugins/config-kde/config-kde.h @@ -0,0 +1,35 @@ +/* config-kde.h + * + * Copyright 2022-2023 Jan-Michael Brummer + * + * 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 + */ + +#pragma once + +#include <glib.h> +#include <libpeas/peas.h> + +G_BEGIN_DECLS + +#define PX_CONFIG_TYPE_KDE (px_config_kde_get_type ()) + +G_DECLARE_FINAL_TYPE (PxConfigKde, px_config_kde, PX, CONFIG_KDE, GObject) + +G_END_DECLS + + diff --git a/src/backend/plugins/config-kde/config-kde.plugin b/src/backend/plugins/config-kde/config-kde.plugin new file mode 100644 index 0000000..b8aabab --- /dev/null +++ b/src/backend/plugins/config-kde/config-kde.plugin @@ -0,0 +1,6 @@ +[Plugin] +Authors=Jan-Michael Brummer <jan.brummer@tabos.org> +Copyright=Copyright © 2023 Jan-Michael Brummer +Description=Read proxy configuration from KDE System Settings +Module=config-kde +Name=KDE
\ No newline at end of file diff --git a/src/backend/plugins/config-kde/meson.build b/src/backend/plugins/config-kde/meson.build new file mode 100644 index 0000000..109e5db --- /dev/null +++ b/src/backend/plugins/config-kde/meson.build @@ -0,0 +1,33 @@ +plugin_name = 'config-kde' + +if get_option(plugin_name) + +plugin_src = [ + '@0@.c'.format(plugin_name), +] + +plugin_data = [ + '@0@.plugin'.format(plugin_name), +] + +plugin_lib = shared_module( + plugin_name, + sources: plugin_src, + include_directories: px_backend_inc, + dependencies: [px_backend_dep], + install_dir: join_paths(px_plugins_dir, plugin_name), + install: true, + name_suffix: module_suffix, +) + +# Starting with Meson 0.64 this can be replaced with fs.copyfile +custom_target( + '@0@-data'.format(plugin_name), + input: plugin_data, + output: plugin_data, + command: ['cp', '@INPUT@', '@OUTDIR@'], + install_dir: join_paths(px_plugins_dir, plugin_name), + install: true, +) + +endif
\ No newline at end of file diff --git a/src/backend/plugins/meson.build b/src/backend/plugins/meson.build index d7d7c4c..09344f0 100644 --- a/src/backend/plugins/meson.build +++ b/src/backend/plugins/meson.build @@ -1,5 +1,6 @@ subdir('config-env') subdir('config-gnome') +subdir('config-kde') subdir('config-osx') subdir('config-sysconfig') subdir('config-windows') @@ -12,6 +13,7 @@ subdir('pacrunner-duktape') summary({ 'Configuration Environment' : get_option('config-env'), 'Configuration GNOME ' : get_option('config-gnome'), + 'Configuration KDE ' : get_option('config-kde'), 'Configuration Windows ' : get_option('config-windows'), 'Configuration sysconfig ' : get_option('config-sysconfig'), 'Configuration OS X ' : get_option('config-osx'), diff --git a/src/tests/config-kde-test.c b/src/tests/config-kde-test.c new file mode 100644 index 0000000..08b950b --- /dev/null +++ b/src/tests/config-kde-test.c @@ -0,0 +1,209 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2022-2023 Jan-Michael Brummer <jan.brummer@tabos.org> + * + * 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 "px-manager.h" + +#include "px-manager-helper.h" + +#include <glib.h> + +typedef struct { + const char *url; + const char *proxy; + gboolean success; +} ConfigKdeTest; + +static const ConfigKdeTest config_kde_manual_test_set[] = { + { "https://www.example.com", "http://127.0.0.1:8080", TRUE}, + { "http://www.example.com", "http://127.0.0.1:8080", TRUE}, + { "ftp://www.example.com", "ftp://127.0.0.1:8080", TRUE}, + { "http://localhost:1234", "http://127.0.0.1:8080", FALSE}, + { "socks://localhost:1234", "http://127.0.0.1:8080", FALSE}, + { "socks://localhost:1234", "socks://127.0.0.1:8080", FALSE}, +}; + +static const ConfigKdeTest config_kde_wpad_test_set[] = { + { "https://www.example.com", "http://127.0.0.1:8080", TRUE}, + { "http://www.example.com", "http://127.0.0.1:8080", TRUE}, + { "ftp://www.example.com", "ftp://127.0.0.1:8080", TRUE}, + { "http://localhost:1234", "http://127.0.0.1:8080", FALSE}, +}; + +static const ConfigKdeTest config_kde_pac_test_set[] = { + { "https://www.example.com", "http://127.0.0.1:8080", TRUE}, +}; + +static void +test_config_kde_disabled (void) +{ + int idx; + + for (idx = 0; idx < G_N_ELEMENTS (config_kde_manual_test_set); idx++) { + g_autoptr (PxManager) manager = NULL; + g_autoptr (GError) error = NULL; + g_autoptr (GUri) uri = NULL; + g_auto (GStrv) config = NULL; + ConfigKdeTest test = config_kde_manual_test_set[idx]; + g_autofree char *path = g_test_build_filename (G_TEST_DIST, "data", "sample-kde-proxy-disabled", NULL); + + if (!g_setenv ("PX_CONFIG_KDE", path, TRUE)) { + g_warning ("Failed to set kde environment"); + continue; + } + + manager = px_test_manager_new ("config-kde"); + g_clear_error (&error); + + uri = g_uri_parse (test.url, G_URI_FLAGS_PARSE_RELAXED, &error); + if (!uri) { + g_warning ("Could not parse url '%s': %s", test.url, error ? error->message : ""); + g_assert_not_reached (); + } + + config = px_manager_get_configuration (manager, uri, &error); + g_assert_cmpstr (config[0], !=, test.proxy); + + g_clear_object (&manager); + } +} + +static void +test_config_kde_manual (void) +{ + int idx; + + for (idx = 0; idx < G_N_ELEMENTS (config_kde_manual_test_set); idx++) { + g_autoptr (PxManager) manager = NULL; + g_autoptr (GError) error = NULL; + g_autoptr (GUri) uri = NULL; + g_auto (GStrv) config = NULL; + ConfigKdeTest test = config_kde_manual_test_set[idx]; + g_autofree char *path = g_test_build_filename (G_TEST_DIST, "data", "sample-kde-proxy-manual", NULL); + + if (!g_setenv ("PX_CONFIG_KDE", path, TRUE)) { + g_warning ("Failed to set kde environment"); + continue; + } + + manager = px_test_manager_new ("config-kde"); + g_clear_error (&error); + + uri = g_uri_parse (test.url, G_URI_FLAGS_PARSE_RELAXED, &error); + if (!uri) { + g_warning ("Could not parse url '%s': %s", test.url, error ? error->message : ""); + g_assert_not_reached (); + } + + config = px_manager_get_configuration (manager, uri, &error); + if (test.success) + g_assert_cmpstr (config[0], ==, test.proxy); + else + g_assert_cmpstr (config[0], !=, test.proxy); + + g_clear_object (&manager); + } +} + +static void +test_config_kde_wpad (void) +{ + int idx; + + for (idx = 0; idx < G_N_ELEMENTS (config_kde_wpad_test_set); idx++) { + g_autoptr (PxManager) manager = NULL; + g_autoptr (GError) error = NULL; + g_autoptr (GUri) uri = NULL; + g_auto (GStrv) config = NULL; + ConfigKdeTest test = config_kde_wpad_test_set[idx]; + g_autofree char *path = g_test_build_filename (G_TEST_DIST, "data", "sample-kde-proxy-wpad", NULL); + + if (!g_setenv ("PX_CONFIG_KDE", path, TRUE)) { + g_warning ("Failed to set kde environment"); + continue; + } + + manager = px_test_manager_new ("config-kde"); + g_clear_error (&error); + + uri = g_uri_parse (test.url, G_URI_FLAGS_PARSE_RELAXED, &error); + if (!uri) { + g_warning ("Could not parse url '%s': %s", test.url, error ? error->message : ""); + g_assert_not_reached (); + } + + config = px_manager_get_configuration (manager, uri, &error); + if (test.success) + g_assert_cmpstr (config[0], ==, "wpad://"); + else + g_assert_cmpstr (config[0], !=, "wpad://"); + + g_clear_object (&manager); + } +} + +static void +test_config_kde_pac (void) +{ + int idx; + + for (idx = 0; idx < G_N_ELEMENTS (config_kde_pac_test_set); idx++) { + g_autoptr (PxManager) manager = NULL; + g_autoptr (GError) error = NULL; + g_autoptr (GUri) uri = NULL; + g_auto (GStrv) config = NULL; + ConfigKdeTest test = config_kde_pac_test_set[idx]; + g_autofree char *path = g_test_build_filename (G_TEST_DIST, "data", "sample-kde-proxy-pac", NULL); + + if (!g_setenv ("PX_CONFIG_KDE", path, TRUE)) { + g_warning ("Failed to set kde environment"); + continue; + } + + manager = px_test_manager_new ("config-kde"); + g_clear_error (&error); + + uri = g_uri_parse (test.url, G_URI_FLAGS_PARSE_RELAXED, &error); + if (!uri) { + g_warning ("Could not parse url '%s': %s", test.url, error ? error->message : ""); + g_assert_not_reached (); + } + + config = px_manager_get_configuration (manager, uri, &error); + if (test.success) + g_assert_cmpstr (config[0], ==, "pac+http://127.0.0.1/test.pac"); + else + g_assert_cmpstr (config[0], !=, "pac+http://127.0.0.1/test.pac"); + + g_clear_object (&manager); + } +} + +int +main (int argc, + char **argv) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/config/kde/disabled", test_config_kde_disabled); + g_test_add_func ("/config/kde/manual", test_config_kde_manual); + g_test_add_func ("/config/kde/wpad", test_config_kde_wpad); + g_test_add_func ("/config/kde/pac", test_config_kde_pac); + + return g_test_run (); +} diff --git a/src/tests/data/sample-kde-proxy-disabled b/src/tests/data/sample-kde-proxy-disabled new file mode 100644 index 0000000..9598abd --- /dev/null +++ b/src/tests/data/sample-kde-proxy-disabled @@ -0,0 +1,11 @@ +ProxyUrlDisplayFlags=15 + +[Proxy Settings] +NoProxyFor=localhost,127.0.0.1 +Proxy Config Script=http://127.0.0.1/test.pac +ProxyType=0 +ReversedException=false +ftpProxy=ftp://127.0.0.1 8080 +httpProxy=http://127.0.0.1 8080 +httpsProxy=http://127.0.0.1 8080 +socksProxy=socks://127.0.0.1 8080
\ No newline at end of file diff --git a/src/tests/data/sample-kde-proxy-manual b/src/tests/data/sample-kde-proxy-manual new file mode 100644 index 0000000..c0a293b --- /dev/null +++ b/src/tests/data/sample-kde-proxy-manual @@ -0,0 +1,11 @@ +ProxyUrlDisplayFlags=15 + +[Proxy Settings] +NoProxyFor=localhost,127.0.0.1 +Proxy Config Script= +ProxyType=1 +ReversedException=false +ftpProxy=ftp://127.0.0.1 8080 +httpProxy=http://127.0.0.1 8080 +httpsProxy=http://127.0.0.1 8080 +socksProxy=socks://127.0.0.1 8080
\ No newline at end of file diff --git a/src/tests/data/sample-kde-proxy-pac b/src/tests/data/sample-kde-proxy-pac new file mode 100644 index 0000000..c0db824 --- /dev/null +++ b/src/tests/data/sample-kde-proxy-pac @@ -0,0 +1,11 @@ +ProxyUrlDisplayFlags=15 + +[Proxy Settings] +NoProxyFor=localhost,127.0.0.1 +Proxy Config Script=http://127.0.0.1/test.pac +ProxyType=2 +ReversedException=false +ftpProxy=ftp://127.0.0.1 8080 +httpProxy=http://127.0.0.1 8080 +httpsProxy=http://127.0.0.1 8080 +socksProxy=socks://127.0.0.1 8080
\ No newline at end of file diff --git a/src/tests/data/sample-kde-proxy-wpad b/src/tests/data/sample-kde-proxy-wpad new file mode 100644 index 0000000..6eb1547 --- /dev/null +++ b/src/tests/data/sample-kde-proxy-wpad @@ -0,0 +1,11 @@ +ProxyUrlDisplayFlags=15 + +[Proxy Settings] +NoProxyFor=localhost,127.0.0.1 +Proxy Config Script= +ProxyType=3 +ReversedException=false +ftpProxy=ftp://127.0.0.1 8080 +httpProxy=http://127.0.0.1 8080 +httpsProxy=http://127.0.0.1 8080 +socksProxy=socks://127.0.0.1 8080
\ No newline at end of file diff --git a/src/tests/meson.build b/src/tests/meson.build index fcdd75c..151905f 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -52,4 +52,16 @@ if get_option('tests') env: [envs, 'XDG_CURRENT_DESKTOP=GNOME'], ) endif + + if get_option('config-kde') + config_kde_test = executable('test-config-kde', + ['config-kde-test.c', 'px-manager-helper.c'], + include_directories: px_backend_inc, + dependencies: [glib_dep, px_backend_dep], + ) + test('Config KDE test', + config_kde_test, + env: [envs, 'KDE_FULL_SESSION=1'], + ) + endif endif |