aaaf97140c11dcbb955f947ec75c525f96652654
[profile/ivi/ofono.git] / unit / test-sms.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
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 version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program 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
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <glib.h>
32 #include <glib/gprintf.h>
33
34 #include "util.h"
35 #include "smsutil.h"
36
37 static const char *simple_deliver = "07911326040000F0"
38                 "040B911346610089F60000208062917314480CC8F71D14969741F977FD07";
39 static const char *alnum_sender = "0791447758100650"
40                 "040DD0F334FC1CA6970100008080312170224008D4F29CDE0EA7D9";
41 static const char *simple_submit = "0011000B916407281553F80000AA"
42                 "0AE8329BFD4697D9EC37";
43
44 static void print_scts(struct sms_scts *scts, const char *prefix)
45 {
46         time_t ts;
47         struct tm remote;
48         char buf[128];
49
50         g_print("%s: (YY-MM-DD) %02d-%02d-%02d\n", prefix,
51                 (int)scts->year, (int)scts->month, (int)scts->day);
52
53         g_print("%s: (HH-MM-SS) %02d:%02d:%02d\n", prefix,
54                 (int)scts->hour, (int)scts->minute, (int)scts->second);
55
56         g_print("%s: Timezone %d hours %d minutes\n", prefix,
57                 (int)scts->timezone / 4,
58                 (int)((abs(scts->timezone) % 4) * 15));
59
60         ts = sms_scts_to_time(scts, &remote);
61
62         strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", localtime(&ts));
63         buf[127] = '\0';
64
65         g_print("local time: %s\n", buf);
66
67         strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", &remote);
68         buf[127] = '\0';
69
70         g_print("remote time: %s\n", buf);
71 }
72
73 static void print_vpf(enum sms_validity_period_format vpf,
74                         struct sms_validity_period *vp)
75 {
76         g_print("Validity Period Format: %d\n", (int)vpf);
77
78         switch (vpf) {
79         case SMS_VALIDITY_PERIOD_FORMAT_ABSENT:
80                 g_print("Validity-Period: Absent\n");
81                 break;
82         case SMS_VALIDITY_PERIOD_FORMAT_RELATIVE:
83                 g_print("Validity-Period: %d\n",
84                         (int)vp->relative);
85                 break;
86         case SMS_VALIDITY_PERIOD_FORMAT_ABSOLUTE:
87                 print_scts(&vp->absolute, "Validity-Period:");
88                 break;
89         case SMS_VALIDITY_PERIOD_FORMAT_ENHANCED:
90                 g_print("Validity-Period: Enhanced");
91                 break;
92         }
93 }
94
95 static void dump_details(struct sms *sms)
96 {
97         if (sms->sc_addr.address[0] == '\0')
98                 g_print("SMSC Address absent, default will be used\n");
99         else
100                 g_print("SMSC Address number_type: %d, number_plan: %d, %s\n",
101                         (int)sms->sc_addr.number_type,
102                         (int)sms->sc_addr.numbering_plan, sms->sc_addr.address);
103
104         switch (sms->type) {
105         case SMS_TYPE_DELIVER:
106                 g_print("Type: Deliver\n");
107
108                 g_print("Originator-Address: %d, %d, %s\n",
109                         (int)sms->deliver.oaddr.number_type,
110                         (int)sms->deliver.oaddr.numbering_plan,
111                         sms->deliver.oaddr.address);
112
113                 g_print("PID: %d\n", (int)sms->deliver.pid);
114                 g_print("DCS: %d\n", (int)sms->deliver.dcs);
115
116                 print_scts(&sms->deliver.scts, "Timestamp");
117
118                 break;
119         case SMS_TYPE_SUBMIT:
120                 g_print("Type: Submit\n");
121
122                 g_print("Message Reference: %u\n", (int)sms->submit.mr);
123
124                 g_print("Destination-Address: %d, %d, %s\n",
125                         (int)sms->submit.daddr.number_type,
126                         (int)sms->submit.daddr.numbering_plan,
127                         sms->submit.daddr.address);
128
129                 g_print("PID: %d\n", (int)sms->submit.pid);
130                 g_print("DCS: %d\n", (int)sms->submit.dcs);
131
132                 print_vpf(sms->submit.vpf, &sms->submit.vp);
133
134                 break;
135         case SMS_TYPE_STATUS_REPORT:
136                 break;
137         case SMS_TYPE_COMMAND:
138         case SMS_TYPE_DELIVER_REPORT_ACK:
139         case SMS_TYPE_DELIVER_REPORT_ERROR:
140         case SMS_TYPE_SUBMIT_REPORT_ACK:
141         case SMS_TYPE_SUBMIT_REPORT_ERROR:
142                 break;
143         }
144 }
145
146 static void test_simple_deliver(void)
147 {
148         struct sms sms;
149         unsigned char *decoded_pdu;
150         long pdu_len;
151         gboolean ret;
152         int data_len;
153         unsigned char *unpacked;
154         char *utf8;
155
156         decoded_pdu = decode_hex(simple_deliver, -1, &pdu_len, 0);
157
158         g_assert(decoded_pdu);
159         g_assert(pdu_len == (long)strlen(simple_deliver) / 2);
160
161         ret = sms_decode(decoded_pdu, pdu_len, FALSE, 30, &sms);
162
163         g_free(decoded_pdu);
164
165         g_assert(ret);
166         g_assert(sms.type == SMS_TYPE_DELIVER);
167
168         if (g_test_verbose())
169                 dump_details(&sms);
170
171         g_assert(sms.sc_addr.number_type == SMS_NUMBER_TYPE_INTERNATIONAL);
172         g_assert(sms.sc_addr.numbering_plan == SMS_NUMBERING_PLAN_ISDN);
173         g_assert(strcmp(sms.sc_addr.address, "31624000000") == 0);
174
175         g_assert(sms.deliver.oaddr.number_type ==
176                         SMS_NUMBER_TYPE_INTERNATIONAL);
177         g_assert(sms.deliver.oaddr.numbering_plan ==
178                         SMS_NUMBERING_PLAN_ISDN);
179         g_assert(strcmp(sms.deliver.oaddr.address, "31641600986") == 0);
180
181         g_assert(sms.deliver.pid == 0);
182         g_assert(sms.deliver.dcs == 0);
183
184         g_assert(sms.deliver.scts.year == 2);
185         g_assert(sms.deliver.scts.month == 8);
186         g_assert(sms.deliver.scts.day == 26);
187         g_assert(sms.deliver.scts.hour == 19);
188         g_assert(sms.deliver.scts.minute == 37);
189         g_assert(sms.deliver.scts.second == 41);
190         g_assert(sms.deliver.scts.timezone == -4);
191
192         g_assert(sms.deliver.udl == 12);
193
194         data_len = sms_udl_in_bytes(sms.deliver.udl, sms.deliver.dcs);
195
196         g_assert(data_len == 11);
197
198         unpacked = unpack_7bit(sms.deliver.ud, data_len, 0, FALSE,
199                                 sms.deliver.udl, NULL, 0xff);
200
201         g_assert(unpacked);
202
203         utf8 = convert_gsm_to_utf8(unpacked, -1, NULL, NULL, 0xff);
204
205         g_free(unpacked);
206
207         g_assert(utf8);
208
209         if (g_test_verbose())
210                 g_print("Decoded user data is: %s\n", utf8);
211
212         g_assert(strcmp(utf8, "How are you?") == 0);
213
214         g_free(utf8);
215 }
216
217 static void test_alnum_sender(void)
218 {
219         struct sms sms;
220         unsigned char *decoded_pdu;
221         long pdu_len;
222         gboolean ret;
223         int data_len;
224         unsigned char *unpacked;
225         char *utf8;
226
227         decoded_pdu = decode_hex(alnum_sender, -1, &pdu_len, 0);
228
229         g_assert(decoded_pdu);
230         g_assert(pdu_len == (long)strlen(alnum_sender) / 2);
231
232         ret = sms_decode(decoded_pdu, pdu_len, FALSE, 27, &sms);
233
234         g_free(decoded_pdu);
235
236         g_assert(ret);
237         g_assert(sms.type == SMS_TYPE_DELIVER);
238
239         if (g_test_verbose())
240                 dump_details(&sms);
241
242         g_assert(sms.sc_addr.number_type == SMS_NUMBER_TYPE_INTERNATIONAL);
243         g_assert(sms.sc_addr.numbering_plan == SMS_NUMBERING_PLAN_ISDN);
244         g_assert(strcmp(sms.sc_addr.address, "447785016005") == 0);
245
246         g_assert(sms.deliver.oaddr.number_type ==
247                         SMS_NUMBER_TYPE_ALPHANUMERIC);
248         g_assert(sms.deliver.oaddr.numbering_plan ==
249                         SMS_NUMBERING_PLAN_UNKNOWN);
250         g_assert(strcmp(sms.deliver.oaddr.address, "sipgate") == 0);
251
252         g_assert(sms.deliver.pid == 0);
253         g_assert(sms.deliver.dcs == 0);
254
255         g_assert(sms.deliver.scts.year == 8);
256         g_assert(sms.deliver.scts.month == 8);
257         g_assert(sms.deliver.scts.day == 13);
258         g_assert(sms.deliver.scts.hour == 12);
259         g_assert(sms.deliver.scts.minute == 07);
260         g_assert(sms.deliver.scts.second == 22);
261         g_assert(sms.deliver.scts.timezone == 4);
262
263         g_assert(sms.deliver.udl == 8);
264
265         data_len = sms_udl_in_bytes(sms.deliver.udl, sms.deliver.dcs);
266
267         g_assert(data_len == 7);
268
269         unpacked = unpack_7bit(sms.deliver.ud, data_len, 0, FALSE,
270                                 sms.deliver.udl, NULL, 0xff);
271
272         g_assert(unpacked);
273
274         utf8 = convert_gsm_to_utf8(unpacked, -1, NULL, NULL, 0xff);
275
276         g_free(unpacked);
277
278         g_assert(utf8);
279
280         if (g_test_verbose())
281                 g_print("Decoded user data is: %s\n", utf8);
282
283         g_assert(strcmp(utf8, "Testmail") == 0);
284
285         g_free(utf8);
286 }
287
288 static void test_deliver_encode(void)
289 {
290         struct sms sms;
291         unsigned char *decoded_pdu;
292         long pdu_len;
293         gboolean ret;
294         unsigned char pdu[176];
295         int encoded_pdu_len;
296         int encoded_tpdu_len;
297         char *encoded_pdu;
298
299         decoded_pdu = decode_hex(simple_deliver, -1, &pdu_len, 0);
300
301         g_assert(decoded_pdu);
302         g_assert(pdu_len == (long)strlen(simple_deliver) / 2);
303
304         ret = sms_decode(decoded_pdu, pdu_len, FALSE, 30, &sms);
305
306         g_free(decoded_pdu);
307
308         g_assert(ret);
309         g_assert(sms.type == SMS_TYPE_DELIVER);
310
311         ret = sms_encode(&sms, &encoded_pdu_len, &encoded_tpdu_len, pdu);
312
313         if (g_test_verbose()) {
314                 int i;
315
316                 for (i = 0; i < encoded_pdu_len; i++)
317                         g_print("%02X", pdu[i]);
318                 g_print("\n");
319         }
320
321         g_assert(ret);
322         g_assert(encoded_tpdu_len == 30);
323         g_assert(encoded_pdu_len == pdu_len);
324
325         encoded_pdu = encode_hex(pdu, encoded_pdu_len, 0);
326
327         g_assert(strcmp(simple_deliver, encoded_pdu) == 0);
328
329         g_free(encoded_pdu);
330
331         decoded_pdu = decode_hex(alnum_sender, -1, &pdu_len, 0);
332
333         g_assert(decoded_pdu);
334         g_assert(pdu_len == (long)strlen(alnum_sender) / 2);
335
336         ret = sms_decode(decoded_pdu, pdu_len, FALSE, 27, &sms);
337
338         g_free(decoded_pdu);
339
340         g_assert(ret);
341         g_assert(sms.type == SMS_TYPE_DELIVER);
342
343         ret = sms_encode(&sms, &encoded_pdu_len, &encoded_tpdu_len, pdu);
344
345         if (g_test_verbose()) {
346                 int i;
347
348                 for (i = 0; i < encoded_pdu_len; i++)
349                         g_print("%02X", pdu[i]);
350                 g_print("\n");
351         }
352
353         g_assert(ret);
354         g_assert(encoded_tpdu_len == 27);
355         g_assert(encoded_pdu_len == pdu_len);
356
357         encoded_pdu = encode_hex(pdu, encoded_pdu_len, 0);
358
359         g_assert(strcmp(alnum_sender, encoded_pdu) == 0);
360
361         g_free(encoded_pdu);
362 }
363
364 static void test_simple_submit(void)
365 {
366         struct sms sms;
367         unsigned char *decoded_pdu;
368         long pdu_len;
369         gboolean ret;
370         int data_len;
371         unsigned char *unpacked;
372         char *utf8;
373
374         decoded_pdu = decode_hex(simple_submit, -1, &pdu_len, 0);
375
376         g_assert(decoded_pdu);
377         g_assert(pdu_len == (long)strlen(simple_submit) / 2);
378
379         ret = sms_decode(decoded_pdu, pdu_len, TRUE, 23, &sms);
380
381         g_free(decoded_pdu);
382
383         g_assert(ret);
384         g_assert(sms.type == SMS_TYPE_SUBMIT);
385
386         if (g_test_verbose())
387                 dump_details(&sms);
388
389         g_assert(strlen(sms.sc_addr.address) == 0);
390
391         g_assert(sms.submit.mr == 0);
392
393         g_assert(sms.submit.daddr.number_type ==
394                         SMS_NUMBER_TYPE_INTERNATIONAL);
395         g_assert(sms.submit.daddr.numbering_plan ==
396                         SMS_NUMBERING_PLAN_ISDN);
397         g_assert(strcmp(sms.submit.daddr.address, "46708251358") == 0);
398
399         g_assert(sms.submit.pid == 0);
400         g_assert(sms.submit.dcs == 0);
401
402         g_assert(sms.submit.vpf == SMS_VALIDITY_PERIOD_FORMAT_RELATIVE);
403         g_assert(sms.submit.vp.relative == 0xAA);
404
405         g_assert(sms.submit.udl == 10);
406
407         data_len = sms_udl_in_bytes(sms.submit.udl, sms.submit.dcs);
408
409         g_assert(data_len == 9);
410
411         unpacked = unpack_7bit(sms.submit.ud, data_len, 0, FALSE,
412                                 sms.submit.udl, NULL, 0xff);
413
414         g_assert(unpacked);
415
416         utf8 = convert_gsm_to_utf8(unpacked, -1, NULL, NULL, 0xff);
417
418         g_free(unpacked);
419
420         g_assert(utf8);
421
422         if (g_test_verbose())
423                 g_print("Decoded user data is: %s\n", utf8);
424
425         g_assert(strcmp(utf8, "hellohello") == 0);
426
427         g_free(utf8);
428 }
429
430 static void test_submit_encode(void)
431 {
432         struct sms sms;
433         unsigned char *decoded_pdu;
434         long pdu_len;
435         gboolean ret;
436         unsigned char pdu[176];
437         int encoded_pdu_len;
438         int encoded_tpdu_len;
439         char *encoded_pdu;
440
441         decoded_pdu = decode_hex(simple_submit, -1, &pdu_len, 0);
442
443         g_assert(decoded_pdu);
444         g_assert(pdu_len == (long)strlen(simple_submit) / 2);
445
446         ret = sms_decode(decoded_pdu, pdu_len, TRUE, 23, &sms);
447
448         g_free(decoded_pdu);
449
450         g_assert(ret);
451         g_assert(sms.type == SMS_TYPE_SUBMIT);
452
453         ret = sms_encode(&sms, &encoded_pdu_len, &encoded_tpdu_len, pdu);
454
455         if (g_test_verbose()) {
456                 int i;
457
458                 for (i = 0; i < encoded_pdu_len; i++)
459                         g_print("%02X", pdu[i]);
460                 g_print("\n");
461         }
462
463         g_assert(ret);
464         g_assert(encoded_tpdu_len == 23);
465         g_assert(encoded_pdu_len == pdu_len);
466
467         encoded_pdu = encode_hex(pdu, encoded_pdu_len, 0);
468
469         g_assert(strcmp(simple_submit, encoded_pdu) == 0);
470
471         g_free(encoded_pdu);
472 }
473
474 struct sms_charset_data {
475         char *pdu;
476         int data_len;
477         enum gsm_dialect locking_lang;
478         enum gsm_dialect single_lang;
479         char expected_text[];
480 };
481
482 static struct sms_charset_data sms_charset_default = {
483         .pdu =
484                 "0001000B91" "5310101010" "1000008080" "8060402818" "0E888462C1"
485                 "68381E9088" "6442A9582E" "988C06C4E9" "783EA09068" "442A994EA8"
486                 "946AC56AB9" "5EB0986C46" "ABD96EB89C" "6EC7EBF97E" "C0A070482C"
487                 "1A8FC8A472" "C96C3A9FD0" "A8744AAD5A" "AFD8AC76CB" "ED7ABFE0B0"
488                 "784C2E9BCF" "E8B47ACD6E" "BBDFF0B87C" "4EAFDBEFF8" "BC7ECFEFFB"
489                 "FF",
490         .data_len = 112,
491         .expected_text = {
492                 0x40, 0xc2, 0xa3, 0x24, 0xc2, 0xa5, 0xc3, 0xa8, 0xc3, 0xa9,
493                 0xc3, 0xb9, 0xc3, 0xac, 0xc3, 0xb2, 0xc3, 0x87, 0x0a, 0xc3,
494                 0x98, 0xc3, 0xb8, 0x0d, 0xc3, 0x85, 0xc3, 0xa5, 0xce, 0x94,
495                 0x5f, 0xce, 0xa6, 0xce, 0x93, 0xce, 0x9b, 0xce, 0xa9, 0xce,
496                 0xa0, 0xce, 0xa8, 0xce, 0xa3, 0xce, 0x98, 0xce, 0x9e, 0x20,
497                 0xc3, 0x86, 0xc3, 0xa6, 0xc3, 0x9f, 0xc3, 0x89, 0x20, 0x21,
498                 0x22, 0x23, 0xc2, 0xa4, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
499                 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
500                 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
501                 0x3f, 0xc2, 0xa1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
502                 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
503                 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xc3,
504                 0x84, 0xc3, 0x96, 0xc3, 0x91, 0xc3, 0x9c, 0xc2, 0xa7, 0xc2,
505                 0xbf, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
506                 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
507                 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xc3, 0xa4, 0xc3,
508                 0xb6, 0xc3, 0xb1, 0xc3, 0xbc, 0xc3, 0xa0, 0x00
509         }
510 };
511
512 static struct sms_charset_data sms_charset_default_ext = {
513         .pdu =
514                 "0001000B91" "5310101010" "100000151B" "C58602DAA0" "36A9CD6BC3"
515                 "DBF436BE0D" "705306",
516         .data_len = 19,
517         .expected_text = {
518                 0x0c, 0x5e, 0x20, 0x7b, 0x7d, 0x5c, 0x5b, 0x7e, 0x5d, 0x7c,
519                 0xe2, 0x82, 0xac, 0x00
520         }
521 };
522
523 static struct sms_charset_data sms_charset_turkey = {
524         .pdu =
525                 "0001000B91" "5310101010" "1000008080" "8060402818" "0E888462C1"
526                 "68381E9088" "6442A9582E" "988C06C4E9" "783EA09068" "442A994EA8"
527                 "946AC56AB9" "5EB0986C46" "ABD96EB89C" "6EC7EBF97E" "C0A070482C"
528                 "1A8FC8A472" "C96C3A9FD0" "A8744AAD5A" "AFD8AC76CB" "ED7ABFE0B0"
529                 "784C2E9BCF" "E8B47ACD6E" "BBDFF0B87C" "4EAFDBEFF8" "BC7ECFEFFB"
530                 "FF",
531         .data_len = 112,
532         .locking_lang = GSM_DIALECT_TURKISH,
533         .expected_text = {
534                 0x40, 0xc2, 0xa3, 0x24, 0xc2, 0xa5, 0xe2, 0x82, 0xac, 0xc3,
535                 0xa9, 0xc3, 0xb9, 0xc4, 0xb1, 0xc3, 0xb2, 0xc3, 0x87, 0x0a,
536                 0xc4, 0x9e, 0xc4, 0x9f, 0x0d, 0xc3, 0x85, 0xc3, 0xa5, 0xce,
537                 0x94, 0x5f, 0xce, 0xa6, 0xce, 0x93, 0xce, 0x9b, 0xce, 0xa9,
538                 0xce, 0xa0, 0xce, 0xa8, 0xce, 0xa3, 0xce, 0x98, 0xce, 0x9e,
539                 0x20, 0xc5, 0x9e, 0xc5, 0x9f, 0xc3, 0x9f, 0xc3, 0x89, 0x20,
540                 0x21, 0x22, 0x23, 0xc2, 0xa4, 0x25, 0x26, 0x27, 0x28, 0x29,
541                 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
542                 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
543                 0x3e, 0x3f, 0xc4, 0xb0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
544                 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
545                 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
546                 0xc3, 0x84, 0xc3, 0x96, 0xc3, 0x91, 0xc3, 0x9c, 0xc2, 0xa7,
547                 0xc3, 0xa7, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
548                 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
549                 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xc3, 0xa4,
550                 0xc3, 0xb6, 0xc3, 0xb1, 0xc3, 0xbc, 0xc3, 0xa0, 0x00
551         }
552 };
553
554 static struct sms_charset_data sms_charset_turkey_ext = {
555         .pdu =
556                 "0001000B91" "5310101010" "1000001A1B" "C586B2416D" "529BD786B7"
557                 "E96D7C1BE0" "02C8011318" "870E",
558         .data_len = 23,
559         .locking_lang = GSM_DIALECT_TURKISH,
560         .single_lang = GSM_DIALECT_TURKISH,
561         .expected_text = {
562                 0x0c, 0x5e, 0x7b, 0x7d, 0x5c, 0x5b, 0x7e, 0x5d, 0x7c, 0xc4,
563                 0x9e, 0xc4, 0xb0, 0xc5, 0x9e, 0xc3, 0xa7, 0xe2, 0x82, 0xac,
564                 0xc4, 0x9f, 0xc4, 0xb1, 0xc5, 0x9f, 0x00
565         }
566 };
567
568 static struct sms_charset_data sms_charset_portugal = {
569         .pdu =
570                 "0001000B91" "5310101010" "1000008080" "8060402818" "0E888462C1"
571                 "68381E9088" "6442A9582E" "988C06C4E9" "783EA09068" "442A994EA8"
572                 "946AC56AB9" "5EB0986C46" "ABD96EB89C" "6EC7EBF97E" "C0A070482C"
573                 "1A8FC8A472" "C96C3A9FD0" "A8744AAD5A" "AFD8AC76CB" "ED7ABFE0B0"
574                 "784C2E9BCF" "E8B47ACD6E" "BBDFF0B87C" "4EAFDBEFF8" "BC7ECFEFFB"
575                 "FF",
576         .data_len = 112,
577         .locking_lang = GSM_DIALECT_PORTUGUESE,
578         .expected_text = {
579                 0x40, 0xc2, 0xa3, 0x24, 0xc2, 0xa5, 0xc3, 0xaa, 0xc3, 0xa9,
580                 0xc3, 0xba, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xa7, 0x0a, 0xc3,
581                 0x94, 0xc3, 0xb4, 0x0d, 0xc3, 0x81, 0xc3, 0xa1, 0xce, 0x94,
582                 0x5f, 0xc2, 0xaa, 0xc3, 0x87, 0xc3, 0x80, 0xe2, 0x88, 0x9e,
583                 0x5e, 0x5c, 0xe2, 0x82, 0xac, 0xc3, 0x93, 0x7c, 0x20, 0xc3,
584                 0x82, 0xc3, 0xa2, 0xc3, 0x8a, 0xc3, 0x89, 0x20, 0x21, 0x22,
585                 0x23, 0xc2, 0xba, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
586                 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
587                 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
588                 0xc3, 0x8d, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
589                 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
590                 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xc3, 0x83,
591                 0xc3, 0x95, 0xc3, 0x9a, 0xc3, 0x9c, 0xc2, 0xa7, 0x7e, 0x61,
592                 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
593                 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
594                 0x76, 0x77, 0x78, 0x79, 0x7a, 0xc3, 0xa3, 0xc3, 0xb5, 0x60,
595                 0xc3, 0xbc, 0xc3, 0xa0, 0x00
596         }
597 };
598
599 static struct sms_charset_data sms_charset_portugal_ext = {
600         .pdu =
601                 "0001000B91" "5310101010" "1000003184" "C446B16038" "1E1BC96662"
602                 "D9543696CD" "6583D9643C" "1BD42675D9" "F0C01B9F86" "02CC74B75C"
603                 "0EE68030EC" "F91D",
604         .data_len = 43,
605         .locking_lang = GSM_DIALECT_PORTUGUESE,
606         .single_lang = GSM_DIALECT_PORTUGUESE,
607         .expected_text = {
608                 0xc3, 0xaa, 0xc3, 0xa7, 0x0c, 0xc3, 0x94, 0xc3, 0xb4, 0xc3,
609                 0x81, 0xc3, 0xa1, 0xce, 0xa6, 0xce, 0x93, 0x5e, 0xce, 0xa9,
610                 0xce, 0xa0, 0xce, 0xa8, 0xce, 0xa3, 0xce, 0x98, 0xc3, 0x8a,
611                 0x7b, 0x7d, 0x5c, 0x5b, 0x7e, 0x5d, 0x7c, 0xc3, 0x80, 0xc3,
612                 0x8d, 0xc3, 0x93, 0xc3, 0x9a, 0xc3, 0x83, 0xc3, 0x95, 0xc3,
613                 0x82, 0xe2, 0x82, 0xac, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba,
614                 0xc3, 0xa3, 0xc3, 0xb5, 0xc3, 0xa2, 0x00
615         }
616 };
617
618 static struct sms_charset_data sms_charset_spain = {
619         .pdu =
620                 "0001000B91" "5310101010" "100000269B" "C446B1A16C" "509BD4E6B5"
621                 "E16D7A1BDF" "06B8096E92" "9BE7A6BA09" "6FCA9BF4E6" "BDA903",
622         .data_len = 34,
623         .locking_lang = GSM_DIALECT_SPANISH,
624         .single_lang = GSM_DIALECT_SPANISH,
625         .expected_text = {
626                 0xc3, 0xa7, 0x0c, 0x5e, 0x7b, 0x7d, 0x5c, 0x5b, 0x7e, 0x5d,
627                 0x7c, 0xc3, 0x81, 0xc3, 0x8d, 0xc3, 0x93, 0xc3, 0x9a, 0xc3,
628                 0xa1, 0xe2, 0x82, 0xac, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba,
629                 0x00
630         }
631 };
632
633 static void test_sms_charset(gconstpointer param)
634 {
635         gboolean ret;
636         struct sms sms;
637         unsigned char *pdu;
638         unsigned char *unpacked;
639         long pdu_len;
640         int data_len;
641         enum sms_charset sms_charset;
642         gboolean sms_compressed;
643         char *text;
644         struct sms_charset_data *data = (struct sms_charset_data *)param;
645
646         pdu = decode_hex(data->pdu, -1, &pdu_len, 0);
647
648         g_assert(pdu);
649         g_assert(pdu_len == (gint64)strlen(data->pdu) / 2);
650
651         ret = sms_decode(pdu, pdu_len, FALSE, pdu_len, &sms);
652
653         g_assert(ret);
654
655         g_free(pdu);
656
657         g_assert(sms.type == SMS_TYPE_DELIVER);
658
659         ret = sms_dcs_decode(sms.deliver.dcs, NULL, &sms_charset,
660                                 &sms_compressed, NULL);
661
662         g_assert(ret);
663         g_assert(sms_charset == SMS_CHARSET_7BIT);
664         g_assert(sms_compressed == FALSE);
665
666         data_len = sms_udl_in_bytes(sms.deliver.udl, sms.deliver.dcs);
667
668         g_assert(data_len == data->data_len);
669
670         unpacked = unpack_7bit(sms.deliver.ud, data_len, 0, FALSE,
671                                 sms.deliver.udl, NULL, 0xff);
672
673         g_assert(unpacked);
674
675         text = convert_gsm_to_utf8_with_lang(unpacked, -1, NULL, NULL, 0xff,
676                 data->locking_lang, data->single_lang);
677
678         g_assert(text);
679
680         g_free(unpacked);
681
682         g_assert(strcmp(data->expected_text, text) == 0);
683
684         g_free(text);
685 }
686
687 struct text_format_header {
688         unsigned char len;
689         unsigned char start;
690         unsigned char span;
691         unsigned char format;
692         unsigned char color;
693 };
694
695 struct ems_udh_test {
696         const char *pdu;
697         unsigned int len;
698         const char *expected;
699         unsigned int udl;
700         unsigned int udhl;
701         unsigned int data_len;
702         struct text_format_header formats[];
703 };
704
705 static struct ems_udh_test ems_udh_test_1 = {
706         .pdu = "0041000B915121551532F40000631A0A031906200A032104100A03270504"
707                 "0A032E05080A043807002B8ACD29A85D9ECFC3E7F21C340EBB41E3B79B1"
708                 "E4EBB41697A989D1EB340E2379BCC02B1C3F27399059AB7C36C3628EC26"
709                 "83C66FF65B5E2683E8653C1D",
710         .len = 100,
711         .expected = "EMS messages can contain italic, bold, large, small and"
712                 " colored text",
713         .formats = {
714                 {
715                         .len = 3,
716                         .start = 0x19,
717                         .span = 0x06,
718                         .format = 0x20,
719                 },
720                 {
721                         .len = 3,
722                         .start = 0x21,
723                         .span = 0x04,
724                         .format = 0x10,
725                 },
726                 {
727                         .len = 3,
728                         .start = 0x27,
729                         .span = 0x05,
730                         .format = 0x04,
731                 },
732                 {
733                         .len = 3,
734                         .start = 0x2E,
735                         .span = 0x05,
736                         .format = 0x08,
737                 },
738                 {
739                         .len = 4,
740                         .start = 0x38,
741                         .span = 0x07,
742                         .format = 0x00,
743                         .color = 0x2B,
744                 },
745                 {
746                         .len = 0,
747                 }
748         },
749         .udl = 99,
750         .udhl = 26,
751         .data_len = 87,
752 };
753
754 static struct ems_udh_test ems_udh_test_2 = {
755         .pdu = "079194712272303351030B915121340195F60000FF80230A030F07230A031"
756                 "806130A031E0A430A032E0D830A033D14020A035104F60A0355010600159"
757                 "D9E83D2735018442FCFE98A243DCC4E97C92C90F8CD26B3407537B92C67A"
758                 "7DD65320B1476934173BA3CBD2ED3D1F277FD8C76299CEF3B280C92A7CF6"
759                 "83A28CC4E9FDD6532E8FE96935D",
760         .len = 126,
761         .expected = "This is a test\nItalied, bold, underlined, and "
762                 "strikethrough.\nNow a right aligned word.",
763         .formats = {
764                 {
765                         .len = 3,
766                         .start = 0x0f,
767                         .span = 0x07,
768                         .format = 0x23,
769                 },
770                 {
771                         .len = 3,
772                         .start = 0x18,
773                         .span = 0x06,
774                         .format = 0x13,
775                 },
776                 {
777                         .len = 3,
778                         .start = 0x1e,
779                         .span = 0x0a,
780                         .format = 0x43,
781                 },
782                 {
783                         .len = 3,
784                         .start = 0x2e,
785                         .span = 0x0d,
786                         .format = 0x83,
787                 },
788                 {
789                         .len = 3,
790                         .start = 0x3d,
791                         .span = 0x14,
792                         .format = 0x02,
793                 },
794                 {
795                         .len = 3,
796                         .start = 0x51,
797                         .span = 0x04,
798                         .format = 0xf6,
799                 },
800                 {
801                         .len = 3,
802                         .start = 0x55,
803                         .span = 0x01,
804                         .format = 0x06,
805                 },
806         },
807         .udl = 128,
808         .udhl = 35,
809         .data_len = 112,
810 };
811
812 static void test_ems_udh(gconstpointer data)
813 {
814         const struct ems_udh_test *test = data;
815         struct sms sms;
816         unsigned char *decoded_pdu;
817         long pdu_len;
818         gboolean ret;
819         unsigned int data_len;
820         unsigned int udhl;
821         struct sms_udh_iter iter;
822         int max_chars;
823         unsigned char *unpacked;
824         char *utf8;
825         int i;
826
827         decoded_pdu = decode_hex(test->pdu, -1, &pdu_len, 0);
828
829         g_assert(decoded_pdu);
830         g_assert(pdu_len == (long)strlen(test->pdu) / 2);
831
832         ret = sms_decode(decoded_pdu, pdu_len, TRUE, test->len, &sms);
833
834         g_free(decoded_pdu);
835
836         g_assert(ret);
837         g_assert(sms.type == SMS_TYPE_SUBMIT);
838
839         if (g_test_verbose())
840                 dump_details(&sms);
841         udhl = sms.submit.ud[0];
842
843         g_assert(sms.submit.udl == test->udl);
844         g_assert(udhl == test->udhl);
845
846         ret = sms_udh_iter_init(&sms, &iter);
847
848         g_assert(ret);
849
850         for (i = 0; test->formats[i].len; i++) {
851                 if (g_test_verbose()) {
852                         int j;
853                         unsigned char data[4];
854
855                         sms_udh_iter_get_ie_data(&iter, data);
856
857                         g_print("Header:\n");
858                         for (j = 0; j < sms_udh_iter_get_ie_length(&iter); j++)
859                                 g_print("0x%02x ", data[j]);
860
861                         g_print("\n");
862                 }
863
864                 g_assert(sms_udh_iter_get_ie_type(&iter) ==
865                                 SMS_IEI_TEXT_FORMAT);
866                 g_assert(sms_udh_iter_get_ie_length(&iter) ==
867                                 test->formats[i].len);
868
869                 if (test->formats[i+1].len) {
870                         g_assert(sms_udh_iter_has_next(&iter) == TRUE);
871                         g_assert(sms_udh_iter_next(&iter) == TRUE);
872                 } else {
873                         g_assert(sms_udh_iter_has_next(&iter) == FALSE);
874                         g_assert(sms_udh_iter_next(&iter) == FALSE);
875                         g_assert(sms_udh_iter_get_ie_type(&iter) ==
876                                         SMS_IEI_INVALID);
877                 }
878         }
879
880         data_len = sms_udl_in_bytes(sms.submit.udl, sms.submit.dcs);
881
882         g_assert(data_len == test->data_len);
883
884         max_chars = (data_len - (udhl + 1)) * 8 / 7;
885
886         unpacked = unpack_7bit(sms.submit.ud + udhl + 1, data_len - (udhl + 1),
887                                 udhl + 1, FALSE, max_chars, NULL, 0xff);
888
889         g_assert(unpacked);
890
891         utf8 = convert_gsm_to_utf8(unpacked, -1, NULL, NULL, 0xff);
892
893         g_free(unpacked);
894
895         g_assert(utf8);
896
897         if (g_test_verbose())
898                 g_print("Decoded user data is: %s\n", utf8);
899
900         g_assert(strcmp(utf8, test->expected) == 0);
901
902         g_free(utf8);
903 }
904
905 static const char *assembly_pdu1 = "038121F340048155550119906041001222048C0500"
906                                         "031E0301041804420430043A002C002004100"
907                                         "43B0435043A04410430043D04340440002000"
908                                         "200441043B044304480430043B00200437043"
909                                         "000200434043204350440044C044E00200020"
910                                         "04380020002004320441043500200431043E0"
911                                         "43B044C044804350020043F04400435043804"
912                                         "41043F043E043B043D044F043B0441044F002"
913                                         "000200433043D0435";
914 static int assembly_pdu_len1 = 155;
915
916 static const char *assembly_pdu2 = "038121F340048155550119906041001222048C0500"
917                                         "031E03020432043E043C002E000A041D04300"
918                                         "43A043E043D04350446002C0020043D043500"
919                                         "200432002004410438043B043004450020043"
920                                         "40430043B043504350020044204350440043F"
921                                         "04350442044C002C0020043E043D002004410"
922                                         "44204400435043C043804420435043B044C04"
923                                         "3D043E002004320431043504360430043B002"
924                                         "004320020043A043E";
925 static int assembly_pdu_len2 = 155;
926
927 static const char *assembly_pdu3 = "038121F340048155550119906041001222044A0500"
928                                         "031E0303043C043D043004420443002C00200"
929                                         "43F043E043704300431044B0432000A043404"
930                                         "3004360435002C002004470442043E0020002"
931                                         "00431044B043B0020043D04300433002E";
932 static int assembly_pdu_len3 = 89;
933
934 static void test_assembly(void)
935 {
936         unsigned char pdu[176];
937         long pdu_len;
938         struct sms sms;
939         struct sms_assembly *assembly = sms_assembly_new(NULL);
940         guint16 ref;
941         guint8 max;
942         guint8 seq;
943         GSList *l;
944         char *utf8;
945         char *reencoded;
946
947         decode_hex_own_buf(assembly_pdu1, -1, &pdu_len, 0, pdu);
948         sms_decode(pdu, pdu_len, FALSE, assembly_pdu_len1, &sms);
949
950         sms_extract_concatenation(&sms, &ref, &max, &seq);
951         l = sms_assembly_add_fragment(assembly, &sms, time(NULL),
952                                         &sms.deliver.oaddr, ref, max, seq);
953
954         if (g_test_verbose()) {
955                 g_print("Ref: %u\n", ref);
956                 g_print("Max: %u\n", max);
957                 g_print("From: %s\n",
958                                 sms_address_to_string(&sms.deliver.oaddr));
959         }
960
961         g_assert(g_slist_length(assembly->assembly_list) == 1);
962         g_assert(l == NULL);
963
964         sms_assembly_expire(assembly, time(NULL) + 40);
965
966         g_assert(g_slist_length(assembly->assembly_list) == 0);
967
968         sms_extract_concatenation(&sms, &ref, &max, &seq);
969         l = sms_assembly_add_fragment(assembly, &sms, time(NULL),
970                                         &sms.deliver.oaddr, ref, max, seq);
971         g_assert(g_slist_length(assembly->assembly_list) == 1);
972         g_assert(l == NULL);
973
974         decode_hex_own_buf(assembly_pdu2, -1, &pdu_len, 0, pdu);
975         sms_decode(pdu, pdu_len, FALSE, assembly_pdu_len2, &sms);
976
977         sms_extract_concatenation(&sms, &ref, &max, &seq);
978         l = sms_assembly_add_fragment(assembly, &sms, time(NULL),
979                                         &sms.deliver.oaddr, ref, max, seq);
980         g_assert(l == NULL);
981
982         decode_hex_own_buf(assembly_pdu3, -1, &pdu_len, 0, pdu);
983         sms_decode(pdu, pdu_len, FALSE, assembly_pdu_len3, &sms);
984
985         sms_extract_concatenation(&sms, &ref, &max, &seq);
986         l = sms_assembly_add_fragment(assembly, &sms, time(NULL),
987                                         &sms.deliver.oaddr, ref, max, seq);
988
989         g_assert(l != NULL);
990
991         utf8 = sms_decode_text(l);
992
993         g_slist_foreach(l, (GFunc)g_free, NULL);
994         g_slist_free(l);
995
996         sms_assembly_free(assembly);
997
998         if (g_test_verbose())
999                 g_printf("Text:\n%s\n", utf8);
1000
1001         l = sms_text_prepare("555", utf8, ref, TRUE, FALSE);
1002         g_assert(l);
1003         g_assert(g_slist_length(l) == 3);
1004
1005         reencoded = sms_decode_text(l);
1006
1007         if (g_test_verbose())
1008                 g_printf("ReEncoded:\n%s\n", reencoded);
1009
1010         g_assert(strcmp(utf8, reencoded) == 0);
1011
1012         g_free(utf8);
1013         g_free(reencoded);
1014 }
1015
1016 static const char *test_no_fragmentation_7bit = "This is testing !";
1017 static const char *expected_no_fragmentation_7bit = "079153485002020911000C915"
1018                         "348870420140000A71154747A0E4ACF41F4F29C9E769F4121";
1019 static const char *sc_addr = "+358405202090";
1020 static const char *da_addr = "+358478400241";
1021 static void test_prepare_7bit(void)
1022 {
1023         GSList *r;
1024         struct sms *sms;
1025         gboolean ret;
1026         unsigned char pdu[176];
1027         int encoded_pdu_len;
1028         int encoded_tpdu_len;
1029         char *encoded_pdu;
1030
1031         r = sms_text_prepare("555", test_no_fragmentation_7bit, 0,
1032                                 FALSE, FALSE);
1033
1034         g_assert(r != NULL);
1035
1036         sms = r->data;
1037
1038         sms->sc_addr.number_type = SMS_NUMBER_TYPE_INTERNATIONAL;
1039         sms->sc_addr.numbering_plan = SMS_NUMBERING_PLAN_ISDN;
1040         strcpy(sms->sc_addr.address, sc_addr+1);
1041
1042         if (g_test_verbose())
1043                 g_print("sc_addr: %s\n", sms_address_to_string(&sms->sc_addr));
1044
1045         g_assert(!strcmp(sc_addr, sms_address_to_string(&sms->sc_addr)));
1046
1047         sms->submit.daddr.number_type = SMS_NUMBER_TYPE_INTERNATIONAL;
1048         sms->submit.daddr.numbering_plan = SMS_NUMBERING_PLAN_ISDN;
1049         strcpy(sms->submit.daddr.address, da_addr+1);
1050
1051         if (g_test_verbose())
1052                 g_print("da_addr: %s\n",
1053                         sms_address_to_string(&sms->submit.daddr));
1054
1055         g_assert(!strcmp(da_addr,
1056                                 sms_address_to_string(&sms->submit.daddr)));
1057
1058         ret = sms_encode(sms, &encoded_pdu_len, &encoded_tpdu_len, pdu);
1059
1060         g_assert(ret);
1061
1062         if (g_test_verbose()) {
1063                 int i;
1064
1065                 for (i = 0; i < encoded_pdu_len; i++)
1066                         g_print("%02X", pdu[i]);
1067                 g_print("\n");
1068         }
1069
1070         encoded_pdu = encode_hex(pdu, encoded_pdu_len, 0);
1071
1072         g_assert(strcmp(expected_no_fragmentation_7bit, encoded_pdu) == 0);
1073
1074         g_free(encoded_pdu);
1075         g_slist_foreach(r, (GFunc)g_free, NULL);
1076         g_slist_free(r);
1077 }
1078
1079 struct sms_concat_data {
1080         const char *str;
1081         unsigned int segments;
1082 };
1083
1084 static struct sms_concat_data shakespeare_test = {
1085         .str = "Shakespeare divided his time between London and Str"
1086         "atford during his career. In 1596, the year before he bought New Plac"
1087         "e as his family home in Stratford, Shakespeare was living in the pari"
1088         "sh of St. Helen's, Bishopsgate, north of the River Thames.",
1089         .segments = 2,
1090 };
1091
1092 /* The string in this test should be padded at the end.  This confuses some
1093  * decoders which do not use udl properly
1094  */
1095 static void test_prepare_concat(gconstpointer data)
1096 {
1097         const struct sms_concat_data *test = data;
1098         GSList *r;
1099         GSList *l;
1100         char *decoded_str;
1101         GSList *pdus = NULL;
1102         unsigned char pdu[176];
1103         struct sms *sms;
1104         struct sms decoded;
1105         int pdu_len, tpdu_len;
1106         struct sms_assembly *assembly = sms_assembly_new(NULL);
1107         guint16 ref;
1108         guint8 max;
1109         guint8 seq;
1110
1111         if (g_test_verbose())
1112                 g_print("strlen: %zd\n", strlen(test->str));
1113
1114         r = sms_text_prepare("+15554449999", test->str, 0, TRUE, FALSE);
1115         g_assert(r);
1116         g_assert(g_slist_length(r) == test->segments);
1117
1118         for (l = r; l; l = l->next) {
1119                 char *strpdu;
1120
1121                 sms = l->data;
1122
1123                 sms_encode(sms, &pdu_len, &tpdu_len, pdu);
1124                 g_assert(pdu_len == (tpdu_len + 1));
1125
1126                 strpdu = encode_hex(pdu, pdu_len, 0);
1127
1128                 if (g_test_verbose())
1129                         g_printf("PDU: %s, len: %d, tlen: %d\n",
1130                                 strpdu, pdu_len, tpdu_len);
1131                 pdus = g_slist_append(pdus, strpdu);
1132         }
1133
1134         g_slist_foreach(r, (GFunc)g_free, NULL);
1135         g_slist_free(r);
1136
1137         for (l = pdus; l; l = l->next) {
1138                 long len;
1139                 gboolean ok;
1140
1141                 decode_hex_own_buf((char *)l->data, -1, &len, 0, pdu);
1142
1143                 if (g_test_verbose())
1144                         g_print("PDU Len: %ld\n", len);
1145
1146                 ok = sms_decode(pdu, len, TRUE, len - 1, &decoded);
1147                 g_assert(ok);
1148
1149                 if (g_test_verbose())
1150                         g_print("Pdu udl: %d\n", (int)decoded.submit.udl);
1151
1152                 sms_extract_concatenation(&decoded, &ref, &max, &seq);
1153                 r = sms_assembly_add_fragment(assembly, &decoded, time(NULL),
1154                                                 &decoded.submit.daddr,
1155                                                 ref, max, seq);
1156         }
1157
1158         g_assert(r);
1159
1160         decoded_str = sms_decode_text(r);
1161
1162         if (g_test_verbose())
1163                 g_printf("Decoded String: %s\n", decoded_str);
1164
1165         g_assert(decoded_str);
1166         g_assert(strcmp(decoded_str, test->str) == 0);
1167         g_free(decoded_str);
1168         sms_assembly_free(assembly);
1169 }
1170
1171 static void test_limit(gunichar uni, int target_size, gboolean use_16bit)
1172 {
1173         char *utf8;
1174         char *decoded;
1175         GSList *l;
1176         unsigned int i;
1177         char utf8_char[6];
1178         unsigned int stride;
1179
1180         stride = g_unichar_to_utf8(uni, utf8_char);
1181
1182         utf8 = g_new0(char, (target_size + 2) * stride);
1183
1184         for (i = 0; i < target_size * stride; i += stride)
1185                 memcpy(utf8 + i, utf8_char, stride);
1186
1187         utf8[i] = '\0';
1188
1189         l = sms_text_prepare("555", utf8, 0, use_16bit, FALSE);
1190
1191         g_assert(l);
1192         g_assert(g_slist_length(l) == 255);
1193
1194         decoded = sms_decode_text(l);
1195         g_assert(g_utf8_strlen(decoded, -1) == target_size);
1196
1197         g_free(decoded);
1198
1199         memcpy(utf8 + i, utf8_char, stride);
1200         utf8[i+stride] = '\0';
1201
1202         l = sms_text_prepare("555", utf8, 0, use_16bit, FALSE);
1203
1204         g_assert(l == NULL);
1205         g_free(utf8);
1206 }
1207
1208 static void test_prepare_limits(void)
1209 {
1210         gunichar ascii = 0x41;
1211         gunichar ucs2 = 0x416;
1212         unsigned int target_size;
1213
1214         /* The limit for 16 bit headers is 255 * 152 for GSM7 */
1215         target_size = 255 * 152;
1216         test_limit(ascii, target_size, TRUE);
1217
1218         /* The limit for 8 bit headers is 255 * 153 for GSM7 */
1219         target_size = 255 * 153;
1220         test_limit(ascii, target_size, FALSE);
1221
1222         /* The limit for 16 bit headers is 255 * 66 for UCS2 */
1223         target_size = 255 * 66;
1224         test_limit(ucs2, target_size, TRUE);
1225
1226         /* The limit for 8 bit headers is 255 * 67 for UCS2 */
1227         target_size = 255 * 67;
1228         test_limit(ucs2, target_size, FALSE);
1229 }
1230
1231 static const char *cbs1 = "011000320111C2327BFC76BBCBEE46A3D168341A8D46A3D1683"
1232         "41A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168"
1233         "341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D100";
1234
1235 static const char *cbs2 = "0110003201114679785E96371A8D46A3D168341A8D46A3D1683"
1236         "41A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168"
1237         "341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D100";
1238
1239 static void test_cbs_encode_decode(void)
1240 {
1241         unsigned char *decoded_pdu;
1242         long pdu_len;
1243         gboolean ret;
1244         struct cbs cbs;
1245         unsigned char pdu[88];
1246         int len;
1247         char *encoded_pdu;
1248         GSList *l;
1249         char iso639_lang[3];
1250         char *utf8;
1251
1252         decoded_pdu = decode_hex(cbs1, -1, &pdu_len, 0);
1253
1254         g_assert(decoded_pdu);
1255         g_assert(pdu_len == (long)strlen(cbs1) / 2);
1256         g_assert(pdu_len == 88);
1257
1258         ret = cbs_decode(decoded_pdu, pdu_len, &cbs);
1259
1260         g_free(decoded_pdu);
1261
1262         g_assert(ret);
1263
1264         g_assert(cbs.gs == CBS_GEO_SCOPE_CELL_IMMEDIATE);
1265         g_assert(cbs.message_code == 17);
1266         g_assert(cbs.update_number == 0);
1267         g_assert(cbs.message_identifier == 50);
1268         g_assert(cbs.dcs == 1);
1269         g_assert(cbs.max_pages == 1);
1270         g_assert(cbs.page == 1);
1271
1272         l = g_slist_append(NULL, &cbs);
1273
1274         utf8 = cbs_decode_text(l, iso639_lang);
1275
1276         g_assert(utf8);
1277
1278         if (g_test_verbose()) {
1279                 g_printf("%s\n", utf8);
1280                 if (iso639_lang[0] == '\0')
1281                         g_printf("Lang: Unspecified\n");
1282                 else
1283                         g_printf("Lang: %s\n", iso639_lang);
1284         }
1285
1286         g_assert(strcmp(utf8, "Belconnen") == 0);
1287         g_assert(strcmp(iso639_lang, "en") == 0);
1288
1289         g_free(utf8);
1290
1291         g_slist_free(l);
1292
1293         ret = cbs_encode(&cbs, &len, pdu);
1294
1295         g_assert(ret);
1296
1297         encoded_pdu = encode_hex(pdu, len, 0);
1298
1299         g_assert(strcmp(cbs1, encoded_pdu) == 0);
1300
1301         g_free(encoded_pdu);
1302 }
1303
1304 static void test_cbs_assembly(void)
1305 {
1306         unsigned char *decoded_pdu;
1307         long pdu_len;
1308         struct cbs dec1;
1309         struct cbs dec2;
1310         struct cbs_assembly *assembly;
1311         char iso639_lang[3];
1312         GSList *l;
1313         char *utf8;
1314
1315         assembly = cbs_assembly_new();
1316
1317         g_assert(assembly);
1318
1319         decoded_pdu = decode_hex(cbs1, -1, &pdu_len, 0);
1320         cbs_decode(decoded_pdu, pdu_len, &dec1);
1321         g_free(decoded_pdu);
1322
1323         decoded_pdu = decode_hex(cbs2, -1, &pdu_len, 0);
1324         cbs_decode(decoded_pdu, pdu_len, &dec2);
1325         g_free(decoded_pdu);
1326
1327         /* Add an initial page to the assembly */
1328         l = cbs_assembly_add_page(assembly, &dec1);
1329         g_assert(l);
1330         g_assert(g_slist_length(assembly->recv_cell) == 1);
1331         g_slist_foreach(l, (GFunc)g_free, NULL);
1332         g_slist_free(l);
1333
1334         /* Can we receive new updates ? */
1335         dec1.update_number = 8;
1336         l = cbs_assembly_add_page(assembly, &dec1);
1337         g_assert(l);
1338         g_assert(g_slist_length(assembly->recv_cell) == 1);
1339         g_slist_foreach(l, (GFunc)g_free, NULL);
1340         g_slist_free(l);
1341
1342         /* Do we ignore old pages ? */
1343         l = cbs_assembly_add_page(assembly, &dec1);
1344         g_assert(l == NULL);
1345
1346         /* Do we ignore older pages ? */
1347         dec1.update_number = 5;
1348         l = cbs_assembly_add_page(assembly, &dec1);
1349         g_assert(l == NULL);
1350
1351         cbs_assembly_location_changed(assembly, TRUE, TRUE, TRUE);
1352         g_assert(assembly->recv_cell == NULL);
1353
1354         dec1.update_number = 9;
1355         dec1.page = 3;
1356         dec1.max_pages = 3;
1357
1358         dec2.update_number = 9;
1359         dec2.page = 2;
1360         dec2.max_pages = 3;
1361
1362         l = cbs_assembly_add_page(assembly, &dec2);
1363         g_assert(l == NULL);
1364         l = cbs_assembly_add_page(assembly, &dec1);
1365         g_assert(l == NULL);
1366
1367         dec1.page = 1;
1368         l = cbs_assembly_add_page(assembly, &dec1);
1369         g_assert(l);
1370
1371         utf8 = cbs_decode_text(l, iso639_lang);
1372
1373         g_assert(utf8);
1374
1375         if (g_test_verbose()) {
1376                 g_printf("%s\n", utf8);
1377                 if (iso639_lang[0] == '\0')
1378                         g_printf("Lang: Unspecified\n");
1379                 else
1380                         g_printf("Lang: %s\n", iso639_lang);
1381         }
1382
1383         g_assert(strcmp(utf8, "BelconnenFraserBelconnen") == 0);
1384
1385         g_free(utf8);
1386         g_slist_foreach(l, (GFunc)g_free, NULL);
1387         g_slist_free(l);
1388
1389         cbs_assembly_free(assembly);
1390 }
1391
1392 static const char *ranges[] = { "1-5, 2, 3, 600, 569-900, 999",
1393                                 "0-20, 33, 44, 50-60, 20-50, 1-5, 5, 3, 5",
1394                                 NULL };
1395 static const char *inv_ranges[] = { "1-5, 3333", "1-5, afbcd", "1-5, 3-5,,",
1396                                         "1-5, 3-5, c", NULL };
1397
1398 static void test_range_minimizer(void)
1399 {
1400         int i = 0;
1401
1402         while (inv_ranges[i]) {
1403                 GSList *l = cbs_extract_topic_ranges(inv_ranges[i]);
1404
1405                 g_assert(l == NULL);
1406                 i++;
1407         }
1408
1409         i = 0;
1410
1411         while (ranges[i]) {
1412                 GSList *r = cbs_extract_topic_ranges(ranges[i]);
1413                 char *rangestr;
1414
1415                 g_assert(r != NULL);
1416                 i++;
1417
1418                 rangestr = cbs_topic_ranges_to_string(r);
1419
1420                 g_assert(rangestr);
1421
1422                 if (g_test_verbose())
1423                         g_print("range: %s\n", rangestr);
1424
1425                 g_free(rangestr);
1426                 g_slist_foreach(r, (GFunc)g_free, NULL);
1427                 g_slist_free(r);
1428         }
1429 }
1430
1431 static void test_sr_assembly(void)
1432 {
1433         const char *sr_pdu1 = "06040D91945152991136F00160124130340A0160124130"
1434                                 "940A00";
1435         const char *sr_pdu2 = "06050D91945152991136F00160124130640A0160124130"
1436                                 "450A00";
1437         const char *sr_pdu3 = "0606098121436587F9019012413064A0019012413045A0"
1438                                 "00";
1439         struct sms sr1;
1440         struct sms sr2;
1441         struct sms sr3;
1442         unsigned char pdu[176];
1443         long pdu_len;
1444         struct status_report_assembly *sra;
1445         gboolean delivered;
1446         struct sms_address addr;
1447         unsigned char sha1[SMS_MSGID_LEN] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
1448                                                 10, 11, 12, 13, 14, 15,
1449                                                 16, 17, 18, 19 };
1450         unsigned char id[SMS_MSGID_LEN];
1451
1452         /* international address, mr 4 & mr 5 */
1453
1454         decode_hex_own_buf(sr_pdu1, -1, &pdu_len, 0, pdu);
1455         g_assert(sms_decode(pdu, pdu_len, FALSE, 26, &sr1) == TRUE);
1456
1457         decode_hex_own_buf(sr_pdu2, -1, &pdu_len, 0, pdu);
1458         g_assert(sms_decode(pdu, pdu_len, FALSE, 26, &sr2) == TRUE);
1459
1460         /* national address, mr 6 */
1461
1462         decode_hex_own_buf(sr_pdu3, -1, &pdu_len, 0, pdu);
1463         g_assert(sms_decode(pdu, pdu_len, FALSE, 24, &sr3) == TRUE);
1464
1465         if (g_test_verbose()) {
1466                 g_print("sr1 address: %s, mr: %d\n",
1467                         sms_address_to_string(&sr1.status_report.raddr),
1468                         sr1.status_report.mr);
1469
1470                 g_print("sr2 address: %s, mr: %d\n",
1471                         sms_address_to_string(&sr2.status_report.raddr),
1472                         sr2.status_report.mr);
1473
1474                 g_print("sr3 address: %s, mr: %d\n",
1475                         sms_address_to_string(&sr3.status_report.raddr),
1476                         sr3.status_report.mr);
1477         }
1478
1479         sms_address_from_string(&addr, "+4915259911630");
1480
1481         sra = status_report_assembly_new(NULL);
1482
1483         status_report_assembly_add_fragment(sra, sha1, &addr, 4, time(NULL), 2);
1484         status_report_assembly_add_fragment(sra, sha1, &addr, 5, time(NULL), 2);
1485
1486         status_report_assembly_expire(sra, time(NULL) + 40);
1487         g_assert(g_hash_table_size(sra->assembly_table) == 0);
1488
1489         status_report_assembly_add_fragment(sra, sha1, &addr, 4, time(NULL), 2);
1490         status_report_assembly_add_fragment(sra, sha1, &addr, 5, time(NULL), 2);
1491
1492         g_assert(!status_report_assembly_report(sra, &sr1, id, &delivered));
1493         g_assert(status_report_assembly_report(sra, &sr2, id, &delivered));
1494
1495         g_assert(memcmp(id, sha1, SMS_MSGID_LEN) == 0);
1496         g_assert(delivered == TRUE);
1497
1498         /*
1499          * Send sms-message in the national address-format,
1500          * but receive in the international address-format.
1501          */
1502         sms_address_from_string(&addr, "9911630");
1503         status_report_assembly_add_fragment(sra, sha1, &addr, 4, time(NULL), 2);
1504         status_report_assembly_add_fragment(sra, sha1, &addr, 5, time(NULL), 2);
1505
1506         g_assert(!status_report_assembly_report(sra, &sr1, id, &delivered));
1507         g_assert(status_report_assembly_report(sra, &sr2, id, &delivered));
1508
1509         g_assert(memcmp(id, sha1, SMS_MSGID_LEN) == 0);
1510         g_assert(delivered == TRUE);
1511         g_assert(g_hash_table_size(sra->assembly_table) == 0);
1512
1513         /*
1514          * Send sms-message in the international address-format,
1515          * but receive in the national address-format.
1516          */
1517         sms_address_from_string(&addr, "+358123456789");
1518         status_report_assembly_add_fragment(sra, sha1, &addr, 6, time(NULL), 1);
1519
1520         g_assert(status_report_assembly_report(sra, &sr3, id, &delivered));
1521
1522         g_assert(memcmp(id, sha1, SMS_MSGID_LEN) == 0);
1523         g_assert(delivered == TRUE);
1524         g_assert(g_hash_table_size(sra->assembly_table) == 0);
1525
1526         status_report_assembly_free(sra);
1527 }
1528
1529 struct wap_push_data {
1530         const char *pdu;
1531         int len;
1532 };
1533
1534 static struct wap_push_data wap_push_1 = {
1535         .pdu = "0791947122725014440185F039F501801140311480720605040B8423F00106"
1536                 "246170706C69636174696F6E2F766E642E7761702E6D6D732D6D657373616"
1537                 "76500AF84B4868C82984F67514B4B42008D9089088045726F74696B009650"
1538                 "696E2D557073008A808E0240008805810303F48083687474703A2F2F65707"
1539                 "3332E64652F4F2F5A39495A4F00",
1540         .len = 128,
1541 };
1542
1543 static void test_wap_push(gconstpointer data)
1544 {
1545         const struct wap_push_data *test = data;
1546         struct sms sms;
1547         unsigned char *decoded_pdu;
1548         gboolean ret;
1549         long pdu_len;
1550         long data_len;
1551         enum sms_class cls;
1552         enum sms_charset charset;
1553         GSList *list;
1554         unsigned char *wap_push;
1555         int dst_port, src_port;
1556         gboolean is_8bit;
1557
1558         decoded_pdu = decode_hex(test->pdu, -1, &pdu_len, 0);
1559
1560         g_assert(decoded_pdu);
1561
1562         ret = sms_decode(decoded_pdu, pdu_len, FALSE, test->len, &sms);
1563
1564         g_free(decoded_pdu);
1565
1566         g_assert(ret);
1567         g_assert(sms.type == SMS_TYPE_DELIVER);
1568
1569         if (g_test_verbose())
1570                 dump_details(&sms);
1571
1572         ret = sms_dcs_decode(sms.deliver.dcs, &cls, &charset, NULL, NULL);
1573
1574         g_assert(ret == TRUE);
1575         g_assert(charset == SMS_CHARSET_8BIT);
1576
1577         g_assert(sms_extract_app_port(&sms, &dst_port, &src_port, &is_8bit));
1578
1579         if (g_test_verbose()) {
1580                 g_print("8bit: %d\n", is_8bit);
1581                 g_print("src: %d, dst: %d\n", src_port, dst_port);
1582         }
1583
1584         g_assert(is_8bit == FALSE);
1585         g_assert(dst_port == 2948);
1586
1587         list = g_slist_append(NULL, &sms);
1588
1589         wap_push = sms_decode_datagram(list, &data_len);
1590
1591         if (g_test_verbose()) {
1592                 int i;
1593
1594                 g_print("data_len: %ld\n", data_len);
1595
1596                 for (i = 0; i < data_len; i++) {
1597                         g_print("%02x", wap_push[i]);
1598
1599                         if ((i % 16) == 15)
1600                                 g_print("\n");
1601                 }
1602
1603                 g_print("\n");
1604         }
1605
1606         g_assert(wap_push);
1607
1608         g_free(wap_push);
1609         g_slist_free(list);
1610 }
1611
1612 int main(int argc, char **argv)
1613 {
1614         char long_string[152*33 + 1];
1615         struct sms_concat_data long_string_test;
1616
1617         g_test_init(&argc, &argv, NULL);
1618
1619         g_test_add_func("/testsms/Test Simple Deliver", test_simple_deliver);
1620         g_test_add_func("/testsms/Test Alnum Deliver", test_alnum_sender);
1621         g_test_add_func("/testsms/Test Deliver Encode", test_deliver_encode);
1622         g_test_add_func("/testsms/Test Simple Submit", test_simple_submit);
1623         g_test_add_func("/testsms/Test Submit Encode", test_submit_encode);
1624
1625         g_test_add_data_func("/testsms/Test "
1626                 "GSM 7 bit Default Alphabet Decode",
1627                 &sms_charset_default, test_sms_charset);
1628
1629         g_test_add_data_func("/testsms/Test "
1630                 "GSM 7 bit Default Alphabet Extension Table Decode",
1631                 &sms_charset_default_ext, test_sms_charset);
1632
1633         g_test_add_data_func("/testsms/Test "
1634                 "Turkish National Language Locking Shift Table Decode",
1635                 &sms_charset_turkey, test_sms_charset);
1636
1637         g_test_add_data_func("/testsms/Test "
1638                 "Turkish National Language Single Shift Table Decode",
1639                 &sms_charset_turkey_ext, test_sms_charset);
1640
1641         g_test_add_data_func("/testsms/Test "
1642                 "Portuguese National Language Locking Shift Table Decode",
1643                 &sms_charset_portugal, test_sms_charset);
1644
1645         g_test_add_data_func("/testsms/Test "
1646                 "Portuguese National Language Single Shift Table Decode",
1647                 &sms_charset_portugal_ext, test_sms_charset);
1648
1649         g_test_add_data_func("/testsms/Test "
1650                 "Spanish National Language Single Shift Table Decode",
1651                 &sms_charset_spain, test_sms_charset);
1652
1653         g_test_add_data_func("/testsms/Test EMS UDH 1",
1654                         &ems_udh_test_1, test_ems_udh);
1655         g_test_add_data_func("/testsms/Test EMS UDH 2",
1656                         &ems_udh_test_2, test_ems_udh);
1657
1658         g_test_add_func("/testsms/Test Assembly", test_assembly);
1659         g_test_add_func("/testsms/Test Prepare 7Bit", test_prepare_7bit);
1660
1661         g_test_add_data_func("/testsms/Test Prepare Concat",
1662                         &shakespeare_test, test_prepare_concat);
1663
1664         memset(long_string, 'a', 152*30);
1665         memset(long_string + 152*30, 'b', 152);
1666         memset(long_string + 152*31, 'c', 152);
1667         memset(long_string + 152*32, 'd', 152);
1668         long_string[152*33] = '\0';
1669
1670         long_string_test.str = long_string;
1671         long_string_test.segments = 33;
1672
1673         g_test_add_data_func("/testsms/Test Prepare Concat 30+ segments",
1674                         &long_string_test, test_prepare_concat);
1675
1676         g_test_add_func("/testsms/Test Prepare Limits", test_prepare_limits);
1677
1678         g_test_add_func("/testsms/Test CBS Encode / Decode",
1679                         test_cbs_encode_decode);
1680         g_test_add_func("/testsms/Test CBS Assembly", test_cbs_assembly);
1681
1682         g_test_add_func("/testsms/Range minimizer", test_range_minimizer);
1683
1684         g_test_add_func("/testsms/Status Report Assembly", test_sr_assembly);
1685
1686         g_test_add_data_func("/testsms/Test WAP Push 1", &wap_push_1,
1687                                 test_wap_push);
1688
1689         return g_test_run();
1690 }