added GNU header
[ussd-widget] / ussd-common / src / usr / lib / python2.5 / gsmdecode.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published
5 ## by the Free Software Foundation; version 2 and higer.
6 ##
7 ## Martin Grimme (martin.grimme # gmail.com) 2010
8
9
10 LANG_DE = 0x0
11 LANG_EN = 0x1
12 LANG_IT = 0x2
13 LANG_FR = 0x3
14 LANG_ES = 0x4
15 LANG_NL = 0x5
16 LANG_SE = 0x6
17 LANG_DA = 0x7
18 LANG_PO = 0x8
19 LANG_FI = 0x9
20 LANG_NO = 0xa
21 LANG_GR = 0xb
22 LANG_TR = 0xc
23 LANG_UNSPECIFIED = 0xf
24
25
26 GSM_DEFAULT_ALPHABET = [
27     u"@",
28     u"\u00a3",
29     u"$",
30     u"\u00a5",
31     u"\u00e8",
32     u"\u00e9",
33     u"\u00f9",
34     u"\u00ec",
35     u"\u00f2",
36     u"\u00c7",
37     u"\n",
38     u"\u00d8",
39     u"\u00f8",
40     u"\r",
41     u"\u00c5",
42     u"\u00e5",
43     
44     u"\u0394",
45     u"_",
46     u"\u03a6",
47     u"\u0393",
48     u"\u039b",
49     u"\u03a9",
50     u"\u03a0",
51     u"\u03a8",
52     u"\u03a3",
53     u"\u0398",
54     u"\u039e",
55     u" ",
56     u"\u00c6",
57     u"\u00e6",
58     u"\u00df",
59     u"\u00c9",
60     
61     u" ",
62     u"!",
63     u"\"",
64     u"#",
65     u"\u00a4",
66     u"%",
67     u"&",
68     u"'",
69     u"(",
70     u")",
71     u"*",
72     u"+",
73     u",",
74     u"-",
75     u".",
76     u"/",
77     
78     u"0",
79     u"1",
80     u"2",
81     u"3",
82     u"4",
83     u"5",
84     u"6",
85     u"7",
86     u"8",
87     u"9",
88     u":",
89     u";",
90     u"<",
91     u"=",
92     u">",
93     u"?",
94     
95     u"\u00a1",
96     u"A",
97     u"B",
98     u"C",
99     u"D",
100     u"E",
101     u"F",
102     u"G",
103     u"H",
104     u"I",
105     u"J",
106     u"K",
107     u"L",
108     u"M",
109     u"N",
110     u"O",
111     
112     u"P",
113     u"Q",
114     u"R",
115     u"S",
116     u"T",
117     u"U",
118     u"V",
119     u"W",
120     u"X",
121     u"Y",
122     u"Z",
123     u"\u00c4",
124     u"\u00d6",
125     u"\u00d1",
126     u"\u00dc",
127     u"\u00a7",
128
129     u"\u00bf",
130     u"a",
131     u"b",
132     u"c",
133     u"d",
134     u"e",
135     u"f",
136     u"g",
137     u"h",
138     u"i",
139     u"j",
140     u"k",
141     u"l",
142     u"m",
143     u"n",
144     u"o",
145
146     u"p",
147     u"q",
148     u"r",
149     u"s",
150     u"t",
151     u"u",
152     u"v",
153     u"w",
154     u"x",
155     u"y",
156     u"z",
157     u"\u00e4",
158     u"\u00f6",
159     u"\u00f1",
160     u"\u00fc",
161     u"\u00e0"
162 ]
163
164
165 def decode(s, n):
166     """
167     Decodes the given string using the given cell broadcast data coding scheme.
168     
169     @param s: string to decode
170     @param n: GSM cell broadcast data coding scheme
171     @return: UTF-8 string
172     """
173
174     # separate into nibbles
175     hbits = (n & 0xf0) >> 4
176     lbits = (n & 0x0f)
177     
178     if (hbits == 0x0):
179         # language
180         return _decode_language(s, lbits)
181
182     elif (0x1 <= hbits <= 0x3):
183         # reserved language
184         return s
185         
186     elif (0x4 <= hbits <= 0x7):
187         # general data coding indication
188         return _decode_general_data_coding(s, hbits, lbits)
189         
190     elif (0x8 <= hbits <= 0xe):
191         # reserved coding group
192         return s
193         
194     elif (hbits == 0xf):
195         # data coding / message handling
196         return s
197
198
199 def _decode_language(s, lang):
200
201     return _decode_default_alphabet(s)
202
203
204 def _decode_default_alphabet(s):
205     
206     # TODO: we really might have to do 7 bit character unpacking here
207     
208     # ought to be all in the 7 bit GSM character map
209     chars = [ GSM_DEFAULT_ALPHABET[ord(c)] for c in s ]
210     u_str = "".join(chars)
211     return u_str.encode("utf-8")
212
213
214 def _decode_hex(s):
215
216     return s.decode("hex")
217
218
219 def _decode_usc2(s):
220
221     return s.decode("hex").decode("utf-16-be").encode("utf-8")
222
223
224 def _decode_general_data_coding(s, h, l):
225
226     is_compressed = (h & 0x2)
227     
228     alphabet = (l & 0xc) >> 2
229
230     if (alphabet == 0x0):
231         # default alphabet
232         return _decode_defaul_alphabet(s)
233         
234     elif (alphabet == 0x1):
235         # 8 bit
236         # actually, encoding is user-defined, but let's assume hex'd ASCII
237         # for now
238         return _decode_hex(s)
239         
240     elif (alphabet == 0x2):
241         # USC2 (16 bit, BE)
242         return _decode_usc2(s)
243         
244     elif (alphabet == 0x3):
245         # reserved
246         return s
247