---
 Makefile.am             |    3 +-
 src/operator-settings.c |  292 +++++++++++++++++++++++++++++++++++++++++++++++
 src/operator-settings.h |   37 ++++++
 3 files changed, 331 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 12b3c33..93e4d28 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -319,7 +319,8 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) 
src/ofono.ver \
                        src/radio-settings.c src/stkutil.h src/stkutil.c \
                        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/smsagent.c src/smsagent.h src/ctm.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..7b63d94
--- /dev/null
+++ b/src/operator-settings.c
@@ -0,0 +1,292 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2009-2010 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
+
+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;
+}
+
+static gchar *cleanstr(const char *str)
+{
+       return g_strstrip(g_strdup(str));
+}
+
+/*
+ * Parse settings csv-file line. If MCC/MNC matches, return settings
+ *
+ * Settings file format: Comma separated fields (that cannot contain commas) 
of:
+ *     MCC,MNC,SPN,type,UI name, APN, username, password, protocol,\
+ *     proxy IP address, proxy port, MMS server URL
+ * where type=INTERNET|MMS, protocol=ipv4|ipv6
+ */
+static struct gprs_access_settings *parse_setting_line(const char *line,
+                                                       const char *mcc,
+                                                       const char *mnc)
+{
+       gchar **columns;
+       int count;
+       struct gprs_access_settings *entry = NULL;
+
+       columns = g_strsplit(line, ",", 0);
+       count = g_strv_length(columns);
+
+       /* mandatory values: mcc, mnc, spn, type, name, apn */
+       if (count < 6)
+               goto finish;
+
+       if (strcmp(mcc, columns[0]) != 0 || strcmp(mnc, columns[1]) != 0)
+               goto finish;
+
+       entry = g_try_malloc0(sizeof(*entry));
+       if (entry == NULL)
+               goto finish;
+
+       entry->spn = cleanstr(columns[2]);
+       entry->type = string_to_gprs_context_type(columns[3]);
+       entry->name = cleanstr(columns[4]);
+       entry->apn = cleanstr(columns[5]);
+
+       if (count > 6)
+               entry->username = cleanstr(columns[6]);
+       else
+               entry->username = g_strdup("");
+
+       if (count > 7)
+               entry->password = cleanstr(columns[7]);
+       else
+               entry->password = g_strdup("");
+
+       if (count > 8 && strcmp(columns[8], "ipv6") == 0)
+               entry->proto = OFONO_GPRS_PROTO_IPV6;
+       else
+               entry->proto = OFONO_GPRS_PROTO_IP;
+
+       if (count > 9) {
+               gchar proxy[MAX_PROXY_NAME_LENGTH + 1];
+               g_strlcpy(proxy, columns[9], MAX_PROXY_NAME_LENGTH);
+
+               if (count > 10 && strlen(columns[10]) > 0) {
+                       g_strlcat(proxy, ":", MAX_PROXY_NAME_LENGTH);
+                       g_strlcat(proxy, columns[10], MAX_PROXY_NAME_LENGTH);
+               }
+
+               entry->proxy = cleanstr(proxy);
+       }
+
+       if (count > 11)
+               entry->mms_server = cleanstr(columns[11]);
+
+finish:
+       g_strfreev(columns);
+       return 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)
+{
+       GSList *entries = NULL;
+       FILE *f;
+       char *line = NULL;
+       size_t len = 0;
+       ssize_t read;
+
+       if (filename == NULL || mcc == NULL || mnc == NULL)
+               return NULL;
+
+       f = fopen(filename, "r");
+       if (f == NULL) {
+               DBG("Error opening settings file %s", filename);
+               return NULL;
+       }
+
+       while ((read = getline(&line, &len, f)) != -1) {
+               struct gprs_access_settings *entry;
+               entry = parse_setting_line(line, mcc, mnc);
+               if (entry != NULL)
+                       entries = g_slist_append(entries, entry);
+       }
+
+       free(line);
+       fclose(f);
+
+       return entries;
+}
+
+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 CSV formatted files (*.csv) 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, ".csv")) {
+                       gchar *fn = g_strjoin("/", CONFIGDIR, SETTING_FILE_DIR,
+                                               filename, NULL);
+                       files = g_slist_append(files, fn);
+               }
+       }
+
+       files = g_slist_sort(files, (GCompareFunc) g_strcmp0);
+
+       for (lp = files; lp != NULL; lp = lp->next) {
+               GSList *entries;
+               gchar *fn;
+               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..95f3785
--- /dev/null
+++ b/src/operator-settings.h
@@ -0,0 +1,37 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2009-2010 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