---
 Makefile.am     |    7 +-
 src/manager.c   |   70 ++++++++++----
 src/manual.c    |  277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/manual.h    |   26 +++++
 src/pacrunner.h |   16 +++-
 src/proxy.c     |   76 ++++++++++++---
 6 files changed, 435 insertions(+), 37 deletions(-)
 create mode 100644 src/manual.c
 create mode 100644 src/manual.h

diff --git a/Makefile.am b/Makefile.am
index 5a9aa7e..62fb474 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,3 @@
-
 AM_MAKEFLAGS = --no-print-directory
 
 if DATAFILES
@@ -32,6 +31,7 @@ src_pacrunner_SOURCES = $(gdbus_sources) $(builtin_sources) \
                        src/main.c src/pacrunner.h \
                        src/log.h src/log.c src/plugin.h src/plugin.c \
                        src/download.h src/download.c \
+                       src/manual.h src/manual.c \
                        src/client.c src/manager.c \
                        src/proxy.c src/mozjs.c src/javascript.h
 
@@ -75,8 +75,9 @@ endif
 
 noinst_PROGRAMS = unit/test-mozjs
 
-unit_test_mozjs_SOURCES = unit/test-mozjs.c src/pacrunner.h \
-                               src/proxy.c src/download.c src/mozjs.c
+unit_test_mozjs_SOURCES = unit/test-mozjs.c src/pacrunner.h src/manual.h \
+                               src/manual.c src/proxy.c src/download.c \
+                               src/mozjs.c
 
 unit_test_mozjs_LDADD = @MOZJS_LIBS@ @GLIB_LIBS@
 
diff --git a/src/manager.c b/src/manager.c
index 170ee1d..8303b57 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -82,7 +82,8 @@ static struct proxy_config *create_config(DBusConnection 
*conn,
                                                const char *method,
                                                const char *url,
                                                const char *script,
-                                               const char *server,
+                                               const char *servers,
+                                               const char *excludes,
                                                const char *interface,
                                                const char *domainname,
                                                const char *nameserver)
@@ -113,8 +114,9 @@ static struct proxy_config *create_config(DBusConnection 
*conn,
                                        disconnect_callback, config, NULL);
 
        if (g_strcmp0(method, "manual") == 0) {
-               if (pacrunner_proxy_set_server(config->proxy, server) < 0)
-                       pacrunner_error("Failed to set proxy server");
+               if (pacrunner_proxy_set_manual(config->proxy, servers,
+                                                       excludes) < 0)
+                       pacrunner_error("Failed to set manual proxy");
 
                return config;
        } else if (g_strcmp0(method, "auto") != 0) {
@@ -135,6 +137,34 @@ static struct proxy_config *create_config(DBusConnection 
*conn,
        return config;
 }
 
+static char *get_list_as_string(DBusMessageIter *array)
+{
+       char *str = NULL, *str_tmp;
+
+       DBG(" ");
+
+       while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_STRING) {
+               char *value = NULL;
+
+               dbus_message_iter_get_basic(array, &value);
+
+               if (str == NULL)
+                       str = g_strdup(value);
+               else {
+                       str_tmp = g_strjoin(" ", str, value, NULL);
+                       g_free(str);
+                       str = str_tmp;
+               }
+
+               if (str == NULL)
+                       return NULL;
+
+               dbus_message_iter_next(array);
+       }
+
+       return str;
+}
+
 static DBusMessage *create_proxy_config(DBusConnection *conn,
                                        DBusMessage *msg, void *user_data)
 {
@@ -142,7 +172,7 @@ static DBusMessage *create_proxy_config(DBusConnection 
*conn,
        struct proxy_config *config;
        const char *sender, *method = NULL;
        const char *url = NULL, *script = NULL;
-       const char *server = NULL, *exclude = NULL;
+       char *servers = NULL, *excludes = NULL;
        const char *interface = NULL, *domainname = NULL, *nameserver = NULL;
 
        sender = dbus_message_get_sender(msg);
@@ -187,15 +217,11 @@ static DBusMessage *create_proxy_config(DBusConnection 
*conn,
                                                        DBUS_TYPE_INVALID)
                                break;
 
-                       if (g_str_equal(key, "Servers") == TRUE) {
-                               dbus_message_iter_get_basic(&list, &server);
-                               if (strlen(server) == 0)
-                                       server = NULL;
-                       } else if (g_str_equal(key, "Excludes") == TRUE) {
-                               dbus_message_iter_get_basic(&list, &exclude);
-                               if (strlen(exclude) == 0)
-                                       exclude = NULL;
-                       } else if (g_str_equal(key, "Domains") == TRUE) {
+                       if (g_str_equal(key, "Servers") == TRUE)
+                               servers = get_list_as_string(&list);
+                       else if (g_str_equal(key, "Excludes") == TRUE)
+                               excludes = get_list_as_string(&list);
+                       else if (g_str_equal(key, "Domains") == TRUE) {
                                dbus_message_iter_get_basic(&list, &domainname);
                                if (strlen(domainname) == 0)
                                        domainname = NULL;
@@ -211,18 +237,26 @@ static DBusMessage *create_proxy_config(DBusConnection 
*conn,
        }
 
        DBG("sender %s method %s", sender, method);
-       DBG("url %s script %p server %s exclude %s",
-                               url, script, server, exclude);
+       DBG("url %s script %p servers %p excludes %p",
+                               url, script, servers, excludes);
        DBG("interface %s domainname %s nameserver %s",
                                interface, domainname, nameserver);
 
-       if (method == NULL)
+       if (method == NULL) {
+               g_free(servers);
+               g_free(excludes);
+
                return g_dbus_create_error(msg,
                                        PACRUNNER_ERROR_INTERFACE ".Failed",
                                        "No proxy method specified");
+       }
+
+       config = create_config(conn, sender, method, url, script, servers,
+                               excludes, interface, domainname, nameserver);
+
+       g_free(servers);
+       g_free(excludes);
 
-       config = create_config(conn, sender, method, url, script, server,
-                                       interface, domainname, nameserver);
        if (config == NULL)
                return g_dbus_create_error(msg,
                                        PACRUNNER_ERROR_INTERFACE ".Failed",
diff --git a/src/manual.c b/src/manual.c
new file mode 100644
index 0000000..345e5ca
--- /dev/null
+++ b/src/manual.c
@@ -0,0 +1,277 @@
+/*
+*
+*  PACrunner - Proxy configuration daemon
+*
+*  Copyright (C) 2010  Nokia Corporation. All rights reserved.
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License version 2 as
+*  published by the Free Software Foundation.
+*
+*  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pacrunner.h"
+
+#include "manual.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+
+struct pacrunner_manual_excludes {
+       char *proto;
+       char *host;
+       int host_length;
+       enum pacrunner_manual_exclude_appliance appliance;
+
+       struct pacrunner_manual_excludes *next;
+};
+
+int __pacrunner_manual_parse_uri(const char *uri, char **host,
+                               char **protocol, int no_path, int exclusion)
+{
+       int length;
+       int proto = 0, ret = 0;
+       int post_confirmed = 0;
+       char *scheme, *sep, *cur;
+       char **forbiden_chars = NULL;
+
+       if (host != NULL)
+               *host = NULL;
+
+       if (protocol != NULL)
+               *protocol = NULL;
+
+       scheme = g_strdup(uri);
+       if (scheme == NULL)
+               goto error;
+
+       cur = scheme;
+
+       sep = strstr(cur, "://");
+       if (sep != NULL) {
+               if (sep == cur)
+                       goto error;
+
+               if (protocol != NULL) {
+                       *sep = '\0';
+
+                       *protocol = g_strdup(cur);
+                       if (*protocol == NULL)
+                               goto error;
+               }
+
+               cur = sep + 3;
+               proto = 1;
+
+               if (!exclusion)
+                       ret = PACRUNNER_PROXY_MANUAL_PROTOCOL_BASED;
+       }
+
+       sep = strchr(cur, '/');
+       if (sep != NULL) {
+               if (exclusion || (*(sep + 1) != '\0' && no_path))
+                       goto error;
+
+               *sep = '\0';
+       }
+
+       /* We skip <login:password> if present */
+       sep = strchr(cur, '@');
+       if (sep != NULL) {
+               if (exclusion)
+                       goto error;
+
+               *sep = '\0';
+               cur = sep + 1;
+       }
+
+       /* Are we in front of a possible IPv6 address? */
+       sep = strchr(cur, '[');
+       if (sep != NULL) {
+               char *bracket;
+
+               bracket = strchr(cur, ']');
+               if (bracket == NULL)
+                       goto error;
+
+               cur = sep+1;
+               sep = strchr(bracket, ':');
+               *bracket = '\0';
+       }
+       else
+               sep = strchr(cur, ':');
+
+       /* Checking port validity if present */
+       if (sep != NULL) {
+               long int port = -1;
+               char *err = NULL;
+
+               /* We do not filter out per port in exclusion URI */
+               if (exclusion)
+                       goto error;
+
+               errno = 0;
+               port = strtol(sep+1, &err, 10);
+               if (*err != '\0' || port <= 0 || port > USHRT_MAX ||
+                                       errno == ERANGE || errno == EINVAL)
+                       goto error;
+
+               *sep = '\0';
+       }
+
+       /* We detect/trim '.'/'*' on both ends.
+        * This is not an error only for exclusion URI since
+        * it defines its rule's appliance */
+       for (sep = cur;
+            *sep != '\0' && (*sep == '*' || *sep == '.');
+            *sep = '\0', sep++);
+
+       if (sep != cur) {
+               if (!exclusion)
+                       goto error;
+
+               cur = sep;
+               post_confirmed = 1;
+       }
+
+       length = strlen(cur);
+       if (length > 0) {
+               for (sep = cur + length - 1;
+                    *sep != '\0' && (*sep == '*' || *sep == '.');
+                    *sep = '\0', sep--);
+
+               if (sep - cur + 1 != length) {
+                       if (!exclusion)
+                               goto error;
+
+                       length = sep - cur + 1;
+
+                       ret = PACRUNNER_MANUAL_EXCLUDE_PRE;
+                       if (post_confirmed)
+                               ret = PACRUNNER_MANUAL_EXCLUDE_ANY;
+               }
+
+               if ((length > 255)
+                       || (*cur == '-' || *sep == '-')
+                       || ((*cur == '\0') && (!exclusion ||
+                                               (exclusion && !proto))))
+                       goto error;
+
+               /* We do not allow some characters */
+               forbiden_chars = g_strsplit_set(cur,
+                                       "%?!,;@\\'*|<>{}[]()+=$&~# ", -1);
+
+               if (forbiden_chars != NULL) {
+                       length = g_strv_length(forbiden_chars);
+                       g_strfreev(forbiden_chars);
+
+                       if (length > 1)
+                               goto error;
+               }
+
+               if (host != NULL && *cur != '\0') {
+                       *host = g_strdup(cur);
+                       if (*host == NULL)
+                               goto error;
+               }
+       } else
+               if (!exclusion || (exclusion && !proto))
+                       goto error;
+
+       g_free(scheme);
+       return ret;
+
+error:
+       if (protocol != NULL)
+               g_free(*protocol);
+
+       g_free(scheme);
+       return -EINVAL;
+}
+
+void __pacrunner_manual_free_excludes(struct pacrunner_manual_excludes 
*excludes)
+{
+       struct pacrunner_manual_excludes *free_rule, *next_rule;
+
+       if (excludes == NULL)
+               return;
+
+       for (next_rule = excludes; next_rule != NULL;) {
+               free_rule = next_rule;
+
+               g_free(next_rule->proto);
+               g_free(next_rule->host);
+
+               next_rule = free_rule->next;
+               g_free(free_rule);
+       }
+}
+
+struct pacrunner_manual_excludes *__pacrunner_manual_create_excludes(const 
char *excludes)
+{
+       char *host, *proto;
+       char **uri_list, **uri;
+       struct pacrunner_manual_excludes *rule_list, *new_rule, *cur_rule;
+
+       DBG(" ");
+
+       if (excludes == NULL)
+               return NULL;
+
+       rule_list = NULL;
+       cur_rule = NULL;
+
+       uri_list = g_strsplit_set(excludes, " ", -1);
+
+       for (uri = uri_list; *uri != NULL; uri++) {
+               int ret = __pacrunner_manual_parse_uri(*uri, &host, &proto,
+                                                                       1, 1);
+               if (ret >= 0) {
+                       new_rule = g_try_malloc0(sizeof(
+                                       struct pacrunner_manual_excludes));
+                       if (new_rule == NULL)
+                               break;
+
+                       new_rule->proto = proto;
+                       new_rule->host = host;
+                       new_rule->appliance = ret;
+                       if (host != NULL)
+                           new_rule->host_length = strlen(host);
+
+                       if (rule_list == NULL)
+                               rule_list = new_rule;
+
+                       if (cur_rule != NULL)
+                               cur_rule->next = new_rule;
+
+                       cur_rule = new_rule;
+
+                       proto = NULL;
+                       host = NULL;
+               }
+       }
+
+       g_strfreev(uri_list);
+
+       /* In case previous loop ended at 'break;'*/
+       g_free(proto);
+       g_free(host);
+
+       return rule_list;
+}
diff --git a/src/manual.h b/src/manual.h
new file mode 100644
index 0000000..1028acd
--- /dev/null
+++ b/src/manual.h
@@ -0,0 +1,26 @@
+/*
+*
+*  PACrunner - Proxy configuration daemon
+*
+*  Copyright (C) 2010  Nokia Corporation. All rights reserved.
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License version 2 as
+*  published by the Free Software Foundation.
+*
+*  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*
+*/
+
+enum pacrunner_manual_exclude_appliance {
+       PACRUNNER_MANUAL_EXCLUDE_POST = 0,
+       PACRUNNER_MANUAL_EXCLUDE_PRE  = 1,
+       PACRUNNER_MANUAL_EXCLUDE_ANY  = 2,
+};
diff --git a/src/pacrunner.h b/src/pacrunner.h
index cb5b496..6439908 100644
--- a/src/pacrunner.h
+++ b/src/pacrunner.h
@@ -52,6 +52,13 @@ enum pacrunner_proxy_method {
        PACRUNNER_PROXY_METHOD_AUTO     = 3,
 };
 
+enum pacrunner_proxy_manual_context {
+       PACRUNNER_PROXY_MANUAL_GENERIC        = 0,
+       PACRUNNER_PROXY_MANUAL_PROTOCOL_BASED = 1,
+};
+
+struct pacrunner_manual_excludes;
+
 struct pacrunner_proxy;
 
 struct pacrunner_proxy *pacrunner_proxy_create(const char *interface);
@@ -67,8 +74,8 @@ int pacrunner_proxy_set_direct(struct pacrunner_proxy *proxy);
 int pacrunner_proxy_set_auto(struct pacrunner_proxy *proxy, const char *url);
 int pacrunner_proxy_set_script(struct pacrunner_proxy *proxy,
                                                const char *script);
-int pacrunner_proxy_set_server(struct pacrunner_proxy *proxy,
-                                               const char *server);
+int pacrunner_proxy_set_manual(struct pacrunner_proxy *proxy,
+                               const char *servers, const char *excludes);
 
 int pacrunner_proxy_enable(struct pacrunner_proxy *proxy);
 int pacrunner_proxy_disable(struct pacrunner_proxy *proxy);
@@ -96,3 +103,8 @@ int __pacrunner_mozjs_init(void);
 void __pacrunner_mozjs_cleanup(void);
 int __pacrunner_mozjs_set_proxy(struct pacrunner_proxy *proxy);
 const char *__pacrunner_mozjs_execute(const char *url, const char *host);
+
+int __pacrunner_manual_parse_uri(const char *uri, char **host,
+                               char **protocol, int no_path, int exclusion);
+void __pacrunner_manual_free_excludes(struct pacrunner_manual_excludes 
*excludes);
+struct pacrunner_manual_excludes *__pacrunner_manual_create_excludes(const 
char *excludes);
diff --git a/src/proxy.c b/src/proxy.c
index c50f366..391fa9f 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -34,7 +34,9 @@ struct pacrunner_proxy {
        enum pacrunner_proxy_method method;
        char *url;
        char *script;
-       char *server;
+       enum pacrunner_proxy_manual_context context;
+       char **servers;
+       struct pacrunner_manual_excludes *excludes;
        char *result;
 };
 
@@ -80,8 +82,11 @@ static void reset_proxy(struct pacrunner_proxy *proxy)
        g_free(proxy->script);
        proxy->script = NULL;
 
-       g_free(proxy->server);
-       proxy->server = NULL;
+       g_strfreev(proxy->servers);
+       proxy->servers = NULL;
+
+       __pacrunner_manual_free_excludes(proxy->excludes);
+       proxy->excludes = NULL;
 
        g_free(proxy->result);
        proxy->result = NULL;
@@ -230,31 +235,74 @@ int pacrunner_proxy_set_script(struct pacrunner_proxy 
*proxy,
        return 0;
 }
 
-int pacrunner_proxy_set_server(struct pacrunner_proxy *proxy,
-                                               const char *server)
+int pacrunner_proxy_set_manual(struct pacrunner_proxy *proxy,
+                               const char *servers, const char *excludes)
 {
-       int err;
+       int code;
+       char **uri_list, **valids, **uri;
 
-       DBG("proxy %p server %s", proxy, server);
+       DBG("proxy %p servers %s excludes %s", proxy, servers, excludes);
 
        if (proxy == NULL)
                return -EINVAL;
 
-       if (server == NULL)
+       if (servers == NULL)
                return -EINVAL;
 
-       err = pacrunner_proxy_set_method(proxy, PACRUNNER_PROXY_METHOD_MANUAL);
-       if (err < 0)
-               return err;
+       code = pacrunner_proxy_set_method(proxy,
+                                       PACRUNNER_PROXY_METHOD_MANUAL);
+       if (code < 0)
+               return code;
+
+       proxy->context = PACRUNNER_PROXY_MANUAL_GENERIC;
+
+       g_strfreev(proxy->servers);
+       proxy->servers = NULL;
+
+       __pacrunner_manual_free_excludes(proxy->excludes);
+       proxy->excludes = NULL;
+
+       valids = NULL;
+       uri_list = g_strsplit_set(servers, " ", -1);
+
+       for (uri = uri_list; *uri != NULL; uri++) {
+               code = __pacrunner_manual_parse_uri(*uri, NULL, NULL, 1, 0);
 
-       g_free(proxy->server);
-       proxy->server = g_strdup(server);
+               if (code < 0) {
+                       if (valids != NULL) {
+                               char *str_xchg = *valids;
+
+                               *valids = *uri;
+                               *uri = str_xchg;
+                               valids++;
+                       }
+               } else {
+                       if (valids == NULL)
+                               valids = uri;
+
+                       if (proxy->context == PACRUNNER_PROXY_MANUAL_GENERIC)
+                               proxy->context = code;
+               }
+       }
+
+       proxy->servers = g_strdupv(valids);
+       g_strfreev(uri_list);
+
+       if (proxy->servers == NULL)
+               /* No valid server URI, this is fatal */
+               return -EINVAL;
+
+       proxy->excludes = __pacrunner_manual_create_excludes(excludes);
 
        g_free(proxy->result);
-       proxy->result = g_strdup_printf("PROXY %s", server);
+       proxy->result = g_strdup(proxy->servers[0]);
 
        pacrunner_proxy_enable(proxy);
 
+       DBG("servers = %d - context %d, excludes %p",
+               g_strv_length(proxy->servers),
+               proxy->context, proxy->excludes);
+
        return 0;
 }
 
-- 
1.7.1

_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to