Index: schemas/Makefile.am =================================================================== --- schemas/Makefile.am (revision 7885) +++ schemas/Makefile.am (working copy) @@ -3,7 +3,8 @@ apps_gnome_settings_daemon_screensaver.schemas.in \ apps_gnome_settings_daemon_default_editor.schemas.in \ desktop_gnome_font_rendering.schemas.in \ - apps_gnome_settings_daemon_keybindings.schemas.in + apps_gnome_settings_daemon_keybindings.schemas.in \ + system_proxy.schemas.in schema_DATA = $(schema_in_files:.schemas.in=.schemas) Index: schemas/system_proxy.schemas.in =================================================================== --- schemas/system_proxy.schemas.in (revision 0) +++ schemas/system_proxy.schemas.in (revision 0) @@ -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. + + + + Index: gnome-settings-daemon/novell-sysconfig-proxy-helper =================================================================== --- gnome-settings-daemon/novell-sysconfig-proxy-helper (revision 0) +++ gnome-settings-daemon/novell-sysconfig-proxy-helper (revision 0) @@ -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" Index: gnome-settings-daemon/gnome-settings-proxy.c =================================================================== --- gnome-settings-daemon/gnome-settings-proxy.c (revision 0) +++ gnome-settings-daemon/gnome-settings-proxy.c (revision 0) @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2007 Novell, Inc. + * + * Authors: Federico Mena-Quintero + * + * 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 +#include +#include +#include +#include +#include +#include +#include + + +#include "gnome-settings-module.h" +#include "utils.h" + +/* 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 */ + +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; + +typedef struct { + GnomeSettingsModule parent; +} GnomeSettingsModuleProxy; + +typedef struct { + GnomeSettingsModuleClass parent_class; +} GnomeSettingsModuleProxyClass; + +static GnomeSettingsModuleRunlevel gnome_settings_module_proxy_get_runlevel (GnomeSettingsModule *module); +static gboolean gnome_settings_module_proxy_initialize (GnomeSettingsModule *module, GConfClient *config_client); +static gboolean gnome_settings_module_proxy_start (GnomeSettingsModule *module); +static gboolean gnome_settings_module_proxy_stop (GnomeSettingsModule *module); + +static void +gnome_settings_module_proxy_class_init (GnomeSettingsModuleProxyClass *klass) +{ + GnomeSettingsModuleClass *module_class; + + module_class = (GnomeSettingsModuleClass *) klass; + module_class->get_runlevel = gnome_settings_module_proxy_get_runlevel; + module_class->initialize = gnome_settings_module_proxy_initialize; + module_class->start = gnome_settings_module_proxy_start; + module_class->stop = gnome_settings_module_proxy_stop; +} + +static void +gnome_settings_module_proxy_init (GnomeSettingsModuleProxy *module) +{ +} + +GType +gnome_settings_module_proxy_get_type (void) +{ + static GType module_type = 0; + + if (!module_type) { + const GTypeInfo module_info = { + sizeof (GnomeSettingsModuleProxyClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gnome_settings_module_proxy_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GnomeSettingsModuleProxy), + 0, /* n_preallocs */ + (GInstanceInitFunc) gnome_settings_module_proxy_init, + }; + + module_type = g_type_register_static (GNOME_SETTINGS_TYPE_MODULE, + "GnomeSettingsModuleProxy", + &module_info, 0); + } + + return module_type; +} + +/* 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); +} + +/* Copies the (enabled) system proxy settings in the user's settings */ +static void +copy_proxy_enabled (GConfClient *config_client, SystemSettings *settings) +{ + GnomeVFSURI *uri; + + 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); + + uri = gnome_vfs_uri_new (settings->http_proxy); + if (uri) + { + const char *host; + guint port; + + gconf_client_set_bool (config_client, KEY_USE_HTTP_PROXY, TRUE, NULL); + + host = gnome_vfs_uri_get_host_name (uri); + port = gnome_vfs_uri_get_host_port (uri); + + gconf_client_set_string (config_client, KEY_HTTP_HOST, host, NULL); + gconf_client_set_int (config_client, KEY_HTTP_PORT, (int) port, NULL); + + gnome_vfs_uri_unref (uri); + } + 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 */ + + uri = gnome_vfs_uri_new (settings->https_proxy); + if (uri) + { + const char *host; + guint port; + + host = gnome_vfs_uri_get_host_name (uri); + port = gnome_vfs_uri_get_host_port (uri); + + gconf_client_set_string (config_client, KEY_SECURE_HOST, host, NULL); + gconf_client_set_int (config_client, KEY_SECURE_PORT, (int) port, NULL); + + gnome_vfs_uri_unref (uri); + } + 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 */ + + uri = gnome_vfs_uri_new (settings->ftp_proxy); + + if (uri) + { + const char *host; + guint port; + + host = gnome_vfs_uri_get_host_name (uri); + port = gnome_vfs_uri_get_host_port (uri); + + gconf_client_set_string (config_client, KEY_FTP_HOST, host, NULL); + gconf_client_set_int (config_client, KEY_FTP_PORT, (int) port, NULL); + + gnome_vfs_uri_unref (uri); + } + 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 = gnome_settings_get_config_client (); + + if (strcmp (entry->key, KEY_USE_SYSTEM_SETTINGS) == 0) + use_system_settings_change (client, gconf_value_get_string (entry->value)); +} + +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 (GnomeVFSMonitorHandle *handle, + const gchar *monitor_uri, + const gchar *info_uri, + GnomeVFSMonitorEventType event_type, + gpointer data) +{ + if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED) + return; + + copy_system_values_if_needed ((GConfClient *) data); +} + +static GnomeSettingsModuleRunlevel +gnome_settings_module_proxy_get_runlevel (GnomeSettingsModule *module) +{ + return GNOME_SETTINGS_MODULE_RUNLEVEL_SERVICES; +} + + +static gboolean +gnome_settings_module_proxy_initialize (GnomeSettingsModule *module, GConfClient *config_client) +{ + GConfClient *client = gnome_settings_module_get_config_client (module); + GnomeVFSMonitorHandle *monitor_handle; + char *use_system_settings; + + /* The very first time g-s-d is run, we change the user's keys iff 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 (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 (client, KEY_USE_SYSTEM_SETTINGS, VAL_USE_SYSTEM_SETTINGS_USER_VALUES, NULL); + else + { + copy_system_to_user (config_client); + gconf_client_set_string (client, KEY_USE_SYSTEM_SETTINGS, VAL_USE_SYSTEM_SETTINGS_SYSTEM_VALUES, NULL); + } + } + + if (use_system_settings) + g_free (use_system_settings); + + gnome_settings_register_config_callback (DIR_PROXY, dir_proxy_key_changed_cb); + + if (gnome_vfs_monitor_add (&monitor_handle, ETC_SYSCONFIG_PROXY_URI, GNOME_VFS_MONITOR_FILE, + monitor_cb, client) != GNOME_VFS_OK) + { + g_warning ("Could not install file monitor for /etc/sysconfig/proxy"); + /* Can we do any better than this? */ + } + + return TRUE; +} + +static gboolean +gnome_settings_module_proxy_start (GnomeSettingsModule *module) +{ + GConfClient *client = gnome_settings_module_get_config_client (module); + + copy_system_values_if_needed (client); + + return TRUE; +} + +static gboolean +gnome_settings_module_proxy_stop (GnomeSettingsModule *module) +{ + return TRUE; +} Index: gnome-settings-daemon/gnome-settings-daemon.c =================================================================== --- gnome-settings-daemon/gnome-settings-daemon.c (revision 7885) +++ gnome-settings-daemon/gnome-settings-daemon.c (working copy) @@ -54,6 +54,7 @@ GType gnome_settings_module_typing_break_get_type (void); GType gnome_settings_module_xrdb_get_type (void); GType gnome_settings_module_xsettings_get_type (void); +GType gnome_settings_module_proxy_get_type (void); static GObject *parent_class = NULL; XSettingsManager **managers = NULL; @@ -199,7 +200,8 @@ || !gnome_settings_module_sound_get_type () || !gnome_settings_module_typing_break_get_type () || !gnome_settings_module_xrdb_get_type () - || !gnome_settings_module_xsettings_get_type ()) + || !gnome_settings_module_xsettings_get_type () + || !gnome_settings_module_proxy_get_type ()) return; /* create hash table for loaded modules */ Index: gnome-settings-daemon/Makefile.am =================================================================== --- gnome-settings-daemon/Makefile.am (revision 7885) +++ gnome-settings-daemon/Makefile.am (working copy) @@ -11,7 +11,8 @@ -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \ -DGNOMECC_GLADE_DIR="\"$(pkgdatadir)/glade\"" \ - -DGNOMECC_PIXMAPS_DIR="\"$(pkgdatadir)/pixmaps\"" + -DGNOMECC_PIXMAPS_DIR="\"$(pkgdatadir)/pixmaps\"" \ + -DLIBEXECDIR="\"$(libexecdir)\"" libexec_PROGRAMS=gnome-settings-daemon @@ -50,6 +51,7 @@ gnome-settings-xsettings.c \ gsd-media-keys-window.c \ gsd-media-keys-window.h \ + gnome-settings-proxy.c \ list.c \ list.h \ reaper.c \ @@ -91,6 +93,11 @@ Gladedir = $(pkgdatadir)/glade Glade_DATA = modmap-dialog.glade +helperdir = $(libexecdir) +helperfile = novell-sysconfig-proxy-helper + +install-data-hook : + $(INSTALL_SCRIPT) $(srcdir)/$(helperfile) $(DESTDIR)$(libexecdir)/$(helperfile) Dbusapidir = $(includedir)/gnome-settings-daemon-2.0/gnome-settings-daemon Dbusapi_DATA = gnome-settings-client.h @@ -116,7 +123,7 @@ org.gnome.SettingsDaemon.service: org.gnome.SettingsDaemon.service.in Makefile @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ -EXTRA_DIST = $(Glade_DATA) $(Dbusapi_DATA) \ +EXTRA_DIST = $(Glade_DATA) $(Dbusapi_DATA) $(helperfile) \ gnome-settings-daemon.pc.in gsd-infos.xml \ org.gnome.SettingsDaemon.service.in gnome-settings-marshal.list CLEANFILES = $(BUILT_SOURCES) $(service_DATA)