1# imsi.py - functions for handling International Mobile Subscriber Identity 2# (IMSI) numbers 3# 4# Copyright (C) 2011-2015 Arthur de Jong 5# 6# This library is free software; you can redistribute it and/or 7# modify it under the terms of the GNU Lesser General Public 8# License as published by the Free Software Foundation; either 9# version 2.1 of the License, or (at your option) any later version. 10# 11# This library is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14# Lesser General Public License for more details. 15# 16# You should have received a copy of the GNU Lesser General Public 17# License along with this library; if not, write to the Free Software 18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19# 02110-1301 USA 20 21"""IMSI (International Mobile Subscriber Identity). 22 23The IMSI (International Mobile Subscriber Identity) is used to identify 24mobile phone users (the SIM). 25 26>>> validate('429011234567890') 27'429011234567890' 28>>> validate('439011234567890') # unknown MCC 29Traceback (most recent call last): 30 ... 31InvalidComponent: ... 32>>> split('429011234567890') 33('429', '01', '1234567890') 34>>> split('310150123456789') 35('310', '150', '123456789') 36>>> info('460001234567890')['mcc'] 37'460' 38>>> str(info('460001234567890')['country']) 39'China' 40""" 41 42from stdnum.exceptions import * 43from stdnum.util import clean, isdigits 44 45 46def compact(number): 47 """Convert the IMSI number to the minimal representation. This strips the 48 number of any valid separators and removes surrounding whitespace.""" 49 return clean(number, ' -').strip().upper() 50 51 52def split(number): 53 """Split the specified IMSI into a Mobile Country Code (MCC), a Mobile 54 Network Code (MNC), a Mobile Station Identification Number (MSIN).""" 55 from stdnum import numdb 56 # clean up number 57 number = compact(number) 58 # split the number 59 return tuple(numdb.get('imsi').split(number)) 60 61 62def validate(number): 63 """Check if the number provided is a valid IMSI.""" 64 number = compact(number) 65 if not isdigits(number): 66 raise InvalidFormat() 67 if len(number) not in (14, 15): 68 raise InvalidLength() 69 if len(split(number)) < 2: 70 raise InvalidComponent() # unknown MCC 71 return number 72 73 74def info(number): 75 """Return a dictionary of data about the supplied number.""" 76 from stdnum import numdb 77 # clean up number 78 number = compact(number) 79 # split the number 80 info = dict(number=number) 81 mcc_info, mnc_info, msin_info = numdb.get('imsi').info(number) 82 info['mcc'] = mcc_info[0] 83 info.update(mcc_info[1]) 84 info['mnc'] = mnc_info[0] 85 info.update(mnc_info[1]) 86 info['msin'] = msin_info[0] 87 info.update(msin_info[1]) 88 return info 89 90 91def is_valid(number): 92 """Check if the number provided is a valid IMSI.""" 93 try: 94 return bool(validate(number)) 95 except ValidationError: 96 return False 97