/*
* Copyright (C) 2014 Akihiro Tsukada
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*
*/
#include
#include "libdvbv5/countries.h"
#include
#include
#include
#include
struct cCountry {
enum dvb_country_t id;
const char *alpha2_name;
const char *alpha3_name;
const char *short_name;
};
/*
* constants from ISO 3166-1.
* sorted alphabetically by two-letter(alpha-2) country name and
* in the same order with enum dvb_country_t.
*/
static const struct cCountry country_list[] = {
/* id, alpha-2, alpha-3, short name */
{ COUNTRY_UNKNOWN, "", "", "(Unknown Country)" },
{ AD, "AD", "AND", "Andorra" },
{ AE, "AE", "ARE", "United Arab Emirates" },
{ AF, "AF", "AFG", "Afghanistan" },
{ AG, "AG", "ATG", "Antigua and Barbuda" },
{ AI, "AI", "AIA", "Anguilla" },
{ AL, "AL", "ALB", "Albania" },
{ AM, "AM", "ARM", "Armenia" },
{ AO, "AO", "AGO", "Angola" },
{ AQ, "AQ", "ATA", "Antarctica" },
{ AR, "AR", "ARG", "Argentina" },
{ AS, "AS", "ASM", "American Samoa" },
{ AT, "AT", "AUT", "Austria" },
{ AU, "AU", "AUS", "Australia" },
{ AW, "AW", "ABW", "Aruba" },
{ AX, "AX", "ALA", "Aland Islands" },
{ AZ, "AZ", "AZE", "Azerbaijan" },
{ BA, "BA", "BIH", "Bosnia and Herzegovina" },
{ BB, "BB", "BRB", "Barbados" },
{ BD, "BD", "BGD", "Bangladesh" },
{ BE, "BE", "BEL", "Belgium" },
{ BF, "BF", "BFA", "Burkina Faso" },
{ BG, "BG", "BGR", "Bulgaria" },
{ BH, "BH", "BHR", "Bahrain" },
{ BI, "BI", "BDI", "Burundi" },
{ BJ, "BJ", "BEN", "Benin" },
{ BL, "BL", "534", "Saint Barthelemy" },
{ BM, "BM", "BMU", "Bermuda" },
{ BN, "BN", "BRN", "Brunei Darussalam" },
{ BO, "BO", "BOL", "Plurinational State of Bolivia" },
{ BQ, "BQ", "BES", "Bonaire, Saint Eustatius and Saba" },
{ BR, "BR", "BRA", "Brazil" },
{ BS, "BS", "BHS", "Bahamas" },
{ BT, "BT", "BTN", "Bhutan" },
{ BV, "BV", "BVT", "Bouvet Island" },
{ BW, "BW", "BWA", "Botswana" },
{ BY, "BY", "BLR", "Belarus" },
{ BZ, "BZ", "BLZ", "Belize" },
{ CA, "CA", "CAN", "Canada" },
{ CC, "CC", "CCK", "Cocos (Keeling) Islands" },
{ CD, "CD", "COD", "The Democratic Republic of the Congo" },
{ CF, "CF", "CAF", "Central African Republic" },
{ CG, "CG", "COG", "Congo" },
{ CH, "CH", "CHE", "Switzerland" },
{ CI, "CI", "CIV", "Cote d'Ivoire" },
{ CK, "CK", "COK", "Cook Islands" },
{ CL, "CL", "CHL", "Chile" },
{ CM, "CM", "CMR", "Cameroon" },
{ CN, "CN", "CHN", "China" },
{ CO, "CO", "COL", "Colombia" },
{ CR, "CR", "CRI", "Costa Rica" },
{ CU, "CU", "CUB", "Cuba" },
{ CV, "CV", "CPV", "Cape Verde" },
{ CW, "CW", "CUW", "Curacao" },
{ CX, "CX", "CXR", "Christmas Island" },
{ CY, "CY", "CYP", "Cyprus" },
{ CZ, "CZ", "CZE", "Czech Republic" },
{ DE, "DE", "DEU", "Germany" },
{ DJ, "DJ", "DJI", "Djibouti" },
{ DK, "DK", "DNK", "Denmark" },
{ DM, "DM", "DMA", "Dominica" },
{ DO, "DO", "DOM", "Dominican Republic" },
{ DZ, "DZ", "DZA", "Algeria" },
{ EC, "EC", "ECU", "Ecuador" },
{ EE, "EE", "EST", "Estonia" },
{ EG, "EG", "EGY", "Egypt" },
{ EH, "EH", "ESH", "Western Sahara" },
{ ER, "ER", "ERI", "Eritrea" },
{ ES, "ES", "ESP", "Spain" },
{ ET, "ET", "ETH", "Ethiopia" },
{ FI, "FI", "FIN", "Finland" },
{ FJ, "FJ", "FJI", "Fiji" },
{ FK, "FK", "FLK", "Falkland Islands (Malvinas)" },
{ FM, "FM", "FSM", "Federated States of Micronesia" },
{ FO, "FO", "534", "Faroe Islands" },
{ FR, "FR", "FRA", "France" },
{ GA, "GA", "GAB", "Gabon" },
{ GB, "GB", "GBR", "United Kingdom" },
{ GD, "GD", "GRD", "Grenada" },
{ GE, "GE", "GEO", "Georgia" },
{ GF, "GF", "GUF", "French Guiana" },
{ GG, "GG", "GGY", "Guernsey" },
{ GH, "GH", "GHA", "Ghana" },
{ GI, "GI", "GIB", "Gibraltar" },
{ GL, "GL", "GRL", "Greenland" },
{ GM, "GM", "GMB", "Gambia" },
{ GN, "GN", "GIN", "Guinea" },
{ GP, "GP", "GLP", "Guadeloupe" },
{ GQ, "GQ", "GNQ", "Equatorial Guinea" },
{ GR, "GR", "GRC", "Greece" },
{ GS, "GS", "SGS", "South Georgia and the South Sandwich Islands" },
{ GT, "GT", "GTM", "Guatemala" },
{ GU, "GU", "GUM", "Guam" },
{ GW, "GW", "GNB", "Guinea-Bissau" },
{ GY, "GY", "GUY", "Guyana" },
{ HK, "HK", "HKG", "Hong Kong" },
{ HM, "HM", "HMD", "Heard Island and McDonald Islands" },
{ HN, "HN", "HND", "Honduras" },
{ HR, "HR", "HRV", "Croatia" },
{ HT, "HT", "HTI", "Haiti" },
{ HU, "HU", "HUN", "Hungary" },
{ ID, "ID", "IDN", "Indonesia" },
{ IE, "IE", "IRL", "Ireland" },
{ IL, "IL", "ISR", "Israel" },
{ IM, "IM", "IMN", "Isle of Man" },
{ IN, "IN", "IND", "India" },
{ IO, "IO", "IOT", "British Indian Ocean Territory" },
{ IQ, "IQ", "IRQ", "Iraq" },
{ IR, "IR", "IRN", "Islamic Republic of Iran" },
{ IS, "IS", "ISL", "Iceland" },
{ IT, "IT", "ITA", "Italy" },
{ JE, "JE", "JEY", "Jersey" },
{ JM, "JM", "JAM", "Jamaica" },
{ JO, "JO", "JOR", "Jordan" },
{ JP, "JP", "JPN", "Japan" },
{ KE, "KE", "KEN", "Kenya" },
{ KG, "KG", "KGZ", "Kyrgyzstan" },
{ KH, "KH", "KHM", "Cambodia" },
{ KI, "KI", "KIR", "Kiribati" },
{ KM, "KM", "COM", "Comoros" },
{ KN, "KN", "KNA", "Saint Kitts and Nevis" },
{ KP, "KP", "PRK", "Democratic People's Republic of Korea" },
{ KR, "KR", "KOR", "Republic of Korea" },
{ KW, "KW", "KWT", "Kuwait" },
{ KY, "KY", "CYM", "Cayman Islands" },
{ KZ, "KZ", "KAZ", "Kazakhstan" },
{ LA, "LA", "LAO", "Lao People's Democratic Republic" },
{ LB, "LB", "LBN", "Lebanon" },
{ LC, "LC", "LCA", "Saint Lucia" },
{ LI, "LI", "LIE", "Liechtenstein" },
{ LK, "LK", "LKA", "Sri Lanka" },
{ LR, "LR", "LBR", "Liberia" },
{ LS, "LS", "LSO", "Lesotho" },
{ LT, "LT", "LTU", "Lithuania" },
{ LU, "LU", "LUX", "Luxembourg" },
{ LV, "LV", "LVA", "Latvia" },
{ LY, "LY", "LBY", "Libyan Arab Jamahiriya" },
{ MA, "MA", "MAR", "Morocco" },
{ MC, "MC", "MCO", "Monaco" },
{ MD, "MD", "MDA", "Republic of Moldova" },
{ ME, "ME", "MNE", "Montenegro" },
{ MF, "MF", "MAF", "Saint Martin (French part)" },
{ MG, "MG", "MDG", "Madagascar" },
{ MH, "MH", "MHL", "Marshall Islands" },
{ MK, "MK", "MKD", "The Former Yugoslav Republic of Macedonia" },
{ ML, "ML", "MLI", "Mali" },
{ MM, "MM", "MMR", "Myanmar" },
{ MN, "MN", "MNG", "Mongolia" },
{ MO, "MO", "MAC", "Macao" },
{ MP, "MP", "MNP", "Northern Mariana Islands" },
{ MQ, "MQ", "MTQ", "Martinique" },
{ MR, "MR", "MRT", "Mauritania" },
{ MS, "MS", "MSR", "Montserrat" },
{ MT, "MT", "MLT", "Malta" },
{ MU, "MU", "MUS", "Mauritius" },
{ MV, "MV", "MDV", "Maldives" },
{ MW, "MW", "MWI", "Malawi" },
{ MX, "MX", "MEX", "Mexico" },
{ MY, "MY", "MYS", "Malaysia" },
{ MZ, "MZ", "MOZ", "Mozambique" },
{ NA, "NA", "NAM", "Namibia" },
{ NC, "NC", "NCL", "New Caledonia" },
{ NE, "NE", "NER", "Niger" },
{ NF, "NF", "NFK", "Norfolk Island" },
{ NG, "NG", "NGA", "Nigeria" },
{ NI, "NI", "NIC", "Nicaragua" },
{ NL, "NL", "NLD", "Netherlands" },
{ NO, "NO", "NOR", "Norway" },
{ NP, "NP", "NPL", "Nepal" },
{ NR, "NR", "NRU", "Nauru" },
{ NU, "NU", "NIU", "Niue" },
{ NZ, "NZ", "NZL", "New Zealand" },
{ OM, "OM", "OMN", "Oman" },
{ PA, "PA", "PAN", "Panama" },
{ PE, "PE", "PER", "Peru" },
{ PF, "PF", "PYF", "French Polynesia" },
{ PG, "PG", "PNG", "Papua New Guinea" },
{ PH, "PH", "PHL", "Philippines" },
{ PK, "PK", "PAK", "Pakistan" },
{ PL, "PL", "POL", "Poland" },
{ PM, "PM", "SPM", "Saint Pierre and Miquelon" },
{ PN, "PN", "PCN", "Pitcairn" },
{ PR, "PR", "PRI", "Puerto Rico" },
{ PS, "PS", "PSE", "Occupied Palestinian Territory" },
{ PT, "PT", "PRT", "Portugal" },
{ PW, "PW", "PLW", "Palau" },
{ PY, "PY", "PRY", "Paraguay" },
{ QA, "QA", "QAT", "Qatar" },
{ RE, "RE", "REU", "Reunion" },
{ RO, "RO", "ROU", "Romania" },
{ RS, "RS", "SRB", "Serbia" },
{ RU, "RU", "RUS", "Russian Federation" },
{ RW, "RW", "RWA", "Rwanda" },
{ SA, "SA", "SAU", "Saudi Arabia" },
{ SB, "SB", "SLB", "Solomon Islands" },
{ SC, "SC", "SYC", "Seychelles" },
{ SD, "SD", "SDN", "Sudan" },
{ SE, "SE", "SWE", "Sweden" },
{ SG, "SG", "SGP", "Singapore" },
{ SH, "SH", "SHN", "Saint Helena, Ascension and Tristan da Cunha" },
{ SI, "SI", "SVN", "Slovenia" },
{ SJ, "SJ", "534", "Svalbard and Jan Mayen" },
{ SK, "SK", "SVK", "Slovakia" },
{ SL, "SL", "SLE", "Sierra Leone" },
{ SM, "SM", "SMR", "San Marino" },
{ SN, "SN", "SEN", "Senegal" },
{ SO, "SO", "SOM", "Somalia" },
{ SR, "SR", "SUR", "Suriname" },
{ SS, "SS", "SSD", "South Sudan" },
{ ST, "ST", "STP", "Sao Tome and Principe" },
{ SV, "SV", "SLV", "El Salvador" },
{ SX, "SX", "SXM", "Sint Maarten (Dutch part)" },
{ SY, "SY", "SYR", "Syrian Arab Republic" },
{ SZ, "SZ", "SWZ", "Swaziland" },
{ TC, "TC", "TCA", "Turks and Caicos Islands" },
{ TD, "TD", "TCD", "Chad" },
{ TF, "TF", "ATF", "French Southern Territories" },
{ TG, "TG", "TGO", "Togo" },
{ TH, "TH", "THA", "Thailand" },
{ TJ, "TJ", "TJK", "Tajikistan" },
{ TK, "TK", "TKL", "Tokelau" },
{ TL, "TL", "TLS", "Timor-Leste" },
{ TM, "TM", "TKM", "Turkmenistan" },
{ TN, "TN", "TUN", "Tunisia" },
{ TO, "TO", "TON", "Tonga" },
{ TR, "TR", "TUR", "Turkey" },
{ TT, "TT", "TTO", "Trinidad and Tobago" },
{ TV, "TV", "TUV", "Tuvalu" },
{ TW, "TW", "TWN", "Taiwan, Province of China" },
{ TZ, "TZ", "TZA", "United Republic of Tanzania" },
{ UA, "UA", "UKR", "Ukraine" },
{ UG, "UG", "UGA", "Uganda" },
{ UM, "UM", "UMI", "United States Minor Outlying Islands" },
{ US, "US", "USA", "United States" },
{ UY, "UY", "URY", "Uruguay" },
{ UZ, "UZ", "UZB", "Uzbekistan" },
{ VA, "VA", "VAT", "Holy See (Vatican City State)" },
{ VC, "VC", "VCT", "Saint Vincent and The Grenadines" },
{ VE, "VE", "VEN", "Bolivarian Republic of Venezuela" },
{ VG, "VG", "VGB", "British Virgin Islands" },
{ VI, "VI", "VIR", "U.S. Virgin Islands" },
{ VN, "VN", "VNM", "Viet Nam" },
{ VU, "VU", "VUT", "Vanuatu" },
{ WF, "WF", "WLF", "Wallis and Futuna" },
{ WS, "WS", "WSM", "Samoa" },
{ YE, "YE", "YEM", "Yemen" },
{ YT, "YT", "MYT", "Mayotte" },
{ ZA, "ZA", "ZAF", "South Africa" },
{ ZM, "ZM", "ZMB", "Zambia" },
{ ZW, "ZW", "ZWE", "Zimbabwe" },
};
#define COUNTRY_COUNT (sizeof(country_list)/sizeof(struct cCountry))
static int cmp_alpha2(const void *key, const void *b)
{
const struct cCountry *elem = b;
return strcasecmp(key, elem->alpha2_name);
}
static int cmp_alpha3(const void *key, const void *b)
{
const struct cCountry *elem = b;
return strcasecmp(key, elem->alpha3_name);
}
/* convert ISO 3166-1 two-letter constant (alpha-2)
* to index number
* return 0(COUNTRY_UNKNOWN) if not found.
*/
enum dvb_country_t dvb_country_a2_to_id(const char *name)
{
const struct cCountry *p;
p = bsearch(name, country_list,
COUNTRY_COUNT, sizeof(country_list[0]), cmp_alpha2);
return p ? p->id : COUNTRY_UNKNOWN;
}
/* convert ISO 3166-1 three-letter constant (alpha-3)
* to index number
* return 0(COUNTRY_UNKNOWN) if not found.
*/
enum dvb_country_t dvb_country_a3_to_id(const char *name)
{
const struct cCountry *p;
p = bsearch(name, country_list,
COUNTRY_COUNT, sizeof(country_list[0]), cmp_alpha3);
return p ? p->id : COUNTRY_UNKNOWN;
}
/* convert index number
* to ISO 3166-1 two-letter constant
* return NULL if not found.
*/
const char *dvb_country_to_2letters(int idx)
{
return (idx >= 1 && idx < COUNTRY_COUNT)
? country_list[idx].alpha2_name : NULL;
}
/* convert index number
* to ISO 3166-1 three-letter constant
* return NULL if not found.
*/
const char *dvb_country_to_3letters(int idx)
{
return (idx >= 1 && idx < COUNTRY_COUNT)
? country_list[idx].alpha3_name : NULL;
}
/* convert index number
* to country name
* return NULL if not found.
*/
const char *dvb_country_to_name(int idx)
{
return (idx >= 1 && idx < COUNTRY_COUNT)
? country_list[idx].short_name : NULL;
}
#ifndef HAVE_SECURE_GETENV
# ifdef HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
# else
# define secure_getenv getenv
# endif
#endif
#define MIN(X,Y) (X < Y ? X : Y)
static const char * cats[] = {
"LC_ALL", "LC_CTYPE", "LC_COLLATE", "LC_MESSAGES", "LANG"
};
enum dvb_country_t dvb_guess_user_country(void)
{
char * buf, * pch, * pbuf;
unsigned cat;
enum dvb_country_t id = COUNTRY_UNKNOWN;
for (cat = 0; cat < sizeof(cats)/sizeof(cats[0]); cat++) {
// the returned char * should be "C", "POSIX" or something valid.
// If valid, we can only *guess* which format is returned.
// Assume here something like "de_DE.iso8859-1@euro" or "de_DE.utf-8"
buf = secure_getenv(cats[cat]);
if (! buf || strlen(buf) < 2)
continue;
if (! strncmp(buf, "POSIX", MIN(strlen(buf), 5)) ||
! (strncmp(buf, "en", MIN(strlen(buf), 2)) && !isalpha(buf[2])) )
continue;
buf = strdup(buf);
pbuf= buf;
// assuming 'language_country.encoding@variant'
// country after '_', if given
if ((pch = strchr(buf, '_')))
pbuf = pch + 1;
// remove all after '@', including '@'
if ((pch = strchr(pbuf, '@')))
*pch = 0;
// remove all after '.', including '.'
if ((pch = strchr(pbuf, '.')))
*pch = 0;
if (strlen(pbuf) == 2)
id = dvb_country_a2_to_id(pbuf);
free(buf);
if (id != COUNTRY_UNKNOWN)
return id;
}
return COUNTRY_UNKNOWN;
}