From e61dc951c432d489b17e3bdaf1e566ac15958c6b Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Thu, 14 Aug 2008 18:55:55 -0500 Subject: [PATCH 1/8] Add a new plugin for proxy settings. We read the system's configuration from /etc/sysconfig/proxy and propagate it to GNOME's GConf keys. --- plugins/proxy/Makefile.am | 57 +++ plugins/proxy/gsd-proxy-manager.c | 571 ++++++++++++++++++++++++++ plugins/proxy/gsd-proxy-manager.h | 57 +++ plugins/proxy/gsd-proxy-plugin.c | 103 +++++ plugins/proxy/gsd-proxy-plugin.h | 59 +++ plugins/proxy/novell-sysconfig-proxy-helper | 19 + plugins/proxy/proxy.gnome-settings-plugin.in | 8 + 7 files changed, 874 insertions(+), 0 deletions(-) create mode 100644 plugins/proxy/Makefile.am create mode 100644 plugins/proxy/gsd-proxy-manager.c create mode 100644 plugins/proxy/gsd-proxy-manager.h create mode 100644 plugins/proxy/gsd-proxy-plugin.c create mode 100644 plugins/proxy/gsd-proxy-plugin.h create mode 100644 plugins/proxy/novell-sysconfig-proxy-helper create mode 100644 plugins/proxy/proxy.gnome-settings-plugin.in diff --git a/plugins/proxy/Makefile.am b/plugins/proxy/Makefile.am new file mode 100644 index 0000000..6a4ba90 --- /dev/null +++ b/plugins/proxy/Makefile.am @@ -0,0 +1,57 @@ +NULL = + +plugin_LTLIBRARIES = \ + libproxy.la \ + $(NULL) + +libproxy_la_SOURCES = \ + gsd-proxy-plugin.h \ + gsd-proxy-plugin.c \ + gsd-proxy-manager.h \ + gsd-proxy-manager.c \ + $(NULL) + +libproxy_la_CPPFLAGS = \ + -I$(top_srcdir)/gnome-settings-daemon \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ + $(AM_CPPFLAGS) + +libproxy_la_CFLAGS = \ + $(SETTINGS_PLUGIN_CFLAGS) \ + -DLIBEXECDIR="\"$(libexecdir)\"" \ + $(AM_CFLAGS) + +libproxy_la_LDFLAGS = \ + $(GSD_PLUGIN_LDFLAGS) \ + $(NULL) + +libproxy_la_LIBADD = \ + $(SETTINGS_PLUGIN_LIBS) \ + $(NULL) + +plugin_in_files = \ + proxy.gnome-settings-plugin.in \ + $(NULL) + +plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) + +helperdir = $(libexecdir) +helperfile = novell-sysconfig-proxy-helper + +install-data-hook : + $(INSTALL_SCRIPT) $(srcdir)/$(helperfile) $(DESTDIR)$(libexecdir)/$(helperfile) + +EXTRA_DIST = \ + $(plugin_in_files) \ + $(helperfile) \ + $(NULL) + +CLEANFILES = \ + $(plugin_DATA) \ + $(NULL) + +DISTCLEANFILES = \ + $(plugin_DATA) \ + $(NULL) + +@GSD_INTLTOOL_PLUGIN_RULE@ diff --git a/plugins/proxy/gsd-proxy-manager.c b/plugins/proxy/gsd-proxy-manager.c new file mode 100644 index 0000000..9092b00 --- /dev/null +++ b/plugins/proxy/gsd-proxy-manager.c @@ -0,0 +1,571 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Rodrigo Moya + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "gnome-settings-profile.h" +#include "gsd-proxy-manager.h" + +#define GSD_PROXY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_PROXY_MANAGER, GsdProxyManagerPrivate)) + +/* Novell extension */ +#define KEY_USE_SYSTEM_SETTINGS "/system/proxy/use_system_settings" /* string */ +#define VAL_USE_SYSTEM_SETTINGS_ONLY_IF_NOT_SET "only_if_mode_not_set" +#define VAL_USE_SYSTEM_SETTINGS_SYSTEM_VALUES "system_values" +#define VAL_USE_SYSTEM_SETTINGS_USER_VALUES "user_values" + +#define ETC_SYSCONFIG_PROXY_URI "file:///etc/sysconfig/proxy" + +/* Gnome keys */ +#define DIR_PROXY "/system/proxy" +#define KEY_USE_HTTP_PROXY "/system/http_proxy/use_http_proxy" /* bool */ +#define KEY_HTTP_HOST "/system/http_proxy/host" /* string */ +#define KEY_HTTP_PORT "/system/http_proxy/port" /* int */ +#define KEY_HTTP_USE_AUTHENTICATION "/system/http_proxy/use_authentication" /* bool */ +#define KEY_HTTP_AUTHENTICATION_USER "/system/http_proxy/authentication_user" /* string */ +#define KEY_HTTP_AUTHENTICATION_PASSWORD "/system/http_proxy/authentication_password" /* string */ +#define KEY_HTTP_IGNORE_HOSTS "/system/http_proxy/ignore_hosts" /* list-of-string */ +#define KEY_MODE "/system/proxy/mode" /* string */ +#define KEY_SECURE_HOST "/system/proxy/secure_host" /* string */ +#define KEY_SECURE_PORT "/system/proxy/secure_port" /* int */ +#define KEY_FTP_HOST "/system/proxy/ftp_host" /* string */ +#define KEY_FTP_PORT "/system/proxy/ftp_port" /* int */ +#define KEY_SOCKS_HOST "/system/proxy/socks_host" /* string */ +#define KEY_SOCKS_PORT "/system/proxy/socks_port" /* int */ +#define KEY_AUTOCONFIG_URL "/system/proxy/autoconfig_url" /* string */ + +struct GsdProxyManagerPrivate +{ +}; + +typedef struct { + char *proxy_enabled; /* "yes"/"no" */ + char *http_proxy; /* "http://host:port" */ + char *https_proxy; /* "http://host:port" */ + char *ftp_proxy; /* "http://host:port" */ + /* char *gopher_proxy; Gnome doesn't have a Gopher proxy setting as of 2.10 */ + char *no_proxy; /* "www.me.de, do.main, localhost" */ + /* char *user; + * char *password; + * Yast2 currently doesn't support a public username/password; they are just + * stored in /root/.wgetrc and /root/.curlrc + */ +} SystemSettings; + +static void gsd_proxy_manager_class_init (GsdProxyManagerClass *klass); +static void gsd_proxy_manager_init (GsdProxyManager *proxy_manager); +static void gsd_proxy_manager_finalize (GObject *object); + +G_DEFINE_TYPE (GsdProxyManager, gsd_proxy_manager, G_TYPE_OBJECT) + +static gpointer manager_object = NULL; + +/* Returns whether the /system/proxy/mode key has ever been set by the user */ +static gboolean +user_mode_is_set (GConfClient *config_client) +{ + GConfValue *value; + + value = gconf_client_get_without_default (config_client, KEY_MODE, NULL); + + if (value) + { + gconf_value_free (value); + return TRUE; + } + else + return FALSE; +} + +static const char * +until_newline (const char *str, char **dest) +{ + const char *p; + + p = strchr (str, '\n'); + if (!p) + p = str + strlen (str); + + if (dest) + *dest = g_strstrip (g_strndup (str, p - str)); + + return p; +} + +static const char * +scan_for_token_and_jump_until_newline (const char *buf, const char *token, char **dest) +{ + int len; + + len = strlen (token); + + if (strncmp (buf, token, len) == 0) + return until_newline (buf + len, dest); + else + return buf; +} + +/* Reads the system's proxy settings */ +static void +read_system_settings (SystemSettings *settings) +{ + char *out; + const char *p; + int total_len; + struct tokens { + const char *token; + char **dest; + } tokens[] = { + { "PROXY_ENABLED ", &settings->proxy_enabled }, + { "HTTP_PROXY ", &settings->http_proxy }, + { "HTTPS_PROXY ", &settings->https_proxy }, + { "FTP_PROXY ", &settings->ftp_proxy }, + { "NO_PROXY ", &settings->no_proxy } + }; + int num_tokens = G_N_ELEMENTS (tokens); + + settings->proxy_enabled = NULL; + settings->http_proxy = NULL; + settings->https_proxy = NULL; + settings->ftp_proxy = NULL; + settings->no_proxy = NULL; + + if (!g_spawn_command_line_sync (LIBEXECDIR "/novell-sysconfig-proxy-helper", + &out, + NULL, + NULL, + NULL)) + + return; + + total_len = strlen (out); + + p = out; + while (p < out + total_len) + { + int i; + + for (i = 0; i < num_tokens; i++) + p = scan_for_token_and_jump_until_newline (p, tokens[i].token, tokens[i].dest); + + if (i == num_tokens) + p = until_newline (p, NULL); + + if (*p == '\n') + p++; + } + + g_free (out); +} + +static void +system_settings_free (SystemSettings *settings) +{ + g_free (settings->proxy_enabled); + g_free (settings->http_proxy); + g_free (settings->https_proxy); + g_free (settings->ftp_proxy); + g_free (settings->no_proxy); +} + +/* Disables the proxy in the user's settings */ +static void +copy_proxy_disabled (GConfClient *config_client) +{ + gconf_client_set_bool (config_client, KEY_USE_HTTP_PROXY, FALSE, NULL); + gconf_client_set_string (config_client, KEY_MODE, "none", NULL); +} + +/* parses a URI to get the host and port */ +static gboolean +parse_uri (const gchar *uri, gchar **host, guint *port) +{ + char **tokens; + + tokens = g_strsplit_set (uri, ":", 0); + if (tokens[1] != NULL) { + *host = g_strdup (tokens[1] + 2); + } + + if (tokens[2] != NULL) { + *port = (guint) atoi (tokens[2]); + } + + g_debug ("Proxy host: %s:%d", *host, *port); + + g_strfreev (tokens); + return TRUE; +} + +/* Copies the (enabled) system proxy settings in the user's settings */ +static void +copy_proxy_enabled (GConfClient *config_client, SystemSettings *settings) +{ + gchar *host; + guint port; + + gconf_client_set_string (config_client, KEY_MODE, "manual", NULL); + + /* 1. HTTP proxy */ + + /* Yast2 currently doesn't support a public username/password */ + gconf_client_set_bool (config_client, KEY_HTTP_USE_AUTHENTICATION, FALSE, NULL); + gconf_client_set_string (config_client, KEY_HTTP_AUTHENTICATION_USER, "", NULL); + gconf_client_set_string (config_client, KEY_HTTP_AUTHENTICATION_PASSWORD, "", NULL); + + if (parse_uri (settings->http_proxy, &host, &port)) + { + gconf_client_set_bool (config_client, KEY_USE_HTTP_PROXY, TRUE, NULL); + + gconf_client_set_string (config_client, KEY_HTTP_HOST, host, NULL); + gconf_client_set_int (config_client, KEY_HTTP_PORT, (int) port, NULL); + + g_free (host); + } + else + { + gconf_client_set_bool (config_client, KEY_USE_HTTP_PROXY, FALSE, NULL); + gconf_client_set_string (config_client, KEY_HTTP_HOST, "", NULL); + gconf_client_set_int (config_client, KEY_HTTP_PORT, 0, NULL); + gconf_client_set_list (config_client, KEY_HTTP_IGNORE_HOSTS, GCONF_VALUE_STRING, NULL, NULL); + } + + /* 2. HTTPS proxy */ + + if (parse_uri (settings->https_proxy, &host, &port)) + { + gconf_client_set_string (config_client, KEY_SECURE_HOST, host, NULL); + gconf_client_set_int (config_client, KEY_SECURE_PORT, (int) port, NULL); + + g_free (host); + } + else + { + gconf_client_set_string (config_client, KEY_SECURE_HOST, "", NULL); + gconf_client_set_int (config_client, KEY_SECURE_PORT, 0, NULL); + } + + /* 3. FTP proxy */ + + if (parse_uri (settings->ftp_proxy, &host, &port)) + { + gconf_client_set_string (config_client, KEY_FTP_HOST, host, NULL); + gconf_client_set_int (config_client, KEY_FTP_PORT, (int) port, NULL); + + g_free (host); + } + else + { + gconf_client_set_string (config_client, KEY_FTP_HOST, "", NULL); + gconf_client_set_int (config_client, KEY_FTP_PORT, 0, NULL); + } + + /* 4. No-proxy hosts */ + + if (settings->no_proxy != NULL) + { + char **tokens; + int i; + GSList *list; + + tokens = g_strsplit_set (settings->no_proxy, ", ", 0); + + list = NULL; + + for (i = 0; tokens[i] != NULL; i++) + { + char *s; + + s = tokens[i]; + if (strlen (s) != 0) + list = g_slist_prepend (list, s); + } + + list = g_slist_reverse (list); + + gconf_client_set_list (config_client, KEY_HTTP_IGNORE_HOSTS, GCONF_VALUE_STRING, list, NULL); + + g_slist_free (list); + g_strfreev (tokens); + } + else + gconf_client_set_list (config_client, KEY_HTTP_IGNORE_HOSTS, GCONF_VALUE_STRING, NULL, NULL); +} + +/* Copies the system's proxy settings to the user's settings */ +static void +copy_system_to_user (GConfClient *config_client) +{ + SystemSettings settings; + + read_system_settings (&settings); + + if (settings.proxy_enabled == NULL) + copy_proxy_disabled (config_client); + else + { + if (strcmp (settings.proxy_enabled, "no") == 0) + copy_proxy_disabled (config_client); + else if (strcmp (settings.proxy_enabled, "yes") == 0) + copy_proxy_enabled (config_client, &settings); + } + + system_settings_free (&settings); +} + +static void +use_system_settings_change (GConfClient *config_client, const char *value) +{ + if (strcmp (value, VAL_USE_SYSTEM_SETTINGS_SYSTEM_VALUES) == 0) + { + copy_system_to_user (config_client); + } + else if (strcmp (value, VAL_USE_SYSTEM_SETTINGS_USER_VALUES) == 0) + { + /* nothing; the user's values are already set */ + } +} + +static void +dir_proxy_key_changed_cb (GConfEntry *entry) +{ + GConfClient *client = gconf_client_get_default (); + + if (strcmp (entry->key, KEY_USE_SYSTEM_SETTINGS) == 0) + use_system_settings_change (client, gconf_value_get_string (entry->value)); + + g_object_unref (client); +} + +static void +copy_system_values_if_needed (GConfClient *client) +{ + char *value; + + value = gconf_client_get_string (client, KEY_USE_SYSTEM_SETTINGS, NULL); + if (!value) + return; + + use_system_settings_change (client, value); + g_free (value); +} + +/* File monitor callback for /etc/sysconfig/proxy */ +static void +monitor_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer data) +{ + GConfClient *client; + + if (event_type != G_FILE_MONITOR_EVENT_CHANGED) + return; + + client = gconf_client_get_default (); + copy_system_values_if_needed (client); + g_object_unref (G_OBJECT (client)); +} + +gboolean +gsd_proxy_manager_start (GsdProxyManager *manager, + GError **error) +{ + GConfClient *config_client; + GFile *sysconfig_proxy; + GFileMonitor *monitor; + char *use_system_settings; + + g_debug ("Starting proxy manager"); + gnome_settings_profile_start (NULL); + + config_client = gconf_client_get_default (); + + /* The very first time g-s-d is run, we change the user's keys if the new + * use_system_settings key is not set at all or is set to the default. + * Afterwards, that key will be set to reflect what the user had previously + * configured. + */ + + use_system_settings = gconf_client_get_string (config_client, KEY_USE_SYSTEM_SETTINGS, NULL); + if (!use_system_settings || strcmp (use_system_settings, VAL_USE_SYSTEM_SETTINGS_ONLY_IF_NOT_SET) == 0) + { + if (user_mode_is_set (config_client)) + gconf_client_set_string (config_client, KEY_USE_SYSTEM_SETTINGS, VAL_USE_SYSTEM_SETTINGS_USER_VALUES, NULL); + else + { + copy_system_to_user (config_client); + gconf_client_set_string (config_client, KEY_USE_SYSTEM_SETTINGS, VAL_USE_SYSTEM_SETTINGS_SYSTEM_VALUES, NULL); + } + } + + if (use_system_settings) + g_free (use_system_settings); + + gconf_client_add_dir (config_client, DIR_PROXY, GCONF_CLIENT_PRELOAD_NONE, NULL); + gconf_client_notify_add (config_client, DIR_PROXY, dir_proxy_key_changed_cb, NULL, NULL, NULL); + + sysconfig_proxy = g_file_new_for_uri (ETC_SYSCONFIG_PROXY_URI); + monitor = g_file_monitor_file (sysconfig_proxy, 0, NULL, NULL); + g_signal_connect (monitor, "changed", G_CALLBACK (monitor_cb), NULL); + + copy_system_values_if_needed (config_client); + + g_object_unref (config_client); + + gnome_settings_profile_end (NULL); + + return TRUE; +} + +void +gsd_proxy_manager_stop (GsdProxyManager *manager) +{ + g_debug ("Stopping proxy manager"); +} + +static void +gsd_proxy_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GsdProxyManager *self; + + self = GSD_PROXY_MANAGER (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gsd_proxy_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GsdProxyManager *self; + + self = GSD_PROXY_MANAGER (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GObject * +gsd_proxy_manager_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GsdProxyManager *proxy_manager; + GsdProxyManagerClass *klass; + + klass = GSD_PROXY_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_PROXY_MANAGER)); + + proxy_manager = GSD_PROXY_MANAGER (G_OBJECT_CLASS (gsd_proxy_manager_parent_class)->constructor (type, + n_construct_properties, + construct_properties)); + + return G_OBJECT (proxy_manager); +} + +static void +gsd_proxy_manager_dispose (GObject *object) +{ + GsdProxyManager *proxy_manager; + + proxy_manager = GSD_PROXY_MANAGER (object); + + G_OBJECT_CLASS (gsd_proxy_manager_parent_class)->dispose (object); +} + +static void +gsd_proxy_manager_class_init (GsdProxyManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = gsd_proxy_manager_get_property; + object_class->set_property = gsd_proxy_manager_set_property; + object_class->constructor = gsd_proxy_manager_constructor; + object_class->dispose = gsd_proxy_manager_dispose; + object_class->finalize = gsd_proxy_manager_finalize; + + g_type_class_add_private (klass, sizeof (GsdProxyManagerPrivate)); +} + +static void +gsd_proxy_manager_init (GsdProxyManager *manager) +{ + manager->priv = GSD_PROXY_MANAGER_GET_PRIVATE (manager); +} + +static void +gsd_proxy_manager_finalize (GObject *object) +{ + GsdProxyManager *proxy_manager; + + g_return_if_fail (object != NULL); + g_return_if_fail (GSD_IS_PROXY_MANAGER (object)); + + proxy_manager = GSD_PROXY_MANAGER (object); + + g_return_if_fail (proxy_manager->priv != NULL); + + G_OBJECT_CLASS (gsd_proxy_manager_parent_class)->finalize (object); +} + +GsdProxyManager * +gsd_proxy_manager_new (void) +{ + if (manager_object != NULL) { + g_object_ref (manager_object); + } else { + manager_object = g_object_new (GSD_TYPE_PROXY_MANAGER, NULL); + g_object_add_weak_pointer (manager_object, + (gpointer *) &manager_object); + } + + return GSD_PROXY_MANAGER (manager_object); +} diff --git a/plugins/proxy/gsd-proxy-manager.h b/plugins/proxy/gsd-proxy-manager.h new file mode 100644 index 0000000..3f97d01 --- /dev/null +++ b/plugins/proxy/gsd-proxy-manager.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Rodrigo Moya + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GSD_PROXY_MANAGER_H +#define __GSD_PROXY_MANAGER_H + +#include + +G_BEGIN_DECLS + +#define GSD_TYPE_PROXY_MANAGER (gsd_proxy_manager_get_type ()) +#define GSD_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_PROXY_MANAGER, GsdProxyManager)) +#define GSD_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_PROXY_MANAGER, GsdProxyManagerClass)) +#define GSD_IS_PROXY_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_PROXY_MANAGER)) +#define GSD_IS_PROXY_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_PROXY_MANAGER)) +#define GSD_PROXY_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_PROXY_MANAGER, GsdProxyManagerClass)) + +typedef struct GsdProxyManagerPrivate GsdProxyManagerPrivate; + +typedef struct +{ + GObject parent; + GsdProxyManagerPrivate *priv; +} GsdProxyManager; + +typedef struct +{ + GObjectClass parent_class; +} GsdProxyManagerClass; + +GType gsd_proxy_manager_get_type (void); + +GsdProxyManager * gsd_proxy_manager_new (void); +gboolean gsd_proxy_manager_start (GsdProxyManager *manager, + GError **error); +void gsd_proxy_manager_stop (GsdProxyManager *manager); + +G_END_DECLS + +#endif /* __GSD_PROXY_MANAGER_H */ diff --git a/plugins/proxy/gsd-proxy-plugin.c b/plugins/proxy/gsd-proxy-plugin.c new file mode 100644 index 0000000..843ff16 --- /dev/null +++ b/plugins/proxy/gsd-proxy-plugin.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Rodrigo Moya + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include +#include + +#include "gnome-settings-plugin.h" +#include "gsd-proxy-plugin.h" +#include "gsd-proxy-manager.h" + +struct GsdProxyPluginPrivate { + GsdProxyManager *manager; +}; + +#define GSD_PROXY_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_PROXY_PLUGIN, GsdProxyPluginPrivate)) + +GNOME_SETTINGS_PLUGIN_REGISTER (GsdProxyPlugin, gsd_proxy_plugin) + +static void +gsd_proxy_plugin_init (GsdProxyPlugin *plugin) +{ + plugin->priv = GSD_PROXY_PLUGIN_GET_PRIVATE (plugin); + + g_debug ("GsdProxyPlugin initializing"); + + plugin->priv->manager = gsd_proxy_manager_new (); +} + +static void +gsd_proxy_plugin_finalize (GObject *object) +{ + GsdProxyPlugin *plugin; + + g_return_if_fail (object != NULL); + g_return_if_fail (GSD_IS_PROXY_PLUGIN (object)); + + g_debug ("GsdProxyPlugin finalizing"); + + plugin = GSD_PROXY_PLUGIN (object); + + g_return_if_fail (plugin->priv != NULL); + + if (plugin->priv->manager != NULL) { + g_object_unref (plugin->priv->manager); + } + + G_OBJECT_CLASS (gsd_proxy_plugin_parent_class)->finalize (object); +} + +static void +impl_activate (GnomeSettingsPlugin *plugin) +{ + gboolean res; + GError *error; + + g_debug ("Activating proxy plugin"); + + error = NULL; + res = gsd_proxy_manager_start (GSD_PROXY_PLUGIN (plugin)->priv->manager, &error); + if (! res) { + g_warning ("Unable to start proxy manager: %s", error->message); + g_error_free (error); + } +} + +static void +impl_deactivate (GnomeSettingsPlugin *plugin) +{ + g_debug ("Deactivating proxy plugin"); +} + +static void +gsd_proxy_plugin_class_init (GsdProxyPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GnomeSettingsPluginClass *plugin_class = GNOME_SETTINGS_PLUGIN_CLASS (klass); + + object_class->finalize = gsd_proxy_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + + g_type_class_add_private (klass, sizeof (GsdProxyPluginPrivate)); +} diff --git a/plugins/proxy/gsd-proxy-plugin.h b/plugins/proxy/gsd-proxy-plugin.h new file mode 100644 index 0000000..8f81ecb --- /dev/null +++ b/plugins/proxy/gsd-proxy-plugin.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Rodrigo Moya + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GSD_PROXY_PLUGIN_H__ +#define __GSD_PROXY_PLUGIN_H__ + +#include +#include +#include + +#include "gnome-settings-plugin.h" + +G_BEGIN_DECLS + +#define GSD_TYPE_PROXY_PLUGIN (gsd_proxy_plugin_get_type ()) +#define GSD_PROXY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_PROXY_PLUGIN, GsdProxyPlugin)) +#define GSD_PROXY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_PROXY_PLUGIN, GsdProxyPluginClass)) +#define GSD_IS_PROXY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_PROXY_PLUGIN)) +#define GSD_IS_PROXY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_PROXY_PLUGIN)) +#define GSD_PROXY_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_PROXY_PLUGIN, GsdProxyPluginClass)) + +typedef struct GsdProxyPluginPrivate GsdProxyPluginPrivate; + +typedef struct +{ + GnomeSettingsPlugin parent; + GsdProxyPluginPrivate *priv; +} GsdProxyPlugin; + +typedef struct +{ + GnomeSettingsPluginClass parent_class; +} GsdProxyPluginClass; + +GType gsd_proxy_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_gnome_settings_plugin (GTypeModule *module); + +G_END_DECLS + +#endif /* __GSD_PROXY_PLUGIN_H__ */ diff --git a/plugins/proxy/novell-sysconfig-proxy-helper b/plugins/proxy/novell-sysconfig-proxy-helper new file mode 100644 index 0000000..98b76da --- /dev/null +++ b/plugins/proxy/novell-sysconfig-proxy-helper @@ -0,0 +1,19 @@ +#!/bin/sh + +if [ ! -f /etc/sysconfig/proxy ] +then + exit 0 +fi + +source /etc/sysconfig/proxy + +# This may look convoluted, but it's an easy way to let random shell +# script code appear in /etc/sysconfig/proxy and still let user code +# read the variables in it easily. + +echo "PROXY_ENABLED $PROXY_ENABLED" +echo "HTTP_PROXY $HTTP_PROXY" +echo "HTTPS_PROXY $HTTPS_PROXY" +echo "FTP_PROXY $FTP_PROXY" +echo "GOPHER_PROXY $GOPHER_PROXY" +echo "NO_PROXY $NO_PROXY" diff --git a/plugins/proxy/proxy.gnome-settings-plugin.in b/plugins/proxy/proxy.gnome-settings-plugin.in new file mode 100644 index 0000000..19ce10c --- /dev/null +++ b/plugins/proxy/proxy.gnome-settings-plugin.in @@ -0,0 +1,8 @@ +[GNOME Settings Plugin] +Module=proxy +IAge=0 +_Name=Network Proxy +_Description=Network proxy plugin +Authors=Rodrigo Moya +Copyright= +Website= -- 1.5.6 From b0bf83da99fce538da8d747e5386853626d456ec Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Thu, 14 Aug 2008 19:00:41 -0500 Subject: [PATCH 2/8] Add schemas for the system proxy settings. See the documentation about this in http://en.opensuse.org/GNOME/Proxy_configuration --- data/system_proxy.schemas.in | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) create mode 100644 data/system_proxy.schemas.in diff --git a/data/system_proxy.schemas.in b/data/system_proxy.schemas.in new file mode 100644 index 0000000..5f01b2e --- /dev/null +++ b/data/system_proxy.schemas.in @@ -0,0 +1,26 @@ + + + + + /schemas/system/proxy/use_system_settings + /system/proxy/use_system_settings + string + only_if_mode_not_set + + Use the system's proxy settings + Whether to use the system's proxy settings. + Possible values are "only_if_mode_not_set", "system_values", and + "user_values". The first one is the default value; in + it, the system's proxy settings will be used if and + only if the user has never set his /system/proxy/mode + key. Once the user sets that key, use_system_settings + will switch to "system_values", which indicates that + the system's proxy settings should be used, or + "user_values", which indicates that the user's + settings should be used. The key will alternate + between these last two values in the future and will + not go back to the default value. + + + + -- 1.5.6 From b149af05692650efe6947aa084287fcdda428108 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Thu, 14 Aug 2008 18:58:46 -0500 Subject: [PATCH 3/8] Add the proxy plugin to the plugins/Makefile.am --- plugins/Makefile.am | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2d33061..82f3eae 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -12,6 +12,7 @@ SUBDIRS = \ keyboard \ media-keys \ mouse \ + proxy \ screensaver \ sound \ typing-break \ -- 1.5.6 From 97e29c68cf89a34db1c35656a3cc7e2e3d8f565d Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Thu, 14 Aug 2008 18:59:21 -0500 Subject: [PATCH 4/8] Add the proxy plugin to configure.ac --- configure.ac | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index bc336c1..ec5e5f3 100644 --- a/configure.ac +++ b/configure.ac @@ -441,6 +441,7 @@ plugins/keyboard/Makefile plugins/media-keys/Makefile plugins/media-keys/actions/Makefile plugins/mouse/Makefile +plugins/proxy/Makefile plugins/screensaver/Makefile plugins/sound/Makefile plugins/sound/libsounds/Makefile -- 1.5.6 From ddab86c79a40b5d95a8d0420e1ea88e1d3ddbac9 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Thu, 14 Aug 2008 18:59:54 -0500 Subject: [PATCH 5/8] Add the proxy schemas to data/Makefile.am --- data/Makefile.am | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/data/Makefile.am b/data/Makefile.am index 2f0d4ca..c2494ec 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -9,6 +9,7 @@ schemas_in_files = \ apps_gnome_settings_daemon_screensaver.schemas.in \ desktop_gnome_font_rendering.schemas.in \ apps_gnome_settings_daemon_xrandr.schemas.in \ + system_proxy.schemas.in \ $(NULL) schemas_DATA = $(schemas_in_files:.schemas.in=.schemas) -- 1.5.6 From 89cd97f780087457a9ee9d93f5922b2764beffaa Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 8 Dec 2008 13:32:02 -0600 Subject: [PATCH 6/8] Enable the proxy plugin in g-s-d's toplevel schemas Signed-off-by: Federico Mena Quintero --- data/gnome-settings-daemon.schemas.in | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/data/gnome-settings-daemon.schemas.in b/data/gnome-settings-daemon.schemas.in index 3f6a426..e4bacd7 100644 --- a/data/gnome-settings-daemon.schemas.in +++ b/data/gnome-settings-daemon.schemas.in @@ -210,6 +210,30 @@ + /schemas/apps/gnome_settings_daemon/plugins/proxy/active + /apps/gnome_settings_daemon/plugins/proxy/active + gnome-settings-daemon + bool + TRUE + + Enable system-proxy plugin + Set to True to enable the plugin to manage the system + proxy settings. + + + + /schemas/apps/gnome_settings_daemon/plugins/proxy/priority + /apps/gnome_settings_daemon/plugins/proxy/priority + gnome-settings-daemon + int + 7 + + + + + + + /schemas/apps/gnome_settings_daemon/plugins/screensaver/active /apps/gnome_settings_daemon/plugins/screensaver/active gnome-settings-daemon -- 1.5.6 From 2765d441f29be5bfb53cf54c9d191c21522f95d0 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 8 Dec 2008 14:06:55 -0600 Subject: [PATCH 7/8] Add a dummy field to GsdProxyManagerPrivate so the struct isn't zero-sized Signed-off-by: Federico Mena Quintero --- plugins/proxy/gsd-proxy-manager.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/plugins/proxy/gsd-proxy-manager.c b/plugins/proxy/gsd-proxy-manager.c index 9092b00..345c1ad 100644 --- a/plugins/proxy/gsd-proxy-manager.c +++ b/plugins/proxy/gsd-proxy-manager.c @@ -71,6 +71,11 @@ struct GsdProxyManagerPrivate { + /* This is to avoid "sizeof (GsdProxyManagerPrivate) == 0" when adding + * the private struct with g_type_class_add_private(). Feel free to + * remove this dummy field if you add real fields here. + */ + int dummy; }; typedef struct { -- 1.5.6 From 2fd84c545f46e8cff53eaef638cc3a4906d05116 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 8 Dec 2008 14:54:34 -0600 Subject: [PATCH 8/8] Steal gedit_utils_decode_uri() and use it instead of a broken URI-parsing function Signed-off-by: Federico Mena Quintero --- plugins/proxy/gsd-proxy-manager.c | 181 ++++++++++++++++++++++++++++++++++--- 1 files changed, 168 insertions(+), 13 deletions(-) diff --git a/plugins/proxy/gsd-proxy-manager.c b/plugins/proxy/gsd-proxy-manager.c index 345c1ad..662ef98 100644 --- a/plugins/proxy/gsd-proxy-manager.c +++ b/plugins/proxy/gsd-proxy-manager.c @@ -216,24 +216,179 @@ copy_proxy_disabled (GConfClient *config_client) gconf_client_set_string (config_client, KEY_MODE, "none", NULL); } -/* parses a URI to get the host and port */ + + +/* The following two functions (the main one being gedit_utils_decode_uri) are + * stolen from gedit/gedit/gedit-utils.c. This is because GIO doesn't yet + * export a function to parse URIs, sigh. + */ + +static void +null_ptr (gchar **ptr) +{ + if (ptr) + *ptr = NULL; +} + +/** +* gedit_utils_decode_uri: +* @uri: the uri to decode +* @scheme: return value pointer for the uri's scheme (e.g. http, sftp, ...) +* @user: return value pointer for the uri user info +* @port: return value pointer for the uri port +* @host: return value pointer for the uri host +* @path: return value pointer for the uri path +* +* Parse and break an uri apart in its individual components like the uri +* scheme, user info, port, host and path. The return value pointer can be +* NULL to ignore certain parts of the uri. If the function returns TRUE, then +* all return value pointers should be freed using g_free +* +* Return value: TRUE if the uri could be properly decoded, FALSE otherwise. +*/ static gboolean -parse_uri (const gchar *uri, gchar **host, guint *port) +gedit_utils_decode_uri (const gchar *uri, + gchar **scheme, + gchar **user, + gchar **host, + gchar **port, + gchar **path) { - char **tokens; - - tokens = g_strsplit_set (uri, ":", 0); - if (tokens[1] != NULL) { - *host = g_strdup (tokens[1] + 2); + /* Largely copied from glib/gio/gdummyfile.c:_g_decode_uri. This + * functionality should be in glib/gio, but for now we implement it + * ourselves (see bug #546182) */ + + const char *p, *in, *hier_part_start, *hier_part_end; + char *out; + char c; + + /* From RFC 3986 Decodes: + * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + */ + + p = uri; + + null_ptr (scheme); + null_ptr (user); + null_ptr (port); + null_ptr (host); + null_ptr (path); + + /* Decode scheme: + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ + + if (!g_ascii_isalpha (*p)) + return FALSE; + + while (1) { + c = *p++; + + if (c == ':') + break; + + if (!(g_ascii_isalnum(c) || + c == '+' || + c == '-' || + c == '.')) + return FALSE; } - - if (tokens[2] != NULL) { - *port = (guint) atoi (tokens[2]); + + if (scheme) { + *scheme = g_malloc (p - uri); + out = *scheme; + + for (in = uri; in < p - 1; in++) + *out++ = g_ascii_tolower (*in); + + *out = '\0'; } - + + hier_part_start = p; + hier_part_end = p + strlen (p); + + if (hier_part_start[0] == '/' && hier_part_start[1] == '/') { + const char *authority_start, *authority_end; + const char *userinfo_start, *userinfo_end; + const char *host_start, *host_end; + const char *port_start; + + authority_start = hier_part_start + 2; + /* authority is always followed by / or nothing */ + authority_end = memchr (authority_start, '/', hier_part_end - authority_start); + + if (authority_end == NULL) + authority_end = hier_part_end; + + /* 3.2: + * authority = [ userinfo "@" ] host [ ":" port ] + */ + + userinfo_end = memchr (authority_start, '@', authority_end - authority_start); + + if (userinfo_end) { + userinfo_start = authority_start; + + if (user) + *user = g_uri_unescape_segment (userinfo_start, userinfo_end, NULL); + + if (user && *user == NULL) { + if (scheme) + g_free (*scheme); + + return FALSE; + } + + host_start = userinfo_end + 1; + } else + host_start = authority_start; + + port_start = memchr (host_start, ':', authority_end - host_start); + + if (port_start) { + host_end = port_start++; + + if (port) + *port = g_strndup (port_start, authority_end - port_start); + } else + host_end = authority_end; + + if (host) + *host = g_strndup (host_start, host_end - host_start); + + hier_part_start = authority_end; + } + + if (path) + *path = g_uri_unescape_segment (hier_part_start, hier_part_end, "/"); + + return TRUE; +} + + + +/* parses a URI to get the host and port */ +static gboolean +parse_uri (const gchar *uri, gchar **host, guint *port) +{ + gchar *port_str; + + if (!gedit_utils_decode_uri (uri, + NULL, /* scheme */ + NULL, /* user */ + host, /* host */ + &port_str, /* port */ + NULL)) /* path */ + return FALSE; + + if (port_str) { + *port = atoi (port_str); + g_free (port_str); + } else + *port = 0; + g_debug ("Proxy host: %s:%d", *host, *port); - - g_strfreev (tokens); + return TRUE; } -- 1.5.6