Gammu internals  1.38.0
coding.c
Go to the documentation of this file.
1 /* (c) 2002-2004 by Marcin Wiacek, Michal Cihar and others */
2 /* based on some work from MyGnokii (www.mwiacek.com) */
3 /* based on some work from Gnokii (www.gnokii.org)
4  * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
5  * GNU GPL version 2 or later
6  */
7 /* Due to a problem in the source code management, the names of some of
8  * the authors have unfortunately been lost. We do not mean to belittle
9  * their efforts and hope they will contact us to see their names
10  * properly added to the Copyright notice above.
11  * Having published their contributions under the terms of the GNU
12  * General Public License (GPL) [version 2], the Copyright of these
13  * authors will remain respected by adhering to the license they chose
14  * to publish their code under.
15  */
16 
17 #include <gammu-config.h>
18 
19 #ifdef HAVE_WCHAR_H
20 # include <wchar.h>
21 #endif
22 #ifdef HAVE_WCTYPE_H
23 # include <wctype.h>
24 #endif
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <locale.h>
31 #include <limits.h>
32 #ifdef WIN32
33 # define WIN32_LEAN_AND_MEAN
34 # include <windows.h>
35 #endif
36 
37 #include "../../debug.h"
38 #include "coding.h"
39 
40 /* function changes #10 #13 chars to \n \r */
41 unsigned char *EncodeUnicodeSpecialChars(unsigned char *dest, const unsigned char *buffer)
42 {
43  int Pos=0, Pos2=0;
44 
45  while (buffer[Pos*2]!=0x00 || buffer[Pos*2+1]!=0x00) {
46  if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 10) {
47  dest[Pos2*2] = 0x00;
48  dest[Pos2*2+1] = '\\';
49  Pos2++;
50  dest[Pos2*2] = 0x00;
51  dest[Pos2*2+1] = 'n';
52  Pos2++;
53  } else if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 13) {
54  dest[Pos2*2] = 0x00;
55  dest[Pos2*2+1] = '\\';
56  Pos2++;
57  dest[Pos2*2] = 0x00;
58  dest[Pos2*2+1] = 'r';
59  Pos2++;
60  } else if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == '\\') {
61  dest[Pos2*2] = 0x00;
62  dest[Pos2*2+1] = '\\';
63  Pos2++;
64  dest[Pos2*2] = 0x00;
65  dest[Pos2*2+1] = '\\';
66  Pos2++;
67  } else if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == ';') {
68  dest[Pos2*2] = 0x00;
69  dest[Pos2*2+1] = '\\';
70  Pos2++;
71  dest[Pos2*2] = 0x00;
72  dest[Pos2*2+1] = ';';
73  Pos2++;
74  } else if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == ',') {
75  dest[Pos2*2] = 0x00;
76  dest[Pos2*2+1] = '\\';
77  Pos2++;
78  dest[Pos2*2] = 0x00;
79  dest[Pos2*2+1] = ',';
80  Pos2++;
81  } else {
82  dest[Pos2*2] = buffer[Pos*2];
83  dest[Pos2*2+1] = buffer[Pos*2+1];
84  Pos2++;
85  }
86  Pos++;
87  }
88  dest[Pos2*2] = 0;
89  dest[Pos2*2+1] = 0;
90  return dest;
91 }
92 
93 /* function changes #10 #13 chars to \n \r */
94 char *EncodeSpecialChars(char *dest, const char *buffer)
95 {
96  int Pos=0, Pos2=0;
97 
98  while (buffer[Pos]!=0x00) {
99  switch (buffer[Pos]) {
100  case 10:
101  dest[Pos2++] = '\\';
102  dest[Pos2++] = 'n';
103  break;
104  case 13:
105  dest[Pos2++] = '\\';
106  dest[Pos2++] = 'r';
107  break;
108  case '\\':
109  dest[Pos2++] = '\\';
110  dest[Pos2++] = '\\';
111  break;
112  default:
113  dest[Pos2++] = buffer[Pos];
114  }
115  Pos++;
116  }
117  dest[Pos2] = 0;
118  return dest;
119 }
120 
121 unsigned char *DecodeUnicodeSpecialChars(unsigned char *dest, const unsigned char *buffer)
122 {
123  int Pos=0, Pos2=0, level=0;
124 
125  while (buffer[Pos*2]!=0x00 || buffer[Pos*2+1]!=0x00) {
126  dest[Pos2*2] = buffer[Pos*2];
127  dest[Pos2*2+1] = buffer[Pos*2+1];
128  switch (level) {
129  case 0:
130  if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == '\\') {
131  level = 1;
132  } else {
133  Pos2++;
134  }
135  break;
136  case 1:
137  if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 'n') {
138  dest[Pos2*2] = 0;
139  dest[Pos2*2+1] = 10;
140  } else
141  if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 'r') {
142  dest[Pos2*2] = 0;
143  dest[Pos2*2+1] = 13;
144  } else
145  if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == '\\') {
146  dest[Pos2*2] = 0;
147  dest[Pos2*2+1] = '\\';
148  }
149  Pos2++;
150  level = 0;
151  }
152  Pos++;
153  }
154  dest[Pos2*2] = 0;
155  dest[Pos2*2+1] = 0;
156  return dest;
157 }
158 
159 char *DecodeSpecialChars(char *dest, const char *buffer)
160 {
161  int Pos=0, Pos2=0, level=0;
162 
163  while (buffer[Pos]!=0x00) {
164  dest[Pos2] = buffer[Pos];
165  switch (level) {
166  case 0:
167  if (buffer[Pos] == '\\') {
168  level = 1;
169  } else {
170  Pos2++;
171  }
172  break;
173  case 1:
174  if (buffer[Pos] == 'n') dest[Pos2] = 10;
175  if (buffer[Pos] == 'r') dest[Pos2] = 13;
176  if (buffer[Pos] == '\\') dest[Pos2] = '\\';
177  Pos2++;
178  level = 0;
179  }
180  Pos++;
181  }
182  dest[Pos2] = 0;
183  return dest;
184 }
185 
186 size_t UnicodeLength(const unsigned char *str)
187 {
188  size_t len = 0;
189 
190  if (str == NULL) return 0;
191 
192  while(str[len*2] != 0 || str[len*2+1] != 0) len++;
193 
194  return len;
195 }
196 
197 /* Convert Unicode char saved in src to dest */
198 int EncodeWithUnicodeAlphabet(const unsigned char *src, wchar_t *dest)
199 {
200  int retval;
201 
202  switch (retval = mbtowc(dest, src, MB_CUR_MAX)) {
203  case -1 :
204  case 0 : return 1;
205  default : return retval;
206  }
207 }
208 
209 /* Convert Unicode char saved in src to dest */
210 int DecodeWithUnicodeAlphabet(wchar_t src, unsigned char *dest)
211 {
212  int retval;
213 
214  switch (retval = wctomb(dest, src)) {
215  case -1:
216  *dest = '?';
217  return 1;
218  default:
219  return retval;
220  }
221 }
222 
223 void DecodeUnicode (const unsigned char *src, char *dest)
224 {
225  int i=0,o=0;
226  wchar_t value, second;
227 
228  while (src[(2*i)+1]!=0x00 || src[2*i]!=0x00) {
229  value = src[i * 2] * 256 + src[i * 2 + 1];
230  /* Decode UTF-16 */
231  if (value >= 0xD800 && value <= 0xDBFF) {
232  second = src[(i + 1) * 2] * 256 + src[(i + 1) * 2 + 1];
233  if (second >= 0xDC00 && second <= 0xDFFF) {
234  i++;
235  value = ((value - 0xD800) << 10) + (second - 0xDC00) + 0x010000;
236  }
237  }
238  o += DecodeWithUnicodeAlphabet(value, dest + o);
239  i++;
240  }
241  dest[o]=0;
242 }
243 
244 /* Decode Unicode string and return as function result */
245 char *DecodeUnicodeString (const unsigned char *src)
246 {
247  static char dest[500];
248 
249  DecodeUnicode(src,dest);
250  return dest;
251 }
252 
253 /* Decode Unicode string to UTF8 or other console charset
254  * and return as function result
255  */
256 char *DecodeUnicodeConsole(const unsigned char *src)
257 {
258  static char dest[500];
259 
260  if (GSM_global_debug.coding[0] != 0) {
261  if (!strcmp(GSM_global_debug.coding,"utf8")) {
262  EncodeUTF8(dest, src);
263  } else {
264 #ifdef WIN32
265  setlocale(LC_ALL, GSM_global_debug.coding);
266 #endif
267  DecodeUnicode(src,dest);
268  }
269  } else {
270 #ifdef WIN32
271  setlocale(LC_ALL, ".OCP");
272 #endif
273  DecodeUnicode(src,dest);
274 #ifdef WIN32
275  setlocale(LC_ALL, ".ACP");
276 #endif
277  }
278  return dest;
279 }
280 
281 /* Encode string to Unicode. Len is number of input chars */
282 void DecodeISO88591 (unsigned char *dest, const char *src, size_t len)
283 {
284  size_t i;
285 
286  for (i = 0; i < len; i++) {
287  /* Hack for Euro sign */
288  if ((unsigned char)src[i] == 0x80) {
289  dest[2 * i] = 0x20;
290  dest[(2 * i) + 1] = 0xac;
291  } else {
292  dest[2 * i] = 0;
293  dest[(2 * i) + 1] = src[i];
294  }
295  }
296  dest[2 * i] = 0;
297  dest[(2 * i) + 1] = 0;
298 }
299 
300 /* Encode string to Unicode. Len is number of input chars */
301 void EncodeUnicode (unsigned char *dest, const char *src, size_t len)
302 {
303  size_t i_len = 0, o_len;
304  wchar_t wc;
305 
306  for (o_len = 0; i_len < len; o_len++) {
307  i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
308  dest[o_len*2] = (wc >> 8) & 0xff;
309  dest[(o_len*2)+1] = wc & 0xff;
310  }
311  dest[o_len*2] = 0;
312  dest[(o_len*2)+1] = 0;
313 }
314 
315 unsigned char EncodeWithBCDAlphabet(int value)
316 {
317  div_t division;
318 
319  division=div(value,10);
320  return ( ( (value-division.quot*10) & 0x0f) << 4) | (division.quot & 0xf);
321 }
322 
323 int DecodeWithBCDAlphabet(unsigned char value)
324 {
325  return 10*(value & 0x0f)+(value >> 4);
326 }
327 
328 void DecodeBCD (unsigned char *dest, const unsigned char *src, size_t len)
329 {
330  size_t i,current=0;
331  int digit;
332 
333  for (i = 0; i < len; i++) {
334  digit=src[i] & 0x0f;
335  if (digit<10) dest[current++]=digit + '0';
336  digit=src[i] >> 4;
337  if (digit<10) dest[current++]=digit + '0';
338  }
339  dest[current]=0;
340 }
341 
342 void EncodeBCD (unsigned char *dest, const unsigned char *src, size_t len, gboolean fill)
343 {
344  size_t i,current=0;
345 
346  for (i = 0; i < len; i++) {
347  if (i & 0x01) {
348  dest[current]=dest[current] | ((src[i]-'0') << 4);
349  current++;
350  } else {
351  dest[current]=src[i]-'0';
352  }
353  }
354 
355  /* When fill is set: if number consist of odd number of digits,
356  we fill last bits in last byte with 0x0f
357  */
358  if (fill && (len & 0x01)) dest[current]=dest[current] | 0xf0;
359 }
360 
361 int DecodeWithHexBinAlphabet (unsigned char mychar)
362 {
363  if (mychar >= 'A' && mychar <= 'F')
364  return mychar - 'A' + 10;
365 
366  if (mychar >= 'a' && mychar <= 'f')
367  return mychar - 'a' + 10;
368 
369  if (mychar >= '0' && mychar <= '9')
370  return mychar - '0';
371 
372  return -1;
373 }
374 
375 char EncodeWithHexBinAlphabet (int digit)
376 {
377  if (digit >= 0 && digit <= 9) return '0'+(digit);
378  if (digit >=10 && digit <=15) return 'A'+(digit-10);
379  return 0;
380 }
381 
382 gboolean DecodeHexUnicode (unsigned char *dest, const char *src, size_t len)
383 {
384  size_t i, current = 0;
385  int val0, val1, val2, val3;
386 
387  for (i = 0; i < len ; i += 4) {
388  val0 = DecodeWithHexBinAlphabet(src[i + 0]);
389  val1 = DecodeWithHexBinAlphabet(src[i + 1]);
390  val2 = DecodeWithHexBinAlphabet(src[i + 2]);
391  val3 = DecodeWithHexBinAlphabet(src[i + 3]);
392 
393  if (val0 < 0 || val1 < 0 || val2 < 0 || val3 < 0) {
394  return FALSE;
395  }
396 
397  dest[current++] = (val0 << 4) + val1;
398  dest[current++] = (val2 << 4) + val3;
399  }
400  dest[current++] = 0;
401  dest[current] = 0;
402 
403  return TRUE;
404 }
405 
406 void EncodeHexUnicode (char *dest, const unsigned char *src, size_t len)
407 {
408  EncodeHexBin(dest, src, len * 2);
409 }
410 
411 gboolean DecodeHexBin (unsigned char *dest, const unsigned char *src, size_t len)
412 {
413  size_t i,current=0;
414  int low, high;
415 
416  for (i = 0; i < len/2 ; i++) {
417  low = DecodeWithHexBinAlphabet(src[i*2+1]);
418  high = DecodeWithHexBinAlphabet(src[i*2]);
419  if (low < 0 || high < 0) return FALSE;
420  dest[current++] = (high << 4) | low;
421  }
422  dest[current] = 0;
423  return TRUE;
424 }
425 
426 void EncodeHexBin (char *dest, const unsigned char *src, size_t len)
427 {
428  size_t i, outpos = 0;
429 
430  for (i = 0; i < len; i++) {
431  dest[outpos++] = EncodeWithHexBinAlphabet(src[i] >> 4);
432  dest[outpos++] = EncodeWithHexBinAlphabet(src[i] & 0xF);
433  }
434  dest[outpos] = 0;
435 }
436 
437 /* ETSI GSM 03.38, section 6.2.1: Default alphabet for SMS messages */
438 static unsigned char GSM_DefaultAlphabetUnicode[128+1][2] =
439 {
440  {0x00,0x40},{0x00,0xa3},{0x00,0x24},{0x00,0xA5},
441  {0x00,0xE8},{0x00,0xE9},{0x00,0xF9},{0x00,0xEC},/*0x08*/
442  {0x00,0xF2},{0x00,0xC7},{0x00,'\n'},{0x00,0xD8},
443  {0x00,0xF8},{0x00,'\r'},{0x00,0xC5},{0x00,0xE5},
444  {0x03,0x94},{0x00,0x5f},{0x03,0xA6},{0x03,0x93},
445  {0x03,0x9B},{0x03,0xA9},{0x03,0xA0},{0x03,0xA8},
446  {0x03,0xA3},{0x03,0x98},{0x03,0x9E},{0x00,0xb9},
447  {0x00,0xC6},{0x00,0xE6},{0x00,0xDF},{0x00,0xC9},/*0x20*/
448  {0x00,' ' },{0x00,'!' },{0x00,'\"'},{0x00,'#' },
449  {0x00,0xA4},{0x00,'%' },{0x00,'&' },{0x00,'\''},
450  {0x00,'(' },{0x00,')' },{0x00,'*' },{0x00,'+' },
451  {0x00,',' },{0x00,'-' },{0x00,'.' },{0x00,'/' },/*0x30*/
452  {0x00,'0' },{0x00,'1' },{0x00,'2' },{0x00,'3' },
453  {0x00,'4' },{0x00,'5' },{0x00,'6' },{0x00,'7' },
454  {0x00,'8' },{0x00,'9' },{0x00,':' },{0x00,';' },
455  {0x00,'<' },{0x00,'=' },{0x00,'>' },{0x00,'?' },/*0x40*/
456  {0x00,0xA1},{0x00,'A' },{0x00,'B' },{0x00,'C' },
457  {0x00,'D' },{0x00,'E' },{0x00,'F' },{0x00,'G' },
458  {0x00,'H' },{0x00,'I' },{0x00,'J' },{0x00,'K' },
459  {0x00,'L' },{0x00,'M' },{0x00,'N' },{0x00,'O' },
460  {0x00,'P' },{0x00,'Q' },{0x00,'R' },{0x00,'S' },
461  {0x00,'T' },{0x00,'U' },{0x00,'V' },{0x00,'W' },
462  {0x00,'X' },{0x00,'Y' },{0x00,'Z' },{0x00,0xC4},
463  {0x00,0xD6},{0x00,0xD1},{0x00,0xDC},{0x00,0xA7},
464  {0x00,0xBF},{0x00,'a' },{0x00,'b' },{0x00,'c' },
465  {0x00,'d' },{0x00,'e' },{0x00,'f' },{0x00,'g' },
466  {0x00,'h' },{0x00,'i' },{0x00,'j' },{0x00,'k' },
467  {0x00,'l' },{0x00,'m' },{0x00,'n' },{0x00,'o' },
468  {0x00,'p' },{0x00,'q' },{0x00,'r' },{0x00,'s' },
469  {0x00,'t' },{0x00,'u' },{0x00,'v' },{0x00,'w' },
470  {0x00,'x' },{0x00,'y' },{0x00,'z' },{0x00,0xE4},
471  {0x00,0xF6},{0x00,0xF1},{0x00,0xFC},{0x00,0xE0},
472  {0x00,0x00}
473 };
474 
475 /* ETSI GSM 3.38
476  * Some sequences of 2 default alphabet chars (for example,
477  * 0x1b, 0x65) are visible as one single additional char (for example,
478  * 0x1b, 0x65 gives Euro char saved in Unicode as 0x20, 0xAC)
479  * This table contains:
480  * 1. two first char means second char from the sequence of chars from GSM default alphabet (first being 0x1b)
481  * 2. two second is target (encoded) char saved in Unicode
482  */
483 static unsigned char GSM_DefaultAlphabetCharsExtension[][3] =
484 {
485  {0x0a,0x00,0x0c}, /* \r */
486  {0x14,0x00,0x5e}, /* ^ */
487  {0x28,0x00,0x7b}, /* { */
488  {0x29,0x00,0x7d}, /* } */
489  {0x2f,0x00,0x5c}, /* \ */
490  {0x3c,0x00,0x5b}, /* [ */
491  {0x3d,0x00,0x7E}, /* ~ */
492  {0x3e,0x00,0x5d}, /* ] */
493  {0x40,0x00,0x7C}, /* | */
494  {0x65,0x20,0xAC}, /* Euro */
495  {0x00,0x00,0x00}
496 };
497 
498 void DecodeDefault (unsigned char *dest, const unsigned char *src, size_t len, gboolean UseExtensions, unsigned char *ExtraAlphabet)
499 {
500  size_t pos, current = 0, i;
501 
502 #ifdef DEBUG
503  DumpMessageText(&GSM_global_debug, src, len);
504 #endif
505 
506  for (pos = 0; pos < len; pos++) {
507  if ((pos < (len - 1)) && UseExtensions && src[pos] == 0x1b) {
508  for (i = 0; GSM_DefaultAlphabetCharsExtension[i][0] != 0x00; i++) {
509  if (GSM_DefaultAlphabetCharsExtension[i][0] == src[pos + 1]) {
510  dest[current++] = GSM_DefaultAlphabetCharsExtension[i][1];
511  dest[current++] = GSM_DefaultAlphabetCharsExtension[i][2];
512  pos++;
513  break;
514  }
515  }
516  /* Skip rest if we've found something */
517  if (GSM_DefaultAlphabetCharsExtension[i][0] != 0x00) {
518  continue;
519  }
520  }
521  if (ExtraAlphabet != NULL) {
522  for (i = 0; ExtraAlphabet[i] != 0x00; i += 3) {
523  if (ExtraAlphabet[i] == src[pos]) {
524  dest[current++] = ExtraAlphabet[i + 1];
525  dest[current++] = ExtraAlphabet[i + 2];
526  break;
527  }
528  }
529  /* Skip rest if we've found something */
530  if (ExtraAlphabet[i] != 0x00) {
531  continue;
532  }
533  }
534  dest[current++] = GSM_DefaultAlphabetUnicode[src[pos]][0];
535  dest[current++] = GSM_DefaultAlphabetUnicode[src[pos]][1];
536  }
537  dest[current++]=0;
538  dest[current]=0;
539 #ifdef DEBUG
541 #endif
542 }
543 
544 /* There are many national chars with "adds". In phone they're normally
545  * changed to "plain" Latin chars. We have such functionality too.
546  * This table is automatically created from convert.txt file (see
547  * /docs/developers) using --makeconverttable. It contains such chars
548  * to replace in order:
549  * 1. original char (Unicode) 2. destination char (Unicode)
550  */
551 static unsigned char ConvertTable[] =
552 "\x00\xc0\x00\x41" \
553 "\x00\xe0\x00\x61" \
554 "\x00\xc1\x00\x41" \
555 "\x00\xe1\x00\x61" \
556 "\x00\xc2\x00\x41" \
557 "\x00\xe2\x00\x61" \
558 "\x00\xc3\x00\x41" \
559 "\x00\xe3\x00\x61" \
560 "\x1e\xa0\x00\x41" \
561 "\x1e\xa1\x00\x61" \
562 "\x1e\xa2\x00\x41" \
563 "\x1e\xa3\x00\x61" \
564 "\x1e\xa4\x00\x41" \
565 "\x1e\xa5\x00\x61" \
566 "\x1e\xa6\x00\x41" \
567 "\x1e\xa7\x00\x61" \
568 "\x1e\xa8\x00\x41" \
569 "\x1e\xa9\x00\x61" \
570 "\x1e\xaa\x00\x41" \
571 "\x1e\xab\x00\x61" \
572 "\x1e\xac\x00\x41" \
573 "\x1e\xad\x00\x61" \
574 "\x1e\xae\x00\x41" \
575 "\x1e\xaf\x00\x61" \
576 "\x1e\xb0\x00\x41" \
577 "\x1e\xb1\x00\x61" \
578 "\x1e\xb2\x00\x41" \
579 "\x1e\xb3\x00\x61" \
580 "\x1e\xb4\x00\x41" \
581 "\x1e\xb5\x00\x61" \
582 "\x1e\xb6\x00\x41" \
583 "\x1e\xb7\x00\x61" \
584 "\x01\xcd\x00\x41" \
585 "\x01\xce\x00\x61" \
586 "\x01\x00\x00\x41" \
587 "\x01\x01\x00\x61" \
588 "\x01\x02\x00\x41" \
589 "\x01\x03\x00\x61" \
590 "\x01\x04\x00\x41" \
591 "\x01\x05\x00\x61" \
592 "\x01\xfb\x00\x61" \
593 "\x01\x06\x00\x43" \
594 "\x01\x07\x00\x63" \
595 "\x01\x08\x00\x43" \
596 "\x01\x09\x00\x63" \
597 "\x01\x0a\x00\x43" \
598 "\x01\x0b\x00\x63" \
599 "\x01\x0c\x00\x43" \
600 "\x01\x0d\x00\x63" \
601 "\x00\xe7\x00\x63" \
602 "\x01\x0e\x00\x44" \
603 "\x01\x0f\x00\x64" \
604 "\x01\x10\x00\x44" \
605 "\x01\x11\x00\x64" \
606 "\x00\xc8\x00\x45" \
607 "\x00\xca\x00\x45" \
608 "\x00\xea\x00\x65" \
609 "\x00\xcb\x00\x45" \
610 "\x00\xeb\x00\x65" \
611 "\x1e\xb8\x00\x45" \
612 "\x1e\xb9\x00\x65" \
613 "\x1e\xba\x00\x45" \
614 "\x1e\xbb\x00\x65" \
615 "\x1e\xbc\x00\x45" \
616 "\x1e\xbd\x00\x65" \
617 "\x1e\xbe\x00\x45" \
618 "\x1e\xbf\x00\x65" \
619 "\x1e\xc0\x00\x45" \
620 "\x1e\xc1\x00\x65" \
621 "\x1e\xc2\x00\x45" \
622 "\x1e\xc3\x00\x65" \
623 "\x1e\xc4\x00\x45" \
624 "\x1e\xc5\x00\x65" \
625 "\x1e\xc6\x00\x45" \
626 "\x1e\xc7\x00\x65" \
627 "\x01\x12\x00\x45" \
628 "\x01\x13\x00\x65" \
629 "\x01\x14\x00\x45" \
630 "\x01\x15\x00\x65" \
631 "\x01\x16\x00\x45" \
632 "\x01\x17\x00\x65" \
633 "\x01\x18\x00\x45" \
634 "\x01\x19\x00\x65" \
635 "\x01\x1a\x00\x45" \
636 "\x01\x1b\x00\x65" \
637 "\x01\x1c\x00\x47" \
638 "\x01\x1d\x00\x67" \
639 "\x01\x1e\x00\x47" \
640 "\x01\x1f\x00\x67" \
641 "\x01\x20\x00\x47" \
642 "\x01\x21\x00\x67" \
643 "\x01\x22\x00\x47" \
644 "\x01\x23\x00\x67" \
645 "\x01\x24\x00\x48" \
646 "\x01\x25\x00\x68" \
647 "\x01\x26\x00\x48" \
648 "\x01\x27\x00\x68" \
649 "\x00\xcc\x00\x49" \
650 "\x00\xcd\x00\x49" \
651 "\x00\xed\x00\x69" \
652 "\x00\xce\x00\x49" \
653 "\x00\xee\x00\x69" \
654 "\x00\xcf\x00\x49" \
655 "\x00\xef\x00\x69" \
656 "\x01\x28\x00\x49" \
657 "\x01\x29\x00\x69" \
658 "\x01\x2a\x00\x49" \
659 "\x01\x2b\x00\x69" \
660 "\x01\x2c\x00\x49" \
661 "\x01\x2d\x00\x69" \
662 "\x01\x2e\x00\x49" \
663 "\x01\x2f\x00\x69" \
664 "\x01\x30\x00\x49" \
665 "\x01\x31\x00\x69" \
666 "\x01\xcf\x00\x49" \
667 "\x01\xd0\x00\x69" \
668 "\x1e\xc8\x00\x49" \
669 "\x1e\xc9\x00\x69" \
670 "\x1e\xca\x00\x49" \
671 "\x1e\xcb\x00\x69" \
672 "\x01\x34\x00\x4a" \
673 "\x01\x35\x00\x6a" \
674 "\x01\x36\x00\x4b" \
675 "\x01\x37\x00\x6b" \
676 "\x01\x39\x00\x4c" \
677 "\x01\x3a\x00\x6c" \
678 "\x01\x3b\x00\x4c" \
679 "\x01\x3c\x00\x6c" \
680 "\x01\x3d\x00\x4c" \
681 "\x01\x3e\x00\x6c" \
682 "\x01\x3f\x00\x4c" \
683 "\x01\x40\x00\x6c" \
684 "\x01\x41\x00\x4c" \
685 "\x01\x42\x00\x6c" \
686 "\x01\x43\x00\x4e" \
687 "\x01\x44\x00\x6e" \
688 "\x01\x45\x00\x4e" \
689 "\x01\x46\x00\x6e" \
690 "\x01\x47\x00\x4e" \
691 "\x01\x48\x00\x6e" \
692 "\x01\x49\x00\x6e" \
693 "\x00\xd2\x00\x4f" \
694 "\x00\xd3\x00\x4f" \
695 "\x00\xf3\x00\x6f" \
696 "\x00\xd4\x00\x4f" \
697 "\x00\xf4\x00\x6f" \
698 "\x00\xd5\x00\x4f" \
699 "\x00\xf5\x00\x6f" \
700 "\x01\x4c\x00\x4f" \
701 "\x01\x4d\x00\x6f" \
702 "\x01\x4e\x00\x4f" \
703 "\x01\x4f\x00\x6f" \
704 "\x01\x50\x00\x4f" \
705 "\x01\x51\x00\x6f" \
706 "\x01\xa0\x00\x4f" \
707 "\x01\xa1\x00\x6f" \
708 "\x01\xd1\x00\x4f" \
709 "\x01\xd2\x00\x6f" \
710 "\x1e\xcc\x00\x4f" \
711 "\x1e\xcd\x00\x6f" \
712 "\x1e\xce\x00\x4f" \
713 "\x1e\xcf\x00\x6f" \
714 "\x1e\xd0\x00\x4f" \
715 "\x1e\xd1\x00\x6f" \
716 "\x1e\xd2\x00\x4f" \
717 "\x1e\xd3\x00\x6f" \
718 "\x1e\xd4\x00\x4f" \
719 "\x1e\xd5\x00\x6f" \
720 "\x1e\xd6\x00\x4f" \
721 "\x1e\xd7\x00\x6f" \
722 "\x1e\xd8\x00\x4f" \
723 "\x1e\xd9\x00\x6f" \
724 "\x1e\xda\x00\x4f" \
725 "\x1e\xdb\x00\x6f" \
726 "\x1e\xdc\x00\x4f" \
727 "\x1e\xdd\x00\x6f" \
728 "\x1e\xde\x00\x4f" \
729 "\x1e\xdf\x00\x6f" \
730 "\x1e\xe0\x00\x4f" \
731 "\x1e\xe1\x00\x6f" \
732 "\x1e\xe2\x00\x4f" \
733 "\x1e\xe3\x00\x6f" \
734 "\x01\x54\x00\x52" \
735 "\x01\x55\x00\x72" \
736 "\x01\x56\x00\x52" \
737 "\x01\x57\x00\x72" \
738 "\x01\x58\x00\x52" \
739 "\x01\x59\x00\x72" \
740 "\x01\x5a\x00\x53" \
741 "\x01\x5b\x00\x73" \
742 "\x01\x5c\x00\x53" \
743 "\x01\x5d\x00\x73" \
744 "\x01\x5e\x00\x53" \
745 "\x01\x5f\x00\x73" \
746 "\x01\x60\x00\x53" \
747 "\x01\x61\x00\x73" \
748 "\x01\x62\x00\x54" \
749 "\x01\x63\x00\x74" \
750 "\x01\x64\x00\x54" \
751 "\x01\x65\x00\x74" \
752 "\x01\x66\x00\x54" \
753 "\x01\x67\x00\x74" \
754 "\x00\xd9\x00\x55" \
755 "\x00\xda\x00\x55" \
756 "\x00\xfa\x00\x75" \
757 "\x00\xdb\x00\x55" \
758 "\x00\xfb\x00\x75" \
759 "\x01\x68\x00\x55" \
760 "\x01\x69\x00\x75" \
761 "\x01\x6a\x00\x55" \
762 "\x01\x6b\x00\x75" \
763 "\x01\x6c\x00\x55" \
764 "\x01\x6d\x00\x75" \
765 "\x01\x6e\x00\x55" \
766 "\x01\x6f\x00\x75" \
767 "\x01\x70\x00\x55" \
768 "\x01\x71\x00\x75" \
769 "\x01\x72\x00\x55" \
770 "\x01\x73\x00\x75" \
771 "\x01\xaf\x00\x55" \
772 "\x01\xb0\x00\x75" \
773 "\x01\xd3\x00\x55" \
774 "\x01\xd4\x00\x75" \
775 "\x01\xd5\x00\x55" \
776 "\x01\xd6\x00\x75" \
777 "\x01\xd7\x00\x55" \
778 "\x01\xd8\x00\x75" \
779 "\x01\xd9\x00\x55" \
780 "\x01\xda\x00\x75" \
781 "\x01\xdb\x00\x55" \
782 "\x01\xdc\x00\x75" \
783 "\x1e\xe4\x00\x55" \
784 "\x1e\xe5\x00\x75" \
785 "\x1e\xe6\x00\x55" \
786 "\x1e\xe7\x00\x75" \
787 "\x1e\xe8\x00\x55" \
788 "\x1e\xe9\x00\x75" \
789 "\x1e\xea\x00\x55" \
790 "\x1e\xeb\x00\x75" \
791 "\x1e\xec\x00\x55" \
792 "\x1e\xed\x00\x75" \
793 "\x1e\xee\x00\x55" \
794 "\x1e\xef\x00\x75" \
795 "\x1e\xf0\x00\x55" \
796 "\x1e\xf1\x00\x75" \
797 "\x01\x74\x00\x57" \
798 "\x01\x75\x00\x77" \
799 "\x1e\x80\x00\x57" \
800 "\x1e\x81\x00\x77" \
801 "\x1e\x82\x00\x57" \
802 "\x1e\x83\x00\x77" \
803 "\x1e\x84\x00\x57" \
804 "\x1e\x85\x00\x77" \
805 "\x00\xdd\x00\x59" \
806 "\x00\xfd\x00\x79" \
807 "\x00\xff\x00\x79" \
808 "\x01\x76\x00\x59" \
809 "\x01\x77\x00\x79" \
810 "\x01\x78\x00\x59" \
811 "\x1e\xf2\x00\x59" \
812 "\x1e\xf3\x00\x75" \
813 "\x1e\xf4\x00\x59" \
814 "\x1e\xf5\x00\x79" \
815 "\x1e\xf6\x00\x59" \
816 "\x1e\xf7\x00\x79" \
817 "\x1e\xf8\x00\x59" \
818 "\x1e\xf9\x00\x79" \
819 "\x01\x79\x00\x5a" \
820 "\x01\x7a\x00\x7a" \
821 "\x01\x7b\x00\x5a" \
822 "\x01\x7c\x00\x7a" \
823 "\x01\x7d\x00\x5a" \
824 "\x01\x7e\x00\x7a" \
825 "\x01\xfc\x00\xc6" \
826 "\x01\xfd\x00\xe6" \
827 "\x01\xfe\x00\xd8" \
828 "\x01\xff\x00\xf8" \
829 "\x00\x00";
830 
831 void EncodeDefault(unsigned char *dest, const unsigned char *src, size_t *len, gboolean UseExtensions, unsigned char *ExtraAlphabet)
832 {
833  size_t i,current=0;
834  int j,z;
835  char ret;
836  gboolean FoundSpecial,FoundNormal;
837 
838 #ifdef DEBUG
839  DumpMessageText(&GSM_global_debug, src, (*len)*2);
840 #endif
841 
842  for (i = 0; i < *len; i++) {
843  FoundSpecial = FALSE;
844  j = 0;
845  while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00 && UseExtensions) {
846  if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][1] &&
847  src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][2]) {
848  dest[current++] = 0x1b;
849  dest[current++] = GSM_DefaultAlphabetCharsExtension[j][0];
850  FoundSpecial = TRUE;
851  break;
852  }
853  j++;
854  }
855  if (!FoundSpecial) {
856  ret = '?';
857  FoundNormal = FALSE;
858  j = 0;
859  while (GSM_DefaultAlphabetUnicode[j][1]!=0x00) {
860  if (src[i*2] == GSM_DefaultAlphabetUnicode[j][0] &&
861  src[i*2+1] == GSM_DefaultAlphabetUnicode[j][1]) {
862  ret = j;
863  FoundNormal = TRUE;
864  break;
865  }
866  j++;
867  }
868  if (ExtraAlphabet!=NULL && !FoundNormal) {
869  j = 0;
870  while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) {
871  if (ExtraAlphabet[j+1] == src[i*2] &&
872  ExtraAlphabet[j+2] == src[i*2 + 1]) {
873  ret = ExtraAlphabet[j];
874  FoundSpecial = TRUE;
875  break;
876  }
877  j=j+3;
878  }
879  }
880  if (!FoundNormal && !FoundSpecial) {
881  j = 0;
882  FoundNormal = FALSE;
883  while (ConvertTable[j*4] != 0x00 ||
884  ConvertTable[j*4+1] != 0x00) {
885  if (src[i*2] == ConvertTable[j*4] &&
886  src[i*2+1] == ConvertTable[j*4+1]) {
887  z = 0;
888  while (GSM_DefaultAlphabetUnicode[z][1]!=0x00) {
889  if (ConvertTable[j*4+2] == GSM_DefaultAlphabetUnicode[z][0] &&
890  ConvertTable[j*4+3] == GSM_DefaultAlphabetUnicode[z][1]) {
891  ret = z;
892  FoundNormal = TRUE;
893  break;
894  }
895  z++;
896  }
897  if (FoundNormal) break;
898  }
899  j++;
900  }
901  }
902  dest[current++]=ret;
903  }
904  }
905  dest[current]=0;
906 #ifdef DEBUG
907  DumpMessageText(&GSM_global_debug, dest, current);
908 #endif
909 
910  *len = current;
911 }
912 
913 /* You don't have to use ConvertTable here - 1 char is replaced there by 1 char */
914 void FindDefaultAlphabetLen(const unsigned char *src, size_t *srclen, size_t *smslen, size_t maxlen)
915 {
916  size_t current=0,j,i;
917  gboolean FoundSpecial;
918 
919  i = 0;
920  while (src[i*2] != 0x00 || src[i*2+1] != 0x00) {
921  FoundSpecial = FALSE;
922  j = 0;
923  while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) {
924  if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][1] &&
925  src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][2]) {
926  FoundSpecial = TRUE;
927  if (current+2 > maxlen) {
928  *srclen = i;
929  *smslen = current;
930  return;
931  }
932  current+=2;
933  break;
934  }
935  j++;
936  }
937  if (!FoundSpecial) {
938  if (current+1 > maxlen) {
939  *srclen = i;
940  *smslen = current;
941  return;
942  }
943  current++;
944  }
945  i++;
946  }
947  *srclen = i;
948  *smslen = current;
949 }
950 
951 #define ByteMask ((1 << Bits) - 1)
952 
953 int GSM_UnpackEightBitsToSeven(size_t offset, size_t in_length, size_t out_length,
954  const unsigned char *input, unsigned char *output)
955 {
956  /* (c) by Pavel Janik and Pawel Kot */
957 
958  unsigned char *output_pos = output; /* Current pointer to the output buffer */
959  const unsigned char *input_pos = input; /* Current pointer to the input buffer */
960  unsigned char Rest = 0x00;
961  size_t Bits;
962 
963  Bits = offset ? offset : 7;
964 
965  while ((size_t)(input_pos - input) < in_length) {
966 
967  *output_pos = ((*input_pos & ByteMask) << (7 - Bits)) | Rest;
968  Rest = *input_pos >> Bits;
969 
970  /* If we don't start from 0th bit, we shouldn't go to the
971  next char. Under *output_pos we have now 0 and under Rest -
972  _first_ part of the char. */
973  if ((input_pos != input) || (Bits == 7)) output_pos++;
974  input_pos++;
975 
976  if ((size_t)(output_pos - output) >= out_length) break;
977 
978  /* After reading 7 octets we have read 7 full characters but
979  we have 7 bits as well. This is the next character */
980  if (Bits == 1) {
981  *output_pos = Rest;
982  output_pos++;
983  Bits = 7;
984  Rest = 0x00;
985  } else {
986  Bits--;
987  }
988  }
989 
990  return output_pos - output;
991 }
992 
993 int GSM_PackSevenBitsToEight(size_t offset, const unsigned char *input, unsigned char *output, size_t length)
994 {
995  /* (c) by Pavel Janik and Pawel Kot */
996 
997  unsigned char *output_pos = output; /* Current pointer to the output buffer */
998  const unsigned char *input_pos = input; /* Current pointer to the input buffer */
999  int Bits; /* Number of bits directly copied to
1000  * the output buffer */
1001  Bits = (7 + offset) % 8;
1002 
1003  /* If we don't begin with 0th bit, we will write only a part of the
1004  first octet */
1005  if (offset) {
1006  *output_pos = 0x00;
1007  output_pos++;
1008  }
1009 
1010  while ((size_t)(input_pos - input) < length) {
1011  unsigned char Byte = *input_pos;
1012 
1013  *output_pos = Byte >> (7 - Bits);
1014  /* If we don't write at 0th bit of the octet, we should write
1015  a second part of the previous octet */
1016  if (Bits != 7)
1017  *(output_pos-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1);
1018 
1019  Bits--;
1020 
1021  if (Bits == -1) Bits = 7; else output_pos++;
1022 
1023  input_pos++;
1024  }
1025  return (output_pos - output);
1026 }
1027 
1028 GSM_Error GSM_UnpackSemiOctetNumber(GSM_Debug_Info *di, unsigned char *retval, const unsigned char *Number, size_t *pos, size_t bufferlength, gboolean semioctet)
1029 {
1030  unsigned char Buffer[GSM_MAX_NUMBER_LENGTH + 1];
1031  size_t length = Number[*pos];
1032  GSM_Error ret = ERR_NONE;
1033 
1034  smfprintf(di, "Number Length=%ld\n", (long)length);
1035 
1036  if (length == 0) {
1037  strcpy(Buffer, "");
1038  goto out;
1039  }
1040 
1041  /* Default ouput on error */
1042  strcpy(Buffer, "<NOT DECODED>");
1043 
1044  if (length > bufferlength) {
1045  smfprintf(di, "Number too long!\n");
1046  return ERR_UNKNOWN;
1047  }
1048 
1049  if (semioctet) {
1050  /* Convert number of semioctets to number of chars */
1051  if (length % 2) length++;
1052  length=length / 2 + 1;
1053  }
1054 
1055  /* Check length */
1056  if (length > GSM_MAX_NUMBER_LENGTH) {
1057  smfprintf(di, "Number too big, not decoding! (Length=%ld, MAX=%d)\n", (long)length, GSM_MAX_NUMBER_LENGTH);
1058  ret = ERR_UNKNOWN;
1059  goto out;
1060  }
1061 
1062  /*without leading byte with format of number*/
1063  length--;
1064 
1065  smfprintf(di, "Number type %02x (%d %d %d %d|%d %d %d %d)\n", Number[*pos + 1],
1066  Number[*pos + 1] & 0x80 ? 1 : 0,
1067  Number[*pos + 1] & 0x40 ? 1 : 0,
1068  Number[*pos + 1] & 0x20 ? 1 : 0,
1069  Number[*pos + 1] & 0x10 ? 1 : 0,
1070  Number[*pos + 1] & 0x08 ? 1 : 0,
1071  Number[*pos + 1] & 0x04 ? 1 : 0,
1072  Number[*pos + 1] & 0x02 ? 1 : 0,
1073  Number[*pos + 1] & 0x01 ? 1 : 0
1074  );
1075 
1076  if ((Number[*pos + 1] & 0x80) == 0) {
1077  smfprintf(di, "Numbering plan not supported!\n");
1078  ret = ERR_UNKNOWN;
1079  goto out;
1080  }
1081 
1082  switch ((Number[*pos + 1] & 0x70)) {
1084  if (length > 6) length++;
1085  smfprintf(di, "Alphanumeric number, length %ld\n", (long)length);
1086  GSM_UnpackEightBitsToSeven(0, length, length, Number+*pos+2, Buffer);
1087  Buffer[length]=0;
1088  break;
1090  smfprintf(di, "International number\n");
1091  Buffer[0]='+';
1092  DecodeBCD(Buffer+1,Number+*pos+2, length);
1093  break;
1094  default:
1095  DecodeBCD (Buffer, Number+*pos+2, length);
1096  break;
1097  }
1098 
1099  smfprintf(di, "Len %ld\n", (long)length);
1100 out:
1101  EncodeUnicode(retval,Buffer,strlen(Buffer));
1102  if (semioctet) {
1103  *pos += 2 + ((Number[*pos] + 1) / 2);
1104  } else {
1105  *pos += 1 + Number[*pos];
1106  }
1107  return ret;
1108 }
1109 
1125 int GSM_PackSemiOctetNumber(const unsigned char *Number, unsigned char *Output, gboolean semioctet)
1126 {
1127  unsigned char format;
1128  int length, i, skip = 0;
1129  unsigned char *buffer;
1130 
1131  length = UnicodeLength(Number);
1132  buffer = (unsigned char*)malloc(length + 2);
1133 
1134  if (buffer == NULL) {
1135  return 0;
1136  }
1137 
1138  DecodeUnicode(Number, buffer);
1139 
1140  /* Checking for format number */
1141  if (buffer[0] == '+') {
1143  skip = 1;
1144  } else if (buffer[0] == '0' && buffer[1] == '0') {
1146  skip = 2;
1147  } else if (buffer[0] == '+' && buffer[1] == '0' && buffer[2] == '0') {
1148  /* This is obviously wrong, but try to cope with that */
1150  skip = 3;
1151  } else {
1153  }
1154  for (i = 0; i < length; i++) {
1155  /* If there is something which can not be in normal
1156  * number, mark it as alphanumberic */
1157  if (strchr("+0123456789*#pP", buffer[i]) == NULL) {
1159  }
1160  }
1161 
1166  Output[0]=format;
1167 
1168  /* After number type we will have number. GSM 03.40 section 9.1.2 */
1169  switch (format) {
1171  length=GSM_PackSevenBitsToEight(0, buffer, Output+1, strlen(buffer))*2;
1172  if (strlen(buffer)==7) length--;
1173  break;
1175  length -= skip;
1176  EncodeBCD (Output+1, buffer + skip, length, TRUE);
1177  break;
1178  default:
1179  EncodeBCD (Output+1, buffer, length, TRUE);
1180  break;
1181  }
1182 
1183  free(buffer);
1184 
1185  if (semioctet) return length;
1186 
1187  /* Convert number of semioctets to number of chars */
1188  if (length % 2) length++;
1189  return length / 2 + 1;
1190 }
1191 
1192 void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
1193 {
1194  int j = 0;
1195 
1196  /* No need to copy if both are on same address */
1197  if (Dest == Source) return;
1198 
1199  while (Source[j]!=0x00 || Source[j+1]!=0x00) {
1200  Dest[j] = Source[j];
1201  Dest[j+1] = Source[j+1];
1202  j=j+2;
1203  }
1204  Dest[j] = 0;
1205  Dest[j+1] = 0;
1206 }
1207 
1208 /* Changes minor/major order in Unicode string */
1209 void ReverseUnicodeString(unsigned char *String)
1210 {
1211  int j = 0;
1212  unsigned char byte1, byte2;
1213 
1214  while (String[j]!=0x00 || String[j+1]!=0x00) {
1215  byte1 = String[j];
1216  byte2 = String[j+1];
1217  String[j+1] = byte1;
1218  String[j] = byte2;
1219  j=j+2;
1220  }
1221  String[j] = 0;
1222  String[j+1] = 0;
1223 }
1224 
1225 /* All input is in Unicode. First char can show Unicode minor/major order.
1226  Output is Unicode string in Gammu minor/major order */
1227 void ReadUnicodeFile(unsigned char *Dest, const unsigned char *Source)
1228 {
1229  int j = 0, current = 0;
1230 
1231  if (Source[0] == 0xFF && Source[1] == 0xFE) j = 2;
1232  if (Source[0] == 0xFE && Source[1] == 0xFF) j = 2;
1233 
1234  while (Source[j]!=0x00 || Source[j+1]!=0x00) {
1235  if (Source[0] == 0xFF) {
1236  Dest[current++] = Source[j+1];
1237  Dest[current++] = Source[j];
1238  } else {
1239  Dest[current++] = Source[j];
1240  Dest[current++] = Source[j+1];
1241  }
1242  j=j+2;
1243  }
1244  Dest[current++] = 0;
1245  Dest[current] = 0;
1246 }
1247 
1248 int GetBit(unsigned char *Buffer, size_t BitNum)
1249 {
1250  return Buffer[BitNum / 8] & (1 << (7 - (BitNum % 8)));
1251 }
1252 
1253 int SetBit(unsigned char *Buffer, size_t BitNum)
1254 {
1255  return Buffer[BitNum / 8] |= 1 << (7 - (BitNum % 8));
1256 }
1257 
1258 int ClearBit(unsigned char *Buffer, size_t BitNum)
1259 {
1260  return Buffer[BitNum / 8] &= 255 - (1 << (7 - (BitNum % 8)));
1261 }
1262 
1263 void BufferAlign(unsigned char *Destination, size_t *CurrentBit)
1264 {
1265  int i=0;
1266 
1267  while(((*CurrentBit) + i) % 8 != 0) {
1268  ClearBit(Destination, (*CurrentBit)+i);
1269  i++;
1270  }
1271 
1272  (*CurrentBit) = (*CurrentBit) + i;
1273 }
1274 
1275 void BufferAlignNumber(size_t *CurrentBit)
1276 {
1277  int i=0;
1278 
1279  while(((*CurrentBit) + i) % 8 != 0) {
1280  i++;
1281  }
1282 
1283  (*CurrentBit) = (*CurrentBit) + i;
1284 }
1285 
1286 void AddBuffer(unsigned char *Destination,
1287  size_t *CurrentBit,
1288  unsigned char *Source,
1289  size_t BitsToProcess)
1290 {
1291  size_t i;
1292 
1293  for (i = 0; i < BitsToProcess; i++) {
1294  if (GetBit(Source, i)) {
1295  SetBit(Destination, (*CurrentBit)+i);
1296  } else {
1297  ClearBit(Destination, (*CurrentBit)+i);
1298  }
1299  }
1300  (*CurrentBit) = (*CurrentBit) + BitsToProcess;
1301 }
1302 
1303 void AddBufferByte(unsigned char *Destination,
1304  size_t *CurrentBit,
1305  unsigned char Source,
1306  size_t BitsToProcess)
1307 {
1308  AddBuffer(Destination, CurrentBit, &Source, BitsToProcess);
1309 }
1310 
1311 void GetBuffer(unsigned char *Source,
1312  size_t *CurrentBit,
1313  unsigned char *Destination,
1314  size_t BitsToProcess)
1315 {
1316  size_t i=0;
1317 
1318  while (i!=BitsToProcess) {
1319  if (GetBit(Source, (*CurrentBit)+i)) {
1320  SetBit(Destination, i);
1321  } else {
1322  ClearBit(Destination, i);
1323  }
1324  i++;
1325  }
1326  (*CurrentBit) = (*CurrentBit) + BitsToProcess;
1327 }
1328 
1329 void GetBufferInt(unsigned char *Source,
1330  size_t *CurrentBit,
1331  int *integer,
1332  size_t BitsToProcess)
1333 {
1334  size_t l=0,z=128,i=0;
1335 
1336  while (i!=BitsToProcess) {
1337  if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
1338  z=z/2;
1339  i++;
1340  }
1341  *integer=l;
1342  (*CurrentBit) = (*CurrentBit) + i;
1343 }
1344 
1345 void GetBufferI(unsigned char *Source,
1346  size_t *CurrentBit,
1347  int *result,
1348  size_t BitsToProcess)
1349 {
1350  size_t l=0,z,i=0;
1351 
1352  z = 1<<(BitsToProcess-1);
1353 
1354  while (i!=BitsToProcess) {
1355  if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
1356  z=z>>1;
1357  i++;
1358  }
1359  *result=l;
1360  (*CurrentBit) = (*CurrentBit) + i;
1361 }
1362 
1363 /* Unicode char 0x00 0x01 makes blinking in some Nokia phones.
1364  * We replace single ~ chars into it. When user give double ~, it's replaced
1365  * to single ~
1366  */
1367 void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
1368 {
1369  size_t i,current = 0;
1370  gboolean special=FALSE;
1371 
1372  for (i = 0; i < len; i++) {
1373  if (special) {
1374  if (src[i*2] == 0x00 && src[i*2+1] == '~') {
1375  dest[current++] = 0x00;
1376  dest[current++] = '~';
1377  } else {
1378  dest[current++] = 0x00;
1379  dest[current++] = 0x01;
1380  dest[current++] = src[i*2];
1381  dest[current++] = src[i*2+1];
1382  }
1383  special = FALSE;
1384  } else {
1385  if (src[i*2] == 0x00 && src[i*2+1] == '~') {
1386  special = TRUE;
1387  } else {
1388  dest[current++] = src[i*2];
1389  dest[current++] = src[i*2+1];
1390  }
1391  }
1392  }
1393  if (special) {
1394  dest[current++] = 0x00;
1395  dest[current++] = 0x01;
1396  }
1397  dest[current++] = 0x00;
1398  dest[current] = 0x00;
1399 }
1400 
1401 void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
1402 {
1403  size_t i=0,current=0;
1404 
1405  for (i=0;i<len;i++) {
1406  switch (src[2*i]) {
1407  case 0x00:
1408  switch (src[2*i+1]) {
1409  case 0x01:
1410  dest[current++] = 0x00;
1411  dest[current++] = '~';
1412  break;
1413  case '~':
1414  dest[current++] = 0x00;
1415  dest[current++] = '~';
1416  dest[current++] = 0x00;
1417  dest[current++] = '~';
1418  break;
1419  default:
1420  dest[current++] = src[i*2];
1421  dest[current++] = src[i*2+1];
1422  }
1423  break;
1424  default:
1425  dest[current++] = src[i*2];
1426  dest[current++] = src[i*2+1];
1427  }
1428  }
1429  dest[current++] = 0x00;
1430  dest[current] = 0x00;
1431 }
1432 
1433 
1434 /* Compares two Unicode strings without regarding to case.
1435  * Return TRUE, when they're equal
1436  */
1437 gboolean mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
1438 {
1439  int i;
1440  wchar_t wc,wc2;
1441 
1442  if (a == NULL || b == NULL) return FALSE;
1443 
1444  if (num == 0) num = -1;
1445 
1446  for (i = 0; i != num; i++) {
1447  if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) && (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return TRUE;
1448  if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) || (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return FALSE;
1449  wc = a[i*2+1] | (a[i*2] << 8);
1450  wc2 = b[i*2+1] | (b[i*2] << 8);
1451  if (towlower(wc) != towlower(wc2)) return FALSE;
1452  }
1453  return TRUE;
1454 }
1455 
1456 /* wcscmp in Mandrake 9.0 is wrong */
1457 gboolean mywstrncmp(unsigned const char *a, unsigned const char *b, int num)
1458 {
1459  int i=0;
1460 
1461  while (1) {
1462  if (a[i*2] != b[i*2] || a[i*2+1] != b[i*2+1]) return FALSE;
1463  if (a[i*2] == 0x00 && a[i*2+1] == 0x00) return TRUE;
1464  i++;
1465  if (num == i) return TRUE;
1466  }
1467 }
1468 
1469 /* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
1470 gboolean myiswspace(unsigned const char *src)
1471 {
1472 #ifndef HAVE_ISWSPACE
1473  int o;
1474  unsigned char dest[10];
1475 #endif
1476  wchar_t wc;
1477 
1478  wc = src[1] | (src[0] << 8);
1479 
1480 #ifndef HAVE_ISWSPACE
1481  o = DecodeWithUnicodeAlphabet(wc, dest);
1482  if (o == 1) {
1483  if (isspace(((int)dest[0]))!=0) return TRUE;
1484  return FALSE;
1485  }
1486  return FALSE;
1487 #else
1488  if (iswspace(wc)) return TRUE;
1489  return FALSE;
1490 #endif
1491 }
1492 
1493 /*
1494  * Following code is based on wcsstr from the GNU C Library, original
1495  * comment follows:
1496  */
1497 /*
1498  * The original strstr() file contains the following comment:
1499  *
1500  * My personal strstr() implementation that beats most other algorithms.
1501  * Until someone tells me otherwise, I assume that this is the
1502  * fastest implementation of strstr() in C.
1503  * I deliberately chose not to comment it. You should have at least
1504  * as much fun trying to understand it, as I had to write it :-).
1505  *
1506  * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
1507 
1508 unsigned char *mywstrstr (const unsigned char *haystack, const unsigned char *needle)
1509 {
1510 /* One crazy define to convert unicode used in Gammu to standard wchar_t */
1511 #define tolowerwchar(x) (towlower((wchar_t)( (((&(x))[0] & 0xff) << 8) | (((&(x))[1] & 0xff)) )))
1512  register wint_t a, b, c;
1513  register const unsigned char *rhaystack, *rneedle;
1514 
1515 
1516  if ((b = tolowerwchar(*needle)) != L'\0') {
1517  haystack -= 2; /* possible ANSI violation */
1518  do {
1519  haystack += 2;
1520  if ((c = tolowerwchar(*haystack)) == L'\0')
1521  goto ret0;
1522  } while (c != b);
1523 
1524  needle += 2;
1525  if ((c = tolowerwchar(*needle)) == L'\0')
1526  goto foundneedle;
1527  needle += 2;
1528  goto jin;
1529 
1530  for (;;) {
1531  do {
1532  haystack += 2;
1533  if ((a = tolowerwchar(*haystack)) == L'\0')
1534  goto ret0;
1535  if (a == b)
1536  break;
1537  haystack += 2;
1538  if ((a = tolowerwchar(*haystack)) == L'\0')
1539  goto ret0;
1540 shloop: ;
1541  } while (a != b);
1542 
1543 jin: haystack += 2;
1544  if ((a = tolowerwchar(*haystack)) == L'\0')
1545  goto ret0;
1546 
1547  if (a != c)
1548  goto shloop;
1549 
1550  rhaystack = haystack + 2;
1551  haystack -= 2;
1552  rneedle = needle;
1553  if (tolowerwchar(*rhaystack) == (a = tolowerwchar(*rneedle)))
1554  do {
1555  if (a == L'\0')
1556  goto foundneedle;
1557  rhaystack += 2;
1558  needle += 2;
1559  if (tolowerwchar(*rhaystack) != (a = tolowerwchar(*needle)))
1560  break ;
1561  if (a == L'\0')
1562  goto foundneedle;
1563  rhaystack += 2;
1564  needle += 2;
1565  } while (tolowerwchar(*rhaystack) == (a = tolowerwchar(*needle)));
1566 
1567  needle = rneedle; /* took the register-poor approach */
1568 
1569  if (a == L'\0')
1570  break;
1571  }
1572  }
1573 foundneedle:
1574  return (unsigned char *)haystack;
1575 ret0:
1576  return NULL;
1577 #undef tolowerwchar
1578 }
1579 
1580 GSM_Error MyGetLine(char *Buffer, size_t *Pos, char *OutBuffer, size_t MaxLen, size_t MaxOutLen, gboolean MergeLines)
1581 {
1582  gboolean skip = FALSE;
1583  gboolean quoted_printable = FALSE;
1584  gboolean was_cr = FALSE, was_lf = FALSE;
1585  size_t pos;
1586  int tmp;
1587 
1588  OutBuffer[0] = 0;
1589  pos = 0;
1590  if (Buffer == NULL) return ERR_NONE;
1591  for (; (*Pos) < MaxLen; (*Pos)++) {
1592  switch (Buffer[*Pos]) {
1593  case 0x00:
1594  return ERR_NONE;
1595  case 0x0A:
1596  case 0x0D:
1597  if (skip) {
1598  if (Buffer[*Pos] == 0x0d) {
1599  if (was_cr && skip) return ERR_NONE;
1600  was_cr = TRUE;
1601  } else {
1602  if (was_lf && skip) return ERR_NONE;
1603  was_lf = TRUE;
1604  }
1605  } else {
1606  if (MergeLines) {
1607  /* (Quote printable new line) Does string end with = ? */
1608  if (quoted_printable && pos > 0 && OutBuffer[pos - 1] == '=') {
1609  pos--;
1610  OutBuffer[pos] = 0;
1611  skip = TRUE;
1612  was_cr = (Buffer[*Pos] == 0x0d);
1613  was_lf = (Buffer[*Pos] == 0x0a);
1614  break;
1615  }
1616  /* (vCard continuation) Next line start with space? */
1617  tmp = *Pos + 1;
1618  if (Buffer[*Pos + 1] == 0x0a || Buffer[*Pos + 1] == 0x0d) {
1619  tmp += 1;
1620  }
1621  if (Buffer[tmp] == ' ') {
1622  *Pos = tmp;
1623  break;
1624  }
1625  /* We ignore empty lines in this mode */
1626  if (pos == 0) {
1627  continue;
1628  }
1629  }
1630  if (Buffer[*Pos] == 0x0d && (*Pos)+1 < MaxLen && Buffer[*Pos + 1] == 0x0a) {
1631  /* Skip \r\n */
1632  (*Pos) += 2;
1633  } else {
1634  /* Skip single \r or \n */
1635  (*Pos)++;
1636  }
1637  return ERR_NONE;
1638  }
1639  break;
1640  default:
1641  /* Detect quoted printable for possible escaping */
1642  if (Buffer[*Pos] == ':' &&
1643  strstr(OutBuffer, ";ENCODING=QUOTED-PRINTABLE") != NULL) {
1644  quoted_printable = TRUE;
1645  }
1646  skip = FALSE;
1647  OutBuffer[pos] = Buffer[*Pos];
1648  pos++;
1649  OutBuffer[pos] = 0;
1650  if (pos + 1 >= MaxOutLen) return ERR_MOREMEMORY;
1651  }
1652  }
1653  return ERR_NONE;
1654 }
1655 
1656 GSM_Error GSM_GetVCSLine(char **OutBuffer, char *Buffer, size_t *Pos, size_t MaxLen, gboolean MergeLines)
1657 {
1658  gboolean skip = FALSE;
1659  gboolean quoted_printable = FALSE;
1660  gboolean was_cr = FALSE, was_lf = FALSE;
1661  size_t pos=0;
1662  int tmp=0;
1663  size_t OutLen = 200;
1664 
1665  *OutBuffer = (char *)malloc(OutLen);
1666  if (*OutBuffer == NULL) return ERR_MOREMEMORY;
1667  (*OutBuffer)[0] = 0;
1668  pos = 0;
1669  if (Buffer == NULL) return ERR_NONE;
1670  while ((*Pos) < MaxLen) {
1671  switch (Buffer[*Pos]) {
1672  case 0x00:
1673  return ERR_NONE;
1674  case 0x0A:
1675  case 0x0D:
1676  if (skip) {
1677  if (Buffer[*Pos] == 0x0d) {
1678  if (was_cr && skip) return ERR_NONE;
1679  was_cr = TRUE;
1680  } else {
1681  if (was_lf && skip) return ERR_NONE;
1682  was_lf = TRUE;
1683  }
1684  }
1685  if (pos != 0 && !skip) {
1686  if (MergeLines) {
1687  /* (Quote printable new line) Does string end with = ? */
1688  if ((*OutBuffer)[pos - 1] == '=' && quoted_printable) {
1689  pos--;
1690  (*OutBuffer)[pos] = 0;
1691  skip = TRUE;
1692  was_cr = (Buffer[*Pos] == 0x0d);
1693  was_lf = (Buffer[*Pos] == 0x0a);
1694  break;
1695  }
1696  /* (vCard continuation) Next line start with space? */
1697  tmp = *Pos + 1;
1698  if (Buffer[*Pos + 1] == 0x0a || Buffer[*Pos + 1] == 0x0d) {
1699  tmp += 1;
1700  }
1701  if (Buffer[tmp] == ' ') {
1702  *Pos = tmp;
1703  break;
1704  }
1705  }
1706  return ERR_NONE;
1707  }
1708  break;
1709  default:
1710  /* Detect quoted printable for possible escaping */
1711  if (Buffer[*Pos] == ':' &&
1712  strstr(*OutBuffer, ";ENCODING=QUOTED-PRINTABLE") != NULL) {
1713  quoted_printable = TRUE;
1714  }
1715  skip = FALSE;
1716  (*OutBuffer)[pos] = Buffer[*Pos];
1717  pos++;
1718  (*OutBuffer)[pos] = 0;
1719  if (pos + 2 >= OutLen) {
1720  OutLen += 100;
1721  *OutBuffer = (char *)realloc(*OutBuffer, OutLen);
1722  if (*OutBuffer == NULL) return ERR_MOREMEMORY;
1723  }
1724  }
1725  (*Pos)++;
1726  }
1727  return ERR_NONE;
1728 }
1729 
1730 
1731 void StringToDouble(char *text, double *d)
1732 {
1733  gboolean before=TRUE;
1734  double multiply = 1;
1735  unsigned int i;
1736 
1737  *d = 0;
1738  for (i=0;i<strlen(text);i++) {
1739  if (isdigit((int)text[i])) {
1740  if (before) {
1741  (*d)=(*d)*10+(text[i]-'0');
1742  } else {
1743  multiply=multiply*0.1;
1744  (*d)=(*d)+(text[i]-'0')*multiply;
1745  }
1746  }
1747  if (text[i]=='.' || text[i]==',') before=FALSE;
1748  }
1749 }
1750 
1751 /* When char can be converted, convert it from Unicode to UTF8 */
1752 int EncodeWithUTF8Alphabet(unsigned long src, unsigned char *ret)
1753 {
1754  if (src < 0x80) {
1755  ret[0] = src;
1756  return 1;
1757  } else if (src < 0x800) {
1758  ret[0] = 192 + (src / 64);
1759  ret[1] = 128 + (src % 64);
1760  return 2;
1761  } else if (src < 0x10000) {
1762  ret[0] = 224 + (src / (64 * 64));
1763  ret[1] = 128 + ((src / 64) % 64);
1764  ret[2] = 128 + (src % 64);
1765  return 3;
1766  } else if (src < 0x200000) {
1767  ret[0] = 240 + (src / (64 * 64 * 64));
1768  ret[1] = 128 + ((src / (64 * 64)) % 64);
1769  ret[2] = 128 + ((src / 64) % 64);
1770  ret[3] = 128 + (src % 64);
1771  return 4;
1772  } else if (src < 0x4000000) {
1773  ret[0] = 248 + (src / (64 * 64 * 64 * 64));
1774  ret[1] = 128 + ((src / (64 * 64 * 64)) % 64);
1775  ret[2] = 128 + ((src / (64 * 64)) % 64);
1776  ret[3] = 128 + ((src / 64) % 64);
1777  ret[4] = 128 + (src % 64);
1778  return 5;
1779  } else if (src < 0x80000000L) {
1780  ret[0] = 252 + (src / (64 * 64 * 64 * 64 * 64));
1781  ret[1] = 128 + ((src / (64 * 64 * 64 * 64)) % 64);
1782  ret[2] = 128 + ((src / (64 * 64 * 64)) % 64);
1783  ret[3] = 128 + ((src / (64 * 64)) % 64);
1784  ret[4] = 128 + ((src / 64) % 64);
1785  ret[5] = 128 + (src % 64);
1786  return 6;
1787  }
1788 
1789  ret[0] = src;
1790  return 1;
1791 }
1792 
1793 /* Make UTF8 string from Unicode input string */
1794 gboolean EncodeUTF8QuotedPrintable(char *dest, const unsigned char *src)
1795 {
1796  size_t i, j=0, z, w, len;
1797  unsigned char mychar[8];
1798  gboolean retval = FALSE;
1799  unsigned long value, second;
1800 
1801  len = UnicodeLength(src);
1802 
1803  for (i = 0; i < len; i++) {
1804  value = src[i * 2] * 256 + src[i * 2 + 1];
1805  /* Decode UTF-16 */
1806  if (value >= 0xD800 && value <= 0xDBFF && (i + 1) < len) {
1807  second = src[(i + 1) * 2] * 256 + src[(i + 1) * 2 + 1];
1808  if (second >= 0xDC00 && second <= 0xDFFF) {
1809  value = ((value - 0xD800) << 10) + (second - 0xDC00) + 0x010000;
1810  }
1811  }
1812  z = EncodeWithUTF8Alphabet(value, mychar);
1813  if (z == 1 && mychar[0] < 32) {
1814  /* Need quoted printable for chars < 32 */
1815  sprintf(dest + j, "=%02X", mychar[0]);
1816  j = j + 3;
1817  } else if (z == 1) {
1818  memcpy(dest + j, mychar, z);
1819  j += z;
1820  } else {
1821  /* Quoted printable unicode */
1822  for (w = 0; w < z; w++) {
1823  sprintf(dest + j, "=%02X", mychar[w]);
1824  j = j + 3;
1825  }
1826  if (z > 1) {
1827  retval = TRUE;
1828  }
1829  }
1830  }
1831  dest[j] = 0;
1832  return retval;
1833 }
1834 
1835 gboolean EncodeUTF8(char *dest, const unsigned char *src)
1836 {
1837  size_t i, j=0, z, len;
1838  unsigned char mychar[8];
1839  gboolean retval = FALSE;
1840  unsigned long value, second;
1841 
1842  len = UnicodeLength(src);
1843 
1844  for (i = 0; i < len; i++) {
1845  value = src[i * 2] * 256 + src[i * 2 + 1];
1846  /* Decode UTF-16 */
1847  if (value >= 0xD800 && value <= 0xDBFF && (i + 1) < len) {
1848  second = src[(i + 1) * 2] * 256 + src[(i + 1) * 2 + 1];
1849  if (second >= 0xDC00 && second <= 0xDFFF) {
1850  i++;
1851  value = ((value - 0xD800) << 10) + (second - 0xDC00) + 0x010000;
1852  }
1853  }
1854  z = EncodeWithUTF8Alphabet(value, mychar);
1855  memcpy(dest + j, mychar, z);
1856  j += z;
1857  if (z > 1) {
1858  retval = TRUE;
1859  }
1860  }
1861  dest[j] = 0;
1862  return retval;
1863 }
1864 
1865 /* Decode UTF8 char to Unicode char */
1866 int DecodeWithUTF8Alphabet(const unsigned char *src, wchar_t *dest, size_t len)
1867 {
1868  if (len < 1) return 0;
1869  if (src[0] < 128) {
1870  (*dest) = src[0];
1871  return 1;
1872  }
1873  if (src[0] < 194) return 0;
1874  if (src[0] < 224) {
1875  if (len < 2) return 0;
1876  (*dest) = (src[0]-192)*64 + (src[1]-128);
1877  return 2;
1878  }
1879  if (src[0] < 240) {
1880  if (len < 3) return 0;
1881  (*dest) = (src[0]-224)*4096 + (src[1]-128)*64 + (src[2]-128);
1882  return 3;
1883  }
1884  return 0;
1885 }
1886 
1887 
1888 /* Make Unicode string from ISO-8859-1 string */
1889 void DecodeISO88591QuotedPrintable(unsigned char *dest, const unsigned char *src, size_t len)
1890 {
1891  size_t i = 0, j = 0;
1892 
1893  while (i < len) {
1894  if (src[i] == '=' && i + 2 < len
1895  && DecodeWithHexBinAlphabet(src[i + 1]) != -1
1896  && DecodeWithHexBinAlphabet(src[i + 2]) != -1) {
1897  dest[j++] = 0;
1898  dest[j++] = 16 * DecodeWithHexBinAlphabet(src[i + 1]) + DecodeWithHexBinAlphabet(src[i + 2]);
1899  i += 2;
1900  } else {
1901  dest[j++] = 0;
1902  dest[j++] = src[i];
1903  }
1904  i++;
1905  }
1906  dest[j++] = 0;
1907  dest[j] = 0;
1908 }
1909 
1910 /* Make Unicode string from UTF8 string */
1911 void DecodeUTF8QuotedPrintable(unsigned char *dest, const char *src, size_t len)
1912 {
1913  size_t i,j=0;
1914  int z;
1915  unsigned char mychar[10];
1916  wchar_t ret;
1917 
1918  for (i = 0; i<=len; ) {
1919  z=0;
1920  while (TRUE) {
1921  if (src[z*3+i] != '=' || z*3+i+3>len ||
1922  DecodeWithHexBinAlphabet(src[z*3+i+1])==-1 ||
1923  DecodeWithHexBinAlphabet(src[z*3+i+2])==-1) {
1924  break;
1925  }
1926  mychar[z] = 16*DecodeWithHexBinAlphabet(src[z*3+i+1])+DecodeWithHexBinAlphabet(src[z*3+i+2]);
1927  z++;
1928  /* Is it plain ASCII? */
1929  if (z == 1 && mychar[0] < 194) break;
1930  /* Do we already have valid UTF-8 char? */
1931  if (DecodeWithUTF8Alphabet(mychar, &ret, z) == z) break;
1932  }
1933  if (z>0) {
1934  i += z * 3;
1935  /* we ignore wrong sequence */
1936  if (DecodeWithUTF8Alphabet(mychar,&ret,z)==0) continue;
1937  } else {
1938  i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1939  }
1940  dest[j++] = (ret >> 8) & 0xff;
1941  dest[j++] = ret & 0xff;
1942  }
1943  dest[j++] = 0;
1944  dest[j] = 0;
1945 }
1946 
1947 void DecodeUTF8(unsigned char *dest, const char *src, size_t len)
1948 {
1949  size_t i=0,j=0,z;
1950  wchar_t ret;
1951 
1952  while (i < len) {
1953  z = DecodeWithUTF8Alphabet(src+i,&ret,len-i);
1954  if (z<2) {
1955  i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1956  } else {
1957  i+=z;
1958  }
1959  dest[j++] = (ret >> 8) & 0xff;
1960  dest[j++] = ret & 0xff;
1961  }
1962  dest[j++] = 0;
1963  dest[j] = 0;
1964 }
1965 
1966 void DecodeXMLUTF8(unsigned char *dest, const char *src, size_t len)
1967 {
1968  char *tmp;
1969  char *pos, *pos_end;
1970  const char *lastpos;
1971  char *entity;
1972  unsigned long long int c;
1973  int tmplen;
1974 
1975  /* Allocate buffer */
1976  tmp = (char *)calloc(2 * len, sizeof(char));
1977  if (tmp == NULL) {
1978  /* We have no memory for XML decoding */
1979  DecodeUTF8(dest, src, len);
1980  return;
1981  }
1982  if (src == NULL) {
1983  *dest = 0;
1984  free(tmp);
1985  return;
1986  }
1987 
1988  /* Find ampersand and decode the */
1989  lastpos = src;
1990  while ((*lastpos != 0) && ((pos = strchr(lastpos, '&')) != NULL)) {
1991  /* Store current string */
1992  strncat(tmp, lastpos, pos - lastpos);
1993  lastpos = pos;
1994  /* Skip ampersand */
1995  pos++;
1996  /* Detect end of string */
1997  if (*pos == 0) break;
1998  /* Find entity length */
1999  pos_end = strchr(pos, ';');
2000  if (pos_end - pos > 6 || pos_end == NULL) {
2001  if (pos_end == NULL) {
2002  dbgprintf(NULL, "No entity end found, ignoring!\n");
2003  } else {
2004  dbgprintf(NULL, "Too long html entity, ignoring!\n");
2005  }
2006  strncat(tmp, lastpos, 1);
2007  lastpos++;
2008  continue;
2009  }
2010  /* Create entity */
2011  /* strndup would be better, but not portable */
2012  entity = strdup(pos);
2013  if (entity == NULL) break;
2014  entity[pos_end - pos] = 0;
2015  dbgprintf(NULL, "Found XML entity: %s\n", entity);
2016  if (entity[0] == '#') {
2017  if (entity[1] == 'x' || entity[1] == 'X') {
2018  c = strtoull(entity + 2, NULL, 16);
2019  } else {
2020  c = strtoull(entity + 1, NULL, 10);
2021  }
2022  dbgprintf(NULL, "Unicode char 0x%04llx\n", c);
2023  tmplen = strlen(tmp);
2024  tmplen += EncodeWithUTF8Alphabet(c, tmp + tmplen);
2025  tmp[tmplen] = 0;
2026  } else if (strcmp(entity, "amp") == 0) {
2027  strcat(tmp, "&");
2028  } else if (strcmp(entity, "apos") == 0) {
2029  strcat(tmp, "'");
2030  } else if (strcmp(entity, "gt") == 0) {
2031  strcat(tmp, ">");
2032  } else if (strcmp(entity, "lt") == 0) {
2033  strcat(tmp, "<");
2034  } else if (strcmp(entity, "quot") == 0) {
2035  strcat(tmp, "\"");
2036  } else {
2037  dbgprintf(NULL, "Could not decode XML entity!\n");
2038  strncat(tmp, lastpos, pos_end - pos + 1);
2039  }
2040  free(entity);
2041  entity=NULL;
2042  lastpos = pos_end + 1;
2043  }
2044  /* Copy rest of string */
2045  strcat(tmp, lastpos);
2046  DecodeUTF8(dest, tmp, strlen(tmp));
2047  free(tmp);
2048  tmp=NULL;
2049 }
2050 
2051 void DecodeUTF7(unsigned char *dest, const unsigned char *src, size_t len)
2052 {
2053  size_t i=0,j=0,z,p;
2054  wchar_t ret;
2055 
2056  while (i<=len) {
2057  if (len-5>=i) {
2058  if (src[i] == '+') {
2059  z=0;
2060  while (src[z+i+1] != '-' && z+i+1<len) z++;
2061  p=DecodeBASE64(src+i+1, dest+j, z);
2062  if (p%2 != 0) p--;
2063  j+=p;
2064  i+=z+2;
2065  } else {
2066  i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
2067  dest[j++] = (ret >> 8) & 0xff;
2068  dest[j++] = ret & 0xff;
2069  }
2070  } else {
2071  i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
2072  dest[j++] = (ret >> 8) & 0xff;
2073  dest[j++] = ret & 0xff;
2074  }
2075  }
2076  dest[j++] = 0;
2077  dest[j] = 0;
2078 }
2079 
2080 /*
2081 Bob Trower 08/04/01
2082 Copyright (c) Trantor Standard Systems Inc., 2001
2083 
2084 Permission is hereby granted, free of charge, to any person
2085 obtaining a copy of this software and associated
2086 documentation files (the "Software"), to deal in the
2087 Software without restriction, including without limitation
2088 the rights to use, copy, modify, merge, publish, distribute,
2089 sublicense, and/or sell copies of the Software, and to
2090 permit persons to whom the Software is furnished to do so,
2091 subject to the following conditions:
2092 
2093 The above copyright notice and this permission notice shall
2094 be included in all copies or substantial portions of the
2095 Software.
2096 
2097 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
2098 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
2099 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
2100 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
2101 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2102 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2103 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2104 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2105 */
2106 
2107 static void EncodeBASE64Block(const unsigned char in[3], char out[4], const size_t len)
2108 {
2109  /* BASE64 translation Table as described in RFC1113 */
2110  unsigned char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2111 
2112  out[0] = cb64[ in[0] >> 2 ];
2113  out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
2114  out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
2115  out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
2116 }
2117 
2118 void EncodeBASE64(const unsigned char *Input, char *Output, const size_t Length)
2119 {
2120  unsigned char in[3], out[4];
2121  size_t i, pos = 0, len, outpos = 0;
2122 
2123  while (pos < Length) {
2124  len = 0;
2125  for (i = 0; i < 3; i++) {
2126  in[i] = 0;
2127  if (pos < Length) {
2128  in[i] = Input[pos];
2129  len++;
2130  pos++;
2131  }
2132  }
2133  if(len) {
2134  EncodeBASE64Block(in, out, len);
2135  for (i = 0; i < 4; i++) Output[outpos++] = out[i];
2136  }
2137  }
2138 
2139  Output[outpos] = 0;
2140 }
2141 
2142 static void DecodeBASE64Block(const char in[4], unsigned char out[3])
2143 {
2144  out[0] = (unsigned char) ((in[0] << 2) | (in[1] >> 4));
2145  out[1] = (unsigned char) ((in[1] << 4) | (in[2] >> 2));
2146  out[2] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]);
2147 }
2148 
2149 int DecodeBASE64(const char *Input, unsigned char *Output, const size_t Length)
2150 {
2151  unsigned char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
2152  unsigned char in[4], out[3], v;
2153  size_t i, len, pos = 0, outpos = 0;
2154 
2155  while (pos < Length) {
2156  len = 0;
2157  for(i = 0; i < 4; i++) {
2158  v = 0;
2159  while(v == 0) {
2160  if (pos >= Length) break;
2161  v = (unsigned char) Input[pos++];
2162  v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
2163  if (v) v = (unsigned char) ((v == '$') ? 0 : v - 61);
2164  }
2165  if(pos<=Length) {
2166  if (v) {
2167  len++;
2168  in[i] = (unsigned char) (v - 1);
2169  }
2170  }
2171  }
2172  if (len) {
2173  DecodeBASE64Block(in, out);
2174  for(i = 0; i < len - 1; i++) Output[outpos++] = out[i];
2175  }
2176  }
2177  Output[outpos] = 0;
2178  return outpos;
2179 }
2180 
2181 #ifdef ICONV_FOUND
2182 
2183 #include <iconv.h>
2184 
2185 #ifdef ICONV_SECOND_ARGUMENT_IS_CONST
2186 # define SECOND_ICONV_ARG const char *
2187 #else
2188 # define SECOND_ICONV_ARG char *
2189 #endif
2190 
2191 gboolean IconvDecode(const char *charset, const char *input, const size_t inlen, unsigned char *output, size_t outlen)
2192 {
2193  iconv_t ic;
2194  /* Add one to convert also trailing zero, this is broken for
2195  * multibyte input, but we don't use iconv for this so far */
2196  size_t rest = inlen + 1;
2197  SECOND_ICONV_ARG in;
2198  char *out;
2199 
2200  ic = iconv_open("UCS-2BE", charset);
2201  if (ic == (iconv_t)(-1)) return FALSE;
2202 
2203  /* I know I loose const here, but it's iconv choice... */
2204  in = (SECOND_ICONV_ARG)input;
2205  out = output;
2206  iconv(ic, &in, &rest, &out, &outlen);
2207 
2208  iconv_close(ic);
2209 
2210  return (rest == 0);
2211 }
2212 
2213 gboolean IconvEncode(const char *charset, const unsigned char *input, const size_t inlen, char *output, size_t outlen)
2214 {
2215  iconv_t ic;
2216  size_t rest = inlen;
2217  SECOND_ICONV_ARG in;
2218  char *out;
2219 
2220  ic = iconv_open(charset, "UCS-2BE");
2221  if (ic == (iconv_t)(-1)) return FALSE;
2222 
2223  /* I know I loose const here, but it's iconv choice... */
2224  in = (SECOND_ICONV_ARG)input;
2225  out = output;
2226  iconv(ic, &in, &rest, &out, &outlen);
2227 
2228  iconv_close(ic);
2229 
2230  return (rest == 0);
2231 }
2232 #endif
2233 
2234 
2235 /* How should editor hadle tabs in this file? Add editor commands here.
2236  * vim: noexpandtab sw=8 ts=8 sts=8:
2237  */
void DecodeBCD(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:328
char * DecodeUnicodeConsole(const unsigned char *src)
Definition: coding.c:256
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void EncodeBCD(unsigned char *dest, const unsigned char *src, size_t len, gboolean fill)
Definition: coding.c:342
unsigned char * DecodeUnicodeSpecialChars(unsigned char *dest, const unsigned char *buffer)
Definition: coding.c:121
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
static unsigned char ConvertTable[]
Definition: coding.c:551
void DecodeDefault(unsigned char *dest, const unsigned char *src, size_t len, gboolean UseExtensions, unsigned char *ExtraAlphabet)
Definition: coding.c:498
GSM_Error GSM_GetVCSLine(char **OutBuffer, char *Buffer, size_t *Pos, size_t MaxLen, gboolean MergeLines)
Definition: coding.c:1656
void DecodeISO88591QuotedPrintable(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:1889
void FindDefaultAlphabetLen(const unsigned char *src, size_t *srclen, size_t *smslen, size_t maxlen)
Definition: coding.c:914
int GSM_PackSemiOctetNumber(const unsigned char *Number, unsigned char *Output, gboolean semioctet)
Definition: coding.c:1125
void AddBufferByte(unsigned char *Destination, size_t *CurrentBit, unsigned char Source, size_t BitsToProcess)
Definition: coding.c:1303
void DecodeUTF7(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:2051
void BufferAlign(unsigned char *Destination, size_t *CurrentBit)
Definition: coding.c:1263
#define GSM_MAX_NUMBER_LENGTH
Definition: gammu-limits.h:77
gboolean EncodeUTF8QuotedPrintable(char *dest, const unsigned char *src)
Definition: coding.c:1794
void GetBufferInt(unsigned char *Source, size_t *CurrentBit, int *integer, size_t BitsToProcess)
Definition: coding.c:1329
void EncodeBASE64(const unsigned char *Input, char *Output, const size_t Length)
Definition: coding.c:2118
int DecodeWithUTF8Alphabet(const unsigned char *src, wchar_t *dest, size_t len)
Definition: coding.c:1866
void GetBufferI(unsigned char *Source, size_t *CurrentBit, int *result, size_t BitsToProcess)
Definition: coding.c:1345
void DumpMessageText(GSM_Debug_Info *d, const unsigned char *message, const size_t messagesize)
Definition: debug.c:371
static unsigned char GSM_DefaultAlphabetUnicode[128+1][2]
Definition: coding.c:438
int ClearBit(unsigned char *Buffer, size_t BitNum)
Definition: coding.c:1258
int GSM_PackSevenBitsToEight(size_t offset, const unsigned char *input, unsigned char *output, size_t length)
Definition: coding.c:993
GSM_Error
Definition: gammu-error.h:23
gboolean mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
Definition: coding.c:1437
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
void DecodeISO88591(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:282
void EncodeHexUnicode(char *dest, const unsigned char *src, size_t len)
Definition: coding.c:406
char EncodeWithHexBinAlphabet(int digit)
Definition: coding.c:375
const char * coding
Definition: debug.h:38
void StringToDouble(char *text, double *d)
Definition: coding.c:1731
unsigned char EncodeWithBCDAlphabet(int value)
Definition: coding.c:315
void BufferAlignNumber(size_t *CurrentBit)
Definition: coding.c:1275
gboolean DecodeHexUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:382
int gboolean
Definition: gammu-types.h:23
void DecodeUTF8QuotedPrintable(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:1911
GSM_Debug_Info GSM_global_debug
Definition: debug.c:33
void GetBuffer(unsigned char *Source, size_t *CurrentBit, unsigned char *Destination, size_t BitsToProcess)
Definition: coding.c:1311
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
#define FALSE
Definition: gammu-types.h:25
static void EncodeBASE64Block(const unsigned char in[3], char out[4], const size_t len)
Definition: coding.c:2107
int wint_t
Definition: coding.h:27
void ReverseUnicodeString(unsigned char *String)
Definition: coding.c:1209
char * EncodeSpecialChars(char *dest, const char *buffer)
Definition: coding.c:94
void DecodeUTF8(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:1947
int DecodeWithBCDAlphabet(unsigned char value)
Definition: coding.c:323
gboolean mywstrncmp(unsigned const char *a, unsigned const char *b, int num)
Definition: coding.c:1457
int SetBit(unsigned char *Buffer, size_t BitNum)
Definition: coding.c:1253
int EncodeWithUnicodeAlphabet(const unsigned char *src, wchar_t *dest)
Definition: coding.c:198
void AddBuffer(unsigned char *Destination, size_t *CurrentBit, unsigned char *Source, size_t BitsToProcess)
Definition: coding.c:1286
void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:1401
GSM_Error GSM_UnpackSemiOctetNumber(GSM_Debug_Info *di, unsigned char *retval, const unsigned char *Number, size_t *pos, size_t bufferlength, gboolean semioctet)
Definition: coding.c:1028
int GSM_UnpackEightBitsToSeven(size_t offset, size_t in_length, size_t out_length, const unsigned char *input, unsigned char *output)
Definition: coding.c:953
#define dbgprintf
Definition: debug.h:72
void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:1367
unsigned char * mywstrstr(const unsigned char *haystack, const unsigned char *needle)
Definition: coding.c:1508
#define tolowerwchar(x)
gboolean DecodeHexBin(unsigned char *dest, const unsigned char *src, size_t len)
Definition: coding.c:411
void EncodeHexBin(char *dest, const unsigned char *src, size_t len)
Definition: coding.c:426
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240
char * DecodeSpecialChars(char *dest, const char *buffer)
Definition: coding.c:159
void DecodeUnicode(const unsigned char *src, char *dest)
Definition: coding.c:223
unsigned char * EncodeUnicodeSpecialChars(unsigned char *dest, const unsigned char *buffer)
Definition: coding.c:41
gboolean EncodeUTF8(char *dest, const unsigned char *src)
Definition: coding.c:1835
#define ByteMask
Definition: coding.c:951
void ReadUnicodeFile(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1227
#define TRUE
Definition: gammu-types.h:28
int EncodeWithUTF8Alphabet(unsigned long src, unsigned char *ret)
Definition: coding.c:1752
void DecodeXMLUTF8(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:1966
void EncodeDefault(unsigned char *dest, const unsigned char *src, size_t *len, gboolean UseExtensions, unsigned char *ExtraAlphabet)
Definition: coding.c:831
GSM_Error MyGetLine(char *Buffer, size_t *Pos, char *OutBuffer, size_t MaxLen, size_t MaxOutLen, gboolean MergeLines)
Definition: coding.c:1580
int DecodeWithHexBinAlphabet(unsigned char mychar)
Definition: coding.c:361
int DecodeWithUnicodeAlphabet(wchar_t src, unsigned char *dest)
Definition: coding.c:210
int GetBit(unsigned char *Buffer, size_t BitNum)
Definition: coding.c:1248
static void DecodeBASE64Block(const char in[4], unsigned char out[3])
Definition: coding.c:2142
static unsigned char GSM_DefaultAlphabetCharsExtension[][3]
Definition: coding.c:483
gboolean myiswspace(unsigned const char *src)
Definition: coding.c:1470
int DecodeBASE64(const char *Input, unsigned char *Output, const size_t Length)
Definition: coding.c:2149