laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/pysim/+/38118?usp=email )

Change subject: utils: move enc_msisdn and dec_msisdn to legacy/utils.py
......................................................................

utils: move enc_msisdn and dec_msisdn to legacy/utils.py

We now have a construct based encoder/decoder for the record content
of EF.MSISDN. This means that we do not need the functions enc_msisdn
and dec_msisdn in the non-legacy code anymore. We can now move both
to legacy/utils.py.

Related: OS#5714
Change-Id: I19ec8ba14551ec282fc0cc12ae2f6d528bdfc527
---
M pySim-read.py
M pySim/legacy/cards.py
M pySim/legacy/utils.py
M pySim/utils.py
M tests/unittests/test_utils.py
5 files changed, 97 insertions(+), 96 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved




diff --git a/pySim-read.py b/pySim-read.py
index aae5ad4..4ede6dd 100755
--- a/pySim-read.py
+++ b/pySim-read.py
@@ -42,8 +42,8 @@
 from pySim.transport import init_reader, argparse_add_reader_args
 from pySim.exceptions import SwMatchError
 from pySim.legacy.cards import card_detect, SimCard, UsimCard, IsimCard
-from pySim.utils import dec_imsi, dec_iccid, dec_msisdn
-from pySim.legacy.utils import format_xplmn_w_act, dec_st
+from pySim.utils import dec_imsi, dec_iccid
+from pySim.legacy.utils import format_xplmn_w_act, dec_st, dec_msisdn

 option_parser = argparse.ArgumentParser(description='Legacy tool for reading 
some parts of a SIM card',
                                         
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
diff --git a/pySim/legacy/cards.py b/pySim/legacy/cards.py
index 5e64e95..1f5db8a 100644
--- a/pySim/legacy/cards.py
+++ b/pySim/legacy/cards.py
@@ -7,11 +7,11 @@
 from pytlv.TLV import *

 from pySim.cards import SimCardBase, UiccCardBase
-from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_msisdn, 
enc_msisdn
+from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi
 from pySim.utils import enc_plmn, get_addr_type
 from pySim.utils import is_hex, h2b, b2h, h2s, s2h, lpad, rpad
 from pySim.legacy.utils import enc_ePDGSelection, format_xplmn_w_act, 
format_xplmn, dec_st, enc_st
-from pySim.legacy.utils import format_ePDGSelection, dec_addr_tlv, enc_addr_tlv
+from pySim.legacy.utils import format_ePDGSelection, dec_addr_tlv, 
enc_addr_tlv, dec_msisdn, enc_msisdn
 from pySim.legacy.ts_51_011 import EF, DF
 from pySim.legacy.ts_31_102 import EF_USIM_ADF_map
 from pySim.legacy.ts_31_103 import EF_ISIM_ADF_map
diff --git a/pySim/legacy/utils.py b/pySim/legacy/utils.py
index cf2416e..4bfd061 100644
--- a/pySim/legacy/utils.py
+++ b/pySim/legacy/utils.py
@@ -20,8 +20,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #

+from typing import Optional, Tuple
 from pySim.utils import Hexstr, rpad, enc_plmn, h2i, i2s, s2h
 from pySim.utils import dec_xplmn_w_act, dec_xplmn, dec_mcc_from_plmn, 
dec_mnc_from_plmn
+from osmocom.utils import swap_nibbles, h2b, b2h

 def hexstr_to_Nbytearr(s, nbytes):
     return [s[i:i+(nbytes*2)] for i in range(0, len(s), (nbytes*2))]
@@ -330,3 +332,82 @@
         s += '80' + ('%02x' % ((len(ipv4_str)//2)+2)) + '01' + 'ff' + ipv4_str

     return s
+
+
+def dec_msisdn(ef_msisdn: Hexstr) -> Optional[Tuple[int, int, Optional[str]]]:
+    """
+    Decode MSISDN from EF.MSISDN or EF.ADN (same structure).
+    See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3.
+    """
+
+    # Convert from str to (kind of) 'bytes'
+    ef_msisdn = h2b(ef_msisdn)
+
+    # Make sure mandatory fields are present
+    if len(ef_msisdn) < 14:
+        raise ValueError("EF.MSISDN is too short")
+
+    # Skip optional Alpha Identifier
+    xlen = len(ef_msisdn) - 14
+    msisdn_lhv = ef_msisdn[xlen:]
+
+    # Parse the length (in bytes) of the BCD encoded number
+    bcd_len = msisdn_lhv[0]
+    # BCD length = length of dial num (max. 10 bytes) + 1 byte ToN and NPI
+    if bcd_len == 0xff:
+        return None
+    elif bcd_len > 11 or bcd_len < 1:
+        raise ValueError(
+            "Length of MSISDN (%d bytes) is out of range" % bcd_len)
+
+    # Parse ToN / NPI
+    ton = (msisdn_lhv[1] >> 4) & 0x07
+    npi = msisdn_lhv[1] & 0x0f
+    bcd_len -= 1
+
+    # No MSISDN?
+    if not bcd_len:
+        return (npi, ton, None)
+
+    msisdn = swap_nibbles(b2h(msisdn_lhv[2:][:bcd_len])).rstrip('f')
+    # International number 10.5.118/3GPP TS 24.008
+    if ton == 0x01:
+        msisdn = '+' + msisdn
+
+    return (npi, ton, msisdn)
+
+
+def enc_msisdn(msisdn: str, npi: int = 0x01, ton: int = 0x03) -> Hexstr:
+    """
+    Encode MSISDN as LHV so it can be stored to EF.MSISDN.
+    See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3. (The result
+    will not contain the optional Alpha Identifier at the beginning.)
+
+    Default NPI / ToN values:
+      - NPI: ISDN / telephony numbering plan (E.164 / E.163),
+      - ToN: network specific or international number (if starts with '+').
+    """
+
+    # If no MSISDN is supplied then encode the file contents as all "ff"
+    if msisdn in ["", "+"]:
+        return "ff" * 14
+
+    # Leading '+' indicates International Number
+    if msisdn[0] == '+':
+        msisdn = msisdn[1:]
+        ton = 0x01
+
+    # An MSISDN must not exceed 20 digits
+    if len(msisdn) > 20:
+        raise ValueError("msisdn must not be longer than 20 digits")
+
+    # Append 'f' padding if number of digits is odd
+    if len(msisdn) % 2 > 0:
+        msisdn += 'f'
+
+    # BCD length also includes NPI/ToN header
+    bcd_len = len(msisdn) // 2 + 1
+    npi_ton = (npi & 0x0f) | ((ton & 0x07) << 4) | 0x80
+    bcd = rpad(swap_nibbles(msisdn), 10 * 2)  # pad to 10 octets
+
+    return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
diff --git a/pySim/utils.py b/pySim/utils.py
index 05ad962..c706b34 100644
--- a/pySim/utils.py
+++ b/pySim/utils.py
@@ -341,86 +341,6 @@

     return mnc

-
-def dec_msisdn(ef_msisdn: Hexstr) -> Optional[Tuple[int, int, Optional[str]]]:
-    """
-    Decode MSISDN from EF.MSISDN or EF.ADN (same structure).
-    See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3.
-    """
-
-    # Convert from str to (kind of) 'bytes'
-    ef_msisdn = h2b(ef_msisdn)
-
-    # Make sure mandatory fields are present
-    if len(ef_msisdn) < 14:
-        raise ValueError("EF.MSISDN is too short")
-
-    # Skip optional Alpha Identifier
-    xlen = len(ef_msisdn) - 14
-    msisdn_lhv = ef_msisdn[xlen:]
-
-    # Parse the length (in bytes) of the BCD encoded number
-    bcd_len = msisdn_lhv[0]
-    # BCD length = length of dial num (max. 10 bytes) + 1 byte ToN and NPI
-    if bcd_len == 0xff:
-        return None
-    elif bcd_len > 11 or bcd_len < 1:
-        raise ValueError(
-            "Length of MSISDN (%d bytes) is out of range" % bcd_len)
-
-    # Parse ToN / NPI
-    ton = (msisdn_lhv[1] >> 4) & 0x07
-    npi = msisdn_lhv[1] & 0x0f
-    bcd_len -= 1
-
-    # No MSISDN?
-    if not bcd_len:
-        return (npi, ton, None)
-
-    msisdn = swap_nibbles(b2h(msisdn_lhv[2:][:bcd_len])).rstrip('f')
-    # International number 10.5.118/3GPP TS 24.008
-    if ton == 0x01:
-        msisdn = '+' + msisdn
-
-    return (npi, ton, msisdn)
-
-
-def enc_msisdn(msisdn: str, npi: int = 0x01, ton: int = 0x03) -> Hexstr:
-    """
-    Encode MSISDN as LHV so it can be stored to EF.MSISDN.
-    See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3. (The result
-    will not contain the optional Alpha Identifier at the beginning.)
-
-    Default NPI / ToN values:
-      - NPI: ISDN / telephony numbering plan (E.164 / E.163),
-      - ToN: network specific or international number (if starts with '+').
-    """
-
-    # If no MSISDN is supplied then encode the file contents as all "ff"
-    if msisdn in ["", "+"]:
-        return "ff" * 14
-
-    # Leading '+' indicates International Number
-    if msisdn[0] == '+':
-        msisdn = msisdn[1:]
-        ton = 0x01
-
-    # An MSISDN must not exceed 20 digits
-    if len(msisdn) > 20:
-        raise ValueError("msisdn must not be longer than 20 digits")
-
-    # Append 'f' padding if number of digits is odd
-    if len(msisdn) % 2 > 0:
-        msisdn += 'f'
-
-    # BCD length also includes NPI/ToN header
-    bcd_len = len(msisdn) // 2 + 1
-    npi_ton = (npi & 0x0f) | ((ton & 0x07) << 4) | 0x80
-    bcd = rpad(swap_nibbles(msisdn), 10 * 2)  # pad to 10 octets
-
-    return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
-
-
 def sanitize_pin_adm(pin_adm, pin_adm_hex=None) -> Hexstr:
     """
     The ADM pin can be supplied either in its hexadecimal form or as
diff --git a/tests/unittests/test_utils.py b/tests/unittests/test_utils.py
index 0e61a61..30a01d2 100755
--- a/tests/unittests/test_utils.py
+++ b/tests/unittests/test_utils.py
@@ -145,31 +145,31 @@
                self.assertEqual(encoded.lower(), 
self.testfile_suci_calc_info.lower())

        def testEnc_msisdn(self):
-               msisdn_encoded = utils.enc_msisdn("+4916012345678", npi=0x01, 
ton=0x03)
+               msisdn_encoded = legacy_utils.enc_msisdn("+4916012345678", 
npi=0x01, ton=0x03)
                self.assertEqual(msisdn_encoded, "0891946110325476f8ffffffffff")
-               msisdn_encoded = utils.enc_msisdn("123456", npi=0x01, ton=0x03)
+               msisdn_encoded = legacy_utils.enc_msisdn("123456", npi=0x01, 
ton=0x03)
                self.assertEqual(msisdn_encoded, "04b1214365ffffffffffffffffff")
-               msisdn_encoded = utils.enc_msisdn("12345678901234567890", 
npi=0x01, ton=0x03)
+               msisdn_encoded = 
legacy_utils.enc_msisdn("12345678901234567890", npi=0x01, ton=0x03)
                self.assertEqual(msisdn_encoded, "0bb121436587092143658709ffff")
-               msisdn_encoded = utils.enc_msisdn("+12345678901234567890", 
npi=0x01, ton=0x03)
+               msisdn_encoded = 
legacy_utils.enc_msisdn("+12345678901234567890", npi=0x01, ton=0x03)
                self.assertEqual(msisdn_encoded, "0b9121436587092143658709ffff")
-               msisdn_encoded = utils.enc_msisdn("", npi=0x01, ton=0x03)
+               msisdn_encoded = legacy_utils.enc_msisdn("", npi=0x01, ton=0x03)
                self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")
-               msisdn_encoded = utils.enc_msisdn("+", npi=0x01, ton=0x03)
+               msisdn_encoded = legacy_utils.enc_msisdn("+", npi=0x01, 
ton=0x03)
                self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")

        def testDec_msisdn(self):
-               msisdn_decoded = 
utils.dec_msisdn("0891946110325476f8ffffffffff")
+               msisdn_decoded = 
legacy_utils.dec_msisdn("0891946110325476f8ffffffffff")
                self.assertEqual(msisdn_decoded, (1, 1, "+4916012345678"))
-               msisdn_decoded = 
utils.dec_msisdn("04b1214365ffffffffffffffffff")
+               msisdn_decoded = 
legacy_utils.dec_msisdn("04b1214365ffffffffffffffffff")
                self.assertEqual(msisdn_decoded, (1, 3, "123456"))
-               msisdn_decoded = 
utils.dec_msisdn("0bb121436587092143658709ffff")
+               msisdn_decoded = 
legacy_utils.dec_msisdn("0bb121436587092143658709ffff")
                self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
-               msisdn_decoded = 
utils.dec_msisdn("ffffffffffffffffffffffffffff")
+               msisdn_decoded = 
legacy_utils.dec_msisdn("ffffffffffffffffffffffffffff")
                self.assertEqual(msisdn_decoded, None)
-               msisdn_decoded = 
utils.dec_msisdn("00112233445566778899AABBCCDDEEFF001122330bb121436587092143658709ffff")
+               msisdn_decoded = 
legacy_utils.dec_msisdn("00112233445566778899AABBCCDDEEFF001122330bb121436587092143658709ffff")
                self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
-               msisdn_decoded = 
utils.dec_msisdn("ffffffffffffffffffffffffffffffffffffffff0bb121436587092143658709ffff")
+               msisdn_decoded = 
legacy_utils.dec_msisdn("ffffffffffffffffffffffffffffffffffffffff0bb121436587092143658709ffff")
                self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))

 class TestLuhn(unittest.TestCase):

--
To view, visit https://gerrit.osmocom.org/c/pysim/+/38118?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I19ec8ba14551ec282fc0cc12ae2f6d528bdfc527
Gerrit-Change-Number: 38118
Gerrit-PatchSet: 13
Gerrit-Owner: dexter <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>

Reply via email to