|
Packit |
fabffb |
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
Packit |
fabffb |
/*
|
|
Packit |
fabffb |
* This library is free software; you can redistribute it and/or
|
|
Packit |
fabffb |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
fabffb |
* License as published by the Free Software Foundation; either
|
|
Packit |
fabffb |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
fabffb |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
fabffb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
fabffb |
* Lesser General Public License for more details.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
fabffb |
* License along with this library; if not, write to the
|
|
Packit |
fabffb |
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Packit |
fabffb |
* Boston, MA 02110-1301 USA.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Copyright (C) 2009 Novell, Inc.
|
|
Packit |
fabffb |
* Author: Tambet Ingo (tambet@gmail.com).
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Copyright (C) 2009 - 2012 Red Hat, Inc.
|
|
Packit |
fabffb |
* Copyright (C) 2012 Lanedo GmbH
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
#include "nm-default.h"
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
#include <string.h>
|
|
Packit |
fabffb |
#include <errno.h>
|
|
Packit |
fabffb |
#include <stdlib.h>
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
#include "nm-mobile-providers.h"
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
#define ISO_3166_COUNTRY_CODES ISO_CODES_PREFIX"/share/xml/iso-codes/iso_3166.xml"
|
|
Packit |
fabffb |
#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX"/share/locale"
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* Access method type */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
G_DEFINE_BOXED_TYPE (NMAMobileAccessMethod,
|
|
Packit |
fabffb |
nma_mobile_access_method,
|
|
Packit |
fabffb |
nma_mobile_access_method_ref,
|
|
Packit |
fabffb |
nma_mobile_access_method_unref)
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
struct _NMAMobileAccessMethod {
|
|
Packit |
fabffb |
volatile gint refs;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
char *name;
|
|
Packit |
fabffb |
/* maps lang (char *) -> name (char *) */
|
|
Packit |
fabffb |
GHashTable *lcl_names;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
char *username;
|
|
Packit |
fabffb |
char *password;
|
|
Packit |
fabffb |
char *gateway;
|
|
Packit |
fabffb |
GPtrArray *dns; /* GPtrArray of 'char *' */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Only used with 3GPP family type providers */
|
|
Packit |
fabffb |
char *apn;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
NMAMobileFamily family;
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static NMAMobileAccessMethod *
|
|
Packit |
fabffb |
access_method_new (void)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMAMobileAccessMethod *method;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
method = g_slice_new0 (NMAMobileAccessMethod);
|
|
Packit |
fabffb |
method->refs = 1;
|
|
Packit |
fabffb |
method->lcl_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
Packit |
fabffb |
(GDestroyNotify) g_free,
|
|
Packit |
fabffb |
(GDestroyNotify) g_free);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
NMAMobileAccessMethod *
|
|
Packit |
fabffb |
nma_mobile_access_method_ref (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
g_return_val_if_fail (method->refs > 0, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_atomic_int_inc (&method->refs);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
void
|
|
Packit |
fabffb |
nma_mobile_access_method_unref (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_if_fail (method != NULL);
|
|
Packit |
fabffb |
g_return_if_fail (method->refs > 0);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (g_atomic_int_dec_and_test (&method->refs)) {
|
|
Packit |
fabffb |
g_free (method->name);
|
|
Packit |
fabffb |
g_hash_table_destroy (method->lcl_names);
|
|
Packit |
fabffb |
g_free (method->username);
|
|
Packit |
fabffb |
g_free (method->password);
|
|
Packit |
fabffb |
g_free (method->gateway);
|
|
Packit |
fabffb |
g_free (method->apn);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (method->dns)
|
|
Packit |
fabffb |
g_ptr_array_unref (method->dns);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_slice_free (NMAMobileAccessMethod, method);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_name:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the name of the method.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_mobile_access_method_get_name (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->name;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_username:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the username.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_mobile_access_method_get_username (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->username;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_password:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the password.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_mobile_access_method_get_password (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->password;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_gateway:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the gateway.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_mobile_access_method_get_gateway (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->gateway;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_dns:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none) (array zero-terminated=1) (element-type utf8): the list of DNS.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar **
|
|
Packit |
fabffb |
nma_mobile_access_method_get_dns (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->dns ? (const gchar **)method->dns->pdata : NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_3gpp_apn:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the 3GPP APN.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_mobile_access_method_get_3gpp_apn (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->apn;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_access_method_get_family:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: a #NMAMobileFamily.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
NMAMobileFamily
|
|
Packit |
fabffb |
nma_mobile_access_method_get_family (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (method != NULL, NMA_MOBILE_FAMILY_UNKNOWN);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return method->family;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* Mobile provider type */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
G_DEFINE_BOXED_TYPE (NMAMobileProvider,
|
|
Packit |
fabffb |
nma_mobile_provider,
|
|
Packit |
fabffb |
nma_mobile_provider_ref,
|
|
Packit |
fabffb |
nma_mobile_provider_unref)
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
struct _NMAMobileProvider {
|
|
Packit |
fabffb |
volatile gint refs;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
char *name;
|
|
Packit |
fabffb |
/* maps lang (char *) -> name (char *) */
|
|
Packit |
fabffb |
GHashTable *lcl_names;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
GSList *methods; /* GSList of NmaMobileAccessMethod */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
GPtrArray *mcc_mnc; /* GPtrArray of strings */
|
|
Packit |
fabffb |
GArray *cdma_sid; /* GArray of guint32 */
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static NMAMobileProvider *
|
|
Packit |
fabffb |
provider_new (void)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMAMobileProvider *provider;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
provider = g_slice_new0 (NMAMobileProvider);
|
|
Packit |
fabffb |
provider->refs = 1;
|
|
Packit |
fabffb |
provider->lcl_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
Packit |
fabffb |
(GDestroyNotify) g_free,
|
|
Packit |
fabffb |
(GDestroyNotify) g_free);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
NMAMobileProvider *
|
|
Packit |
fabffb |
nma_mobile_provider_ref (NMAMobileProvider *provider)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (provider != NULL, NULL);
|
|
Packit |
fabffb |
g_return_val_if_fail (provider->refs > 0, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_atomic_int_inc (&provider->refs);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
void
|
|
Packit |
fabffb |
nma_mobile_provider_unref (NMAMobileProvider *provider)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (g_atomic_int_dec_and_test (&provider->refs)) {
|
|
Packit |
fabffb |
g_free (provider->name);
|
|
Packit |
fabffb |
g_hash_table_destroy (provider->lcl_names);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_slist_free_full (provider->methods, (GDestroyNotify) nma_mobile_access_method_unref);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (provider->mcc_mnc)
|
|
Packit |
fabffb |
g_ptr_array_unref (provider->mcc_mnc);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (provider->cdma_sid)
|
|
Packit |
fabffb |
g_array_unref (provider->cdma_sid);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_slice_free (NMAMobileProvider, provider);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_provider_get_name:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the name of the provider.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_mobile_provider_get_name (NMAMobileProvider *provider)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (provider != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider->name;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_provider_get_methods:
|
|
Packit |
fabffb |
* @provider: a #NMAMobileProvider
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (element-type NMGtk.MobileAccessMethod) (transfer none): the
|
|
Packit |
fabffb |
* list of #NMAMobileAccessMethod this provider exposes.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
GSList *
|
|
Packit |
fabffb |
nma_mobile_provider_get_methods (NMAMobileProvider *provider)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (provider != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider->methods;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_provider_get_3gpp_mcc_mnc:
|
|
Packit |
fabffb |
* @provider: a #NMAMobileProvider
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none) (array zero-terminated=1) (element-type utf8): a
|
|
Packit |
fabffb |
* list of strings with the MCC and MNC codes this provider exposes.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar **
|
|
Packit |
fabffb |
nma_mobile_provider_get_3gpp_mcc_mnc (NMAMobileProvider *provider)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (provider != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider->mcc_mnc ? (const gchar **)provider->mcc_mnc->pdata : NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_provider_get_cdma_sid:
|
|
Packit |
fabffb |
* @provider: a #NMAMobileProvider
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none) (array zero-terminated=1) (element-type guint32): the
|
|
Packit |
fabffb |
* list of CDMA SIDs this provider exposes
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const guint32 *
|
|
Packit |
fabffb |
nma_mobile_provider_get_cdma_sid (NMAMobileProvider *provider)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (provider != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider->cdma_sid ? (const guint32 *)provider->cdma_sid->data : NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* Country Info type */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
G_DEFINE_BOXED_TYPE (NMACountryInfo,
|
|
Packit |
fabffb |
nma_country_info,
|
|
Packit |
fabffb |
nma_country_info_ref,
|
|
Packit |
fabffb |
nma_country_info_unref)
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
struct _NMACountryInfo {
|
|
Packit |
fabffb |
volatile gint refs;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
char *country_code;
|
|
Packit |
fabffb |
char *country_name;
|
|
Packit |
fabffb |
GSList *providers;
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static NMACountryInfo *
|
|
Packit |
fabffb |
country_info_new (const char *country_code,
|
|
Packit |
fabffb |
const gchar *country_name)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMACountryInfo *country_info;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
country_info = g_slice_new0 (NMACountryInfo);
|
|
Packit |
fabffb |
country_info->refs = 1;
|
|
Packit |
fabffb |
country_info->country_code = g_strdup (country_code);
|
|
Packit |
fabffb |
country_info->country_name = g_strdup (country_name);
|
|
Packit |
fabffb |
return country_info;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
NMACountryInfo *
|
|
Packit |
fabffb |
nma_country_info_ref (NMACountryInfo *country_info)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (country_info != NULL, NULL);
|
|
Packit |
fabffb |
g_return_val_if_fail (country_info->refs > 0, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_atomic_int_inc (&country_info->refs);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return country_info;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
void
|
|
Packit |
fabffb |
nma_country_info_unref (NMACountryInfo *country_info)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (g_atomic_int_dec_and_test (&country_info->refs)) {
|
|
Packit |
fabffb |
g_free (country_info->country_code);
|
|
Packit |
fabffb |
g_free (country_info->country_name);
|
|
Packit |
fabffb |
g_slist_free_full (country_info->providers,
|
|
Packit |
fabffb |
(GDestroyNotify) nma_mobile_provider_unref);
|
|
Packit |
fabffb |
g_slice_free (NMACountryInfo, country_info);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_country_info_get_country_code:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the code of the country.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_country_info_get_country_code (NMACountryInfo *country_info)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (country_info != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return country_info->country_code;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_country_info_get_country_name:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): the name of the country.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
const gchar *
|
|
Packit |
fabffb |
nma_country_info_get_country_name (NMACountryInfo *country_info)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (country_info != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return country_info->country_name;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_country_info_get_providers:
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (element-type NMGtk.MobileProvider) (transfer none): the
|
|
Packit |
fabffb |
* list of #NMAMobileProvider this country exposes.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
GSList *
|
|
Packit |
fabffb |
nma_country_info_get_providers (NMACountryInfo *country_info)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (country_info != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return country_info->providers;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* XML Parser for iso_3166.xml */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
iso_3166_parser_start_element (GMarkupParseContext *context,
|
|
Packit |
fabffb |
const gchar *element_name,
|
|
Packit |
fabffb |
const gchar **attribute_names,
|
|
Packit |
fabffb |
const gchar **attribute_values,
|
|
Packit |
fabffb |
gpointer data,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
int i;
|
|
Packit |
fabffb |
const char *country_code = NULL;
|
|
Packit |
fabffb |
const char *common_name = NULL;
|
|
Packit |
fabffb |
const char *name = NULL;
|
|
Packit |
fabffb |
GHashTable *table = (GHashTable *) data;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!strcmp (element_name, "iso_3166_entry")) {
|
|
Packit |
fabffb |
NMACountryInfo *country_info;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
Packit |
fabffb |
if (!strcmp (attribute_names[i], "alpha_2_code"))
|
|
Packit |
fabffb |
country_code = attribute_values[i];
|
|
Packit |
fabffb |
else if (!strcmp (attribute_names[i], "common_name"))
|
|
Packit |
fabffb |
common_name = attribute_values[i];
|
|
Packit |
fabffb |
else if (!strcmp (attribute_names[i], "name"))
|
|
Packit |
fabffb |
name = attribute_values[i];
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
if (!country_code) {
|
|
Packit |
fabffb |
g_warning ("%s: missing mandatory 'alpha_2_code' atribute in '%s'"
|
|
Packit |
fabffb |
" element.", __func__, element_name);
|
|
Packit |
fabffb |
return;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
if (!name) {
|
|
Packit |
fabffb |
g_warning ("%s: missing mandatory 'name' atribute in '%s'"
|
|
Packit |
fabffb |
" element.", __func__, element_name);
|
|
Packit |
fabffb |
return;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
country_info = country_info_new (country_code,
|
|
Packit |
fabffb |
dgettext ("iso_3166", common_name ? common_name : name));
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_hash_table_insert (table, g_strdup (country_code), country_info);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static const GMarkupParser iso_3166_parser = {
|
|
Packit |
fabffb |
iso_3166_parser_start_element,
|
|
Packit |
fabffb |
NULL, /* end element */
|
|
Packit |
fabffb |
NULL, /* text */
|
|
Packit |
fabffb |
NULL, /* passthrough */
|
|
Packit |
fabffb |
NULL /* error */
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static GHashTable *
|
|
Packit |
fabffb |
read_country_codes (const gchar *country_codes_file,
|
|
Packit |
fabffb |
GCancellable *cancellable,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GHashTable *table = NULL;
|
|
Packit |
fabffb |
GMarkupParseContext *ctx;
|
|
Packit |
fabffb |
char *buf;
|
|
Packit |
fabffb |
gsize buf_len;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Set domain to iso_3166 for country name translation */
|
|
Packit |
fabffb |
bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
|
|
Packit |
fabffb |
bind_textdomain_codeset ("iso_3166", "UTF-8");
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!g_file_get_contents (country_codes_file, &buf, &buf_len, error)) {
|
|
Packit |
fabffb |
g_prefix_error (error,
|
|
Packit |
fabffb |
"Failed to load '%s' from 'iso-codes': ",
|
|
Packit |
fabffb |
country_codes_file);
|
|
Packit |
fabffb |
return NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
table = g_hash_table_new_full (g_str_hash,
|
|
Packit |
fabffb |
g_str_equal,
|
|
Packit |
fabffb |
g_free,
|
|
Packit |
fabffb |
(GDestroyNotify)nma_country_info_unref);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
ctx = g_markup_parse_context_new (&iso_3166_parser, 0, table, NULL);
|
|
Packit |
fabffb |
if (!g_markup_parse_context_parse (ctx, buf, buf_len, error)) {
|
|
Packit |
fabffb |
g_prefix_error (error,
|
|
Packit |
fabffb |
"Failed to parse '%s' from 'iso-codes': ",
|
|
Packit |
fabffb |
country_codes_file);
|
|
Packit |
fabffb |
g_hash_table_destroy (table);
|
|
Packit |
fabffb |
return NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_markup_parse_context_free (ctx);
|
|
Packit |
fabffb |
g_free (buf);
|
|
Packit |
fabffb |
return table;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* XML Parser for serviceproviders.xml */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
typedef enum {
|
|
Packit |
fabffb |
PARSER_TOPLEVEL = 0,
|
|
Packit |
fabffb |
PARSER_COUNTRY,
|
|
Packit |
fabffb |
PARSER_PROVIDER,
|
|
Packit |
fabffb |
PARSER_METHOD_GSM,
|
|
Packit |
fabffb |
PARSER_METHOD_GSM_APN,
|
|
Packit |
fabffb |
PARSER_METHOD_CDMA,
|
|
Packit |
fabffb |
PARSER_ERROR
|
|
Packit |
fabffb |
} MobileContextState;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
typedef struct {
|
|
Packit |
fabffb |
GHashTable *table;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
char *current_country;
|
|
Packit |
fabffb |
GSList *current_providers;
|
|
Packit |
fabffb |
NMAMobileProvider *current_provider;
|
|
Packit |
fabffb |
NMAMobileAccessMethod *current_method;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
char *text_buffer;
|
|
Packit |
fabffb |
MobileContextState state;
|
|
Packit |
fabffb |
} MobileParser;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
provider_list_free (gpointer data)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GSList *list = (GSList *) data;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
while (list) {
|
|
Packit |
fabffb |
nma_mobile_provider_unref ((NMAMobileProvider *) list->data);
|
|
Packit |
fabffb |
list = g_slist_delete_link (list, list);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_toplevel_start (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name,
|
|
Packit |
fabffb |
const char **attribute_names,
|
|
Packit |
fabffb |
const char **attribute_values)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
int i;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!strcmp (name, "serviceproviders")) {
|
|
Packit |
fabffb |
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
Packit |
fabffb |
if (!strcmp (attribute_names[i], "format")) {
|
|
Packit |
fabffb |
if (strcmp (attribute_values[i], "2.0")) {
|
|
Packit |
fabffb |
g_warning ("%s: mobile broadband provider database format '%s'"
|
|
Packit |
fabffb |
" not supported.", __func__, attribute_values[i]);
|
|
Packit |
fabffb |
parser->state = PARSER_ERROR;
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
} else if (!strcmp (name, "country")) {
|
|
Packit |
fabffb |
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
Packit |
fabffb |
if (!strcmp (attribute_names[i], "code")) {
|
|
Packit |
fabffb |
char *country_code;
|
|
Packit |
fabffb |
NMACountryInfo *country_info;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
country_code = g_ascii_strup (attribute_values[i], -1);
|
|
Packit |
fabffb |
country_info = g_hash_table_lookup (parser->table, country_code);
|
|
Packit |
fabffb |
/* Ensure we have a country provider for this country code */
|
|
Packit |
fabffb |
if (!country_info) {
|
|
Packit |
fabffb |
g_warning ("%s: adding providers for unknown country '%s'", __func__, country_code);
|
|
Packit |
fabffb |
country_info = country_info_new (country_code, NULL);
|
|
Packit |
fabffb |
g_hash_table_insert (parser->table, country_code, country_info);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
parser->current_country = country_code;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser->state = PARSER_COUNTRY;
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_country_start (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name,
|
|
Packit |
fabffb |
const char **attribute_names,
|
|
Packit |
fabffb |
const char **attribute_values)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "provider")) {
|
|
Packit |
fabffb |
parser->state = PARSER_PROVIDER;
|
|
Packit |
fabffb |
parser->current_provider = provider_new ();
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_provider_start (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name,
|
|
Packit |
fabffb |
const char **attribute_names,
|
|
Packit |
fabffb |
const char **attribute_values)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "gsm"))
|
|
Packit |
fabffb |
parser->state = PARSER_METHOD_GSM;
|
|
Packit |
fabffb |
else if (!strcmp (name, "cdma")) {
|
|
Packit |
fabffb |
parser->state = PARSER_METHOD_CDMA;
|
|
Packit |
fabffb |
parser->current_method = access_method_new ();
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_gsm_start (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name,
|
|
Packit |
fabffb |
const char **attribute_names,
|
|
Packit |
fabffb |
const char **attribute_values)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "network-id")) {
|
|
Packit |
fabffb |
const char *mcc = NULL, *mnc = NULL;
|
|
Packit |
fabffb |
int i;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
Packit |
fabffb |
if (!strcmp (attribute_names[i], "mcc"))
|
|
Packit |
fabffb |
mcc = attribute_values[i];
|
|
Packit |
fabffb |
else if (!strcmp (attribute_names[i], "mnc"))
|
|
Packit |
fabffb |
mnc = attribute_values[i];
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (mcc && strlen (mcc) && mnc && strlen (mnc)) {
|
|
Packit |
fabffb |
gchar *mccmnc;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!parser->current_provider->mcc_mnc)
|
|
Packit |
fabffb |
parser->current_provider->mcc_mnc = g_ptr_array_new_full (2, g_free);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
mccmnc = g_strdup_printf ("%s%s", mcc, mnc);
|
|
Packit |
fabffb |
g_ptr_array_add (parser->current_provider->mcc_mnc, mccmnc);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
} else if (!strcmp (name, "apn")) {
|
|
Packit |
fabffb |
int i;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
Packit |
fabffb |
if (!strcmp (attribute_names[i], "value")) {
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser->state = PARSER_METHOD_GSM_APN;
|
|
Packit |
fabffb |
parser->current_method = access_method_new ();
|
|
Packit |
fabffb |
parser->current_method->apn = g_strstrip (g_strdup (attribute_values[i]));
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_cdma_start (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name,
|
|
Packit |
fabffb |
const char **attribute_names,
|
|
Packit |
fabffb |
const char **attribute_values)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "sid")) {
|
|
Packit |
fabffb |
int i;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
|
Packit |
fabffb |
if (!strcmp (attribute_names[i], "value")) {
|
|
Packit |
fabffb |
guint32 tmp;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
errno = 0;
|
|
Packit |
fabffb |
tmp = (guint32) strtoul (attribute_values[i], NULL, 10);
|
|
Packit |
fabffb |
if (errno == 0 && tmp > 0) {
|
|
Packit |
fabffb |
if (!parser->current_provider->cdma_sid)
|
|
Packit |
fabffb |
parser->current_provider->cdma_sid = g_array_sized_new (TRUE, FALSE, sizeof (guint32), 2);
|
|
Packit |
fabffb |
g_array_append_val (parser->current_provider->cdma_sid, tmp);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
mobile_parser_start_element (GMarkupParseContext *context,
|
|
Packit |
fabffb |
const gchar *element_name,
|
|
Packit |
fabffb |
const gchar **attribute_names,
|
|
Packit |
fabffb |
const gchar **attribute_values,
|
|
Packit |
fabffb |
gpointer data,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
MobileParser *parser = (MobileParser *) data;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (parser->text_buffer) {
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
switch (parser->state) {
|
|
Packit |
fabffb |
case PARSER_TOPLEVEL:
|
|
Packit |
fabffb |
parser_toplevel_start (parser, element_name, attribute_names, attribute_values);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_COUNTRY:
|
|
Packit |
fabffb |
parser_country_start (parser, element_name, attribute_names, attribute_values);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_PROVIDER:
|
|
Packit |
fabffb |
parser_provider_start (parser, element_name, attribute_names, attribute_values);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_METHOD_GSM:
|
|
Packit |
fabffb |
parser_gsm_start (parser, element_name, attribute_names, attribute_values);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_METHOD_CDMA:
|
|
Packit |
fabffb |
parser_cdma_start (parser, element_name, attribute_names, attribute_values);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
default:
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_country_end (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "country")) {
|
|
Packit |
fabffb |
NMACountryInfo *country_info;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
country_info = g_hash_table_lookup (parser->table, parser->current_country);
|
|
Packit |
fabffb |
g_assert (country_info);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Store providers for this country */
|
|
Packit |
fabffb |
country_info->providers = parser->current_providers;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_free (parser->current_country);
|
|
Packit |
fabffb |
parser->current_country = NULL;
|
|
Packit |
fabffb |
parser->current_providers = NULL;
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
parser->state = PARSER_TOPLEVEL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_provider_end (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "name")) {
|
|
Packit |
fabffb |
if (!parser->current_provider->name) {
|
|
Packit |
fabffb |
/* Use the first one. */
|
|
Packit |
fabffb |
parser->current_provider->name = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
} else if (!strcmp (name, "provider")) {
|
|
Packit |
fabffb |
if (parser->current_provider->mcc_mnc)
|
|
Packit |
fabffb |
g_ptr_array_add (parser->current_provider->mcc_mnc, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser->current_provider->methods = g_slist_reverse (parser->current_provider->methods);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser->current_providers = g_slist_prepend (parser->current_providers, parser->current_provider);
|
|
Packit |
fabffb |
parser->current_provider = NULL;
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
parser->state = PARSER_COUNTRY;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_gsm_end (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "gsm")) {
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
parser->state = PARSER_PROVIDER;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_gsm_apn_end (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "name")) {
|
|
Packit |
fabffb |
if (!parser->current_method->name) {
|
|
Packit |
fabffb |
/* Use the first one. */
|
|
Packit |
fabffb |
parser->current_method->name = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
} else if (!strcmp (name, "username")) {
|
|
Packit |
fabffb |
parser->current_method->username = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "password")) {
|
|
Packit |
fabffb |
parser->current_method->password = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "dns")) {
|
|
Packit |
fabffb |
if (!parser->current_method->dns)
|
|
Packit |
fabffb |
parser->current_method->dns = g_ptr_array_new_full (2, g_free);
|
|
Packit |
fabffb |
g_ptr_array_add (parser->current_method->dns, parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "gateway")) {
|
|
Packit |
fabffb |
parser->current_method->gateway = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "apn")) {
|
|
Packit |
fabffb |
parser->current_method->family = NMA_MOBILE_FAMILY_3GPP;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!parser->current_method->name)
|
|
Packit |
fabffb |
parser->current_method->name = g_strdup (_("Default"));
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (parser->current_method->dns)
|
|
Packit |
fabffb |
g_ptr_array_add (parser->current_method->dns, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser->current_provider->methods = g_slist_prepend (parser->current_provider->methods,
|
|
Packit |
fabffb |
parser->current_method);
|
|
Packit |
fabffb |
parser->current_method = NULL;
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
parser->state = PARSER_METHOD_GSM;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
parser_cdma_end (MobileParser *parser,
|
|
Packit |
fabffb |
const char *name)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
if (!strcmp (name, "username")) {
|
|
Packit |
fabffb |
parser->current_method->username = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "password")) {
|
|
Packit |
fabffb |
parser->current_method->password = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "dns")) {
|
|
Packit |
fabffb |
if (!parser->current_method->dns)
|
|
Packit |
fabffb |
parser->current_method->dns = g_ptr_array_new_full (2, g_free);
|
|
Packit |
fabffb |
g_ptr_array_add (parser->current_method->dns, parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "gateway")) {
|
|
Packit |
fabffb |
parser->current_method->gateway = parser->text_buffer;
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
} else if (!strcmp (name, "cdma")) {
|
|
Packit |
fabffb |
parser->current_method->family = NMA_MOBILE_FAMILY_CDMA;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!parser->current_method->name)
|
|
Packit |
fabffb |
parser->current_method->name = g_strdup (parser->current_provider->name);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (parser->current_method->dns)
|
|
Packit |
fabffb |
g_ptr_array_add (parser->current_method->dns, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser->current_provider->methods = g_slist_prepend (parser->current_provider->methods,
|
|
Packit |
fabffb |
parser->current_method);
|
|
Packit |
fabffb |
parser->current_method = NULL;
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = NULL;
|
|
Packit |
fabffb |
parser->state = PARSER_PROVIDER;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
mobile_parser_end_element (GMarkupParseContext *context,
|
|
Packit |
fabffb |
const gchar *element_name,
|
|
Packit |
fabffb |
gpointer data,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
MobileParser *parser = (MobileParser *) data;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
switch (parser->state) {
|
|
Packit |
fabffb |
case PARSER_COUNTRY:
|
|
Packit |
fabffb |
parser_country_end (parser, element_name);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_PROVIDER:
|
|
Packit |
fabffb |
parser_provider_end (parser, element_name);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_METHOD_GSM:
|
|
Packit |
fabffb |
parser_gsm_end (parser, element_name);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_METHOD_GSM_APN:
|
|
Packit |
fabffb |
parser_gsm_apn_end (parser, element_name);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PARSER_METHOD_CDMA:
|
|
Packit |
fabffb |
parser_cdma_end (parser, element_name);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
default:
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
mobile_parser_characters (GMarkupParseContext *context,
|
|
Packit |
fabffb |
const gchar *text,
|
|
Packit |
fabffb |
gsize text_len,
|
|
Packit |
fabffb |
gpointer data,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
MobileParser *parser = (MobileParser *) data;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_free (parser->text_buffer);
|
|
Packit |
fabffb |
parser->text_buffer = g_strdup (text);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static const GMarkupParser mobile_parser = {
|
|
Packit |
fabffb |
mobile_parser_start_element,
|
|
Packit |
fabffb |
mobile_parser_end_element,
|
|
Packit |
fabffb |
mobile_parser_characters,
|
|
Packit |
fabffb |
NULL, /* passthrough */
|
|
Packit |
fabffb |
NULL /* error */
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static gboolean
|
|
Packit |
fabffb |
read_service_providers (GHashTable *countries,
|
|
Packit |
fabffb |
const gchar *service_providers,
|
|
Packit |
fabffb |
GCancellable *cancellable,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GMarkupParseContext *ctx;
|
|
Packit |
fabffb |
GIOChannel *channel;
|
|
Packit |
fabffb |
MobileParser parser;
|
|
Packit |
fabffb |
char buffer[4096];
|
|
Packit |
fabffb |
GIOStatus status;
|
|
Packit |
fabffb |
gsize len = 0;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
memset (&parser, 0, sizeof (MobileParser));
|
|
Packit |
fabffb |
parser.table = countries;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
channel = g_io_channel_new_file (service_providers, "r", error);
|
|
Packit |
fabffb |
if (!channel) {
|
|
Packit |
fabffb |
g_prefix_error (error,
|
|
Packit |
fabffb |
"Could not read '%s': ",
|
|
Packit |
fabffb |
service_providers);
|
|
Packit |
fabffb |
return FALSE;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
parser.state = PARSER_TOPLEVEL;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
ctx = g_markup_parse_context_new (&mobile_parser, 0, &parser, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
status = G_IO_STATUS_NORMAL;
|
|
Packit |
fabffb |
while (status == G_IO_STATUS_NORMAL) {
|
|
Packit |
fabffb |
status = g_io_channel_read_chars (channel, buffer, sizeof (buffer), &len, error);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
switch (status) {
|
|
Packit |
fabffb |
case G_IO_STATUS_NORMAL:
|
|
Packit |
fabffb |
if (!g_markup_parse_context_parse (ctx, buffer, len, error)) {
|
|
Packit |
fabffb |
status = G_IO_STATUS_ERROR;
|
|
Packit |
fabffb |
g_prefix_error (error,
|
|
Packit |
fabffb |
"Error while parsing XML at '%s': ",
|
|
Packit |
fabffb |
service_providers);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case G_IO_STATUS_EOF:
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case G_IO_STATUS_ERROR:
|
|
Packit |
fabffb |
g_prefix_error (error,
|
|
Packit |
fabffb |
"Error while reading '%s': ",
|
|
Packit |
fabffb |
service_providers);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case G_IO_STATUS_AGAIN:
|
|
Packit |
fabffb |
/* FIXME: Try again a few times, but really, it never happens, right? */
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
Packit |
fabffb |
status = G_IO_STATUS_ERROR;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_io_channel_unref (channel);
|
|
Packit |
fabffb |
g_markup_parse_context_free (ctx);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (parser.current_provider) {
|
|
Packit |
fabffb |
g_warning ("pending current provider");
|
|
Packit |
fabffb |
nma_mobile_provider_unref (parser.current_provider);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (parser.current_providers) {
|
|
Packit |
fabffb |
g_warning ("pending current providers");
|
|
Packit |
fabffb |
provider_list_free (parser.current_providers);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_free (parser.current_country);
|
|
Packit |
fabffb |
g_free (parser.text_buffer);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return (status == G_IO_STATUS_EOF);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static GHashTable *
|
|
Packit |
fabffb |
mobile_providers_parse_sync (const gchar *country_codes,
|
|
Packit |
fabffb |
const gchar *service_providers,
|
|
Packit |
fabffb |
GCancellable *cancellable,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GHashTable *countries;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Use default paths if none given */
|
|
Packit |
fabffb |
if (!country_codes)
|
|
Packit |
fabffb |
country_codes = ISO_3166_COUNTRY_CODES;
|
|
Packit |
fabffb |
if (!service_providers)
|
|
Packit |
fabffb |
service_providers = MOBILE_BROADBAND_PROVIDER_INFO_DATABASE;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
countries = read_country_codes (country_codes,
|
|
Packit |
fabffb |
cancellable,
|
|
Packit |
fabffb |
error);
|
|
Packit |
fabffb |
if (!countries)
|
|
Packit |
fabffb |
return NULL;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (!read_service_providers (countries,
|
|
Packit |
fabffb |
service_providers,
|
|
Packit |
fabffb |
cancellable,
|
|
Packit |
fabffb |
error)) {
|
|
Packit |
fabffb |
g_hash_table_unref (countries);
|
|
Packit |
fabffb |
return NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return countries;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* Dump to stdout contents */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
dump_generic (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_print (" username: %s\n", method->username ? method->username : "");
|
|
Packit |
fabffb |
g_print (" password: %s\n", method->password ? method->password : "");
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (method->dns) {
|
|
Packit |
fabffb |
guint i;
|
|
Packit |
fabffb |
const gchar **dns;
|
|
Packit |
fabffb |
GString *dns_str;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
dns = nma_mobile_access_method_get_dns (method);
|
|
Packit |
fabffb |
dns_str = g_string_new (NULL);
|
|
Packit |
fabffb |
for (i = 0; dns[i]; i++)
|
|
Packit |
fabffb |
g_string_append_printf (dns_str, "%s%s", i == 0 ? "" : ", ", dns[i]);
|
|
Packit |
fabffb |
g_print (" dns : %s\n", dns_str->str);
|
|
Packit |
fabffb |
g_string_free (dns_str, TRUE);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_print (" gateway : %s\n", method->gateway ? method->gateway : "");
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
dump_cdma (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_print (" CDMA: %s\n", method->name);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
dump_generic (method);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
dump_3gpp (NMAMobileAccessMethod *method)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_print (" APN: %s (%s)\n", method->name, method->apn);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
dump_generic (method);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
dump_country (gpointer key, gpointer value, gpointer user_data)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GSList *miter, *citer;
|
|
Packit |
fabffb |
NMACountryInfo *country_info = value;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_print ("Country: %s (%s)\n",
|
|
Packit |
fabffb |
country_info->country_code,
|
|
Packit |
fabffb |
country_info->country_name);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (citer = country_info->providers; citer; citer = g_slist_next (citer)) {
|
|
Packit |
fabffb |
NMAMobileProvider *provider = citer->data;
|
|
Packit |
fabffb |
const gchar **mcc_mnc;
|
|
Packit |
fabffb |
const guint *sid;
|
|
Packit |
fabffb |
guint n;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_print (" Provider: %s (%s)\n", provider->name, (const char *) key);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
mcc_mnc = nma_mobile_provider_get_3gpp_mcc_mnc (provider);
|
|
Packit |
fabffb |
if (mcc_mnc) {
|
|
Packit |
fabffb |
for (n = 0; mcc_mnc[n]; n++)
|
|
Packit |
fabffb |
g_print (" MCC/MNC: %s\n", mcc_mnc[n]);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
sid = nma_mobile_provider_get_cdma_sid (provider);
|
|
Packit |
fabffb |
if (sid) {
|
|
Packit |
fabffb |
for (n = 0; sid[n]; n++)
|
|
Packit |
fabffb |
g_print (" SID: %u\n", sid[n]);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (miter = provider->methods; miter; miter = g_slist_next (miter)) {
|
|
Packit |
fabffb |
NMAMobileAccessMethod *method = miter->data;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
switch (method->family) {
|
|
Packit |
fabffb |
case NMA_MOBILE_FAMILY_CDMA:
|
|
Packit |
fabffb |
dump_cdma (method);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case NMA_MOBILE_FAMILY_3GPP:
|
|
Packit |
fabffb |
dump_3gpp (method);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
default:
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
g_print ("\n");
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* Mobile providers database type */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void initable_iface_init (GInitableIface *iface);
|
|
Packit |
fabffb |
static void async_initable_iface_init (GAsyncInitableIface *iface);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
G_DEFINE_TYPE_EXTENDED (NMAMobileProvidersDatabase, nma_mobile_providers_database, G_TYPE_OBJECT, 0,
|
|
Packit |
fabffb |
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
|
|
Packit |
fabffb |
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init))
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
enum {
|
|
Packit |
fabffb |
PROP_0,
|
|
Packit |
fabffb |
PROP_COUNTRY_CODES_PATH,
|
|
Packit |
fabffb |
PROP_SERVICE_PROVIDERS_PATH,
|
|
Packit |
fabffb |
PROP_LAST
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static GParamSpec *properties[PROP_LAST];
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
struct _NMAMobileProvidersDatabasePrivate {
|
|
Packit |
fabffb |
/* Paths to input files */
|
|
Packit |
fabffb |
gchar *country_codes_path;
|
|
Packit |
fabffb |
gchar *service_providers_path;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* The HT with country code as key and NMACountryInfo as value. */
|
|
Packit |
fabffb |
GHashTable *countries;
|
|
Packit |
fabffb |
};
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**********************************/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_get_countries:
|
|
Packit |
fabffb |
* @self: a #NMAMobileProvidersDatabase.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (element-type utf8 NMGtk.CountryInfo) (transfer none): a
|
|
Packit |
fabffb |
* hash table where keys are country names #gchar and values are #NMACountryInfo.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
GHashTable *
|
|
Packit |
fabffb |
nma_mobile_providers_database_get_countries (NMAMobileProvidersDatabase *self)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Warn if the object hasn't been initialized */
|
|
Packit |
fabffb |
g_return_val_if_fail (self->priv->countries != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return self->priv->countries;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_dump:
|
|
Packit |
fabffb |
* @self: a #NMAMobileProvidersDatabase.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
void
|
|
Packit |
fabffb |
nma_mobile_providers_database_dump (NMAMobileProvidersDatabase *self)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self));
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Warn if the object hasn't been initialized */
|
|
Packit |
fabffb |
g_return_if_fail (self->priv->countries != NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_hash_table_foreach (self->priv->countries, dump_country, NULL);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_lookup_country:
|
|
Packit |
fabffb |
* @self: a #NMAMobileProvidersDatabase.
|
|
Packit |
fabffb |
* @country_code: the country code string to look for.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): a #NMACountryInfo or %NULL if not found.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
NMACountryInfo *
|
|
Packit |
fabffb |
nma_mobile_providers_database_lookup_country (NMAMobileProvidersDatabase *self,
|
|
Packit |
fabffb |
const gchar *country_code)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Warn if the object hasn't been initialized */
|
|
Packit |
fabffb |
g_return_val_if_fail (self->priv->countries != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return (NMACountryInfo *) g_hash_table_lookup (self->priv->countries, country_code);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_lookup_3gpp_mcc_mnc:
|
|
Packit |
fabffb |
* @self: a #NMAMobileProvidersDatabase.
|
|
Packit |
fabffb |
* @mccmnc: the MCC/MNC string to look for.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): a #NMAMobileProvider or %NULL if not found.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
NMAMobileProvider *
|
|
Packit |
fabffb |
nma_mobile_providers_database_lookup_3gpp_mcc_mnc (NMAMobileProvidersDatabase *self,
|
|
Packit |
fabffb |
const gchar *mccmnc)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GHashTableIter iter;
|
|
Packit |
fabffb |
gpointer value;
|
|
Packit |
fabffb |
GSList *piter;
|
|
Packit |
fabffb |
NMAMobileProvider *provider_match_2mnc = NULL;
|
|
Packit |
fabffb |
guint mccmnc_len;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
|
|
Packit |
fabffb |
g_return_val_if_fail (mccmnc != NULL, NULL);
|
|
Packit |
fabffb |
/* Warn if the object hasn't been initialized */
|
|
Packit |
fabffb |
g_return_val_if_fail (self->priv->countries != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Expect only 5 or 6 digit MCCMNC strings */
|
|
Packit |
fabffb |
mccmnc_len = strlen (mccmnc);
|
|
Packit |
fabffb |
if (mccmnc_len != 5 && mccmnc_len != 6)
|
|
Packit |
fabffb |
return NULL;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_hash_table_iter_init (&iter, self->priv->countries);
|
|
Packit |
fabffb |
/* Search through each country */
|
|
Packit |
fabffb |
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
|
Packit |
fabffb |
NMACountryInfo *country_info = value;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Search through each country's providers */
|
|
Packit |
fabffb |
for (piter = nma_country_info_get_providers (country_info);
|
|
Packit |
fabffb |
piter;
|
|
Packit |
fabffb |
piter = g_slist_next (piter)) {
|
|
Packit |
fabffb |
NMAMobileProvider *provider = piter->data;
|
|
Packit |
fabffb |
const gchar **mccmnc_list;
|
|
Packit |
fabffb |
guint i;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Search through MCC/MNC list */
|
|
Packit |
fabffb |
mccmnc_list = nma_mobile_provider_get_3gpp_mcc_mnc (provider);
|
|
Packit |
fabffb |
if (!mccmnc_list)
|
|
Packit |
fabffb |
continue;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (i = 0; mccmnc_list[i]; i++) {
|
|
Packit |
fabffb |
const gchar *mccmnc_iter;
|
|
Packit |
fabffb |
guint mccmnc_iter_len;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
mccmnc_iter = mccmnc_list[i];
|
|
Packit |
fabffb |
mccmnc_iter_len = strlen (mccmnc_iter);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Match both 2-digit and 3-digit MNC; prefer a
|
|
Packit |
fabffb |
* 3-digit match if found, otherwise a 2-digit one.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (strncmp (mccmnc_iter, mccmnc, 3))
|
|
Packit |
fabffb |
/* MCC was wrong */
|
|
Packit |
fabffb |
continue;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Now we have the following match cases, examples given:
|
|
Packit |
fabffb |
* a) input: 123/456 --> iter: 123/456 (3-digit match)
|
|
Packit |
fabffb |
* b) input: 123/45 --> iter: 123/045 (3-digit match)
|
|
Packit |
fabffb |
* c) input: 123/045 --> iter: 123/45 (2-digit match)
|
|
Packit |
fabffb |
* d) input: 123/45 --> iter: 123/45 (2-digit match)
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (mccmnc_iter_len == 6) {
|
|
Packit |
fabffb |
/* Covers cases a) and b) */
|
|
Packit |
fabffb |
if ( (mccmnc_len == 6 && !strncmp (mccmnc + 3, mccmnc_iter + 3, 3))
|
|
Packit |
fabffb |
|| (mccmnc_len == 5 && mccmnc_iter[3] == '0' && !strncmp (mccmnc + 3, mccmnc_iter + 4, 2)))
|
|
Packit |
fabffb |
/* 3-digit MNC match! */
|
|
Packit |
fabffb |
return provider;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* MNC was wrong */
|
|
Packit |
fabffb |
continue;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if ( !provider_match_2mnc
|
|
Packit |
fabffb |
&& mccmnc_iter_len == 5) {
|
|
Packit |
fabffb |
if ( (mccmnc_len == 5 && !strncmp (mccmnc + 3, mccmnc_iter + 3, 2))
|
|
Packit |
fabffb |
|| (mccmnc_len == 6 && mccmnc[3] == '0' && !strncmp (mccmnc + 4, mccmnc_iter + 3, 2))) {
|
|
Packit |
fabffb |
/* Store the 2-digit MNC match, but keep looking,
|
|
Packit |
fabffb |
* we may have a 3-digit MNC match */
|
|
Packit |
fabffb |
provider_match_2mnc = provider;
|
|
Packit |
fabffb |
continue;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* MNC was wrong */
|
|
Packit |
fabffb |
continue;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return provider_match_2mnc;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_lookup_cdma_sid:
|
|
Packit |
fabffb |
* @self: a #NMAMobileProvidersDatabase.
|
|
Packit |
fabffb |
* @sid: the SID to look for.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer none): a #NMAMobileProvider, or %NULL if not found.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
NMAMobileProvider *
|
|
Packit |
fabffb |
nma_mobile_providers_database_lookup_cdma_sid (NMAMobileProvidersDatabase *self,
|
|
Packit |
fabffb |
guint32 sid)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GHashTableIter iter;
|
|
Packit |
fabffb |
gpointer value;
|
|
Packit |
fabffb |
GSList *piter;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
|
|
Packit |
fabffb |
g_return_val_if_fail (sid > 0, NULL);
|
|
Packit |
fabffb |
/* Warn if the object hasn't been initialized */
|
|
Packit |
fabffb |
g_return_val_if_fail (self->priv->countries != NULL, NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_hash_table_iter_init (&iter, self->priv->countries);
|
|
Packit |
fabffb |
/* Search through each country */
|
|
Packit |
fabffb |
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
|
Packit |
fabffb |
NMACountryInfo *country_info = value;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Search through each country's providers */
|
|
Packit |
fabffb |
for (piter = nma_country_info_get_providers (country_info);
|
|
Packit |
fabffb |
piter;
|
|
Packit |
fabffb |
piter = g_slist_next (piter)) {
|
|
Packit |
fabffb |
NMAMobileProvider *provider = piter->data;
|
|
Packit |
fabffb |
const guint32 *sid_list;
|
|
Packit |
fabffb |
guint i;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Search through CDMA SID list */
|
|
Packit |
fabffb |
sid_list = nma_mobile_provider_get_cdma_sid (provider);
|
|
Packit |
fabffb |
if (!sid_list)
|
|
Packit |
fabffb |
continue;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
for (i = 0; sid_list[i]; i++) {
|
|
Packit |
fabffb |
if (sid == sid_list[i])
|
|
Packit |
fabffb |
return provider;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**********************************/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static gboolean
|
|
Packit |
fabffb |
initable_init_sync (GInitable *initable,
|
|
Packit |
fabffb |
GCancellable *cancellable,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (initable);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Parse the files */
|
|
Packit |
fabffb |
self->priv->countries = mobile_providers_parse_sync (self->priv->country_codes_path,
|
|
Packit |
fabffb |
self->priv->service_providers_path,
|
|
Packit |
fabffb |
cancellable,
|
|
Packit |
fabffb |
error);
|
|
Packit |
fabffb |
if (!self->priv->countries)
|
|
Packit |
fabffb |
return FALSE;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* All good */
|
|
Packit |
fabffb |
return TRUE;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**********************************/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_new:
|
|
Packit |
fabffb |
* @country_codes: (allow-none): Path to the country codes file.
|
|
Packit |
fabffb |
* @service_providers: (allow-none): Path to the service providers file.
|
|
Packit |
fabffb |
* @cancellable: (allow-none): A #GCancellable or %NULL.
|
|
Packit |
fabffb |
* @callback: A #GAsyncReadyCallback to call when the request is satisfied.
|
|
Packit |
fabffb |
* @user_data: User data to pass to @callback.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
void
|
|
Packit |
fabffb |
nma_mobile_providers_database_new (const gchar *country_codes,
|
|
Packit |
fabffb |
const gchar *service_providers,
|
|
Packit |
fabffb |
GCancellable *cancellable,
|
|
Packit |
fabffb |
GAsyncReadyCallback callback,
|
|
Packit |
fabffb |
gpointer user_data)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
g_async_initable_new_async (NMA_TYPE_MOBILE_PROVIDERS_DATABASE,
|
|
Packit |
fabffb |
G_PRIORITY_DEFAULT,
|
|
Packit |
fabffb |
cancellable,
|
|
Packit |
fabffb |
callback,
|
|
Packit |
fabffb |
user_data,
|
|
Packit |
fabffb |
"country-codes", country_codes,
|
|
Packit |
fabffb |
"service-providers", service_providers,
|
|
Packit |
fabffb |
NULL);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_new_finish:
|
|
Packit |
fabffb |
* @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to nma_mobile_providers_database_new().
|
|
Packit |
fabffb |
* @error: Return location for error or %NULL.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer full) (type NMAMobileProvidersDatabase): The constructed object or %NULL if @error is set.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
NMAMobileProvidersDatabase *
|
|
Packit |
fabffb |
nma_mobile_providers_database_new_finish (GAsyncResult *res,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GObject *initable;
|
|
Packit |
fabffb |
GObject *out;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
initable = g_async_result_get_source_object (res);
|
|
Packit |
fabffb |
out = g_async_initable_new_finish (G_ASYNC_INITABLE (initable), res, error);
|
|
Packit |
fabffb |
g_object_unref (initable);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return out ? NMA_MOBILE_PROVIDERS_DATABASE (out) : NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_database_new_sync:
|
|
Packit |
fabffb |
* @country_codes: (allow-none): Path to the country codes file.
|
|
Packit |
fabffb |
* @service_providers: (allow-none): Path to the service providers file.
|
|
Packit |
fabffb |
* @cancellable: (allow-none): A #GCancellable or %NULL.
|
|
Packit |
fabffb |
* @error: Return location for error or %NULL.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: (transfer full) (type NMAMobileProvidersDatabase): The constructed object or %NULL if @error is set.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
NMAMobileProvidersDatabase *
|
|
Packit |
fabffb |
nma_mobile_providers_database_new_sync (const gchar *country_codes,
|
|
Packit |
fabffb |
const gchar *service_providers,
|
|
Packit |
fabffb |
GCancellable *cancellable,
|
|
Packit |
fabffb |
GError **error)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GObject *out;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
out = g_initable_new (NMA_TYPE_MOBILE_PROVIDERS_DATABASE,
|
|
Packit |
fabffb |
cancellable,
|
|
Packit |
fabffb |
error,
|
|
Packit |
fabffb |
"country-codes", country_codes,
|
|
Packit |
fabffb |
"service-providers", service_providers,
|
|
Packit |
fabffb |
NULL);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
return out ? NMA_MOBILE_PROVIDERS_DATABASE (out) : NULL;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**********************************/
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
set_property (GObject *object,
|
|
Packit |
fabffb |
guint prop_id,
|
|
Packit |
fabffb |
const GValue *value,
|
|
Packit |
fabffb |
GParamSpec *pspec)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (object);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
switch (prop_id) {
|
|
Packit |
fabffb |
case PROP_COUNTRY_CODES_PATH:
|
|
Packit |
fabffb |
self->priv->country_codes_path = g_value_dup_string (value);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PROP_SERVICE_PROVIDERS_PATH:
|
|
Packit |
fabffb |
self->priv->service_providers_path = g_value_dup_string (value);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
default:
|
|
Packit |
fabffb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
get_property (GObject *object,
|
|
Packit |
fabffb |
guint prop_id,
|
|
Packit |
fabffb |
GValue *value,
|
|
Packit |
fabffb |
GParamSpec *pspec)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (object);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
switch (prop_id) {
|
|
Packit |
fabffb |
case PROP_COUNTRY_CODES_PATH:
|
|
Packit |
fabffb |
g_value_set_string (value, self->priv->country_codes_path);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
case PROP_SERVICE_PROVIDERS_PATH:
|
|
Packit |
fabffb |
g_value_set_string (value, self->priv->service_providers_path);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
default:
|
|
Packit |
fabffb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit |
fabffb |
break;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
nma_mobile_providers_database_init (NMAMobileProvidersDatabase *self)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
/* Setup private data */
|
|
Packit |
fabffb |
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
|
Packit |
fabffb |
NMA_TYPE_MOBILE_PROVIDERS_DATABASE,
|
|
Packit |
fabffb |
NMAMobileProvidersDatabasePrivate);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
finalize (GObject *object)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (object);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_free (self->priv->country_codes_path);
|
|
Packit |
fabffb |
g_free (self->priv->service_providers_path);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
if (self->priv->countries)
|
|
Packit |
fabffb |
g_hash_table_unref (self->priv->countries);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
G_OBJECT_CLASS (nma_mobile_providers_database_parent_class)->finalize (object);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
initable_iface_init (GInitableIface *iface)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
iface->init = initable_init_sync;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
async_initable_iface_init (GAsyncInitableIface *iface)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
/* Just use defaults (run sync init() in a thread) */
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
static void
|
|
Packit |
fabffb |
nma_mobile_providers_database_class_init (NMAMobileProvidersDatabaseClass *klass)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_type_class_add_private (object_class, sizeof (NMAMobileProvidersDatabasePrivate));
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* Virtual methods */
|
|
Packit |
fabffb |
object_class->get_property = get_property;
|
|
Packit |
fabffb |
object_class->set_property = set_property;
|
|
Packit |
fabffb |
object_class->finalize = finalize;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
properties[PROP_COUNTRY_CODES_PATH] =
|
|
Packit |
fabffb |
g_param_spec_string ("country-codes",
|
|
Packit |
fabffb |
"Country Codes",
|
|
Packit |
fabffb |
"Path to the country codes file",
|
|
Packit |
fabffb |
NULL,
|
|
Packit |
fabffb |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
|
Packit |
fabffb |
g_object_class_install_property (object_class, PROP_COUNTRY_CODES_PATH, properties[PROP_COUNTRY_CODES_PATH]);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
properties[PROP_SERVICE_PROVIDERS_PATH] =
|
|
Packit |
fabffb |
g_param_spec_string ("service-providers",
|
|
Packit |
fabffb |
"Service Providers",
|
|
Packit |
fabffb |
"Path to the service providers file",
|
|
Packit |
fabffb |
NULL,
|
|
Packit |
fabffb |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
|
Packit |
fabffb |
g_object_class_install_property (object_class, PROP_SERVICE_PROVIDERS_PATH, properties[PROP_SERVICE_PROVIDERS_PATH]);
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/******************************************************************************/
|
|
Packit |
fabffb |
/* Utils */
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/**
|
|
Packit |
fabffb |
* nma_mobile_providers_split_3gpp_mcc_mnc:
|
|
Packit |
fabffb |
* @mccmnc: input MCCMNC string.
|
|
Packit |
fabffb |
* @mcc: (out) (transfer full): the MCC.
|
|
Packit |
fabffb |
* @mnc: (out) (transfer full): the MNC.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Splits the input MCCMNC string into separate MCC and MNC strings.
|
|
Packit |
fabffb |
*
|
|
Packit |
fabffb |
* Returns: %TRUE if correctly split and @mcc and @mnc are set; %FALSE otherwise.
|
|
Packit |
fabffb |
*/
|
|
Packit |
fabffb |
gboolean
|
|
Packit |
fabffb |
nma_mobile_providers_split_3gpp_mcc_mnc (const gchar *mccmnc,
|
|
Packit |
fabffb |
gchar **mcc,
|
|
Packit |
fabffb |
gchar **mnc)
|
|
Packit |
fabffb |
{
|
|
Packit |
fabffb |
gint len;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
g_return_val_if_fail (mccmnc != NULL, FALSE);
|
|
Packit |
fabffb |
g_return_val_if_fail (mcc != NULL, FALSE);
|
|
Packit |
fabffb |
g_return_val_if_fail (mnc != NULL, FALSE);
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
len = strlen (mccmnc);
|
|
Packit |
fabffb |
if (len != 5 && len != 6)
|
|
Packit |
fabffb |
return FALSE;
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
/* MCCMNC is all digits */
|
|
Packit |
fabffb |
while (len > 0) {
|
|
Packit |
fabffb |
if (!g_ascii_isdigit (mccmnc[--len]))
|
|
Packit |
fabffb |
return FALSE;
|
|
Packit |
fabffb |
}
|
|
Packit |
fabffb |
|
|
Packit |
fabffb |
*mcc = g_strndup (mccmnc, 3);
|
|
Packit |
fabffb |
*mnc = g_strdup (mccmnc + 3);
|
|
Packit |
fabffb |
return TRUE;
|
|
Packit |
fabffb |
}
|