Harald Welte | 75a58d1 | 2022-07-31 15:51:19 +0200 | [diff] [blame] | 1 | """Code related to SMS Encoding/Decoding""" |
| 2 | # simplistic SMS T-PDU code, as unfortunately nobody bothered to port the python smspdu |
| 3 | # module to python3, and I gave up after >= 3 hours of trying and failing to do so |
| 4 | |
| 5 | # (C) 2022 by Harald Welte <laforge@osmocom.org> |
| 6 | # |
| 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by |
| 9 | # the Free Software Foundation, either version 2 of the License, or |
| 10 | # (at your option) any later version. |
| 11 | # |
| 12 | # This program is distributed in the hope that it will be useful, |
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | # GNU General Public License for more details. |
| 16 | # |
| 17 | # You should have received a copy of the GNU General Public License |
| 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | |
| 20 | import typing |
| 21 | from construct import Int8ub, Bytes |
| 22 | from construct import Struct, Tell, this, RepeatUntil |
| 23 | |
| 24 | from pySim.utils import Hexstr, h2b, b2h |
| 25 | |
| 26 | BytesOrHex = typing.Union[Hexstr, bytes] |
| 27 | |
| 28 | class UserDataHeader: |
| 29 | # a single IE in the user data header |
| 30 | ie_c = Struct('offset'/Tell, 'iei'/Int8ub, 'length'/Int8ub, 'data'/Bytes(this.length)) |
| 31 | # parser for the full UDH: Length octet followed by sequence of IEs |
| 32 | _construct = Struct('udhl'/Int8ub, |
| 33 | # FIXME: somehow the below lambda is not working, we always only get the first IE? |
| 34 | 'ies'/RepeatUntil(lambda obj,lst,ctx: ctx._io.tell() > 1+this.udhl, ie_c)) |
| 35 | |
| 36 | def __init__(self, ies=[]): |
| 37 | self.ies = ies |
| 38 | |
| 39 | def __repr__(self) -> str: |
| 40 | return 'UDH(%r)' % self.ies |
| 41 | |
| 42 | def has_ie(self, iei:int) -> bool: |
| 43 | for ie in self.ies: |
| 44 | if ie['iei'] == iei: |
| 45 | return True |
| 46 | return False |
| 47 | |
| 48 | @classmethod |
| 49 | def fromBytes(cls, inb: BytesOrHex) -> typing.Tuple['UserDataHeader', bytes]: |
| 50 | if isinstance(inb, str): |
| 51 | inb = h2b(inb) |
| 52 | res = cls._construct.parse(inb) |
| 53 | return cls(res['ies']), inb[1+res['udhl']:] |