mobile-providers: use libnm-gtk to work with mobile providers
This commit removes all the code in charge of playing with the database of mobile providers, which was originally included in order to perform MCCMNC->OperatorName and SID->OperatorName conversions. This logic is now exposed by libnm-gtk. https://bugzilla.gnome.org/show_bug.cgi?id=688943
This commit is contained in:
parent
393a3a079f
commit
8dd880d0c8
@ -2,73 +2,37 @@
|
|||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Shell = imports.gi.Shell;
|
const NMGtk = imports.gi.NMGtk;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
// _getMobileProvidersDatabase:
|
||||||
|
//
|
||||||
|
// Gets the database of mobile providers, with references between MCCMNC/SID and
|
||||||
|
// operator name
|
||||||
|
//
|
||||||
|
let _mpd;
|
||||||
|
function _getMobileProvidersDatabase() {
|
||||||
|
if (_mpd == null) {
|
||||||
|
try {
|
||||||
|
_mpd = new NMGtk.MobileProvidersDatabase();
|
||||||
|
_mpd.init(null);
|
||||||
|
} catch (e) {
|
||||||
|
log(e.message);
|
||||||
|
_mpd = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// _getProvidersTable:
|
return _mpd;
|
||||||
//
|
|
||||||
// Gets the table of references between MCCMNC and operator name
|
|
||||||
//
|
|
||||||
let _providersTable;
|
|
||||||
function _getProvidersTable() {
|
|
||||||
if (_providersTable)
|
|
||||||
return _providersTable;
|
|
||||||
return _providersTable = Shell.mobile_providers_parse(null,null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// findProviderForMCCMNC:
|
// _findProviderForMccMnc:
|
||||||
// @table: a table of country code keys and Shell.CountryMobileProvider values
|
|
||||||
// @needle: operator code, given as MCCMNC string
|
|
||||||
//
|
|
||||||
// Tries to find the operator name corresponding to the given MCCMNC
|
|
||||||
//
|
|
||||||
function findProviderForMCCMNC(table, needle) {
|
|
||||||
let needlemcc = needle.substring(0, 3);
|
|
||||||
let needlemnc = needle.substring(3, needle.length);
|
|
||||||
|
|
||||||
let name2, name3;
|
|
||||||
for (let iter in table) {
|
|
||||||
let country = table[iter];
|
|
||||||
let providers = country.get_providers();
|
|
||||||
|
|
||||||
// Search through each country's providers
|
|
||||||
for (let i = 0; i < providers.length; i++) {
|
|
||||||
let provider = providers[i];
|
|
||||||
|
|
||||||
// Search through MCC/MNC list
|
|
||||||
let list = provider.get_gsm_mcc_mnc();
|
|
||||||
for (let j = 0; j < list.length; j++) {
|
|
||||||
let mccmnc = list[j];
|
|
||||||
|
|
||||||
// Match both 2-digit and 3-digit MNC; prefer a
|
|
||||||
// 3-digit match if found, otherwise a 2-digit one.
|
|
||||||
if (mccmnc.mcc != needlemcc)
|
|
||||||
continue; // MCC was wrong
|
|
||||||
|
|
||||||
if (!name3 && needle.length == 6 && needlemnc == mccmnc.mnc)
|
|
||||||
name3 = provider.name;
|
|
||||||
|
|
||||||
if (!name2 && needlemnc.substring(0, 2) == mccmnc.mnc.substring(0, 2))
|
|
||||||
name2 = provider.name;
|
|
||||||
|
|
||||||
if (name2 && name3)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return name3 || name2 || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// findOperatorName:
|
|
||||||
// @operator_name: operator name
|
// @operator_name: operator name
|
||||||
// @operator_code: operator code
|
// @operator_code: operator code
|
||||||
//
|
//
|
||||||
// Given an operator name string (which may not be a real operator name) and an
|
// Given an operator name string (which may not be a real operator name) and an
|
||||||
// operator code string, tries to find a proper operator name to display.
|
// operator code string, tries to find a proper operator name to display.
|
||||||
//
|
//
|
||||||
function findOperatorName(operator_name, operator_code) {
|
function _findProviderForMccMnc(operator_name, operator_code) {
|
||||||
if (operator_name) {
|
if (operator_name) {
|
||||||
if (operator_name.length != 0 &&
|
if (operator_name.length != 0 &&
|
||||||
(operator_name.length > 6 || operator_name.length < 5)) {
|
(operator_name.length > 6 || operator_name.length < 5)) {
|
||||||
@ -92,41 +56,34 @@ function findOperatorName(operator_name, operator_code) {
|
|||||||
else // nothing to search
|
else // nothing to search
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let table = _getProvidersTable();
|
let mpd = _getMobileProvidersDatabase();
|
||||||
return findProviderForMCCMNC(table, needle);
|
if (mpd) {
|
||||||
|
let provider = mpd.lookup_3gpp_mcc_mnc(needle);
|
||||||
|
if (provider)
|
||||||
|
return provider.get_name();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// findProviderForSid:
|
// _findProviderForSid:
|
||||||
// @table: a table of country code keys and Shell.CountryMobileProvider values
|
|
||||||
// @sid: System Identifier of the serving CDMA network
|
// @sid: System Identifier of the serving CDMA network
|
||||||
//
|
//
|
||||||
// Tries to find the operator name corresponding to the given SID
|
// Tries to find the operator name corresponding to the given SID
|
||||||
//
|
//
|
||||||
function findProviderForSid(table, sid) {
|
function _findProviderForSid(sid) {
|
||||||
if (sid == 0)
|
if (sid == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Search through each country
|
let mpd = _getMobileProvidersDatabase();
|
||||||
for (let iter in table) {
|
if (mpd) {
|
||||||
let country = table[iter];
|
let provider = mpd.lookup_cdma_sid(sid);
|
||||||
let providers = country.get_providers();
|
if (provider)
|
||||||
|
return provider.get_name();
|
||||||
// Search through each country's providers
|
|
||||||
for (let i = 0; i < providers.length; i++) {
|
|
||||||
let provider = providers[i];
|
|
||||||
let cdma_sid = provider.get_cdma_sid();
|
|
||||||
|
|
||||||
// Search through CDMA SID list
|
|
||||||
for (let j = 0; j < cdma_sid.length; j++) {
|
|
||||||
if (cdma_sid[j] == sid)
|
|
||||||
return provider.name;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Support for the old ModemManager interface (MM < 0.7)
|
// Support for the old ModemManager interface (MM < 0.7)
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -184,7 +141,7 @@ const ModemGsm = new Lang.Class({
|
|||||||
this.emit('notify::signal-quality');
|
this.emit('notify::signal-quality');
|
||||||
}));
|
}));
|
||||||
this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
|
this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
|
||||||
this.operator_name = findOperatorName(name, code);
|
this.operator_name = _findProviderForMccMnc(name, code);
|
||||||
this.emit('notify::operator-name');
|
this.emit('notify::operator-name');
|
||||||
}));
|
}));
|
||||||
this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function([result], err) {
|
this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function([result], err) {
|
||||||
@ -194,7 +151,7 @@ const ModemGsm = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let [status, code, name] = result;
|
let [status, code, name] = result;
|
||||||
this.operator_name = findOperatorName(name, code);
|
this.operator_name = _findProviderForMccMnc(name, code);
|
||||||
this.emit('notify::operator-name');
|
this.emit('notify::operator-name');
|
||||||
}));
|
}));
|
||||||
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||||
@ -246,12 +203,9 @@ const ModemCdma = new Lang.Class({
|
|||||||
// it will return an error if the device is not connected
|
// it will return an error if the device is not connected
|
||||||
this.operator_name = null;
|
this.operator_name = null;
|
||||||
} else {
|
} else {
|
||||||
let [bandClass, band, id] = result;
|
let [bandClass, band, sid] = result;
|
||||||
if (name.length > 0) {
|
|
||||||
let table = _getProvidersTable();
|
this.operator_name = _findProviderForSid(sid)
|
||||||
this.operator_name = findProviderForSid(table, id);
|
|
||||||
} else
|
|
||||||
this.operator_name = null;
|
|
||||||
}
|
}
|
||||||
this.emit('notify::operator-name');
|
this.emit('notify::operator-name');
|
||||||
}));
|
}));
|
||||||
@ -334,13 +288,13 @@ const BroadbandModem = new Lang.Class({
|
|||||||
_reload3gppOperatorName: function() {
|
_reload3gppOperatorName: function() {
|
||||||
let name = this._proxy_3gpp.OperatorName;
|
let name = this._proxy_3gpp.OperatorName;
|
||||||
let code = this._proxy_3gpp.OperatorCode;
|
let code = this._proxy_3gpp.OperatorCode;
|
||||||
this.operator_name_3gpp = findOperatorName(name, code);
|
this.operator_name_3gpp = _findProviderForMccMnc(name, code);
|
||||||
this._reloadOperatorName();
|
this._reloadOperatorName();
|
||||||
},
|
},
|
||||||
|
|
||||||
_reloadCdmaOperatorName: function() {
|
_reloadCdmaOperatorName: function() {
|
||||||
let sid = this._proxy_cdma.Sid;
|
let sid = this._proxy_cdma.Sid;
|
||||||
this.operator_name_cdma = findProviderForSid(sid);
|
this.operator_name_cdma = _findProviderForSid(sid);
|
||||||
this._reloadOperatorName();
|
this._reloadOperatorName();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -115,7 +115,6 @@ shell_public_headers_h = \
|
|||||||
shell-global.h \
|
shell-global.h \
|
||||||
shell-invert-lightness-effect.h \
|
shell-invert-lightness-effect.h \
|
||||||
shell-keybinding-modes.h \
|
shell-keybinding-modes.h \
|
||||||
shell-mobile-providers.h \
|
|
||||||
shell-mount-operation.h \
|
shell-mount-operation.h \
|
||||||
shell-network-agent.h \
|
shell-network-agent.h \
|
||||||
shell-perf-log.h \
|
shell-perf-log.h \
|
||||||
@ -160,7 +159,6 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-invert-lightness-effect.c \
|
shell-invert-lightness-effect.c \
|
||||||
shell-keyring-prompt.h \
|
shell-keyring-prompt.h \
|
||||||
shell-keyring-prompt.c \
|
shell-keyring-prompt.c \
|
||||||
shell-mobile-providers.c \
|
|
||||||
shell-mount-operation.c \
|
shell-mount-operation.c \
|
||||||
shell-network-agent.c \
|
shell-network-agent.c \
|
||||||
shell-perf-log.c \
|
shell-perf-log.c \
|
||||||
|
@ -1,914 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Novell, Inc.
|
|
||||||
* Author: Tambet Ingo (tambet@gmail.com).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 - 2010 Red Hat, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
|
||||||
|
|
||||||
#include "shell-mobile-providers.h"
|
|
||||||
|
|
||||||
#ifndef MOBILE_BROADBAND_PROVIDER_INFO
|
|
||||||
#define MOBILE_BROADBAND_PROVIDER_INFO DATADIR "/mobile-broadband-provider-info/serviceproviders.xml"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ISO_3166_COUNTRY_CODES DATADIR "/zoneinfo/iso3166.tab"
|
|
||||||
|
|
||||||
static ShellCountryMobileProvider *country_mobile_provider_new (const char *country_code,
|
|
||||||
const gchar *country_name);
|
|
||||||
|
|
||||||
static GHashTable *
|
|
||||||
read_country_codes (const gchar *country_codes)
|
|
||||||
{
|
|
||||||
GHashTable *table;
|
|
||||||
GIOChannel *channel;
|
|
||||||
GString *buffer;
|
|
||||||
GError *error = NULL;
|
|
||||||
GIOStatus status;
|
|
||||||
|
|
||||||
channel = g_io_channel_new_file (country_codes, "r", &error);
|
|
||||||
if (!channel) {
|
|
||||||
if (error) {
|
|
||||||
g_warning ("Could not read %s: %s", country_codes, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
} else
|
|
||||||
g_warning ("Could not read %s: Unknown error", country_codes);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
table = g_hash_table_new_full (g_str_hash,
|
|
||||||
g_str_equal,
|
|
||||||
g_free,
|
|
||||||
(GDestroyNotify)shell_country_mobile_provider_unref);
|
|
||||||
buffer = g_string_sized_new (32);
|
|
||||||
|
|
||||||
status = G_IO_STATUS_NORMAL;
|
|
||||||
while (status == G_IO_STATUS_NORMAL) {
|
|
||||||
status = g_io_channel_read_line_string (channel, buffer, NULL, &error);
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case G_IO_STATUS_NORMAL:
|
|
||||||
if (buffer->str[0] != '#') {
|
|
||||||
ShellCountryMobileProvider *country_provider;
|
|
||||||
char **pieces;
|
|
||||||
|
|
||||||
pieces = g_strsplit (buffer->str, "\t", 2);
|
|
||||||
|
|
||||||
/* Hack for rh#556292; iso3166.tab is just wrong */
|
|
||||||
pieces[1] = pieces[1] ? g_strchomp (pieces[1]) : NULL;
|
|
||||||
if (pieces[1] && !strcmp (pieces[1], "Britain (UK)")) {
|
|
||||||
g_free (pieces[1]);
|
|
||||||
pieces[1] = g_strdup (_("United Kingdom"));
|
|
||||||
}
|
|
||||||
|
|
||||||
country_provider = country_mobile_provider_new (pieces[0], pieces[1]);
|
|
||||||
g_hash_table_insert (table, pieces[0], country_provider);
|
|
||||||
g_free (pieces);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_truncate (buffer, 0);
|
|
||||||
break;
|
|
||||||
case G_IO_STATUS_EOF:
|
|
||||||
break;
|
|
||||||
case G_IO_STATUS_ERROR:
|
|
||||||
g_warning ("Error while reading: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
break;
|
|
||||||
case G_IO_STATUS_AGAIN:
|
|
||||||
/* FIXME: Try again a few times, but really, it never happes, right? */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_free (buffer, TRUE);
|
|
||||||
g_io_channel_unref (channel);
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XML Parser */
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PARSER_TOPLEVEL = 0,
|
|
||||||
PARSER_COUNTRY,
|
|
||||||
PARSER_PROVIDER,
|
|
||||||
PARSER_METHOD_GSM,
|
|
||||||
PARSER_METHOD_GSM_APN,
|
|
||||||
PARSER_METHOD_CDMA,
|
|
||||||
PARSER_ERROR
|
|
||||||
} MobileContextState;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GHashTable *table;
|
|
||||||
|
|
||||||
char *current_country;
|
|
||||||
GSList *current_providers;
|
|
||||||
ShellMobileProvider *current_provider;
|
|
||||||
ShellMobileAccessMethod *current_method;
|
|
||||||
|
|
||||||
char *text_buffer;
|
|
||||||
MobileContextState state;
|
|
||||||
} MobileParser;
|
|
||||||
|
|
||||||
static ShellGsmMccMnc *
|
|
||||||
mcc_mnc_new (const char *mcc, const char *mnc)
|
|
||||||
{
|
|
||||||
ShellGsmMccMnc *m;
|
|
||||||
|
|
||||||
m = g_slice_new (ShellGsmMccMnc);
|
|
||||||
m->mcc = g_strstrip (g_strdup (mcc));
|
|
||||||
m->mnc = g_strstrip (g_strdup (mnc));
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* added in porting */
|
|
||||||
static ShellGsmMccMnc *
|
|
||||||
mcc_mnc_copy (const ShellGsmMccMnc *other) {
|
|
||||||
ShellGsmMccMnc *ret;
|
|
||||||
|
|
||||||
ret = g_slice_new (ShellGsmMccMnc);
|
|
||||||
ret->mcc = g_strdup (other->mcc);
|
|
||||||
ret->mnc = g_strdup (other->mnc);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mcc_mnc_free (ShellGsmMccMnc *m)
|
|
||||||
{
|
|
||||||
g_return_if_fail (m != NULL);
|
|
||||||
g_free (m->mcc);
|
|
||||||
g_free (m->mnc);
|
|
||||||
g_slice_free (ShellGsmMccMnc, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* added in porting */
|
|
||||||
G_DEFINE_BOXED_TYPE (ShellGsmMccMnc, shell_gsm_mcc_mnc, mcc_mnc_copy, mcc_mnc_free)
|
|
||||||
|
|
||||||
static ShellMobileAccessMethod *
|
|
||||||
access_method_new (void)
|
|
||||||
{
|
|
||||||
ShellMobileAccessMethod *method;
|
|
||||||
|
|
||||||
method = g_slice_new0 (ShellMobileAccessMethod);
|
|
||||||
method->refs = 1;
|
|
||||||
method->lcl_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
||||||
(GDestroyNotify) g_free,
|
|
||||||
(GDestroyNotify) g_free);
|
|
||||||
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellMobileAccessMethod *
|
|
||||||
shell_mobile_access_method_ref (ShellMobileAccessMethod *method)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (method != NULL, NULL);
|
|
||||||
g_return_val_if_fail (method->refs > 0, NULL);
|
|
||||||
|
|
||||||
method->refs++;
|
|
||||||
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
shell_mobile_access_method_unref (ShellMobileAccessMethod *method)
|
|
||||||
{
|
|
||||||
g_return_if_fail (method != NULL);
|
|
||||||
g_return_if_fail (method->refs > 0);
|
|
||||||
|
|
||||||
if (--method->refs == 0) {
|
|
||||||
g_free (method->name);
|
|
||||||
g_hash_table_destroy (method->lcl_names);
|
|
||||||
g_free (method->username);
|
|
||||||
g_free (method->password);
|
|
||||||
g_free (method->gateway);
|
|
||||||
g_free (method->gsm_apn);
|
|
||||||
g_slist_foreach (method->dns, (GFunc) g_free, NULL);
|
|
||||||
g_slist_free (method->dns);
|
|
||||||
|
|
||||||
g_slice_free (ShellMobileAccessMethod, method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GType
|
|
||||||
shell_mobile_access_method_get_type (void)
|
|
||||||
{
|
|
||||||
static GType type = 0;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (type == 0)) {
|
|
||||||
type = g_boxed_type_register_static ("ShellMobileAccessMethod",
|
|
||||||
(GBoxedCopyFunc) shell_mobile_access_method_ref,
|
|
||||||
(GBoxedFreeFunc) shell_mobile_access_method_unref);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ShellMobileProvider *
|
|
||||||
provider_new (void)
|
|
||||||
{
|
|
||||||
ShellMobileProvider *provider;
|
|
||||||
|
|
||||||
provider = g_slice_new0 (ShellMobileProvider);
|
|
||||||
provider->refs = 1;
|
|
||||||
provider->lcl_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
||||||
(GDestroyNotify) g_free,
|
|
||||||
(GDestroyNotify) g_free);
|
|
||||||
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellMobileProvider *
|
|
||||||
shell_mobile_provider_ref (ShellMobileProvider *provider)
|
|
||||||
{
|
|
||||||
provider->refs++;
|
|
||||||
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
shell_mobile_provider_unref (ShellMobileProvider *provider)
|
|
||||||
{
|
|
||||||
if (--provider->refs == 0) {
|
|
||||||
g_free (provider->name);
|
|
||||||
g_hash_table_destroy (provider->lcl_names);
|
|
||||||
|
|
||||||
g_slist_foreach (provider->methods, (GFunc) shell_mobile_access_method_unref, NULL);
|
|
||||||
g_slist_free (provider->methods);
|
|
||||||
|
|
||||||
g_slist_foreach (provider->gsm_mcc_mnc, (GFunc) mcc_mnc_free, NULL);
|
|
||||||
g_slist_free (provider->gsm_mcc_mnc);
|
|
||||||
|
|
||||||
g_slist_free (provider->cdma_sid);
|
|
||||||
|
|
||||||
g_slice_free (ShellMobileProvider, provider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GType
|
|
||||||
shell_mobile_provider_get_type (void)
|
|
||||||
{
|
|
||||||
static GType type = 0;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (type == 0)) {
|
|
||||||
type = g_boxed_type_register_static ("ShellMobileProvider",
|
|
||||||
(GBoxedCopyFunc) shell_mobile_provider_ref,
|
|
||||||
(GBoxedFreeFunc) shell_mobile_provider_unref);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ShellCountryMobileProvider *
|
|
||||||
country_mobile_provider_new (const char *country_code,
|
|
||||||
const gchar *country_name)
|
|
||||||
{
|
|
||||||
ShellCountryMobileProvider *country_provider;
|
|
||||||
|
|
||||||
country_provider = g_slice_new0 (ShellCountryMobileProvider);
|
|
||||||
country_provider->refs = 1;
|
|
||||||
country_provider->country_code = g_strdup (country_code);
|
|
||||||
country_provider->country_name = g_strdup (country_name);
|
|
||||||
return country_provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellCountryMobileProvider *
|
|
||||||
shell_country_mobile_provider_ref (ShellCountryMobileProvider *country_provider)
|
|
||||||
{
|
|
||||||
country_provider->refs++;
|
|
||||||
|
|
||||||
return country_provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
shell_country_mobile_provider_unref (ShellCountryMobileProvider *country_provider)
|
|
||||||
{
|
|
||||||
if (--country_provider->refs == 0) {
|
|
||||||
g_free (country_provider->country_code);
|
|
||||||
g_free (country_provider->country_name);
|
|
||||||
g_slist_free_full (country_provider->providers,
|
|
||||||
(GDestroyNotify) shell_mobile_provider_unref);
|
|
||||||
g_slice_free (ShellCountryMobileProvider, country_provider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_country_mobile_provider_get_country_code:
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): the code of the country.
|
|
||||||
*/
|
|
||||||
const gchar *
|
|
||||||
shell_country_mobile_provider_get_country_code (ShellCountryMobileProvider *country_provider)
|
|
||||||
{
|
|
||||||
return country_provider->country_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_country_mobile_provider_get_country_name:
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): the name of the country.
|
|
||||||
*/
|
|
||||||
const gchar *
|
|
||||||
shell_country_mobile_provider_get_country_name (ShellCountryMobileProvider *country_provider)
|
|
||||||
{
|
|
||||||
return country_provider->country_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_country_mobile_provider_get_providers:
|
|
||||||
*
|
|
||||||
* Returns: (element-type Shell.MobileProvider) (transfer none): the
|
|
||||||
* list of #ShellMobileProvider this country exposes.
|
|
||||||
*/
|
|
||||||
GSList *
|
|
||||||
shell_country_mobile_provider_get_providers (ShellCountryMobileProvider *country_provider)
|
|
||||||
{
|
|
||||||
return country_provider->providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
GType
|
|
||||||
shell_country_mobile_provider_get_type (void)
|
|
||||||
{
|
|
||||||
static GType type = 0;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (type == 0)) {
|
|
||||||
type = g_boxed_type_register_static ("ShellCountryMobileProvider",
|
|
||||||
(GBoxedCopyFunc) shell_country_mobile_provider_ref,
|
|
||||||
(GBoxedFreeFunc) shell_country_mobile_provider_unref);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
provider_list_free (gpointer data)
|
|
||||||
{
|
|
||||||
GSList *list = (GSList *) data;
|
|
||||||
|
|
||||||
while (list) {
|
|
||||||
shell_mobile_provider_unref ((ShellMobileProvider *) list->data);
|
|
||||||
list = g_slist_delete_link (list, list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_toplevel_start (MobileParser *parser,
|
|
||||||
const char *name,
|
|
||||||
const char **attribute_names,
|
|
||||||
const char **attribute_values)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!strcmp (name, "serviceproviders")) {
|
|
||||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
||||||
if (!strcmp (attribute_names[i], "format")) {
|
|
||||||
if (strcmp (attribute_values[i], "2.0")) {
|
|
||||||
g_warning ("%s: mobile broadband provider database format '%s'"
|
|
||||||
" not supported.", __func__, attribute_values[i]);
|
|
||||||
parser->state = PARSER_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!strcmp (name, "country")) {
|
|
||||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
||||||
if (!strcmp (attribute_names[i], "code")) {
|
|
||||||
char *country_code;
|
|
||||||
ShellCountryMobileProvider *country_provider;
|
|
||||||
|
|
||||||
country_code = g_ascii_strup (attribute_values[i], -1);
|
|
||||||
country_provider = g_hash_table_lookup (parser->table, country_code);
|
|
||||||
/* Ensure we have a country provider for this country code */
|
|
||||||
if (!country_provider) {
|
|
||||||
g_warning ("%s: adding providers for unknown country '%s'", __func__, country_code);
|
|
||||||
country_provider = country_mobile_provider_new (country_code, NULL);
|
|
||||||
g_hash_table_insert (parser->table, country_code, country_provider);
|
|
||||||
}
|
|
||||||
parser->current_country = country_code;
|
|
||||||
|
|
||||||
parser->state = PARSER_COUNTRY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_country_start (MobileParser *parser,
|
|
||||||
const char *name,
|
|
||||||
const char **attribute_names,
|
|
||||||
const char **attribute_values)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "provider")) {
|
|
||||||
parser->state = PARSER_PROVIDER;
|
|
||||||
parser->current_provider = provider_new ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_provider_start (MobileParser *parser,
|
|
||||||
const char *name,
|
|
||||||
const char **attribute_names,
|
|
||||||
const char **attribute_values)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "gsm"))
|
|
||||||
parser->state = PARSER_METHOD_GSM;
|
|
||||||
else if (!strcmp (name, "cdma")) {
|
|
||||||
parser->state = PARSER_METHOD_CDMA;
|
|
||||||
parser->current_method = access_method_new ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_gsm_start (MobileParser *parser,
|
|
||||||
const char *name,
|
|
||||||
const char **attribute_names,
|
|
||||||
const char **attribute_values)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "network-id")) {
|
|
||||||
const char *mcc = NULL, *mnc = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
||||||
if (!strcmp (attribute_names[i], "mcc"))
|
|
||||||
mcc = attribute_values[i];
|
|
||||||
else if (!strcmp (attribute_names[i], "mnc"))
|
|
||||||
mnc = attribute_values[i];
|
|
||||||
|
|
||||||
if (mcc && strlen (mcc) && mnc && strlen (mnc)) {
|
|
||||||
parser->current_provider->gsm_mcc_mnc = g_slist_prepend (parser->current_provider->gsm_mcc_mnc,
|
|
||||||
mcc_mnc_new (mcc, mnc));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!strcmp (name, "apn")) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
||||||
if (!strcmp (attribute_names[i], "value")) {
|
|
||||||
|
|
||||||
parser->state = PARSER_METHOD_GSM_APN;
|
|
||||||
parser->current_method = access_method_new ();
|
|
||||||
parser->current_method->gsm_apn = g_strstrip (g_strdup (attribute_values[i]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_cdma_start (MobileParser *parser,
|
|
||||||
const char *name,
|
|
||||||
const char **attribute_names,
|
|
||||||
const char **attribute_values)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "sid")) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
||||||
if (!strcmp (attribute_names[i], "value")) {
|
|
||||||
unsigned long tmp;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
tmp = strtoul (attribute_values[i], NULL, 10);
|
|
||||||
if (errno == 0 && tmp > 0)
|
|
||||||
parser->current_provider->cdma_sid = g_slist_prepend (parser->current_provider->cdma_sid,
|
|
||||||
GUINT_TO_POINTER ((guint32) tmp));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mobile_parser_start_element (GMarkupParseContext *context,
|
|
||||||
const gchar *element_name,
|
|
||||||
const gchar **attribute_names,
|
|
||||||
const gchar **attribute_values,
|
|
||||||
gpointer data,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
MobileParser *parser = (MobileParser *) data;
|
|
||||||
|
|
||||||
if (parser->text_buffer) {
|
|
||||||
g_free (parser->text_buffer);
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (parser->state) {
|
|
||||||
case PARSER_TOPLEVEL:
|
|
||||||
parser_toplevel_start (parser, element_name, attribute_names, attribute_values);
|
|
||||||
break;
|
|
||||||
case PARSER_COUNTRY:
|
|
||||||
parser_country_start (parser, element_name, attribute_names, attribute_values);
|
|
||||||
break;
|
|
||||||
case PARSER_PROVIDER:
|
|
||||||
parser_provider_start (parser, element_name, attribute_names, attribute_values);
|
|
||||||
break;
|
|
||||||
case PARSER_METHOD_GSM:
|
|
||||||
parser_gsm_start (parser, element_name, attribute_names, attribute_values);
|
|
||||||
break;
|
|
||||||
case PARSER_METHOD_CDMA:
|
|
||||||
parser_cdma_start (parser, element_name, attribute_names, attribute_values);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_country_end (MobileParser *parser,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "country")) {
|
|
||||||
ShellCountryMobileProvider *country_provider;
|
|
||||||
|
|
||||||
country_provider = g_hash_table_lookup (parser->table, parser->current_country);
|
|
||||||
if (country_provider)
|
|
||||||
/* Store providers for this country */
|
|
||||||
country_provider->providers = parser->current_providers;
|
|
||||||
|
|
||||||
parser->current_country = NULL;
|
|
||||||
parser->current_providers = NULL;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
parser->state = PARSER_TOPLEVEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_provider_end (MobileParser *parser,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "name")) {
|
|
||||||
if (!parser->current_provider->name) {
|
|
||||||
/* Use the first one. */
|
|
||||||
parser->current_provider->name = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
}
|
|
||||||
} else if (!strcmp (name, "provider")) {
|
|
||||||
parser->current_provider->methods = g_slist_reverse (parser->current_provider->methods);
|
|
||||||
|
|
||||||
parser->current_provider->gsm_mcc_mnc = g_slist_reverse (parser->current_provider->gsm_mcc_mnc);
|
|
||||||
parser->current_provider->cdma_sid = g_slist_reverse (parser->current_provider->cdma_sid);
|
|
||||||
|
|
||||||
parser->current_providers = g_slist_prepend (parser->current_providers, parser->current_provider);
|
|
||||||
parser->current_provider = NULL;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
parser->state = PARSER_COUNTRY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_gsm_end (MobileParser *parser,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "gsm")) {
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
parser->state = PARSER_PROVIDER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_gsm_apn_end (MobileParser *parser,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "name")) {
|
|
||||||
if (!parser->current_method->name) {
|
|
||||||
/* Use the first one. */
|
|
||||||
parser->current_method->name = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
}
|
|
||||||
} else if (!strcmp (name, "username")) {
|
|
||||||
parser->current_method->username = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "password")) {
|
|
||||||
parser->current_method->password = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "dns")) {
|
|
||||||
parser->current_method->dns = g_slist_prepend (parser->current_method->dns, parser->text_buffer);
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "gateway")) {
|
|
||||||
parser->current_method->gateway = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "apn")) {
|
|
||||||
parser->current_method->type = SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM;
|
|
||||||
parser->current_method->dns = g_slist_reverse (parser->current_method->dns);
|
|
||||||
|
|
||||||
if (!parser->current_method->name)
|
|
||||||
parser->current_method->name = g_strdup (_("Default"));
|
|
||||||
|
|
||||||
parser->current_provider->methods = g_slist_prepend (parser->current_provider->methods,
|
|
||||||
parser->current_method);
|
|
||||||
parser->current_method = NULL;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
parser->state = PARSER_METHOD_GSM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parser_cdma_end (MobileParser *parser,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (!strcmp (name, "username")) {
|
|
||||||
parser->current_method->username = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "password")) {
|
|
||||||
parser->current_method->password = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "dns")) {
|
|
||||||
parser->current_method->dns = g_slist_prepend (parser->current_method->dns, parser->text_buffer);
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "gateway")) {
|
|
||||||
parser->current_method->gateway = parser->text_buffer;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
} else if (!strcmp (name, "cdma")) {
|
|
||||||
parser->current_method->type = SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA;
|
|
||||||
parser->current_method->dns = g_slist_reverse (parser->current_method->dns);
|
|
||||||
|
|
||||||
if (!parser->current_method->name)
|
|
||||||
parser->current_method->name = g_strdup (parser->current_provider->name);
|
|
||||||
|
|
||||||
parser->current_provider->methods = g_slist_prepend (parser->current_provider->methods,
|
|
||||||
parser->current_method);
|
|
||||||
parser->current_method = NULL;
|
|
||||||
parser->text_buffer = NULL;
|
|
||||||
parser->state = PARSER_PROVIDER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mobile_parser_end_element (GMarkupParseContext *context,
|
|
||||||
const gchar *element_name,
|
|
||||||
gpointer data,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
MobileParser *parser = (MobileParser *) data;
|
|
||||||
|
|
||||||
switch (parser->state) {
|
|
||||||
case PARSER_COUNTRY:
|
|
||||||
parser_country_end (parser, element_name);
|
|
||||||
break;
|
|
||||||
case PARSER_PROVIDER:
|
|
||||||
parser_provider_end (parser, element_name);
|
|
||||||
break;
|
|
||||||
case PARSER_METHOD_GSM:
|
|
||||||
parser_gsm_end (parser, element_name);
|
|
||||||
break;
|
|
||||||
case PARSER_METHOD_GSM_APN:
|
|
||||||
parser_gsm_apn_end (parser, element_name);
|
|
||||||
break;
|
|
||||||
case PARSER_METHOD_CDMA:
|
|
||||||
parser_cdma_end (parser, element_name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mobile_parser_characters (GMarkupParseContext *context,
|
|
||||||
const gchar *text,
|
|
||||||
gsize text_len,
|
|
||||||
gpointer data,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
MobileParser *parser = (MobileParser *) data;
|
|
||||||
|
|
||||||
g_free (parser->text_buffer);
|
|
||||||
parser->text_buffer = g_strdup (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GMarkupParser mobile_parser = {
|
|
||||||
mobile_parser_start_element,
|
|
||||||
mobile_parser_end_element,
|
|
||||||
mobile_parser_characters,
|
|
||||||
NULL, /* passthrough */
|
|
||||||
NULL /* error */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_mobile_providers_parse:
|
|
||||||
* @country_codes: (allow-none) File with the list of country codes.
|
|
||||||
* @service_providers: (allow-none) File with the list of service providers.
|
|
||||||
*
|
|
||||||
* Returns: (element-type utf8 Shell.CountryMobileProvider) (transfer full): a
|
|
||||||
* hash table where keys are country names #gchar and values are #ShellCountryMobileProvider.
|
|
||||||
* Everything is destroyed with g_hash_table_destroy().
|
|
||||||
*/
|
|
||||||
GHashTable *
|
|
||||||
shell_mobile_providers_parse (const gchar *country_codes,
|
|
||||||
const gchar *service_providers)
|
|
||||||
{
|
|
||||||
GMarkupParseContext *ctx;
|
|
||||||
GIOChannel *channel;
|
|
||||||
MobileParser parser;
|
|
||||||
GError *error = NULL;
|
|
||||||
char buffer[4096];
|
|
||||||
GIOStatus status;
|
|
||||||
gsize len = 0;
|
|
||||||
|
|
||||||
/* Use default paths if none given */
|
|
||||||
if (!country_codes)
|
|
||||||
country_codes = ISO_3166_COUNTRY_CODES;
|
|
||||||
if (!service_providers)
|
|
||||||
service_providers = MOBILE_BROADBAND_PROVIDER_INFO;
|
|
||||||
|
|
||||||
memset (&parser, 0, sizeof (MobileParser));
|
|
||||||
|
|
||||||
parser.table = read_country_codes (country_codes);
|
|
||||||
if (!parser.table)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
channel = g_io_channel_new_file (service_providers, "r", &error);
|
|
||||||
if (!channel) {
|
|
||||||
if (error) {
|
|
||||||
g_warning ("Could not read %s: %s", service_providers, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
} else
|
|
||||||
g_warning ("Could not read %s: Unknown error", service_providers);
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.state = PARSER_TOPLEVEL;
|
|
||||||
|
|
||||||
ctx = g_markup_parse_context_new (&mobile_parser, 0, &parser, NULL);
|
|
||||||
|
|
||||||
status = G_IO_STATUS_NORMAL;
|
|
||||||
while (status == G_IO_STATUS_NORMAL) {
|
|
||||||
status = g_io_channel_read_chars (channel, buffer, sizeof (buffer), &len, &error);
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case G_IO_STATUS_NORMAL:
|
|
||||||
if (!g_markup_parse_context_parse (ctx, buffer, len, &error)) {
|
|
||||||
status = G_IO_STATUS_ERROR;
|
|
||||||
g_warning ("Error while parsing XML: %s", error->message);
|
|
||||||
g_error_free (error);;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case G_IO_STATUS_EOF:
|
|
||||||
break;
|
|
||||||
case G_IO_STATUS_ERROR:
|
|
||||||
g_warning ("Error while reading: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
break;
|
|
||||||
case G_IO_STATUS_AGAIN:
|
|
||||||
/* FIXME: Try again a few times, but really, it never happes, right? */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_io_channel_unref (channel);
|
|
||||||
g_markup_parse_context_free (ctx);
|
|
||||||
|
|
||||||
if (parser.current_provider) {
|
|
||||||
g_warning ("pending current provider");
|
|
||||||
shell_mobile_provider_unref (parser.current_provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser.current_providers) {
|
|
||||||
g_warning ("pending current providers");
|
|
||||||
provider_list_free (parser.current_providers);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (parser.current_country);
|
|
||||||
g_free (parser.text_buffer);
|
|
||||||
|
|
||||||
out:
|
|
||||||
|
|
||||||
return parser.table;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dump_generic (ShellMobileAccessMethod *method)
|
|
||||||
{
|
|
||||||
GSList *iter;
|
|
||||||
GString *dns;
|
|
||||||
|
|
||||||
g_print (" username: %s\n", method->username ? method->username : "");
|
|
||||||
g_print (" password: %s\n", method->password ? method->password : "");
|
|
||||||
|
|
||||||
dns = g_string_new (NULL);
|
|
||||||
for (iter = method->dns; iter; iter = g_slist_next (iter))
|
|
||||||
g_string_append_printf (dns, "%s%s", dns->len ? ", " : "", (char *) iter->data);
|
|
||||||
g_print (" dns : %s\n", dns->str);
|
|
||||||
g_string_free (dns, TRUE);
|
|
||||||
|
|
||||||
g_print (" gateway : %s\n", method->gateway ? method->gateway : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dump_cdma (ShellMobileAccessMethod *method)
|
|
||||||
{
|
|
||||||
g_print (" CDMA: %s\n", method->name);
|
|
||||||
|
|
||||||
dump_generic (method);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dump_gsm (ShellMobileAccessMethod *method)
|
|
||||||
{
|
|
||||||
g_print (" APN: %s (%s)\n", method->name, method->gsm_apn);
|
|
||||||
|
|
||||||
dump_generic (method);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dump_country (gpointer key, gpointer value, gpointer user_data)
|
|
||||||
{
|
|
||||||
GSList *miter, *citer;
|
|
||||||
ShellCountryMobileProvider *country_provider = value;
|
|
||||||
|
|
||||||
g_print ("Country: %s (%s)\n",
|
|
||||||
country_provider->country_code,
|
|
||||||
country_provider->country_name);
|
|
||||||
|
|
||||||
for (citer = country_provider->providers; citer; citer = g_slist_next (citer)) {
|
|
||||||
ShellMobileProvider *provider = citer->data;
|
|
||||||
|
|
||||||
g_print (" Provider: %s (%s)\n", provider->name, (const char *) key);
|
|
||||||
for (miter = provider->methods; miter; miter = g_slist_next (miter)) {
|
|
||||||
ShellMobileAccessMethod *method = miter->data;
|
|
||||||
GSList *liter;
|
|
||||||
|
|
||||||
|
|
||||||
for (liter = provider->gsm_mcc_mnc; liter; liter = g_slist_next (liter)) {
|
|
||||||
ShellGsmMccMnc *m = liter->data;
|
|
||||||
g_print (" MCC/MNC: %s-%s\n", m->mcc, m->mnc);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (liter = provider->cdma_sid; liter; liter = g_slist_next (liter))
|
|
||||||
g_print (" SID: %d\n", GPOINTER_TO_UINT (liter->data));
|
|
||||||
|
|
||||||
switch (method->type) {
|
|
||||||
case SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA:
|
|
||||||
dump_cdma (method);
|
|
||||||
break;
|
|
||||||
case SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM:
|
|
||||||
dump_gsm (method);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
g_print ("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
shell_mobile_providers_dump (GHashTable *country_providers)
|
|
||||||
{
|
|
||||||
g_return_if_fail (country_providers != NULL);
|
|
||||||
g_hash_table_foreach (country_providers, dump_country, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All the following don't exist in nm-applet, because C doesn't need
|
|
||||||
those. They're only needed for the introspection annotations
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_mobile_provider_get_gsm_mcc_mnc:
|
|
||||||
* @provider: a #ShellMobileProvider
|
|
||||||
*
|
|
||||||
* Returns: (element-type Shell.GsmMccMnc) (transfer none): the
|
|
||||||
* list of #ShellGsmMccMnc this provider exposes
|
|
||||||
*/
|
|
||||||
GSList *
|
|
||||||
shell_mobile_provider_get_gsm_mcc_mnc (ShellMobileProvider *provider)
|
|
||||||
{
|
|
||||||
return provider->gsm_mcc_mnc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_mobile_provider_get_cdma_sid:
|
|
||||||
* @provider: a #ShellMobileProvider
|
|
||||||
*
|
|
||||||
* Returns: (element-type guint32) (transfer none): the
|
|
||||||
* list of CDMA sids this provider exposes
|
|
||||||
*/
|
|
||||||
GSList *
|
|
||||||
shell_mobile_provider_get_cdma_sid (ShellMobileProvider *provider)
|
|
||||||
{
|
|
||||||
return provider->cdma_sid;
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Novell, Inc.
|
|
||||||
* Author: Tambet Ingo (tambet@gmail.com).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 - 2010 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* Ported to GNOME Shell by Giovanni Campagna <scampa.giovanni@gmail.com>
|
|
||||||
* Porting consisted only in replacing nmn with shell, to be compatible with
|
|
||||||
* GObject Introspection namespacing
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SHELL_MOBILE_PROVIDERS_H
|
|
||||||
#define SHELL_MOBILE_PROVIDERS_H
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
#define SHELL_TYPE_MOBILE_PROVIDER (shell_mobile_provider_get_type ())
|
|
||||||
#define SHELL_TYPE_MOBILE_ACCESS_METHOD (shell_mobile_access_method_get_type ())
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SHELL_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN = 0,
|
|
||||||
SHELL_MOBILE_ACCESS_METHOD_TYPE_GSM,
|
|
||||||
SHELL_MOBILE_ACCESS_METHOD_TYPE_CDMA
|
|
||||||
} ShellMobileAccessMethodType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *mcc;
|
|
||||||
char *mnc;
|
|
||||||
} ShellGsmMccMnc;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
/* maps lang (char *) -> name (char *) */
|
|
||||||
GHashTable *lcl_names;
|
|
||||||
|
|
||||||
char *username;
|
|
||||||
char *password;
|
|
||||||
char *gateway;
|
|
||||||
GSList *dns; /* GSList of 'char *' */
|
|
||||||
|
|
||||||
/* Only used with SHELL_PROVIDER_TYPE_GSM */
|
|
||||||
char *gsm_apn;
|
|
||||||
|
|
||||||
ShellMobileAccessMethodType type;
|
|
||||||
|
|
||||||
gint refs;
|
|
||||||
} ShellMobileAccessMethod;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
/* maps lang (char *) -> name (char *) */
|
|
||||||
GHashTable *lcl_names;
|
|
||||||
|
|
||||||
GSList *methods; /* GSList of ShellMobileAccessMethod */
|
|
||||||
|
|
||||||
GSList *gsm_mcc_mnc; /* GSList of ShellGsmMccMnc */
|
|
||||||
GSList *cdma_sid; /* GSList of guint32 */
|
|
||||||
|
|
||||||
gint refs;
|
|
||||||
} ShellMobileProvider;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *country_code;
|
|
||||||
char *country_name;
|
|
||||||
GSList *providers;
|
|
||||||
|
|
||||||
gint refs;
|
|
||||||
} ShellCountryMobileProvider;
|
|
||||||
|
|
||||||
|
|
||||||
GType shell_gsm_mcc_mnc_get_type (void); /* added in porting */
|
|
||||||
GType shell_mobile_access_method_get_type (void);
|
|
||||||
GType shell_mobile_provider_get_type (void);
|
|
||||||
GType shell_country_mobile_provider_get_type (void);
|
|
||||||
|
|
||||||
ShellMobileProvider *shell_mobile_provider_ref (ShellMobileProvider *provider);
|
|
||||||
void shell_mobile_provider_unref (ShellMobileProvider *provider);
|
|
||||||
GSList * shell_mobile_provider_get_gsm_mcc_mnc (ShellMobileProvider *provider);
|
|
||||||
GSList * shell_mobile_provider_get_cdma_sid (ShellMobileProvider *provider);
|
|
||||||
|
|
||||||
ShellMobileAccessMethod *shell_mobile_access_method_ref (ShellMobileAccessMethod *method);
|
|
||||||
void shell_mobile_access_method_unref (ShellMobileAccessMethod *method);
|
|
||||||
|
|
||||||
ShellCountryMobileProvider *shell_country_mobile_provider_ref (ShellCountryMobileProvider *country_provider);
|
|
||||||
void shell_country_mobile_provider_unref (ShellCountryMobileProvider *country_provider);
|
|
||||||
const gchar *shell_country_mobile_provider_get_country_code (ShellCountryMobileProvider *country_provider);
|
|
||||||
const gchar *shell_country_mobile_provider_get_country_name (ShellCountryMobileProvider *country_provider);
|
|
||||||
GSList *shell_country_mobile_provider_get_providers (ShellCountryMobileProvider *country_provider);
|
|
||||||
|
|
||||||
GHashTable *shell_mobile_providers_parse (const gchar *country_codes,
|
|
||||||
const gchar *service_providers);
|
|
||||||
void shell_mobile_providers_dump (GHashTable *country_providers);
|
|
||||||
|
|
||||||
#endif /* SHELL_MOBILE_PROVIDERS_H */
|
|
@ -26,14 +26,11 @@ TEST_JS = \
|
|||||||
testcommon/border-image.png \
|
testcommon/border-image.png \
|
||||||
testcommon/face-plain.png \
|
testcommon/face-plain.png \
|
||||||
testcommon/ui.js \
|
testcommon/ui.js \
|
||||||
testcommon/iso3166-test.tab \
|
|
||||||
testcommon/serviceproviders-test.xml \
|
|
||||||
unit/format.js \
|
unit/format.js \
|
||||||
unit/insertSorted.js \
|
unit/insertSorted.js \
|
||||||
unit/markup.js \
|
unit/markup.js \
|
||||||
unit/jsParse.js \
|
unit/jsParse.js \
|
||||||
unit/url.js \
|
unit/url.js
|
||||||
unit/mobileProviders.js
|
|
||||||
EXTRA_DIST += $(TEST_JS)
|
EXTRA_DIST += $(TEST_JS)
|
||||||
|
|
||||||
TEST_MISC = \
|
TEST_MISC = \
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
# Test country list
|
|
||||||
ES Spain
|
|
||||||
US United States
|
|
@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<!-- -*- Mode: XML; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- -->
|
|
||||||
|
|
||||||
<!DOCTYPE serviceproviders SYSTEM "serviceproviders.2.dtd">
|
|
||||||
|
|
||||||
<serviceproviders format="2.0">
|
|
||||||
|
|
||||||
<!-- United States -->
|
|
||||||
<country code="us">
|
|
||||||
<provider>
|
|
||||||
<name>AT&T</name>
|
|
||||||
<gsm>
|
|
||||||
<network-id mcc="310" mnc="038"/>
|
|
||||||
<network-id mcc="310" mnc="090"/>
|
|
||||||
<network-id mcc="310" mnc="150"/>
|
|
||||||
</gsm>
|
|
||||||
</provider>
|
|
||||||
<provider>
|
|
||||||
<name>Verizon</name>
|
|
||||||
<gsm>
|
|
||||||
<network-id mcc="310" mnc="995"/>
|
|
||||||
<network-id mcc="311" mnc="480"/>
|
|
||||||
</gsm>
|
|
||||||
<cdma>
|
|
||||||
<sid value="2"/>
|
|
||||||
<sid value="4"/>
|
|
||||||
<sid value="5"/>
|
|
||||||
</cdma>
|
|
||||||
</provider>
|
|
||||||
</country>
|
|
||||||
|
|
||||||
<!-- Spain -->
|
|
||||||
<country code="es">
|
|
||||||
<provider>
|
|
||||||
<name>Movistar (Telefónica)</name>
|
|
||||||
<gsm>
|
|
||||||
<network-id mcc="214" mnc="05"/>
|
|
||||||
<network-id mcc="214" mnc="07"/>
|
|
||||||
</gsm>
|
|
||||||
</provider>
|
|
||||||
</country>
|
|
||||||
|
|
||||||
</serviceproviders>
|
|
@ -1,78 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const JsUnit = imports.jsUnit;
|
|
||||||
const ModemManager = imports.misc.modemManager;
|
|
||||||
const Environment = imports.ui.environment;
|
|
||||||
|
|
||||||
Environment.init();
|
|
||||||
|
|
||||||
// Load test providers table
|
|
||||||
let countrycodesPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/iso3166-test.tab";
|
|
||||||
let serviceprovidersPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/serviceproviders-test.xml";
|
|
||||||
let providersTable = Shell.mobile_providers_parse(countrycodesPath, serviceprovidersPath);
|
|
||||||
|
|
||||||
function assertCountryFound(country_code, expected_country_name) {
|
|
||||||
let country = providersTable[country_code];
|
|
||||||
JsUnit.assertNotUndefined(country);
|
|
||||||
JsUnit.assertEquals(country.get_country_name(), expected_country_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertCountryNotFound(country_code) {
|
|
||||||
let country = providersTable[country_code];
|
|
||||||
JsUnit.assertUndefined(country);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertProviderFoundForMCCMNC(mccmnc, expected_provider_name) {
|
|
||||||
let provider_name = ModemManager.findProviderForMCCMNC(providersTable, mccmnc);
|
|
||||||
JsUnit.assertEquals(provider_name, expected_provider_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertProviderNotFoundForMCCMNC(mccmnc) {
|
|
||||||
let provider_name = ModemManager.findProviderForMCCMNC(providersTable, mccmnc);
|
|
||||||
JsUnit.assertNull(provider_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertProviderFoundForSid(sid, expected_provider_name) {
|
|
||||||
let provider_name = ModemManager.findProviderForSid(providersTable, sid);
|
|
||||||
JsUnit.assertEquals(provider_name, expected_provider_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertProviderNotFoundForSid(sid) {
|
|
||||||
let provider_name = ModemManager.findProviderForSid(providersTable, sid);
|
|
||||||
JsUnit.assertNull(provider_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TEST:
|
|
||||||
// * Both 'US' and 'ES' country info should be loaded
|
|
||||||
assertCountryFound("ES", "Spain");
|
|
||||||
assertCountryFound("US", "United States");
|
|
||||||
|
|
||||||
// TEST:
|
|
||||||
// * Country info for 'FR' not given
|
|
||||||
assertCountryNotFound("FR");
|
|
||||||
|
|
||||||
// TEST:
|
|
||||||
// * Ensure operator names are found for the given MCC/MNC codes
|
|
||||||
assertProviderFoundForMCCMNC("21405", "Movistar (Telefónica)");
|
|
||||||
assertProviderFoundForMCCMNC("21407", "Movistar (Telefónica)");
|
|
||||||
assertProviderFoundForMCCMNC("310038", "AT&T");
|
|
||||||
assertProviderFoundForMCCMNC("310090", "AT&T");
|
|
||||||
assertProviderFoundForMCCMNC("310150", "AT&T");
|
|
||||||
assertProviderFoundForMCCMNC("310995", "Verizon");
|
|
||||||
assertProviderFoundForMCCMNC("311480", "Verizon");
|
|
||||||
|
|
||||||
// TEST:
|
|
||||||
// * Ensure NULL is given for unexpected MCC/MNC codes
|
|
||||||
assertProviderNotFoundForMCCMNC("12345");
|
|
||||||
|
|
||||||
// TEST:
|
|
||||||
// * Ensure operator names are found for the given SID codes
|
|
||||||
assertProviderFoundForSid(2, "Verizon");
|
|
||||||
assertProviderFoundForSid(4, "Verizon");
|
|
||||||
assertProviderFoundForSid(5, "Verizon");
|
|
||||||
|
|
||||||
// TEST:
|
|
||||||
// * Ensure NULL is given for unexpected SID codes
|
|
||||||
assertProviderNotFoundForSid(1);
|
|
Loading…
Reference in New Issue
Block a user