diff options
Diffstat (limited to 'scripts/create-mcc-mnc-table.py')
| -rw-r--r-- | scripts/create-mcc-mnc-table.py | 373 | 
1 files changed, 278 insertions, 95 deletions
| diff --git a/scripts/create-mcc-mnc-table.py b/scripts/create-mcc-mnc-table.py index 761454c..c7afb56 100644 --- a/scripts/create-mcc-mnc-table.py +++ b/scripts/create-mcc-mnc-table.py @@ -1,106 +1,289 @@ -#Generates MTS_IO_MccMncTable.cpp file by pulling latest MCC/MNC values -#from http://mcc-mnc.com +#!/usr/bin/env python3 -#Original Source Idea: https://github.com/musalbas/mcc-mnc-table +""" +Generates MTS_IO_MccMncTable.cpp file by pulling latest MCC/MNC values +from http://mcc-mnc.com or the csv file. +Original Source Idea: https://github.com/musalbas/mcc-mnc-table +""" + +########################################################################################################################  import re -import urllib2 +import urllib.request +import urllib.parse  import datetime +import csv +import argparse + +from typing import Iterable, Generator, Optional, TextIO +from collections import namedtuple + +######################################################################################################################## + +PREAMBLE_TEMPLATE = """\ +/* + * Copyright (C) 2015 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io 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. + * + * libmts-io 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 libmts-io.  If not, see <http://www.gnu.org/licenses/>. + * + */ + +/*! + \\file MTS_IO_MccMncTable.cpp + \\brief Auto-Generated MCC-MNC Lookup Table + \\date {today} + \\author sgodinez + + An Auto-Generated MCC-MNC Lookup Table +*/ +""" + +GENERAL_CODE = """\ +#include <mts/MTS_IO_MccMncTable.h> +#include <mts/MTS_Logger.h> +#include <mts/MTS_Text.h> + +using namespace MTS::IO; + +MTS::AutoPtr<MTS::Lock> MccMncTable::m_apLock(new MTS::Lock()); +MccMncTable* MccMncTable::m_pInstance = NULL; + +MccMncTable* MccMncTable::getInstance() { +    if(m_pInstance == NULL) { +        m_apLock->lock(); +        if (m_pInstance == NULL) { +            m_pInstance = new MccMncTable(); +        } +        m_apLock->unlock(); +    } +    return m_pInstance; +} + +MccMncTable::MccMncTable() { +    createTable(); +} + +Json::Value MccMncTable::lookup(const std::string& sMcc, const std::string& sMnc) { +    uint32_t iMcc, iMnc; +    std::string sNormalizedMnc = sMnc; +    printTrace("[MCCMNC] MCCx[%s] MNCx[%s]", sMcc.c_str(), sMnc.c_str()); +    if (sMnc.length() == 2) { +        sNormalizedMnc += 'f'; +    } +    if (!MTS::Text::parseHex(iMcc, sMcc)) { return Json::Value::null; } +    if (!MTS::Text::parseHex(iMnc, sNormalizedMnc)) { return Json::Value::null; } +    printTrace("[MCCMNC] MCC0X[%d] MNC0X[%d]", iMcc, iMnc); +    if (m_mTable.count(iMcc)) { +        if(m_mTable[iMcc].count(iMnc)) { +            std::vector<std::string> vJson = MTS::Text::split(m_mTable[iMcc][iMnc], ','); +            Json::Value j; +            j["iso"] = vJson[0]; +            j["country"] = vJson[1]; +            j["code"] = vJson[2]; +            j["carrier"] = vJson[3]; +            j["carrierCode"] = vJson[4]; +            return j; +        } +    } + +    return Json::Value::null; +} +""" + +######################################################################################################################## + +MccMncElement = namedtuple( +    'MccMncData', +    field_names=('mcc', 'mcc_int', 'mnc', 'mnc_int', 'iso', 'country', 'country_code', 'carrier', 'carrier_code') +) + + +######################################################################################################################## + +def init_argparse() -> argparse.ArgumentParser: +    parser = argparse.ArgumentParser(description='Generate MCC/MNC table file from Website or CSV') +    parser.add_argument('-w', '--website', action='store_true') +    parser.add_argument('-c', '--csv', type=str) +    parser.add_argument('-t', '--target', type=str, default='-') +    return parser + + +def print_cpp_preamble(*, target: Optional[TextIO] = None) -> None: +    print(PREAMBLE_TEMPLATE.format(today=datetime.date.today()), file=target) + + +def print_cpp_general_code(*, target: Optional[TextIO] = None) -> None: +    print(GENERAL_CODE, file=target) + + +def format_mcc_mnc_line(el: MccMncElement) -> str: +    if el.mnc.upper() != "N/A": +        return '    m_mTable[{mcc_int}][{mnc_int}] = "{iso},{country},{country_code},{carrier},{carrier_code}";'.format( +            mcc_int=el.mcc_int, +            mnc_int=el.mnc_int, +            iso=el.iso, +            country=el.country, +            country_code=el.country_code, +            carrier=el.carrier, +            carrier_code=el.carrier_code +        ) +    else: +        # TODO: The Country and Country Code values were swapped in the original implementation due to a bug. +        # Left as is for compatibility reasons. +        return '    //MCC({mcc}) MNC(N/A) ISO({iso}) Country Code({country}) Country({country_code}) Carrier({carrier}) Carrier Code({carrier_code})'.format( +            mcc=el.mcc, +            iso=el.iso, +            country=el.country, +            country_code=el.country_code, +            carrier=el.carrier, +            carrier_code=el.carrier_code +        ) + + +def print_cpp_mcc_mnc_create_table(source: Iterable[MccMncElement], *, target: Optional[TextIO] = None) -> None: +    print("void MccMncTable::createTable() {", file=target) +    print("    std::string sData;", file=target) + +    for el in source: +        print(format_mcc_mnc_line(el), file=target) + +    print("}", file=target) +    print("", file=target) + + +def print_cpp(source: Iterable[MccMncElement], *, target: Optional[TextIO] = None) -> None: +    print_cpp_preamble(target=target) +    print_cpp_general_code(target=target) +    print_cpp_mcc_mnc_create_table(source, target=target) + + +def mcc_to_mcc_int(src: str) -> str: +    if src.upper() == "N/A": +        return src + +    hash_ = int(src, 16) +    return "{:d}".format(hash_) + + +def mnc_to_mnc_int(src: str) -> str: +    if src.upper() == "N/A": +        return src + +    src_norm = src +    if len(src) == 2: +        src_norm += 'f' + +    hash_ = int(src_norm, 16) +    return "{:d}".format(hash_) + + +def mcc_mnc_from_website(url: str) -> Generator[MccMncElement, None, None]: +    td_re = re.compile('<td>([^<]*)</td>' * 6) +    html_bytes = urllib.request.urlopen(url).read()  # type: bytes +    html = html_bytes.decode(encoding='utf-8') + +    tbody_start = False + +    for line in html.split('\n'): +        if '<tbody>' in line: +            tbody_start = True +        elif '</tbody>' in line: +            break +        elif tbody_start: +            td_search = td_re.search(line) +            mcc = td_search.group(1).strip().replace(',', '') +            mnc = td_search.group(2).strip().replace(',', '') +            iso = td_search.group(3).strip().replace(',', '') +            country = td_search.group(4).strip().replace(',', '') +            country_code = td_search.group(5).strip().replace(',', '') +            carrier = td_search.group(6).strip().replace(',', '') + +            mcc_int = mcc_to_mcc_int(mcc) +            mnc_int = mnc_to_mnc_int(mnc) + +            yield MccMncElement( +                mcc=mcc, +                mcc_int=mcc_int, +                mnc=mnc, +                mnc_int=mnc_int, +                iso=iso, +                country=country, +                country_code=country_code, +                carrier=carrier, +                carrier_code=""  # Multitech-specific, not populated from this source +            ) + + +def mcc_mnc_from_csv(path: str) -> Generator[MccMncElement, None, None]: +    with open(path) as f: +        csv_reader = csv.DictReader(f) +        for row in csv_reader: +            mcc = row['MCC'] +            mnc = row['MNC'] +            iso = row['ISO'] +            country = row['Country'] +            country_code = row['Country Code'] +            carrier = row['Carrier'] +            carrier_code = row['Carrier Code'] + +            mcc_int = mcc_to_mcc_int(mcc) +            mnc_int = mnc_to_mnc_int(mnc) + +            yield MccMncElement( +                mcc=mcc, +                mcc_int=mcc_int, +                mnc=mnc, +                mnc_int=mnc_int, +                iso=iso, +                country=country, +                country_code=country_code, +                carrier=carrier, +                carrier_code=carrier_code +            ) + + +######################################################################################################################## + +def main() -> int: +    parser = init_argparse() +    args = parser.parse_args() + +    if (args.csv is not None) and args.website: +        parser.error('Only one source can be used at a time.') +        return 1 -print "/*!" -print " \\file MTS_IO_MccMncTable.cpp" -print " \\brief Auto-Generated MCC-MNC Lookup Table" -print " \\date " + str(datetime.date.today()) -print " \\author sgodinez" -print "" -print " An Auto-Generated MCC-MNC Lookup Table" -print "*/" -print "" -print "#include <mts/MTS_IO_MccMncTable.h>" -print "#include <mts/MTS_Logger.h>" -print "#include <mts/MTS_Text.h>" -print "" -print "using namespace MTS::IO;" -print "" -print "MTS::AutoPtr<MTS::Lock> MccMncTable::m_apLock(new MTS::Lock());" -print "MccMncTable* MccMncTable::m_pInstance = NULL;" -print "" -print "MccMncTable* MccMncTable::getInstance() {" -print "    if(m_pInstance == NULL) {" -print "        m_apLock->lock();" -print "        if (m_pInstance == NULL) {" -print "            m_pInstance = new MccMncTable();" -print "        }" -print "        m_apLock->unlock();" -print "    }" -print "    return m_pInstance;" -print "}" -print "" -print "MccMncTable::MccMncTable() {" -print "    createTable();" -print "}" -print "" -print "Json::Value MccMncTable::lookup(const std::string& sMcc, const std::string& sMnc) {" -print "    uint32_t iMcc, iMnc;" -print '    printTrace("[MCCMNC] MCCx[%s] MNCx[%s]", sMcc.c_str(), sMnc.c_str());' -print "    if(!MTS::Text::parseHex(iMcc, sMcc)) { return Json::Value::null; }" -print "    if(!MTS::Text::parseHex(iMnc, sMnc)) { return Json::Value::null; }" -print '    printTrace("[MCCMNC] MCC0X[%d] MNC0X[%d]", iMcc, iMnc);' -print "    if (m_mTable.count(iMcc)) {" -print "        if(m_mTable[iMcc].count(iMnc)) {" -print "            std::vector<std::string> vJson = MTS::Text::split(m_mTable[iMcc][iMnc], ',');" -print "            Json::Value j;" -print '            j["iso"] = vJson[0];' -print '            j["country"] = vJson[1];' -print '            j["code"] = vJson[2];' -print '            j["carrier"] = vJson[3];' -print "            return j;" -print "        }" -print "    }" -print "" -print "    return Json::Value::null;" -print "}" -print "" -print "void MccMncTable::createTable() {" -print "    std::string sData;" - -td_re = re.compile('<td>([^<]*)</td>'*6) - -html = urllib2.urlopen('http://mcc-mnc.com/').read() - -tbody_start = False -for line in html.split('\n'): -    if '<tbody>' in line: -        tbody_start = True -    elif '</tbody>' in line: -        break -    elif tbody_start: -        td_search = td_re.search(line) -        mcc = td_search.group(1).strip().replace(',','') -        mnc = td_search.group(2).strip().replace(',','') -        iso = td_search.group(3).strip().replace(',','') -        countryCode = td_search.group(4).strip().replace(',','') -        country = td_search.group(5).strip().replace(',','') -        carrier = td_search.group(6).strip().replace(',','') - -        if mnc != "n/a": -            mcc_int = int(mcc, 16) -            if len(mnc) == 2: -                mnc_int = int(mnc + 'f', 16) -            else: -                mnc_int = int(mnc, 16) -            print '    m_mTable[' + str(mcc_int) + '][' + str(mnc_int) + '] = "' + \ -                  iso + ',' + countryCode + ',' + country + ',' + carrier + '";' -        else:            -            print "    //MCC(" + mcc + ') MNC(N/A) ISO(' + iso + ') Country Code(' + countryCode + ') Country(' + country + ') Carrier(' + carrier + ')' - - - -print "}" -print "" +    if args.csv is None: +        source = mcc_mnc_from_website('http://mcc-mnc.com/') +    else: +        source = mcc_mnc_from_csv(args.csv) +    if args.target == '-': +        # Print to stdout +        print_cpp(source, target=None) +    else: +        # Print to file +        with open(args.target, 'w') as f: +            print_cpp(source, target=f) +    return 0 +######################################################################################################################## +if __name__ == "__main__": +    ret = main() +    exit(ret) | 
