aecc79029d3fad065442016da7fac73f6904b2bf
[profile/ivi/ofono.git] / src / util.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2009-2010  Nokia Corporation and/or its subsidiary(-ies).
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
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, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31
32 #include <glib.h>
33
34 #include "util.h"
35
36 /*
37         Name:                   GSM 03.38 to Unicode
38         Unicode version:        3.0
39         Table version:          1.1
40         Table format:           Format A
41         Date:                   2000 May 30
42         Authors:                Ken Whistler
43                                 Kent Karlsson
44                                 Markus Kuhn
45
46         Copyright (c) 2000 Unicode, Inc.  All Rights reserved.
47
48         This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
49         No claims are made as to fitness for any particular purpose.  No
50         warranties of any kind are expressed or implied.  The recipient
51         agrees to determine applicability of information provided.  If this
52         file has been provided on optical media by Unicode, Inc., the sole
53         remedy for any claim will be exchange of defective media within 90
54         days of receipt.
55
56         Unicode, Inc. hereby grants the right to freely use the information
57         supplied in this file in the creation of products supporting the
58         Unicode Standard, and to make copies of this file in any form for
59         internal or external distribution as long as this notice remains
60         attached.
61 */
62
63 #define GUND                    0xFFFF
64
65 #define UTF8_LENGTH(c) \
66         ((c) < 0x80 ? 1 : ((c) < 0x800 ? 2 : 3))
67
68 #define TABLE_SIZE(t) \
69         (sizeof((t)) / sizeof(struct codepoint))
70
71 struct codepoint {
72         unsigned short from;
73         unsigned short to;
74 };
75
76 struct conversion_table {
77         /* To unicode locking shift table */
78         const struct codepoint *locking_u;
79         unsigned int locking_len_u;
80
81         /* To unicode single shift table */
82         const struct codepoint *single_u;
83         unsigned int single_len_u;
84
85         /* To GSM locking shift table, fixed size */
86         const unsigned short *locking_g;
87
88         /* To GSM single shift table */
89         const struct codepoint *single_g;
90         unsigned int single_len_g;
91 };
92
93 /* GSM to Unicode extension table, for GSM sequences starting with 0x1B */
94 static const struct codepoint def_ext_gsm[] = {
95         { 0x0A, 0x000C },               /* See NOTE 3 in 23.038 */
96         { 0x14, 0x005E },
97         { 0x1B, 0x0020 },               /* See NOTE 1 in 23.038 */
98         { 0x28, 0x007B },
99         { 0x29, 0x007D },
100         { 0x2F, 0x005C },
101         { 0x3C, 0x005B },
102         { 0x3D, 0x007E },
103         { 0x3E, 0x005D },
104         { 0x40, 0x007C },
105         { 0x65, 0x20AC }
106 };
107
108 static const struct codepoint def_ext_unicode[] = {
109         { 0x000C, 0x1B0A },
110         { 0x005B, 0x1B3C },
111         { 0x005C, 0x1B2F },
112         { 0x005D, 0x1B3E },
113         { 0x005E, 0x1B14 },
114         { 0x007B, 0x1B28 },
115         { 0x007C, 0x1B40 },
116         { 0x007D, 0x1B29 },
117         { 0x007E, 0x1B3D },
118         { 0x20AC, 0x1B65 }
119 };
120
121 /* Appendix A.2.1. in 3GPP TS23.038, V.8.2.0 */
122 static const struct codepoint tur_ext_gsm[] = {
123         { 0x0A, 0x000C },               /* See NOTE 3 */
124         { 0x14, 0x005E },
125         { 0x1B, 0x0020 },               /* See NOTE 1 */
126         { 0x28, 0x007B },
127         { 0x29, 0x007D },
128         { 0x2F, 0x005C },
129         { 0x3C, 0x005B },
130         { 0x3D, 0x007E },
131         { 0x3E, 0x005D },
132         { 0x40, 0x007C },
133         { 0x47, 0x011E },
134         { 0x49, 0x0130 },
135         { 0x53, 0x015E },
136         { 0x63, 0x00E7 },
137         { 0x65, 0x20AC },
138         { 0x67, 0x011F },
139         { 0x69, 0x0131 },
140         { 0x73, 0x015F }
141 };
142
143 static const struct codepoint tur_ext_unicode[] = {
144         { 0x000C, 0x1B0A },
145         { 0x005B, 0x1B3C },
146         { 0x005C, 0x1B2F },
147         { 0x005D, 0x1B3E },
148         { 0x005E, 0x1B14 },
149         { 0x007B, 0x1B28 },
150         { 0x007C, 0x1B40 },
151         { 0x007D, 0x1B29 },
152         { 0x007E, 0x1B3D },
153         { 0x00E7, 0x1B63 },
154         { 0x011E, 0x1B47 },
155         { 0x011F, 0x1B67 },
156         { 0x0130, 0x1B49 },
157         { 0x0131, 0x1B69 },
158         { 0x015E, 0x1B53 },
159         { 0x015F, 0x1B73 },
160         { 0x20AC, 0x1B65 }
161 };
162
163 /* Appendix A.2.2. in 3GPP TS23.038 V.8.2.0*/
164 static const struct codepoint spa_ext_gsm[] = {
165         { 0x09, 0x00E7 },
166         { 0x0A, 0x000C },               /* See NOTE 3 */
167         { 0x14, 0x005E },
168         { 0x1B, 0x0020 },               /* See NOTE 1 */
169         { 0x28, 0x007B },
170         { 0x29, 0x007D },
171         { 0x2F, 0x005C },
172         { 0x3C, 0x005B },
173         { 0x3D, 0x007E },
174         { 0x3E, 0x005D },
175         { 0x40, 0x007C },
176         { 0x41, 0x00C1 },
177         { 0x49, 0x00CD },
178         { 0x4F, 0x00D3 },
179         { 0x55, 0x00DA },
180         { 0x61, 0x00E1 },
181         { 0x65, 0x20AC },
182         { 0x69, 0x00ED },
183         { 0x6F, 0x00F3 },
184         { 0x75, 0x00FA }
185 };
186
187 static const struct codepoint spa_ext_unicode[] = {
188         { 0x000C, 0x1B0A },
189         { 0x005B, 0x1B3C },
190         { 0x005C, 0x1B2F },
191         { 0x005D, 0x1B3E },
192         { 0x005E, 0x1B14 },
193         { 0x007B, 0x1B28 },
194         { 0x007C, 0x1B40 },
195         { 0x007D, 0x1B29 },
196         { 0x007E, 0x1B3D },
197         { 0x00C1, 0x1B41 },
198         { 0x00CD, 0x1B49 },
199         { 0x00D3, 0x1B4F },
200         { 0x00DA, 0x1B55 },
201         { 0x00E1, 0x1B61 },
202         { 0x00E7, 0x1B09 },
203         { 0x00ED, 0x1B69 },
204         { 0x00F3, 0x1B6F },
205         { 0x00FA, 0x1B75 },
206         { 0x20AC, 0x1B65 }
207 };
208
209 /* Appendix A.2.3. in 3GPP TS23.038 V.8.2.0 */
210 static const struct codepoint por_ext_gsm[] = {
211         { 0x05, 0x00EA },
212         { 0x09, 0x00E7 },
213         { 0x0A, 0x000C },               /* See NOTE 3 */
214         { 0x0B, 0x00D4 },
215         { 0x0C, 0x00F4 },
216         { 0x0E, 0x00C1 },
217         { 0x0F, 0x00E1 },
218         { 0x12, 0x03A6 },
219         { 0x13, 0x0393 },
220         { 0x14, 0x005E },
221         { 0x15, 0x03A9 },
222         { 0x16, 0x03A0 },
223         { 0x17, 0x03A8 },
224         { 0x18, 0x03A3 },
225         { 0x19, 0x0398 },
226         { 0x1B, 0x0020 },               /* See NOTE 1 */
227         { 0x1F, 0x00CA },
228         { 0x28, 0x007B },
229         { 0x29, 0x007D },
230         { 0x2F, 0x005C },
231         { 0x3C, 0x005B },
232         { 0x3D, 0x007E },
233         { 0x3E, 0x005D },
234         { 0x40, 0x007C },
235         { 0x41, 0x00C0 },
236         { 0x49, 0x00CD },
237         { 0x4F, 0x00D3 },
238         { 0x55, 0x00DA },
239         { 0x5B, 0x00C3 },
240         { 0x5C, 0x00D5 },
241         { 0x61, 0x00C2 },
242         { 0x65, 0x20AC },
243         { 0x69, 0x00ED },
244         { 0x6F, 0x00F3 },
245         { 0x75, 0x00FA },
246         { 0x7B, 0x00E3 },
247         { 0x7C, 0x00F5 },
248         { 0x7F, 0x00E2 }
249 };
250
251 static const struct codepoint por_ext_unicode[] = {
252         { 0x000C, 0x1B0A },
253         { 0x005B, 0x1B3C },
254         { 0x005C, 0x1B2F },
255         { 0x005D, 0x1B3E },
256         { 0x005E, 0x1B14 },
257         { 0x007B, 0x1B28 },
258         { 0x007C, 0x1B40 },
259         { 0x007D, 0x1B29 },
260         { 0x007E, 0x1B3D },
261         { 0x00C0, 0x1B41 },
262         { 0x00C1, 0x1B0E },
263         { 0x00C2, 0x1B61 },
264         { 0x00C3, 0x1B5B },
265         { 0x00CA, 0x1B1F },
266         { 0x00CD, 0x1B49 },
267         { 0x00D3, 0x1B4F },
268         { 0x00D4, 0x1B0B },
269         { 0x00D5, 0x1B5C },
270         { 0x00DA, 0x1B55 },
271         { 0x00E1, 0x1B0F },
272         { 0x00E2, 0x1B7F },
273         { 0x00E3, 0x1B7B },
274         { 0x00E7, 0x1B09 },
275         { 0x00EA, 0x1B05 },
276         { 0x00ED, 0x1B69 },
277         { 0x00F3, 0x1B6F },
278         { 0x00F4, 0x1B0C },
279         { 0x00F5, 0x1B7C },
280         { 0x00FA, 0x1B75 },
281         { 0x0393, 0x1B13 },
282         { 0x0398, 0x1B19 },
283         { 0x03A0, 0x1B16 },
284         { 0x03A3, 0x1B18 },
285         { 0x03A6, 0x1B12 },
286         { 0x03A8, 0x1B17 },
287         { 0x03A9, 0x1B15 },
288         { 0x20AC, 0x1B65 }
289 };
290
291 /* Used for conversion of GSM to Unicode */
292 static const unsigned short def_gsm[] = {
293         0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
294         0x00F2, 0x00C7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
295         0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
296         0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
297         0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027,
298         0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
299         0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
300         0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
301         0x00A1, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
302         0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
303         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
304         0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6, 0x00D1, 0x00DC, 0x00A7,
305         0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
306         0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
307         0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
308         0x0078, 0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0
309 };
310
311 /* Used for conversion of Unicode to GSM */
312 static const struct codepoint def_unicode[] = {
313         { 0x000A, 0x0A }, { 0x000D, 0x0D }, { 0x0020, 0x20 }, { 0x0021, 0x21 },
314         { 0x0022, 0x22 }, { 0x0023, 0x23 }, { 0x0024, 0x02 }, { 0x0025, 0x25 },
315         { 0x0026, 0x26 }, { 0x0027, 0x27 }, { 0x0028, 0x28 }, { 0x0029, 0x29 },
316         { 0x002A, 0x2A }, { 0x002B, 0x2B }, { 0x002C, 0x2C }, { 0x002D, 0x2D },
317         { 0x002E, 0x2E }, { 0x002F, 0x2F }, { 0x0030, 0x30 }, { 0x0031, 0x31 },
318         { 0x0032, 0x32 }, { 0x0033, 0x33 }, { 0x0034, 0x34 }, { 0x0035, 0x35 },
319         { 0x0036, 0x36 }, { 0x0037, 0x37 }, { 0x0038, 0x38 }, { 0x0039, 0x39 },
320         { 0x003A, 0x3A }, { 0x003B, 0x3B }, { 0x003C, 0x3C }, { 0x003D, 0x3D },
321         { 0x003E, 0x3E }, { 0x003F, 0x3F }, { 0x0040, 0x00 }, { 0x0041, 0x41 },
322         { 0x0042, 0x42 }, { 0x0043, 0x43 }, { 0x0044, 0x44 }, { 0x0045, 0x45 },
323         { 0x0046, 0x46 }, { 0x0047, 0x47 }, { 0x0048, 0x48 }, { 0x0049, 0x49 },
324         { 0x004A, 0x4A }, { 0x004B, 0x4B }, { 0x004C, 0x4C }, { 0x004D, 0x4D },
325         { 0x004E, 0x4E }, { 0x004F, 0x4F }, { 0x0050, 0x50 }, { 0x0051, 0x51 },
326         { 0x0052, 0x52 }, { 0x0053, 0x53 }, { 0x0054, 0x54 }, { 0x0055, 0x55 },
327         { 0x0056, 0x56 }, { 0x0057, 0x57 }, { 0x0058, 0x58 }, { 0x0059, 0x59 },
328         { 0x005A, 0x5A }, { 0x005F, 0x11 }, { 0x0061, 0x61 }, { 0x0062, 0x62 },
329         { 0x0063, 0x63 }, { 0x0064, 0x64 }, { 0x0065, 0x65 }, { 0x0066, 0x66 },
330         { 0x0067, 0x67 }, { 0x0068, 0x68 }, { 0x0069, 0x69 }, { 0x006A, 0x6A },
331         { 0x006B, 0x6B }, { 0x006C, 0x6C }, { 0x006D, 0x6D }, { 0x006E, 0x6E },
332         { 0x006F, 0x6F }, { 0x0070, 0x70 }, { 0x0071, 0x71 }, { 0x0072, 0x72 },
333         { 0x0073, 0x73 }, { 0x0074, 0x74 }, { 0x0075, 0x75 }, { 0x0076, 0x76 },
334         { 0x0077, 0x77 }, { 0x0078, 0x78 }, { 0x0079, 0x79 }, { 0x007A, 0x7A },
335         { 0x00A0, 0x20 }, { 0x00A1, 0x40 }, { 0x00A3, 0x01 }, { 0x00A4, 0x24 },
336         { 0x00A5, 0x03 }, { 0x00A7, 0x5F }, { 0x00BF, 0x60 }, { 0x00C4, 0x5B },
337         { 0x00C5, 0x0E }, { 0x00C6, 0x1C }, { 0x00C7, 0x09 }, { 0x00C9, 0x1F },
338         { 0x00D1, 0x5D }, { 0x00D6, 0x5C }, { 0x00D8, 0x0B }, { 0x00DC, 0x5E },
339         { 0x00DF, 0x1E }, { 0x00E0, 0x7F }, { 0x00E4, 0x7B }, { 0x00E5, 0x0F },
340         { 0x00E6, 0x1D }, { 0x00E8, 0x04 }, { 0x00E9, 0x05 }, { 0x00EC, 0x07 },
341         { 0x00F1, 0x7D }, { 0x00F2, 0x08 }, { 0x00F6, 0x7C }, { 0x00F8, 0x0C },
342         { 0x00F9, 0x06 }, { 0x00FC, 0x7E }, { 0x0393, 0x13 }, { 0x0394, 0x10 },
343         { 0x0398, 0x19 }, { 0x039B, 0x14 }, { 0x039E, 0x1A }, { 0x03A0, 0x16 },
344         { 0x03A3, 0x18 }, { 0x03A6, 0x12 }, { 0x03A8, 0x17 }, { 0x03A9, 0x15 }
345 };
346
347 /* Appendix A.3.1 in 3GPP TS23.038 */
348 static const unsigned short tur_gsm[] = {
349         0x0040, 0x00A3, 0x0024, 0x00A5, 0x20AC, 0x00E9, 0x00F9, 0x0131,
350         0x00F2, 0x00C7, 0x000A, 0x011E, 0x011F, 0x000D, 0x00C5, 0x00E5,
351         0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
352         0x03A3, 0x0398, 0x039E, 0x00A0, 0x015E, 0x015F, 0x00DF, 0x00C9,
353         0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027,
354         0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
355         0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
356         0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
357         0x0130, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
358         0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
359         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
360         0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6, 0x00D1, 0x00DC, 0x00A7,
361         0x00E7, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
362         0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
363         0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
364         0x0078, 0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0
365 };
366
367 static const struct codepoint tur_unicode[] = {
368         { 0x000A, 0x0A }, { 0x000D, 0x0D }, { 0x0020, 0x20 }, { 0x0021, 0x21 },
369         { 0x0022, 0x22 }, { 0x0023, 0x23 }, { 0x0024, 0x02 }, { 0x0025, 0x25 },
370         { 0x0026, 0x26 }, { 0x0027, 0x27 }, { 0x0028, 0x28 }, { 0x0029, 0x29 },
371         { 0x002A, 0x2A }, { 0x002B, 0x2B }, { 0x002C, 0x2C }, { 0x002D, 0x2D },
372         { 0x002E, 0x2E }, { 0x002F, 0x2F }, { 0x0030, 0x30 }, { 0x0031, 0x31 },
373         { 0x0032, 0x32 }, { 0x0033, 0x33 }, { 0x0034, 0x34 }, { 0x0035, 0x35 },
374         { 0x0036, 0x36 }, { 0x0037, 0x37 }, { 0x0038, 0x38 }, { 0x0039, 0x39 },
375         { 0x003A, 0x3A }, { 0x003B, 0x3B }, { 0x003C, 0x3C }, { 0x003D, 0x3D },
376         { 0x003E, 0x3E }, { 0x003F, 0x3F }, { 0x0040, 0x00 }, { 0x0041, 0x41 },
377         { 0x0042, 0x42 }, { 0x0043, 0x43 }, { 0x0044, 0x44 }, { 0x0045, 0x45 },
378         { 0x0046, 0x46 }, { 0x0047, 0x47 }, { 0x0048, 0x48 }, { 0x0049, 0x49 },
379         { 0x004A, 0x4A }, { 0x004B, 0x4B }, { 0x004C, 0x4C }, { 0x004D, 0x4D },
380         { 0x004E, 0x4E }, { 0x004F, 0x4F }, { 0x0050, 0x50 }, { 0x0051, 0x51 },
381         { 0x0052, 0x52 }, { 0x0053, 0x53 }, { 0x0054, 0x54 }, { 0x0055, 0x55 },
382         { 0x0056, 0x56 }, { 0x0057, 0x57 }, { 0x0058, 0x58 }, { 0x0059, 0x59 },
383         { 0x005A, 0x5A }, { 0x005F, 0x11 }, { 0x0061, 0x61 }, { 0x0062, 0x62 },
384         { 0x0063, 0x63 }, { 0x0064, 0x64 }, { 0x0065, 0x65 }, { 0x0066, 0x66 },
385         { 0x0067, 0x67 }, { 0x0068, 0x68 }, { 0x0069, 0x69 }, { 0x006A, 0x6A },
386         { 0x006B, 0x6B }, { 0x006C, 0x6C }, { 0x006D, 0x6D }, { 0x006E, 0x6E },
387         { 0x006F, 0x6F }, { 0x0070, 0x70 }, { 0x0071, 0x71 }, { 0x0072, 0x72 },
388         { 0x0073, 0x73 }, { 0x0074, 0x74 }, { 0x0075, 0x75 }, { 0x0076, 0x76 },
389         { 0x0077, 0x77 }, { 0x0078, 0x78 }, { 0x0079, 0x79 }, { 0x007A, 0x7A },
390         { 0x00A0, 0x20 }, { 0x00A3, 0x01 }, { 0x00A4, 0x24 }, { 0x00A5, 0x03 },
391         { 0x00A7, 0x5F }, { 0x00C4, 0x5B }, { 0x00C5, 0x0E }, { 0x00C7, 0x09 },
392         { 0x00C9, 0x1F }, { 0x00D1, 0x5D }, { 0x00D6, 0x5C }, { 0x00DC, 0x5E },
393         { 0x00DF, 0x1E }, { 0x00E0, 0x7F }, { 0x00E4, 0x7B }, { 0x00E5, 0x0F },
394         { 0x00E7, 0x60 }, { 0x00E9, 0x05 }, { 0x00F1, 0x7D }, { 0x00F2, 0x08 },
395         { 0x00F6, 0x7C }, { 0x00F9, 0x06 }, { 0x00FC, 0x7E }, { 0x011E, 0x0B },
396         { 0x011F, 0x0C }, { 0x0130, 0x40 }, { 0x0131, 0x07 }, { 0x015E, 0x1C },
397         { 0x015F, 0x1D }, { 0x0393, 0x13 }, { 0x0394, 0x10 }, { 0x0398, 0x19 },
398         { 0x039B, 0x14 }, { 0x039E, 0x1A }, { 0x03A0, 0x16 }, { 0x03A3, 0x18 },
399         { 0x03A6, 0x12 }, { 0x03A8, 0x17 }, { 0x03A9, 0x15 }, { 0x20AC, 0x04 }
400 };
401
402 /* Appendix A.3.2 in 3GPP TS23.038 */
403 static const unsigned short por_gsm[] = {
404         0x0040, 0x00A3, 0x0024, 0x00A5, 0x00EA, 0x00E9, 0x00FA, 0x00ED,
405         0x00F3, 0x00E7, 0x000A, 0x00D4, 0x00F4, 0x000D, 0x00C1, 0x00E1,
406         0x0394, 0x005F, 0x00AA, 0x00C7, 0x00C0, 0x221E, 0x005E, 0x005C,
407         0x20ac, 0x00D3, 0x007C, 0x00A0, 0x00C2, 0x00E2, 0x00CA, 0x00C9,
408         0x0020, 0x0021, 0x0022, 0x0023, 0x00BA, 0x0025, 0x0026, 0x0027,
409         0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
410         0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
411         0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
412         0x00CD, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
413         0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
414         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
415         0x0058, 0x0059, 0x005A, 0x00C3, 0x00D5, 0x00DA, 0x00DC, 0x00A7,
416         0x007E, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
417         0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
418         0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
419         0x0078, 0x0079, 0x007A, 0x00E3, 0x00F5, 0x0060, 0x00FC, 0x00E0
420 };
421
422 static const struct codepoint por_unicode[] = {
423         { 0x000A, 0x0A }, { 0x000D, 0x0D }, { 0x0020, 0x20 }, { 0x0021, 0x21 },
424         { 0x0022, 0x22 }, { 0x0023, 0x23 }, { 0x0024, 0x02 }, { 0x0025, 0x25 },
425         { 0x0026, 0x26 }, { 0x0027, 0x27 }, { 0x0028, 0x28 }, { 0x0029, 0x29 },
426         { 0x002A, 0x2A }, { 0x002B, 0x2B }, { 0x002C, 0x2C }, { 0x002D, 0x2D },
427         { 0x002E, 0x2E }, { 0x002F, 0x2F }, { 0x0030, 0x30 }, { 0x0031, 0x31 },
428         { 0x0032, 0x32 }, { 0x0033, 0x33 }, { 0x0034, 0x34 }, { 0x0035, 0x35 },
429         { 0x0036, 0x36 }, { 0x0037, 0x37 }, { 0x0038, 0x38 }, { 0x0039, 0x39 },
430         { 0x003A, 0x3A }, { 0x003B, 0x3B }, { 0x003C, 0x3C }, { 0x003D, 0x3D },
431         { 0x003E, 0x3E }, { 0x003F, 0x3F }, { 0x0040, 0x00 }, { 0x0041, 0x41 },
432         { 0x0042, 0x42 }, { 0x0043, 0x43 }, { 0x0044, 0x44 }, { 0x0045, 0x45 },
433         { 0x0046, 0x46 }, { 0x0047, 0x47 }, { 0x0048, 0x48 }, { 0x0049, 0x49 },
434         { 0x004A, 0x4A }, { 0x004B, 0x4B }, { 0x004C, 0x4C }, { 0x004D, 0x4D },
435         { 0x004E, 0x4E }, { 0x004F, 0x4F }, { 0x0050, 0x50 }, { 0x0051, 0x51 },
436         { 0x0052, 0x52 }, { 0x0053, 0x53 }, { 0x0054, 0x54 }, { 0x0055, 0x55 },
437         { 0x0056, 0x56 }, { 0x0057, 0x57 }, { 0x0058, 0x58 }, { 0x0059, 0x59 },
438         { 0x005A, 0x5A }, { 0x005C, 0x17 }, { 0x005E, 0x16 }, { 0x005F, 0x11 },
439         { 0x0060, 0x7D }, { 0x0061, 0x61 }, { 0x0062, 0x62 }, { 0x0063, 0x63 },
440         { 0x0064, 0x64 }, { 0x0065, 0x65 }, { 0x0066, 0x66 }, { 0x0067, 0x67 },
441         { 0x0068, 0x68 }, { 0x0069, 0x69 }, { 0x006A, 0x6A }, { 0x006B, 0x6B },
442         { 0x006C, 0x6C }, { 0x006D, 0x6D }, { 0x006E, 0x6E }, { 0x006F, 0x6F },
443         { 0x0070, 0x70 }, { 0x0071, 0x71 }, { 0x0072, 0x72 }, { 0x0073, 0x73 },
444         { 0x0074, 0x74 }, { 0x0075, 0x75 }, { 0x0076, 0x76 }, { 0x0077, 0x77 },
445         { 0x0078, 0x78 }, { 0x0079, 0x79 }, { 0x007A, 0x7A }, { 0x007C, 0x1A },
446         { 0x007E, 0x60 }, { 0x00A0, 0x20 }, { 0x00A3, 0x01 }, { 0x00A5, 0x03 },
447         { 0x00A7, 0x5F }, { 0x00AA, 0x12 }, { 0x00BA, 0x24 }, { 0x00C0, 0x14 },
448         { 0x00C1, 0x0E }, { 0x00C2, 0x1C }, { 0x00C3, 0x5B }, { 0x00C7, 0x13 },
449         { 0x00C9, 0x1F }, { 0x00CA, 0x1E }, { 0x00CD, 0x40 }, { 0x00D3, 0x19 },
450         { 0x00D4, 0x0B }, { 0x00D5, 0x5C }, { 0x00DA, 0x5D }, { 0x00DC, 0x5E },
451         { 0x00E0, 0x7F }, { 0x00E1, 0x0F }, { 0x00E2, 0x1D }, { 0x00E3, 0x7B },
452         { 0x00E7, 0x09 }, { 0x00E9, 0x05 }, { 0x00EA, 0x04 }, { 0x00ED, 0x07 },
453         { 0x00F3, 0x08 }, { 0x00F4, 0x0C }, { 0x00F5, 0x7C }, { 0x00FA, 0x06 },
454         { 0x00FC, 0x7E }, { 0x0394, 0x10 }, { 0x20AC, 0x18 }, { 0x221E, 0x15 }
455 };
456
457 static int compare_codepoints(const void *a, const void *b)
458 {
459         const struct codepoint *ca = (const struct codepoint *) a;
460         const struct codepoint *cb = (const struct codepoint *) b;
461
462         return (ca->from > cb->from) - (ca->from < cb->from);
463 }
464
465 static unsigned short codepoint_lookup(struct codepoint *key,
466                                         const struct codepoint *table,
467                                         unsigned int len)
468 {
469         struct codepoint *result = NULL;
470
471         result = bsearch(key, table, len, sizeof(struct codepoint),
472                                 compare_codepoints);
473
474         return result ? result->to : GUND;
475 }
476
477 static unsigned short gsm_locking_shift_lookup(struct conversion_table *t,
478                                                 unsigned char k)
479 {
480         return t->locking_g[k];
481 }
482
483 static unsigned short gsm_single_shift_lookup(struct conversion_table *t,
484                                                 unsigned char k)
485 {
486         struct codepoint key = { k, 0 };
487         return codepoint_lookup(&key, t->single_g, t->single_len_g);
488 }
489
490 static unsigned short unicode_locking_shift_lookup(struct conversion_table *t,
491                                                         unsigned short k)
492 {
493         struct codepoint key = { k, 0 };
494         return codepoint_lookup(&key, t->locking_u, t->locking_len_u);
495 }
496
497 static unsigned short unicode_single_shift_lookup(struct conversion_table *t,
498                                                         unsigned short k)
499 {
500         struct codepoint key = { k, 0 };
501         return codepoint_lookup(&key, t->single_u, t->single_len_u);
502 }
503
504 static gboolean populate_locking_shift(struct conversion_table *t,
505                                         enum gsm_dialect lang)
506 {
507         switch (lang) {
508         case GSM_DIALECT_DEFAULT:
509         case GSM_DIALECT_SPANISH:
510                 t->locking_g = def_gsm;
511                 t->locking_u = def_unicode;
512                 t->locking_len_u = TABLE_SIZE(def_unicode);
513                 return TRUE;
514
515         case GSM_DIALECT_TURKISH:
516                 t->locking_g = tur_gsm;
517                 t->locking_u = tur_unicode;
518                 t->locking_len_u = TABLE_SIZE(tur_unicode);
519                 return TRUE;
520
521         case GSM_DIALECT_PORTUGUESE:
522                 t->locking_g = por_gsm;
523                 t->locking_u = por_unicode;
524                 t->locking_len_u = TABLE_SIZE(por_unicode);
525                 return TRUE;
526         }
527
528         return FALSE;
529 }
530
531 static gboolean populate_single_shift(struct conversion_table *t,
532                                         enum gsm_dialect lang)
533 {
534         switch (lang) {
535         case GSM_DIALECT_DEFAULT:
536                 t->single_g = def_ext_gsm;
537                 t->single_len_g = TABLE_SIZE(def_ext_gsm);
538                 t->single_u = def_ext_unicode;
539                 t->single_len_u = TABLE_SIZE(def_ext_unicode);
540                 return TRUE;
541
542         case GSM_DIALECT_TURKISH:
543                 t->single_g = tur_ext_gsm;
544                 t->single_len_g = TABLE_SIZE(tur_ext_gsm);
545                 t->single_u = tur_ext_unicode;
546                 t->single_len_u = TABLE_SIZE(tur_ext_unicode);
547                 return TRUE;
548
549         case GSM_DIALECT_SPANISH:
550                 t->single_g = spa_ext_gsm;
551                 t->single_len_g = TABLE_SIZE(spa_ext_gsm);
552                 t->single_u = spa_ext_unicode;
553                 t->single_len_u = TABLE_SIZE(spa_ext_unicode);
554                 return TRUE;
555
556         case GSM_DIALECT_PORTUGUESE:
557                 t->single_g = por_ext_gsm;
558                 t->single_len_g = TABLE_SIZE(por_ext_gsm);
559                 t->single_u = por_ext_unicode;
560                 t->single_len_u = TABLE_SIZE(por_ext_unicode);
561                 return TRUE;
562         }
563
564         return FALSE;
565 }
566
567 static gboolean conversion_table_init(struct conversion_table *t,
568                                         enum gsm_dialect locking,
569                                         enum gsm_dialect single)
570 {
571         memset(t, 0, sizeof(struct conversion_table));
572
573         return populate_locking_shift(t, locking) &&
574                         populate_single_shift(t, single);
575 }
576
577 /*!
578  * Converts text coded using GSM codec into UTF8 encoded text, using
579  * the given language identifiers for single shift and locking shift
580  * tables.  If len is less than 0, and terminator character is given,
581  * the length is computed automatically.
582  *
583  * Returns newly-allocated UTF8 encoded string or NULL if the conversion
584  * could not be performed.  Returns the number of bytes read from the
585  * GSM encoded string in items_read (if not NULL), not including the
586  * terminator character. Returns the number of bytes written into the UTF8
587  * encoded string in items_written (if not NULL) not including the terminal
588  * '\0' character.  The caller is responsible for freeing the returned value.
589  */
590 char *convert_gsm_to_utf8_with_lang(const unsigned char *text, long len,
591                                         long *items_read, long *items_written,
592                                         unsigned char terminator,
593                                         enum gsm_dialect locking_lang,
594                                         enum gsm_dialect single_lang)
595 {
596         char *res = NULL;
597         char *out;
598         long i = 0;
599         long res_length;
600
601         struct conversion_table t;
602
603         if (conversion_table_init(&t, locking_lang, single_lang) == FALSE)
604                 return NULL;
605
606         if (len < 0 && !terminator)
607                 goto error;
608
609         if (len < 0) {
610                 i = 0;
611
612                 while (text[i] != terminator)
613                         i++;
614
615                 len = i;
616         }
617
618         for (i = 0, res_length = 0; i < len; i++) {
619                 unsigned short c;
620
621                 if (text[i] > 0x7f)
622                         goto error;
623
624                 if (text[i] == 0x1b) {
625                         ++i;
626                         if (i >= len)
627                                 goto error;
628
629                         c = gsm_single_shift_lookup(&t, text[i]);
630
631                         if (c == GUND)
632                                 goto error;
633                 } else {
634                         c = gsm_locking_shift_lookup(&t, text[i]);
635                 }
636
637                 res_length += UTF8_LENGTH(c);
638         }
639
640         res = g_try_malloc(res_length + 1);
641         if (res == NULL)
642                 goto error;
643
644         out = res;
645
646         i = 0;
647         while (out < res + res_length) {
648                 unsigned short c;
649
650                 if (text[i] == 0x1b)
651                         c = gsm_single_shift_lookup(&t, text[++i]);
652                 else
653                         c = gsm_locking_shift_lookup(&t, text[i]);
654
655                 out += g_unichar_to_utf8(c, out);
656
657                 ++i;
658         }
659
660         *out = '\0';
661
662         if (items_written)
663                 *items_written = out - res;
664
665 error:
666         if (items_read)
667                 *items_read = i;
668
669         return res;
670 }
671
672 char *convert_gsm_to_utf8(const unsigned char *text, long len,
673                                 long *items_read, long *items_written,
674                                 unsigned char terminator)
675 {
676         return convert_gsm_to_utf8_with_lang(text, len, items_read,
677                                                 items_written,
678                                                 terminator,
679                                                 GSM_DIALECT_DEFAULT,
680                                                 GSM_DIALECT_DEFAULT);
681 }
682
683 /*!
684  * Converts UTF-8 encoded text to GSM alphabet.  The result is unpacked,
685  * with the 7th bit always 0.  If terminator is not 0, a terminator character
686  * is appended to the result.  This should be in the range 0x80-0xf0
687  *
688  * Returns the encoded data or NULL if the data could not be encoded.  The
689  * data must be freed by the caller.  If items_read is not NULL, it contains
690  * the actual number of bytes read.  If items_written is not NULL, contains
691  * the number of bytes written.
692  */
693 unsigned char *convert_utf8_to_gsm_with_lang(const char *text, long len,
694                                         long *items_read, long *items_written,
695                                         unsigned char terminator,
696                                         enum gsm_dialect locking_lang,
697                                         enum gsm_dialect single_lang)
698 {
699         struct conversion_table t;
700         long nchars = 0;
701         const char *in;
702         unsigned char *out;
703         unsigned char *res = NULL;
704         long res_len;
705         long i;
706
707         if (conversion_table_init(&t, locking_lang, single_lang) == FALSE)
708                 return NULL;
709
710         in = text;
711         res_len = 0;
712
713         while ((len < 0 || text + len - in > 0) && *in) {
714                 long max = len < 0 ? 6 : text + len - in;
715                 gunichar c = g_utf8_get_char_validated(in, max);
716                 unsigned short converted = GUND;
717
718                 if (c & 0x80000000)
719                         goto err_out;
720
721                 if (c > 0xffff)
722                         goto err_out;
723
724                 converted = unicode_locking_shift_lookup(&t, c);
725
726                 if (converted == GUND)
727                         converted = unicode_single_shift_lookup(&t, c);
728
729                 if (converted == GUND)
730                         goto err_out;
731
732                 if (converted & 0x1b00)
733                         res_len += 2;
734                 else
735                         res_len += 1;
736
737                 in = g_utf8_next_char(in);
738                 nchars += 1;
739         }
740
741         res = g_try_malloc(res_len + (terminator ? 1 : 0));
742         if (res == NULL)
743                 goto err_out;
744
745         in = text;
746         out = res;
747         for (i = 0; i < nchars; i++) {
748                 unsigned short converted;
749
750                 gunichar c = g_utf8_get_char(in);
751
752                 converted = unicode_locking_shift_lookup(&t, c);
753
754                 if (converted == GUND)
755                         converted = unicode_single_shift_lookup(&t, c);
756
757                 if (converted & 0x1b00) {
758                         *out = 0x1b;
759                         ++out;
760                 }
761
762                 *out = converted;
763                 ++out;
764
765                 in = g_utf8_next_char(in);
766         }
767
768         if (terminator)
769                 *out = terminator;
770
771         if (items_written)
772                 *items_written = out - res;
773
774 err_out:
775         if (items_read)
776                 *items_read = in - text;
777
778         return res;
779 }
780
781 unsigned char *convert_utf8_to_gsm(const char *text, long len,
782                                         long *items_read, long *items_written,
783                                         unsigned char terminator)
784 {
785         return convert_utf8_to_gsm_with_lang(text, len, items_read,
786                                                 items_written,
787                                                 terminator,
788                                                 GSM_DIALECT_DEFAULT,
789                                                 GSM_DIALECT_DEFAULT);
790 }
791
792 /*!
793  * Converts UTF-8 encoded text to GSM alphabet. It finds an encoding
794  * that uses the minimum set of GSM dialects based on the hint given.
795  *
796  * It first attempts to use the default dialect's single shift and
797  * locking shift tables. It then tries with only the single shift
798  * table of the hinted dialect, and finally with both the single shift
799  * and locking shift tables of the hinted dialect.
800  *
801  * Returns the encoded data or NULL if no suitable encoding could be
802  * found. The data must be freed by the caller. If items_read is not
803  * NULL, it contains the actual number of bytes read. If items_written
804  * is not NULL, it contains the number of bytes written. If
805  * used_locking and used_single are not NULL, they will contain the
806  * dialects used for the locking shift and single shift tables.
807  */
808 unsigned char *convert_utf8_to_gsm_best_lang(const char *utf8, long len,
809                                         long *items_read, long *items_written,
810                                         unsigned char terminator,
811                                         enum gsm_dialect hint,
812                                         enum gsm_dialect *used_locking,
813                                         enum gsm_dialect *used_single)
814 {
815         enum gsm_dialect locking = GSM_DIALECT_DEFAULT;
816         enum gsm_dialect single = GSM_DIALECT_DEFAULT;
817         unsigned char *encoded;
818
819         encoded = convert_utf8_to_gsm_with_lang(utf8, len, items_read,
820                                                 items_written, terminator,
821                                                 locking, single);
822         if (encoded != NULL)
823                 goto out;
824
825         if (hint == GSM_DIALECT_DEFAULT)
826                 return NULL;
827
828         single = hint;
829         encoded = convert_utf8_to_gsm_with_lang(utf8, len, items_read,
830                                                 items_written, terminator,
831                                                 locking, single);
832         if (encoded != NULL)
833                 goto out;
834
835         /* Spanish dialect uses the default locking shift table */
836         if (hint == GSM_DIALECT_SPANISH)
837                 return NULL;
838
839         locking = hint;
840         encoded = convert_utf8_to_gsm_with_lang(utf8, len, items_read,
841                                                 items_written, terminator,
842                                                 locking, single);
843
844         if (encoded == NULL)
845                 return NULL;
846
847 out:
848         if (used_locking != NULL)
849                 *used_locking = locking;
850
851         if (used_single != NULL)
852                 *used_single = single;
853
854         return encoded;
855 }
856
857 /*!
858  * Decodes the hex encoded data and converts to a byte array.  If terminator
859  * is not 0, the terminator character is appended to the end of the result.
860  * This might be useful for converting GSM encoded data if the CSCS is set
861  * to HEX.
862  *
863  * Please note that this since GSM does allow embedded null characeters, use
864  * of the terminator or the items_writen is encouraged to find the real size
865  * of the result.
866  */
867 unsigned char *decode_hex_own_buf(const char *in, long len, long *items_written,
868                                         unsigned char terminator,
869                                         unsigned char *buf)
870 {
871         long i, j;
872         char c;
873         unsigned char b;
874
875         if (len < 0)
876                 len = strlen(in);
877
878         len &= ~0x1;
879
880         for (i = 0, j = 0; i < len; i++, j++) {
881                 c = toupper(in[i]);
882
883                 if (c >= '0' && c <= '9')
884                         b = c - '0';
885                 else if (c >= 'A' && c <= 'F')
886                         b = 10 + c - 'A';
887                 else
888                         return NULL;
889
890                 i += 1;
891
892                 c = toupper(in[i]);
893
894                 if (c >= '0' && c <= '9')
895                         b = b * 16 + c - '0';
896                 else if (c >= 'A' && c <= 'F')
897                         b = b * 16 + 10 + c - 'A';
898                 else
899                         return NULL;
900
901                 buf[j] = b;
902         }
903
904         if (terminator)
905                 buf[j] = terminator;
906
907         if (items_written)
908                 *items_written = j;
909
910         return buf;
911 }
912
913 unsigned char *decode_hex(const char *in, long len, long *items_written,
914                                 unsigned char terminator)
915 {
916         long i;
917         char c;
918         unsigned char *buf;
919
920         if (len < 0)
921                 len = strlen(in);
922
923         len &= ~0x1;
924
925         for (i = 0; i < len; i++) {
926                 c = toupper(in[i]);
927
928                 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
929                         continue;
930
931                 return NULL;
932         }
933
934         buf = g_new(unsigned char, (len >> 1) + (terminator ? 1 : 0));
935
936         return decode_hex_own_buf(in, len, items_written, terminator, buf);
937 }
938
939 /*!
940  * Encodes the data using hexadecimal characters.  len can be negative,
941  * in that case the terminator is used to find the last character.  This is
942  * useful for handling GSM-encoded strings which allow ASCII NULL character
943  * in the stream.
944  */
945 char *encode_hex_own_buf(const unsigned char *in, long len,
946                                 unsigned char terminator, char *buf)
947 {
948         long i, j;
949         char c;
950
951         if (len < 0) {
952                 i = 0;
953
954                 while (in[i] != terminator)
955                         i++;
956
957                 len = i;
958         }
959
960         for (i = 0, j = 0; i < len; i++, j++) {
961                 c = (in[i] >> 4) & 0xf;
962
963                 if (c <= 9)
964                         buf[j] = '0' + c;
965                 else
966                         buf[j] = 'A' + c - 10;
967
968                 j += 1;
969
970                 c = (in[i]) & 0xf;
971
972                 if (c <= 9)
973                         buf[j] = '0' + c;
974                 else
975                         buf[j] = 'A' + c - 10;
976         }
977
978         buf[j] = '\0';
979
980         return buf;
981 }
982
983 char *encode_hex(const unsigned char *in, long len, unsigned char terminator)
984 {
985         char *buf;
986         int i;
987
988         if (len < 0) {
989                 i = 0;
990
991                 while (in[i] != terminator)
992                         i++;
993
994                 len = i;
995         }
996
997         buf = g_new(char, len * 2 + 1);
998
999         return encode_hex_own_buf(in, len, terminator, buf);
1000 }
1001
1002 unsigned char *unpack_7bit_own_buf(const unsigned char *in, long len,
1003                                         int byte_offset, gboolean ussd,
1004                                         long max_to_unpack, long *items_written,
1005                                         unsigned char terminator,
1006                                         unsigned char *buf)
1007 {
1008         unsigned char rest = 0;
1009         unsigned char *out = buf;
1010         int bits = 7 - (byte_offset % 7);
1011         long i;
1012
1013         if (len <= 0)
1014                 return NULL;
1015
1016         /* In the case of CB, unpack as much as possible */
1017         if (ussd == TRUE)
1018                 max_to_unpack = len * 8 / 7;
1019
1020         for (i = 0; (i < len) && ((out-buf) < max_to_unpack); i++) {
1021                 /* Grab what we have in the current octet */
1022                 *out = (in[i] & ((1 << bits) - 1)) << (7 - bits);
1023
1024                 /* Append what we have from the previous octet, if any */
1025                 *out |= rest;
1026
1027                 /* Figure out the remainder */
1028                 rest = (in[i] >> bits) & ((1 << (8-bits)) - 1);
1029
1030                 /*
1031                  * We have the entire character, here we don't increate
1032                  * out if this is we started at an offset.  Instead
1033                  * we effectively populate variable rest
1034                  */
1035                 if (i != 0 || bits == 7)
1036                         out++;
1037
1038                 if ((out-buf) == max_to_unpack)
1039                         break;
1040
1041                 /*
1042                  * We expected only 1 bit from this octet, means there's 7
1043                  * left, take care of them here
1044                  */
1045                 if (bits == 1) {
1046                         *out = rest;
1047                         out++;
1048                         bits = 7;
1049                         rest = 0;
1050                 } else {
1051                         bits = bits - 1;
1052                 }
1053         }
1054
1055         /*
1056          * According to 23.038 6.1.2.3.1, last paragraph:
1057          * "If the total number of characters to be sent equals (8n-1)
1058          * where n=1,2,3 etc. then there are 7 spare bits at the end
1059          * of the message. To avoid the situation where the receiving
1060          * entity confuses 7 binary zero pad bits as the @ character,
1061          * the carriage return or <CR> character shall be used for
1062          * padding in this situation, just as for Cell Broadcast."
1063          *
1064          * "The receiving entity shall remove the final <CR> character where
1065          * the message ends on an octet boundary with <CR> as the last
1066          * character.
1067          */
1068         if (ussd && (((out - buf) % 8) == 0) && (*(out - 1) == '\r'))
1069                 out = out - 1;
1070
1071         if (terminator)
1072                 *out = terminator;
1073
1074         if (items_written)
1075                 *items_written = out - buf;
1076
1077         return buf;
1078 }
1079
1080 unsigned char *unpack_7bit(const unsigned char *in, long len, int byte_offset,
1081                                 gboolean ussd, long max_to_unpack,
1082                                 long *items_written, unsigned char terminator)
1083 {
1084         unsigned char *buf = g_new(unsigned char,
1085                                         len * 8 / 7 + (terminator ? 1 : 0));
1086
1087         return unpack_7bit_own_buf(in, len, byte_offset, ussd, max_to_unpack,
1088                                 items_written, terminator, buf);
1089 }
1090
1091 unsigned char *pack_7bit_own_buf(const unsigned char *in, long len,
1092                                         int byte_offset, gboolean ussd,
1093                                         long *items_written,
1094                                         unsigned char terminator,
1095                                         unsigned char *buf)
1096 {
1097         int bits = 7 - (byte_offset % 7);
1098         unsigned char *out = buf;
1099         long i;
1100         long total_bits;
1101
1102         if (len == 0)
1103                 return NULL;
1104
1105         if (len < 0) {
1106                 i = 0;
1107
1108                 while (in[i] != terminator)
1109                         i++;
1110
1111                 len = i;
1112         }
1113
1114         total_bits = len * 7;
1115
1116         if (bits != 7) {
1117                 total_bits += bits;
1118                 bits = bits - 1;
1119                 *out = 0;
1120         }
1121
1122         for (i = 0; i < len; i++) {
1123                 if (bits != 7) {
1124                         *out |= (in[i] & ((1 << (7 - bits)) - 1)) <<
1125                                         (bits + 1);
1126                         out++;
1127                 }
1128
1129                 /* This is a no op when bits == 0, lets keep valgrind happy */
1130                 if (bits != 0)
1131                         *out = in[i] >> (7 - bits);
1132
1133                 if (bits == 0)
1134                         bits = 7;
1135                 else
1136                         bits = bits - 1;
1137         }
1138
1139         /*
1140          * If <CR> is intended to be the last character and the message
1141          * (including the wanted <CR>) ends on an octet boundary, then
1142          * another <CR> must be added together with a padding bit 0. The
1143          * receiving entity will perform the carriage return function twice,
1144          * but this will not result in misoperation as the definition of
1145          * <CR> in clause 6.1.1 is identical to the definition of <CR><CR>.
1146          */
1147         if (ussd && ((total_bits % 8) == 1))
1148                 *out |= '\r' << 1;
1149
1150         if (bits != 7)
1151                 out++;
1152
1153         if (ussd && ((total_bits % 8) == 0) && (in[len - 1] == '\r')) {
1154                 *out = '\r';
1155                 out++;
1156         }
1157
1158         if (items_written)
1159                 *items_written = out - buf;
1160
1161         return buf;
1162 }
1163
1164 unsigned char *pack_7bit(const unsigned char *in, long len, int byte_offset,
1165                                 gboolean ussd, long *items_written,
1166                                 unsigned char terminator)
1167 {
1168         int bits = 7 - (byte_offset % 7);
1169         long i;
1170         long total_bits;
1171         unsigned char *buf;
1172
1173         if (len == 0 || items_written == NULL)
1174                 return NULL;
1175
1176         if (len < 0) {
1177                 i = 0;
1178
1179                 while (in[i] != terminator)
1180                         i++;
1181
1182                 len = i;
1183         }
1184
1185         total_bits = len * 7;
1186
1187         if (bits != 7)
1188                 total_bits += bits;
1189
1190         /* Round up number of bytes, must append <cr> if true */
1191         if (ussd && ((total_bits % 8) == 0) && (in[len - 1] == '\r'))
1192                 buf = g_new(unsigned char, (total_bits + 14) / 8);
1193         else
1194                 buf = g_new(unsigned char, (total_bits + 7) / 8);
1195
1196         return pack_7bit_own_buf(in, len, byte_offset, ussd, items_written,
1197                                         terminator, buf);
1198 }
1199
1200 char *sim_string_to_utf8(const unsigned char *buffer, int length)
1201 {
1202         struct conversion_table t;
1203         int i;
1204         int j;
1205         int num_chars;
1206         unsigned short ucs2_offset;
1207         int res_len;
1208         int offset;
1209         char *utf8 = NULL;
1210         char *out;
1211
1212         if (conversion_table_init(&t, GSM_DIALECT_DEFAULT,
1213                                         GSM_DIALECT_DEFAULT) == FALSE)
1214                 return NULL;
1215
1216         if (length < 1)
1217                 return NULL;
1218
1219         if (buffer[0] < 0x80) {
1220                 /*
1221                  * We have to find the real length, since on SIM file system
1222                  * alpha fields are 0xff padded
1223                  */
1224                 for (i = 0; i < length; i++)
1225                         if (buffer[i] == 0xff)
1226                                 break;
1227
1228                 return convert_gsm_to_utf8(buffer, i, NULL, NULL, 0);
1229         }
1230
1231         switch (buffer[0]) {
1232         case 0x80:
1233                 if (((length - 1) % 2) == 1) {
1234                         if (buffer[length - 1] != 0xff)
1235                                 return NULL;
1236
1237                         length = length - 1;
1238                 }
1239
1240                 for (i = 1; i < length; i += 2)
1241                         if (buffer[i] == 0xff && buffer[i + 1] == 0xff)
1242                                 break;
1243
1244                 return g_convert((char *) buffer + 1, i - 1,
1245                                         "UTF-8//TRANSLIT", "UCS-2BE",
1246                                         NULL, NULL, NULL);
1247         case 0x81:
1248                 if (length < 3 || (buffer[1] > (length - 3)))
1249                         return NULL;
1250
1251                 num_chars = buffer[1];
1252                 ucs2_offset = buffer[2] << 7;
1253                 offset = 3;
1254                 break;
1255
1256         case 0x82:
1257                 if (length < 4 || buffer[1] > length - 4)
1258                         return NULL;
1259
1260                 num_chars = buffer[1];
1261                 ucs2_offset = (buffer[2] << 8) | buffer[3];
1262                 offset = 4;
1263                 break;
1264
1265         default:
1266                 return NULL;
1267         }
1268
1269         res_len = 0;
1270         i = offset;
1271         j = 0;
1272
1273         while ((i < length) && (j < num_chars)) {
1274                 unsigned short c;
1275
1276                 if (buffer[i] & 0x80) {
1277                         c = (buffer[i++] & 0x7f) + ucs2_offset;
1278
1279                         if (c >= 0xd800 && c < 0xe000)
1280                                 return NULL;
1281
1282                         res_len += UTF8_LENGTH(c);
1283                         j += 1;
1284                         continue;
1285                 }
1286
1287                 if (buffer[i] == 0x1b) {
1288                         ++i;
1289                         if (i >= length)
1290                                 return NULL;
1291
1292                         c = gsm_single_shift_lookup(&t, buffer[i++]);
1293
1294                         if (c == 0)
1295                                 return NULL;
1296
1297                         j += 2;
1298                 } else {
1299                         c = gsm_locking_shift_lookup(&t, buffer[i++]);
1300                         j += 1;
1301                 }
1302
1303                 res_len += UTF8_LENGTH(c);
1304         }
1305
1306         if (j != num_chars)
1307                 return NULL;
1308
1309         /* Check that the string is padded out to the length by 0xff */
1310         for (; i < length; i++)
1311                 if (buffer[i] != 0xff)
1312                         return NULL;
1313
1314         utf8 = g_try_malloc(res_len + 1);
1315         if (utf8 == NULL)
1316                 return NULL;
1317
1318         i = offset;
1319         out = utf8;
1320
1321         while (out < utf8 + res_len) {
1322                 unsigned short c;
1323
1324                 if (buffer[i] & 0x80)
1325                         c = (buffer[i++] & 0x7f) + ucs2_offset;
1326                 else if (buffer[i] == 0x1b) {
1327                         ++i;
1328                         c = gsm_single_shift_lookup(&t, buffer[i++]);
1329                 } else
1330                         c = gsm_locking_shift_lookup(&t, buffer[i++]);
1331
1332                 out += g_unichar_to_utf8(c, out);
1333         }
1334
1335         *out = '\0';
1336
1337         return utf8;
1338 }
1339
1340 unsigned char *utf8_to_sim_string(const char *utf, int max_length,
1341                                         int *out_length)
1342 {
1343         unsigned char *result;
1344         unsigned char *ucs2;
1345         long gsm_bytes;
1346         gsize converted;
1347
1348         result = convert_utf8_to_gsm(utf, -1, NULL, &gsm_bytes, 0);
1349         if (result) {
1350                 if (gsm_bytes > max_length) {
1351                         gsm_bytes = max_length;
1352                         while (gsm_bytes && result[gsm_bytes - 1] == 0x1b)
1353                                 gsm_bytes -= 1;
1354                 }
1355
1356                 *out_length = gsm_bytes;
1357                 return result;
1358         }
1359
1360         /* NOTE: UCS2 formats with an offset are never used */
1361
1362         ucs2 = (guint8 *) g_convert(utf, -1, "UCS-2BE//TRANSLIT", "UTF-8",
1363                                         NULL, &converted, NULL);
1364         if (ucs2 == NULL)
1365                 return NULL;
1366
1367         if (max_length != -1 && (int) converted + 1 > max_length)
1368                 converted = (max_length - 1) & ~1;
1369
1370         result = g_try_malloc(converted + 1);
1371         if (result == NULL) {
1372                 g_free(ucs2);
1373                 return NULL;
1374         }
1375
1376         *out_length = converted + 1;
1377
1378         result[0] = 0x80;
1379         memcpy(&result[1], ucs2, converted);
1380         g_free(ucs2);
1381
1382         return result;
1383 }
1384
1385 /*!
1386  * Converts UCS2 encoded text to GSM alphabet. The result is unpacked,
1387  * with the 7th bit always 0. If terminator is not 0, a terminator character
1388  * is appended to the result.
1389  *
1390  * Returns the encoded data or NULL if the data could not be encoded. The
1391  * data must be freed by the caller. If items_read is not NULL, it contains
1392  * the actual number of bytes read. If items_written is not NULL, contains
1393  * the number of bytes written.
1394  */
1395 unsigned char *convert_ucs2_to_gsm_with_lang(const unsigned char *text,
1396                                         long len, long *items_read,
1397                                         long *items_written,
1398                                         unsigned char terminator,
1399                                         enum gsm_dialect locking_lang,
1400                                         enum gsm_dialect single_lang)
1401 {
1402         struct conversion_table t;
1403         long nchars = 0;
1404         const unsigned char *in;
1405         unsigned char *out;
1406         unsigned char *res = NULL;
1407         long res_len;
1408         long i;
1409
1410         if (conversion_table_init(&t, locking_lang, single_lang) == FALSE)
1411                 return NULL;
1412
1413         if (len < 1 || len % 2)
1414                 return NULL;
1415
1416         in = text;
1417         res_len = 0;
1418
1419         for (i = 0; i < len; i += 2) {
1420                 gunichar c = (in[i] << 8) | in[i + 1];
1421                 unsigned short converted = GUND;
1422
1423                 if (c > 0xffff)
1424                         goto err_out;
1425
1426                 converted = unicode_locking_shift_lookup(&t, c);
1427
1428                 if (converted == GUND)
1429                         converted = unicode_single_shift_lookup(&t, c);
1430
1431                 if (converted == GUND)
1432                         goto err_out;
1433
1434                 if (converted & 0x1b00)
1435                         res_len += 2;
1436                 else
1437                         res_len += 1;
1438
1439                 nchars += 1;
1440         }
1441
1442         res = g_try_malloc(res_len + (terminator ? 1 : 0));
1443         if (res == NULL)
1444                 goto err_out;
1445
1446         in = text;
1447         out = res;
1448
1449         for (i = 0; i < len; i += 2) {
1450                 gunichar c = (in[i] << 8) | in[i + 1];
1451                 unsigned short converted = GUND;
1452
1453                 converted = unicode_locking_shift_lookup(&t, c);
1454
1455                 if (converted == GUND)
1456                         converted = unicode_single_shift_lookup(&t, c);
1457
1458                 if (converted & 0x1b00) {
1459                         *out = 0x1b;
1460                         ++out;
1461                 }
1462
1463                 *out = converted;
1464                 ++out;
1465         }
1466
1467         if (terminator)
1468                 *out = terminator;
1469
1470         if (items_written)
1471                 *items_written = out - res;
1472
1473 err_out:
1474         if (items_read)
1475                 *items_read = i;
1476
1477         return res;
1478 }
1479
1480 unsigned char *convert_ucs2_to_gsm(const unsigned char *text, long len,
1481                                 long *items_read, long *items_written,
1482                                 unsigned char terminator)
1483 {
1484         return convert_ucs2_to_gsm_with_lang(text, len, items_read,
1485                                                 items_written,
1486                                                 terminator,
1487                                                 GSM_DIALECT_DEFAULT,
1488                                                 GSM_DIALECT_DEFAULT);
1489 }