---
 Makefile.am             |    3 +-
 src/operator-settings.c |  314 +++++++++++++++++++++++++++++++++++++++++++++++
 src/operator-settings.h |   37 ++++++
 3 files changed, 353 insertions(+), 1 deletions(-)
 create mode 100644 src/operator-settings.c
 create mode 100644 src/operator-settings.h

diff --git a/Makefile.am b/Makefile.am
index 8a8555d..d0e47e5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -328,7 +328,8 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) 
src/ofono.ver \
                        src/nettime.c src/stkagent.c src/stkagent.h \
                        src/simfs.c src/simfs.h src/audio-settings.c \
                        src/smsagent.c src/smsagent.h src/ctm.c \
-                       src/cdma-voicecall.c
+                       src/cdma-voicecall.c \
+                       src/operator-settings.c src/operator-settings.h
 
 src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
 
diff --git a/src/operator-settings.c b/src/operator-settings.c
new file mode 100644
index 0000000..4cc90d6
--- /dev/null
+++ b/src/operator-settings.c
@@ -0,0 +1,314 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ *  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 <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#include "ofono.h"
+#include "operator-settings.h"
+
+#define MAX_PROXY_NAME_LENGTH 255
+
+struct parser_data {
+       const gchar *mcc;
+       const gchar *mnc;
+       GSList *candidates;
+};
+
+void gprs_access_settings_free(struct gprs_access_settings *settings)
+{
+       if (settings == NULL)
+               return;
+
+       g_free(settings->name);
+       g_free(settings->apn);
+       g_free(settings->username);
+       g_free(settings->password);
+       g_free(settings->proxy);
+       g_free(settings->mms_server);
+       g_free(settings->spn);
+       g_free(settings);
+}
+
+static enum ofono_gprs_context_type string_to_gprs_context_type(const char 
*str)
+{
+       if (str) {
+               if (strcasecmp(str, "INTERNET") == 0)
+                       return OFONO_GPRS_CONTEXT_TYPE_INTERNET;
+               if (strcasecmp(str, "MMS") == 0)
+                       return OFONO_GPRS_CONTEXT_TYPE_MMS;
+       }
+
+       return OFONO_GPRS_CONTEXT_TYPE_ANY;
+}
+
+/*
+ * Parse <access> element.
+ * Mandatory attributes in <access>: mcc, mnc, type, name
+ * If MCC/MNC matches, add entry to candidate setting list.
+ */
+static void settings_start_element_handler (GMarkupParseContext *context,
+                                               const gchar *element_name,
+                                               const gchar **attribute_names,
+                                               const gchar **attribute_values,
+                                               gpointer user_data,
+                                               GError **error)
+{
+       int i;
+       struct parser_data *parser = user_data;
+       struct gprs_access_settings *entry;
+       const char *mcc = NULL, *mnc = NULL;
+
+       if (strcasecmp(element_name, "access") != 0)
+               return;
+
+       entry = g_try_malloc0(sizeof(*entry));
+       if (entry == NULL)
+               return;
+
+       for (i = 0; attribute_names[i]; i++) {
+
+               if (strcasecmp(attribute_names[i], "mcc") == 0)
+                       mcc = attribute_values[i];
+
+               if (strcasecmp(attribute_names[i], "mnc") == 0)
+                       mnc = attribute_values[i];
+
+               if (strcasecmp(attribute_names[i], "spn") == 0)
+                       entry->spn = g_strdup(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "type") == 0)
+                       entry->type = 
string_to_gprs_context_type(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "apn") == 0)
+                       entry->apn = g_strdup(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "name") == 0)
+                       entry->name = g_strdup(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "username") == 0)
+                       entry->username = g_strdup(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "password") == 0)
+                       entry->password = g_strdup(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "protocol") == 0) {
+                       if (strcasecmp(attribute_values[i], "ipv6") == 0)
+                               entry->proto = OFONO_GPRS_PROTO_IPV6;
+                       else
+                               entry->proto = OFONO_GPRS_PROTO_IP;
+               }
+
+               if (strcasecmp(attribute_names[i], "proxy") == 0)
+                       entry->proxy = g_strdup(attribute_values[i]);
+
+               if (strcasecmp(attribute_names[i], "mmsserver") == 0)
+                       entry->mms_server = g_strdup(attribute_values[i]);
+       }
+
+       /*
+        * Match MNC as integers, since settings files often do not
+        * always contain leading zeros in MNC values...
+        */
+       if (mcc != NULL && strcmp(mcc, parser->mcc) == 0 &&
+               mnc != NULL && atoi(mnc) == atoi(parser->mnc) &&
+               entry->type != 0 && entry->name != NULL) {
+               DBG("Settings candidate: %s", entry->name);
+               parser->candidates = g_slist_append(parser->candidates, entry);
+       } else {
+               gprs_access_settings_free(entry);
+       }
+}
+
+/*
+ * Returns list of candidate settings matching mcc/mnc from operator
+ * settings file
+ */
+static GSList *read_settings_file(const char *filename,
+                                       const char *mcc, const char *mnc)
+{
+       gchar *contents = NULL;
+       gsize length;
+       GMarkupParseContext *context;
+
+       struct parser_data parser = {0};
+       GMarkupParser settings_parser = {
+               settings_start_element_handler,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       };
+
+       if (filename == NULL || mcc == NULL || mnc == NULL)
+               return NULL;
+
+       if (g_file_get_contents(filename, &contents, &length, NULL) == FALSE) {
+               DBG("Error reading settings file %s", filename);
+               return NULL;
+       }
+
+       DBG("Reading settings file %s", filename);
+
+       parser.mcc = mcc;
+       parser.mnc = mnc;
+
+       context = g_markup_parse_context_new(&settings_parser, 0,
+                                               &parser, NULL);
+
+       if (g_markup_parse_context_parse(context, contents,
+                                               length, NULL) == FALSE) {
+               DBG("Error parsing XML file %s", filename);
+       }
+
+       g_markup_parse_context_free(context);
+       g_free(contents);
+
+       return parser.candidates;
+}
+
+/* Case insensitive match of type and SPN (if provided) */
+static gboolean is_match(struct gprs_access_settings *entry,
+                               enum ofono_gprs_context_type type,
+                               gchar *spn_casefold)
+{
+       gboolean ret = FALSE;
+       gchar *entryspn_casefold = NULL;
+
+       if (entry->spn != NULL && strlen(entry->spn) > 0)
+               entryspn_casefold = g_utf8_casefold(entry->spn, -1);
+
+       if (type == entry->type) {
+               if (spn_casefold != NULL) {
+                       if (entryspn_casefold &&
+                                       strcmp(spn_casefold,
+                                               entryspn_casefold) == 0) {
+                               ret = TRUE;
+                       }
+               } else {
+                       ret = TRUE;
+               }
+       }
+
+       g_free(entryspn_casefold);
+       return ret;
+}
+
+/*
+ * Find best match from candidate settings based on type and SPN
+ * If there is no candidate matching SPN, take first one matching type.
+ */
+static GSList *match_entry(GSList * candidates,
+                               enum ofono_gprs_context_type type,
+                               const char *spn)
+{
+       GSList *ret = NULL;
+       GSList *lp = candidates;
+       gchar *spn_casefold = NULL;
+
+       if (spn != NULL && strlen(spn) > 0)
+               spn_casefold = g_utf8_casefold(spn, -1);
+
+       while (lp) {
+               struct gprs_access_settings *entry = lp->data;
+               if (is_match(entry, type, spn_casefold)) {
+                       ret = lp;
+                       break;
+               }
+
+               lp = lp->next;
+               if (lp == NULL && spn_casefold != NULL) {
+                       /* No SPN matches, retry with only type */
+                       g_free(spn_casefold);
+                       spn_casefold = NULL;
+                       lp = candidates;
+               }
+       }
+
+       g_free(spn_casefold);
+       return ret;
+}
+
+/*
+ * Returns GPRS context settings (internet and mms types) based on
+ * SIM provided MCC,MNC and Service Provider Name values.
+ * Operator settings for Internet and MMS access points are stored
+ * in XML formatted files (*.xml) under $CONDIFDIR/operator-settings
+ */
+GSList *get_operator_settings(const char *mcc, const char *mnc, const char 
*spn)
+{
+       GSList *ret = NULL;
+       GSList *candidates = NULL;
+       GSList *match;
+       GDir *dir;
+       GSList *files = NULL, *lp;
+       const gchar *filename;
+
+       dir = g_dir_open(CONFIGDIR "/" SETTING_FILE_DIR, 0, NULL);
+       if (dir == NULL) {
+               DBG("Error opening settings directory");
+               return NULL;
+       }
+
+       while ((filename = g_dir_read_name(dir)) != NULL) {
+               if (g_str_has_suffix(filename, ".xml")) {
+                       gchar *fn = g_build_filename(CONFIGDIR,
+                                                       SETTING_FILE_DIR,
+                                                       filename, NULL);
+                       files = g_slist_append(files, fn);
+               }
+       }
+
+       /* Read files in consistent order */
+       files = g_slist_sort(files, (GCompareFunc) g_strcmp0);
+       for (lp = files; lp != NULL; lp = lp->next) {
+               GSList *entries;
+               gchar *fn = lp->data;
+               entries = read_settings_file(fn, mcc, mnc);
+               candidates = g_slist_concat(candidates, entries);
+               g_free(fn);
+       }
+
+       g_slist_free(files);
+       g_dir_close(dir);
+
+       match = match_entry(candidates, OFONO_GPRS_CONTEXT_TYPE_INTERNET, spn);
+       if (match != NULL) {
+               candidates = g_slist_remove_link(candidates, match);
+               ret = g_slist_concat(ret, match);
+       }
+
+       match = match_entry(candidates, OFONO_GPRS_CONTEXT_TYPE_MMS, spn);
+       if (match != NULL) {
+               candidates = g_slist_remove_link(candidates, match);
+               ret = g_slist_concat(ret, match);
+       }
+
+       g_slist_foreach(candidates, (GFunc) gprs_access_settings_free, NULL);
+       g_slist_free(candidates);
+
+       return ret;
+}
diff --git a/src/operator-settings.h b/src/operator-settings.h
new file mode 100644
index 0000000..9725eb6
--- /dev/null
+++ b/src/operator-settings.h
@@ -0,0 +1,37 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ *  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
+ *
+ */
+
+#define SETTING_FILE_DIR "operator-settings"
+
+struct gprs_access_settings {
+       enum ofono_gprs_context_type type;
+       gchar *name;
+       gchar *apn;
+       gchar *username;
+       gchar *password;
+       enum ofono_gprs_proto proto;
+       gchar *proxy;
+       gchar *mms_server;
+       gchar *spn;
+};
+
+GSList *get_operator_settings(const char *mcc, const char *mnc,
+                               const char *spn);
+void gprs_access_settings_free(struct gprs_access_settings *settings);
-- 
1.7.1

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to