summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/misc/coding/coding.c
Unidiff
Diffstat (limited to 'gammu/emb/common/misc/coding/coding.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/misc/coding/coding.c1409
1 files changed, 1409 insertions, 0 deletions
diff --git a/gammu/emb/common/misc/coding/coding.c b/gammu/emb/common/misc/coding/coding.c
new file mode 100644
index 0000000..62543ac
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/coding.c
@@ -0,0 +1,1409 @@
1/* (c) 2002-2004 by Marcin Wiacek, Michal Cihar and others */
2/* based on some work from MyGnokii and Gnokii */
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <ctype.h>
8#include <locale.h>
9#ifndef __OpenBSD__
10# include <wctype.h>
11#endif
12#ifdef WIN32
13# include "windows.h"
14#endif
15
16#include "../misc.h"
17#include "coding.h"
18
19unsigned int UnicodeLength(const unsigned char *str)
20{
21 unsigned int len = 0;
22
23 if (str == NULL) return 0;
24
25 while(str[len*2] != 0 || str[len*2+1] != 0) len++;
26
27 return len;
28}
29
30/* Convert Unicode char saved in src to dest */
31unsigned int EncodeWithUnicodeAlphabet(const unsigned char *src, wchar_t *dest)
32{
33 char retval;
34
35 switch (retval = mbtowc(dest, src, MB_CUR_MAX)) {
36 case -1 :
37 case 0 : return 1;
38 default : return retval;
39 }
40}
41
42/* Convert Unicode char saved in src to dest */
43unsigned int DecodeWithUnicodeAlphabet(wchar_t src, unsigned char *dest)
44{
45 int retval;
46
47 switch (retval = wctomb(dest, src)) {
48 case -1:
49 *dest = '?';
50 return 1;
51 default:
52 return retval;
53 }
54}
55
56void DecodeUnicode (const unsigned char *src, unsigned char *dest)
57{
58 int i=0,o=0;
59 wchar_t wc;
60
61 while (src[(2*i)+1]!=0x00 || src[2*i]!=0x00) {
62 wc = src[(2*i)+1] | (src[2*i] << 8);
63 o += DecodeWithUnicodeAlphabet(wc, dest + o);
64 i++;
65 }
66 dest[o]=0;
67}
68
69/* Decode Unicode string and return as function result */
70unsigned char *DecodeUnicodeString (const unsigned char *src)
71{
72 static char dest[500];
73
74 DecodeUnicode(src,dest);
75 return dest;
76}
77
78/* Decode Unicode string to UTF8 or other console charset
79 * and return as function result
80 */
81unsigned char *DecodeUnicodeConsole(const unsigned char *src)
82{
83 static char dest[500];
84
85 if (di.coding[0] != 0) {
86 if (!strcmp(di.coding,"utf8")) {
87 EncodeUTF8(dest, src);
88 } else {
89#ifdef WIN32
90 setlocale(LC_ALL, di.coding);
91#endif
92 DecodeUnicode(src,dest);
93 }
94 } else {
95#ifdef WIN32
96 setlocale(LC_ALL, ".OCP");
97#endif
98 DecodeUnicode(src,dest);
99#ifdef WIN32
100 setlocale(LC_ALL, ".ACP");
101#endif
102 }
103 return dest;
104}
105
106/* Encode string to Unicode. Len is number of input chars */
107void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len)
108{
109 int i_len = 0, o_len;
110 wchar_t wc;
111
112 for (o_len = 0; i_len < len; o_len++) {
113 i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
114 dest[o_len*2] = (wc >> 8) & 0xff;
115 dest[(o_len*2)+1]= wc & 0xff;
116 }
117 dest[o_len*2] = 0;
118 dest[(o_len*2)+1]= 0;
119}
120
121unsigned char EncodeWithBCDAlphabet(int value)
122{
123 div_t division;
124
125 division=div(value,10);
126 return ( ( (value-division.quot*10) & 0x0f) << 4) | (division.quot & 0xf);
127}
128
129int DecodeWithBCDAlphabet(unsigned char value)
130{
131 return 10*(value & 0x0f)+(value >> 4);
132}
133
134void DecodeBCD (unsigned char *dest, const unsigned char *src, int len)
135{
136 int i,current=0,digit;
137
138 for (i = 0; i < len; i++) {
139 digit=src[i] & 0x0f;
140 if (digit<10) dest[current++]=digit + '0';
141 digit=src[i] >> 4;
142 if (digit<10) dest[current++]=digit + '0';
143 }
144 dest[current++]=0;
145}
146
147void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill)
148{
149 int i,current=0;
150
151 for (i = 0; i < len; i++) {
152 if (i & 0x01) {
153 dest[current]=dest[current] | ((src[i]-'0') << 4);
154 current++;
155 } else {
156 dest[current]=src[i]-'0';
157 }
158 }
159
160 /* When fill is set: if number consist of odd number of digits,
161 we fill last bits in last byte with 0x0f
162 */
163 if (fill && (len & 0x01)) dest[current]=dest[current] | 0xf0;
164}
165
166int DecodeWithHexBinAlphabet (unsigned char mychar)
167{
168 if (mychar>='A' && mychar<='F') return mychar-'A'+10;
169 if (mychar>='a' && mychar<='f') return mychar-'a'+10;
170 if (mychar>='0' && mychar<='9') return mychar-'0';
171 return -1;
172}
173
174unsigned char EncodeWithHexBinAlphabet (int digit)
175{
176 if (digit >= 0 && digit <= 9) return '0'+(digit);
177 if (digit >=10 && digit <=15) return 'A'+(digit-10);
178 return 0;
179}
180
181void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len)
182{
183 int i,current=0;
184 bool first = false;
185
186 if (len != 0 && src[0] == '0' && src[1] == '0') {
187 first = true;
188 } else if (len != 0 && src[2] == '0' && src[3] == '0') {
189 first = false;
190 } else {
191 first = (10 * (src[0] - '0') + (src[1] - '0')) < (10 * (src[2] - '0')+ (src[3] - '0'));
192 }
193 for (i = 0; i < len/4 ; i++) {
194 if (first) {
195 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+
196 DecodeWithHexBinAlphabet(src[i*4+1]);
197 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+
198 DecodeWithHexBinAlphabet(src[i*4+3]);
199 } else {
200 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+
201 DecodeWithHexBinAlphabet(src[i*4+3]);
202 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+
203 DecodeWithHexBinAlphabet(src[i*4+1]);
204 }
205 }
206 dest[current++] = 0;
207 dest[current++] = 0;
208}
209
210void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len)
211{
212 int i,current=0;
213
214 for (i = 0; i < len; i++) {
215 dest[current++] = EncodeWithHexBinAlphabet(src[2*i] >> 0x04);
216 dest[current++] = EncodeWithHexBinAlphabet(src[2*i] & 0x0f);
217 dest[current++] = EncodeWithHexBinAlphabet(src[2*i+1] >> 0x04);
218 dest[current++] = EncodeWithHexBinAlphabet(src[2*i+1] & 0x0f);
219 }
220 dest[current++] = 0;
221}
222
223void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len)
224{
225 int i,current=0;
226
227 for (i = 0; i < len/2 ; i++) {
228 dest[current++] = DecodeWithHexBinAlphabet(src[i*2])*16+
229 DecodeWithHexBinAlphabet(src[i*2+1]);
230 }
231 dest[current++] = 0;
232}
233
234void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len)
235{
236 int i,current=0;
237
238 for (i = 0; i < len; i++) {
239 dest[current++] = EncodeWithHexBinAlphabet(src[i] >> 0x04);
240 dest[current++] = EncodeWithHexBinAlphabet(src[i] & 0x0f);
241 }
242 dest[current++] = 0;
243}
244
245/* ETSI GSM 03.38, section 6.2.1: Default alphabet for SMS messages */
246static unsigned char GSM_DefaultAlphabetUnicode[128+1][2] =
247{
248 {0x00,0x40},{0x00,0xa3},{0x00,0x24},{0x00,0xA5},
249 {0x00,0xE8},{0x00,0xE9},{0x00,0xF9},{0x00,0xEC},/*0x08*/
250 {0x00,0xF2},{0x00,0xC7},{0x00,'\n'},{0x00,0xD8},
251 {0x00,0xF8},{0x00,'\r'},{0x00,0xC5},{0x00,0xE5},
252 {0x03,0x94},{0x00,0x5f},{0x03,0xA6},{0x03,0x93},
253 {0x03,0x9B},{0x03,0xA9},{0x03,0xA0},{0x03,0xA8},
254 {0x03,0xA3},{0x03,0x98},{0x03,0x9E},{0x00,0xb9},
255 {0x00,0xC6},{0x00,0xE6},{0x00,0xDF},{0x00,0xC9},/*0x20*/
256 {0x00,' ' },{0x00,'!' },{0x00,'\"'},{0x00,'#' },
257 {0x00,0xA4},{0x00,'%' },{0x00,'&' },{0x00,'\''},
258 {0x00,'(' },{0x00,')' },{0x00,'*' },{0x00,'+' },
259 {0x00,',' },{0x00,'-' },{0x00,'.' },{0x00,'/' },/*0x30*/
260 {0x00,'0' },{0x00,'1' },{0x00,'2' },{0x00,'3' },
261 {0x00,'4' },{0x00,'5' },{0x00,'6' },{0x00,'7' },
262 {0x00,'8' },{0x00,'9' },{0x00,':' },{0x00,';' },
263 {0x00,'<' },{0x00,'=' },{0x00,'>' },{0x00,'?' },/*0x40*/
264 {0x00,0xA1},{0x00,'A' },{0x00,'B' },{0x00,'C' },
265 {0x00,'D' },{0x00,'E' },{0x00,'F' },{0x00,'G' },
266 {0x00,'H' },{0x00,'I' },{0x00,'J' },{0x00,'K' },
267 {0x00,'L' },{0x00,'M' },{0x00,'N' },{0x00,'O' },
268 {0x00,'P' },{0x00,'Q' },{0x00,'R' },{0x00,'S' },
269 {0x00,'T' },{0x00,'U' },{0x00,'V' },{0x00,'W' },
270 {0x00,'X' },{0x00,'Y' },{0x00,'Z' },{0x00,0xC4},
271 {0x00,0xD6},{0x00,0xD1},{0x00,0xDC},{0x00,0xA7},
272 {0x00,0xBF},{0x00,'a' },{0x00,'b' },{0x00,'c' },
273 {0x00,'d' },{0x00,'e' },{0x00,'f' },{0x00,'g' },
274 {0x00,'h' },{0x00,'i' },{0x00,'j' },{0x00,'k' },
275 {0x00,'l' },{0x00,'m' },{0x00,'n' },{0x00,'o' },
276 {0x00,'p' },{0x00,'q' },{0x00,'r' },{0x00,'s' },
277 {0x00,'t' },{0x00,'u' },{0x00,'v' },{0x00,'w' },
278 {0x00,'x' },{0x00,'y' },{0x00,'z' },{0x00,0xE4},
279 {0x00,0xF6},{0x00,0xF1},{0x00,0xFC},{0x00,0xE0},
280 {0x00,0x00}
281};
282
283/* ETSI GSM 3.38
284 * Some sequences of 2 default alphabet chars (for example,
285 * 0x1b, 0x65) are visible as one single additional char (for example,
286 * 0x1b, 0x65 gives Euro char saved in Unicode as 0x20, 0xAC)
287 * This table contains:
288 * 1. two first chars means sequence of chars from GSM default alphabet
289 * 2. two second is target (encoded) char saved in Unicode
290 */
291static unsigned char GSM_DefaultAlphabetCharsExtension[][4] =
292{
293 {0x1b,0x14,0x00,0x5e}, /* ^*/
294 {0x1b,0x28,0x00,0x7b}, /* {*/
295 {0x1b,0x29,0x00,0x7d}, /* }*/
296 {0x1b,0x2f,0x00,0x5c}, /* \*/
297 {0x1b,0x3c,0x00,0x5b}, /* [*/
298 {0x1b,0x3d,0x00,0x7E}, /* ~*/
299 {0x1b,0x3e,0x00,0x5d}, /* ]*/
300 {0x1b,0x40,0x00,0x7C}, /* |*/
301 {0x1b,0x65,0x20,0xAC},/* Euro */
302 {0x00,0x00,0x00,0x00}
303};
304
305void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet)
306{
307 int i,current=0,j;
308 boolFoundSpecial = false;
309
310#ifdef DEBUG
311 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, src, len);
312#endif
313
314 for (i = 0; i < len; i++) {
315 FoundSpecial = false;
316 if ((i < (len-1)) && UseExtensions) {
317 j=0;
318 while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) {
319 if (GSM_DefaultAlphabetCharsExtension[j][0]==src[i] &&
320 GSM_DefaultAlphabetCharsExtension[j][1]==src[i+1]) {
321 FoundSpecial = true;
322 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][2];
323 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][3];
324 i++;
325 break;
326 }
327 j++;
328 }
329 }
330 if (ExtraAlphabet!=NULL && !FoundSpecial) {
331 j = 0;
332 while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) {
333 if (ExtraAlphabet[j] == src[i]) {
334 dest[current++] = ExtraAlphabet[j+1];
335 dest[current++] = ExtraAlphabet[j+2];
336 FoundSpecial = true;
337 break;
338 }
339 j=j+3;
340 }
341 }
342 if (!FoundSpecial) {
343 dest[current++] = GSM_DefaultAlphabetUnicode[src[i]][0];
344 dest[current++] = GSM_DefaultAlphabetUnicode[src[i]][1];
345 }
346 }
347 dest[current++]=0;
348 dest[current++]=0;
349#ifdef DEBUG
350 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, UnicodeLength(dest)*2);
351#endif
352}
353
354/* There are many national chars with "adds". In phone they're normally
355 * changed to "plain" Latin chars. We have such functionality too.
356 * This table is automatically created from convert.txt file (see
357 * /docs/developers) using --makeconverttable. It contains such chars
358 * to replace in order:
359 * 1. original char (Unicode) 2. destination char (Unicode)
360 */
361static unsigned char ConvertTable[] =
362"\x00\xc0\x00\x41\x00\xe0\x00\x61\x00\xc1\x00\x41\x00\xe1\x00\x61\x00\xc2\x00\x41\x00\xe2\x00\x61\x00\xc3\x00\x41\x00\xe3\x00\x61\x1e\xa0\x00\x41\x1e\xa1\x00\x61\x1e\xa2\x00\x41\x1e\xa3\x00\x61\x1e\xa4\x00\x41\x1e\xa5\x00\x61\x1e\xa6\x00\x41\x1e\xa7\x00\x61\x1e\xa8\x00\x41\x1e\xa9\x00\x61\x1e\xaa\x00\x41\x1e\xab\x00\x61\x1e\xac\x00\x41\x1e\xad\x00\x61\x1e\xae\x00\x41\x1e\xaf\x00\x61\x1e\xb0\x00\x41\x1e\xb1\x00\x61\x1e\xb2\x00\x41\x1e\xb3\x00\x61\x1e\xb4\x00\x41\x1e\xb5\x00\x61\x1e\xb6\x00\x41\x1e\xb7\x00\x61\x01\xcd\x00\x41\x01\xce\x00\x61\x01\x00\x00\x41\x01\x01\x00\x61\x01\x02\x00\x41\x01\x03\x00\x61\x01\x04\x00\x41\x01\x05\x00\x61\x01\xfb\x00\x61\x01\x06\x00\x43\x01\x07\x00\x63\x01\x08\x00\x43\x01\x09\x00\x63\x01\x0a\x00\x43\x01\x0b\x00\x63\x01\x0c\x00\x43\x01\x0d\x00\x63\x00\xe7"\
363"\x00\x63\x01\x0e\x00\x44\x01\x0f\x00\x64\x01\x10\x00\x44\x01\x11\x00\x64\x00\xc8\x00\x45\x00\xca\x00\x45\x00\xea\x00\x65\x00\xcb\x00\x45\x00\xeb\x00\x65\x1e\xb8\x00\x45\x1e\xb9\x00\x65\x1e\xba\x00\x45\x1e\xbb\x00\x65\x1e\xbc\x00\x45\x1e\xbd\x00\x65\x1e\xbe\x00\x45\x1e\xbf\x00\x65\x1e\xc0\x00\x45\x1e\xc1\x00\x65\x1e\xc2\x00\x45\x1e\xc3\x00\x65\x1e\xc4\x00\x45\x1e\xc5\x00\x65\x1e\xc6\x00\x45\x1e\xc7\x00\x65\x01\x12\x00\x45\x01\x13\x00\x65\x01\x14\x00\x45\x01\x15\x00\x65\x01\x16\x00\x45\x01\x17\x00\x65\x01\x18\x00\x45\x01\x19\x00\x65\x01\x1a\x00\x45\x01\x1b\x00\x65\x01\x1c\x00\x47\x01\x1d\x00\x67\x01\x1e\x00\x47\x01\x1f\x00\x67\x01\x20\x00\x47\x01\x21\x00\x67\x01\x22\x00\x47\x01\x23\x00\x67\x01\x24\x00\x48\x01\x25\x00\x68\x01\x26\x00\x48\x01\x27\x00\x68\x00\xcc\x00\x49\x00\xcd\x00\x49\x00\xed"\
364"\x00\x69\x00\xce\x00\x49\x00\xee\x00\x69\x00\xcf\x00\x49\x00\xef\x00\x69\x01\x28\x00\x49\x01\x29\x00\x69\x01\x2a\x00\x49\x01\x2b\x00\x69\x01\x2c\x00\x49\x01\x2d\x00\x69\x01\x2e\x00\x49\x01\x2f\x00\x69\x01\x30\x00\x49\x01\x31\x00\x69\x01\xcf\x00\x49\x01\xd0\x00\x69\x1e\xc8\x00\x49\x1e\xc9\x00\x69\x1e\xca\x00\x49\x1e\xcb\x00\x69\x01\x34\x00\x4a\x01\x35\x00\x6a\x01\x36\x00\x4b\x01\x37\x00\x6b\x01\x39\x00\x4c\x01\x3a\x00\x6c\x01\x3b\x00\x4c\x01\x3c\x00\x6c\x01\x3d\x00\x4c\x01\x3e\x00\x6c\x01\x3f\x00\x4c\x01\x40\x00\x6c\x01\x41\x00\x4c\x01\x42\x00\x6c\x01\x43\x00\x4e\x01\x44\x00\x6e\x01\x45\x00\x4e\x01\x46\x00\x6e\x01\x47\x00\x4e\x01\x48\x00\x6e\x01\x49\x00\x6e\x00\xd2\x00\x4f\x00\xd3\x00\x4f\x00\xf3\x00\x6f\x00\xd4\x00\x4f\x00\xf4\x00\x6f\x00\xd5\x00\x4f\x00\xf5\x00\x6f\x01\x4c\x00\x4f\x01\x4d"\
365"\x00\x6f\x01\x4e\x00\x4f\x01\x4f\x00\x6f\x01\x50\x00\x4f\x01\x51\x00\x6f\x01\xa0\x00\x4f\x01\xa1\x00\x6f\x01\xd1\x00\x4f\x01\xd2\x00\x6f\x1e\xcc\x00\x4f\x1e\xcd\x00\x6f\x1e\xce\x00\x4f\x1e\xcf\x00\x6f\x1e\xd0\x00\x4f\x1e\xd1\x00\x6f\x1e\xd2\x00\x4f\x1e\xd3\x00\x6f\x1e\xd4\x00\x4f\x1e\xd5\x00\x6f\x1e\xd6\x00\x4f\x1e\xd7\x00\x6f\x1e\xd8\x00\x4f\x1e\xd9\x00\x6f\x1e\xda\x00\x4f\x1e\xdb\x00\x6f\x1e\xdc\x00\x4f\x1e\xdd\x00\x6f\x1e\xde\x00\x4f\x1e\xdf\x00\x6f\x1e\xe0\x00\x4f\x1e\xe1\x00\x6f\x1e\xe2\x00\x4f\x1e\xe3\x00\x6f\x01\x54\x00\x52\x01\x55\x00\x72\x01\x56\x00\x52\x01\x57\x00\x72\x01\x58\x00\x52\x01\x59\x00\x72\x01\x5a\x00\x53\x01\x5b\x00\x73\x01\x5c\x00\x53\x01\x5d\x00\x73\x01\x5e\x00\x53\x01\x5f\x00\x73\x01\x60\x00\x53\x01\x61\x00\x73\x01\x62\x00\x54\x01\x63\x00\x74\x01\x64\x00\x54\x01\x65"\
366"\x00\x74\x01\x66\x00\x54\x01\x67\x00\x74\x00\xd9\x00\x55\x00\xda\x00\x55\x00\xfa\x00\x75\x00\xdb\x00\x55\x00\xfb\x00\x75\x01\x68\x00\x55\x01\x69\x00\x75\x01\x6a\x00\x55\x01\x6b\x00\x75\x01\x6c\x00\x55\x01\x6d\x00\x75\x01\x6e\x00\x55\x01\x6f\x00\x75\x01\x70\x00\x55\x01\x71\x00\x75\x01\x72\x00\x55\x01\x73\x00\x75\x01\xaf\x00\x55\x01\xb0\x00\x75\x01\xd3\x00\x55\x01\xd4\x00\x75\x01\xd5\x00\x55\x01\xd6\x00\x75\x01\xd7\x00\x55\x01\xd8\x00\x75\x01\xd9\x00\x55\x01\xda\x00\x75\x01\xdb\x00\x55\x01\xdc\x00\x75\x1e\xe4\x00\x55\x1e\xe5\x00\x75\x1e\xe6\x00\x55\x1e\xe7\x00\x75\x1e\xe8\x00\x55\x1e\xe9\x00\x75\x1e\xea\x00\x55\x1e\xeb\x00\x75\x1e\xec\x00\x55\x1e\xed\x00\x75\x1e\xee\x00\x55\x1e\xef\x00\x75\x1e\xf0\x00\x55\x1e\xf1\x00\x75\x01\x74\x00\x57\x01\x75\x00\x77\x1e\x80\x00\x57\x1e\x81\x00\x77\x1e\x82"\
367"\x00\x57\x1e\x83\x00\x77\x1e\x84\x00\x57\x1e\x85\x00\x77\x00\xdd\x00\x59\x00\xfd\x00\x79\x00\xff\x00\x79\x01\x76\x00\x59\x01\x77\x00\x79\x01\x78\x00\x59\x1e\xf2\x00\x59\x1e\xf3\x00\x75\x1e\xf4\x00\x59\x1e\xf5\x00\x79\x1e\xf6\x00\x59\x1e\xf7\x00\x79\x1e\xf8\x00\x59\x1e\xf9\x00\x79\x01\x79\x00\x5a\x01\x7a\x00\x7a\x01\x7b\x00\x5a\x01\x7c\x00\x7a\x01\x7d\x00\x5a\x01\x7e\x00\x7a\x01\xfc\x00\xc6\x01\xfd\x00\xe6\x01\xfe\x00\xd8\x01\xff\x00\xf8\x00\x00";
368
369void EncodeDefault(unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet)
370{
371 int i,current=0,j,z;
372 char ret;
373 boolFoundSpecial,FoundNormal;
374
375#ifdef DEBUG
376 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, src, (*len)*2);
377#endif
378
379 for (i = 0; i < *len; i++) {
380 FoundSpecial = false;
381 j = 0;
382 while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00 && UseExtensions) {
383 if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] &&
384 src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) {
385 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][0];
386 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][1];
387 FoundSpecial = true;
388 break;
389 }
390 j++;
391 }
392 if (!FoundSpecial) {
393 ret = '?';
394 FoundNormal = false;
395 j = 0;
396 while (GSM_DefaultAlphabetUnicode[j][1]!=0x00) {
397 if (src[i*2]== GSM_DefaultAlphabetUnicode[j][0] &&
398 src[i*2+1]== GSM_DefaultAlphabetUnicode[j][1]) {
399 ret = j;
400 FoundNormal = true;
401 break;
402 }
403 j++;
404 }
405 if (ExtraAlphabet!=NULL && !FoundNormal) {
406 j = 0;
407 while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) {
408 if (ExtraAlphabet[j+1] == src[i*2] &&
409 ExtraAlphabet[j+2] == src[i*2 + 1]) {
410 ret = ExtraAlphabet[j];
411 FoundSpecial= true;
412 break;
413 }
414 j=j+3;
415 }
416 }
417 if (!FoundNormal && !FoundSpecial) {
418 j = 0;
419 FoundNormal = false;
420 while (ConvertTable[j*4] != 0x00 ||
421 ConvertTable[j*4+1] != 0x00) {
422 if (src[i*2] == ConvertTable[j*4] &&
423 src[i*2+1] == ConvertTable[j*4+1]) {
424 z = 0;
425 while (GSM_DefaultAlphabetUnicode[z][1]!=0x00) {
426 if (ConvertTable[j*4+2]== GSM_DefaultAlphabetUnicode[z][0] &&
427 ConvertTable[j*4+3]== GSM_DefaultAlphabetUnicode[z][1]) {
428 ret = z;
429 FoundNormal = true;
430 break;
431 }
432 z++;
433 }
434 if (FoundNormal) break;
435 }
436 j++;
437 }
438 }
439 dest[current++]=ret;
440 }
441 }
442 dest[current]=0;
443#ifdef DEBUG
444 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, current);
445#endif
446
447 *len = current;
448}
449
450/* You don't have to use ConvertTable here - 1 char is replaced there by 1 char */
451void FindDefaultAlphabetLen(const unsigned char *src, int *srclen, int *smslen, int maxlen)
452{
453 int current=0,j,i;
454 boolFoundSpecial;
455
456 i = 0;
457 while (src[i*2] != 0x00 || src[i*2+1] != 0x00) {
458 FoundSpecial = false;
459 j = 0;
460 while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) {
461 if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] &&
462 src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) {
463 FoundSpecial = true;
464 if (current+2 > maxlen) {
465 *srclen = i;
466 *smslen = current;
467 return;
468 }
469 current+=2;
470 break;
471 }
472 j++;
473 }
474 if (!FoundSpecial) {
475 if (current+1 > maxlen) {
476 *srclen = i;
477 *smslen = current;
478 return;
479 }
480 current++;
481 }
482 i++;
483 }
484 *srclen = i;
485 *smslen = current;
486}
487
488#ifndef ENABLE_LGPL
489# define ByteMask ((1 << Bits) - 1)
490#endif
491
492int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length,
493 unsigned char *input, unsigned char *output)
494{
495#ifndef ENABLE_LGPL
496 /* (c) by Pavel Janik and Pawel Kot */
497
498 unsigned char *OUTPUT = output; /* Current pointer to the output buffer */
499 unsigned char *INPUT = input; /* Current pointer to the input buffer */
500 unsigned char Rest = 0x00;
501 int Bits;
502
503 Bits = offset ? offset : 7;
504
505 while ((INPUT - input) < in_length) {
506
507 *OUTPUT = ((*INPUT & ByteMask) << (7 - Bits)) | Rest;
508 Rest = *INPUT >> Bits;
509
510 /* If we don't start from 0th bit, we shouldn't go to the
511 next char. Under *OUTPUT we have now 0 and under Rest -
512 _first_ part of the char. */
513 if ((INPUT != input) || (Bits == 7)) OUTPUT++;
514 INPUT++;
515
516 if ((OUTPUT - output) >= out_length) break;
517
518 /* After reading 7 octets we have read 7 full characters but
519 we have 7 bits as well. This is the next character */
520 if (Bits == 1) {
521 *OUTPUT = Rest;
522 OUTPUT++;
523 Bits = 7;
524 Rest = 0x00;
525 } else {
526 Bits--;
527 }
528 }
529
530 return OUTPUT - output;
531#else
532 return 0;
533#endif
534}
535
536int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output, int length)
537{
538#ifndef ENABLE_LGPL
539 /* (c) by Pavel Janik and Pawel Kot */
540
541 unsigned char *OUTPUT = output; /* Current pointer to the output buffer */
542 unsigned char *INPUT = input; /* Current pointer to the input buffer */
543 int Bits; /* Number of bits directly copied to
544 * the output buffer */
545 Bits = (7 + offset) % 8;
546
547 /* If we don't begin with 0th bit, we will write only a part of the
548 first octet */
549 if (offset) {
550 *OUTPUT = 0x00;
551 OUTPUT++;
552 }
553
554 while ((INPUT - input) < length) {
555 unsigned char Byte = *INPUT;
556
557 *OUTPUT = Byte >> (7 - Bits);
558 /* If we don't write at 0th bit of the octet, we should write
559 a second part of the previous octet */
560 if (Bits != 7)
561 *(OUTPUT-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1);
562
563 Bits--;
564
565 if (Bits == -1) Bits = 7; else OUTPUT++;
566
567 INPUT++;
568 }
569 return (OUTPUT - output);
570#else
571 return 0;
572#endif
573}
574
575void GSM_UnpackSemiOctetNumber(unsigned char *retval, unsigned char *Number, bool semioctet)
576{
577 unsigned char Buffer[50]= "";
578 int length = Number[0];
579
580 if (semioctet) {
581 /* Convert number of semioctets to number of chars */
582 if (length % 2) length++;
583 length=length / 2 + 1;
584 }
585
586 /*without leading byte with format of number*/
587 length--;
588
589 switch (Number[1]) {
590 case NUMBER_ALPHANUMERIC:
591 if (length > 6) length++;
592 dbgprintf("Alphanumeric number, length %i\n",length);
593 GSM_UnpackEightBitsToSeven(0, length, length, Number+2, Buffer);
594 Buffer[length]=0;
595 break;
596 case NUMBER_INTERNATIONAL:
597 dbgprintf("International number\n");
598 Buffer[0]='+';
599 DecodeBCD(Buffer+1,Number+2, length);
600 break;
601 default:
602 dbgprintf("Default number %02x\n",Number[1]);
603 DecodeBCD (Buffer, Number+2, length);
604 break;
605 }
606
607 EncodeUnicode(retval,Buffer,strlen(Buffer));
608}
609
610/**
611 * Packing some phone numbers (SMSC, SMS destination and others)
612 *
613 * See GSM 03.40 9.1.1:
614 * 1 byte - length of number given in semioctets or bytes (when given in
615 * bytes, includes one byte for byte with number format).
616 * Returned by function (set semioctet to true, if want result
617 * in semioctets).
618 * 1 byte - format of number (see GSM_NumberType in coding.h). Returned
619 * in unsigned char *Output.
620 * n bytes - 2n or 2n-1 semioctets with number. Returned in unsigned char
621 * *Output.
622 *
623 * 1 semioctet = 4 bits = half of byte
624 */
625int GSM_PackSemiOctetNumber(unsigned char *Number, unsigned char *Output, bool semioctet)
626{
627 unsigned charformat, buffer[50];
628 int length, i;
629
630 length=UnicodeLength(Number);
631 memcpy(buffer,DecodeUnicodeString(Number),length+1);
632
633 /* Checking for format number */
634 format = NUMBER_UNKNOWN;
635 for (i=0;i<length;i++) {
636 /* first byte is '+'. Number can be international */
637 if (i==0 && buffer[i]=='+') {
638 format=NUMBER_INTERNATIONAL;
639 } else {
640 /*char is not number. It must be alphanumeric*/
641 if (!isdigit(buffer[i])) format=NUMBER_ALPHANUMERIC;
642 }
643 }
644
645 /**
646 * First byte is used for saving type of number. See GSM 03.40
647 * section 9.1.2.5
648 */
649 Output[0]=format;
650
651 /* After number type we will have number. GSM 03.40 section 9.1.2 */
652 switch (format) {
653 case NUMBER_ALPHANUMERIC:
654 length=GSM_PackSevenBitsToEight(0, buffer, Output+1, strlen(buffer))*2;
655 if (strlen(buffer)==7) length--;
656 break;
657 case NUMBER_INTERNATIONAL:
658 length--;
659 EncodeBCD (Output+1, buffer+1, length, true);
660 break;
661 default:
662 EncodeBCD (Output+1, buffer, length, true);
663 break;
664 }
665
666 if (semioctet) return length;
667
668 /* Convert number of semioctets to number of chars */
669 if (length % 2) length++;
670 return length / 2 + 1;
671}
672
673void CopyUnicodeString(unsigned char *Dest, unsigned char *Source)
674{
675 int j = 0;
676
677 while (Source[j]!=0x00 || Source[j+1]!=0x00) {
678 Dest[j] = Source[j];
679 Dest[j+1]= Source[j+1];
680 j=j+2;
681 }
682 Dest[j] = 0;
683 Dest[j+1]= 0;
684}
685
686/* Changes minor/major order in Unicode string */
687void ReverseUnicodeString(unsigned char *String)
688{
689 int j = 0;
690 unsigned charbyte1, byte2;
691
692 while (String[j]!=0x00 || String[j+1]!=0x00) {
693 byte1 = String[j];
694 byte2 = String[j+1];
695 String[j+1]= byte1;
696 String[j]= byte2;
697 j=j+2;
698 }
699 String[j]= 0;
700 String[j+1]= 0;
701}
702
703/* All input is in Unicode. First char can show Unicode minor/major order.
704 Output is Unicode string in Gammu minor/major order */
705void ReadUnicodeFile(unsigned char *Dest, unsigned char *Source)
706{
707 int j = 0, current = 0;
708
709 if (Source[0] == 0xFF && Source[1] == 0xFE) j = 2;
710 if (Source[0] == 0xFE && Source[1] == 0xFF) j = 2;
711
712 while (Source[j]!=0x00 || Source[j+1]!=0x00) {
713 if (Source[0] == 0xFF) {
714 Dest[current++] = Source[j+1];
715 Dest[current++]= Source[j];
716 } else {
717 Dest[current++] = Source[j];
718 Dest[current++]= Source[j+1];
719 }
720 j=j+2;
721 }
722 Dest[current++] = 0;
723 Dest[current++]= 0;
724}
725
726int GetBit(unsigned char *Buffer, int BitNum)
727{
728 return Buffer[BitNum/8] & 1<<(7-(BitNum%8));
729}
730
731int SetBit(unsigned char *Buffer, int BitNum)
732{
733 return Buffer[BitNum/8] |= 1<<(7-(BitNum%8));
734}
735
736int ClearBit(unsigned char *Buffer, int BitNum)
737{
738 return Buffer[BitNum/8] &= 255 - (1 << (7-(BitNum%8)));
739}
740
741void BufferAlign(unsigned char *Destination, int *CurrentBit)
742{
743 int i=0;
744
745 while(((*CurrentBit) + i) % 8 != 0) {
746 ClearBit(Destination, (*CurrentBit)+i);
747 i++;
748 }
749
750 (*CurrentBit) = (*CurrentBit) + i;
751}
752
753void BufferAlignNumber(int *CurrentBit)
754{
755 int i=0;
756
757 while(((*CurrentBit) + i) % 8 != 0) {
758 i++;
759 }
760
761 (*CurrentBit) = (*CurrentBit) + i;
762}
763
764 void AddBuffer(unsigned char *Destination,
765 int *CurrentBit,
766 unsigned char *Source,
767 int BitsToProcess)
768{
769 int i=0;
770
771 while (i!=BitsToProcess) {
772 if (GetBit(Source, i)) {
773 SetBit(Destination, (*CurrentBit)+i);
774 } else {
775 ClearBit(Destination, (*CurrentBit)+i);
776 }
777 i++;
778 }
779 (*CurrentBit) = (*CurrentBit) + BitsToProcess;
780}
781
782void AddBufferByte(unsigned char *Destination,
783 int *CurrentBit,
784 unsigned char Source,
785 int BitsToProcess)
786{
787 unsigned char Byte;
788
789 Byte = Source;
790
791 AddBuffer(Destination, CurrentBit, &Byte, BitsToProcess);
792}
793
794void GetBuffer(unsigned char *Source,
795 int *CurrentBit,
796 unsigned char *Destination,
797 int BitsToProcess)
798{
799 int i=0;
800
801 while (i!=BitsToProcess) {
802 if (GetBit(Source, (*CurrentBit)+i)) {
803 SetBit(Destination, i);
804 } else {
805 ClearBit(Destination, i);
806 }
807 i++;
808 }
809 (*CurrentBit) = (*CurrentBit) + BitsToProcess;
810}
811
812void GetBufferInt(unsigned char *Source,
813 int *CurrentBit,
814 int *integer,
815 int BitsToProcess)
816{
817 int l=0,z=128,i=0;
818
819 while (i!=BitsToProcess) {
820 if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
821 z=z/2;
822 i++;
823 }
824 *integer=l;
825 (*CurrentBit) = (*CurrentBit) + i;
826}
827
828 void GetBufferI(unsigned char *Source,
829 int *CurrentBit,
830 int *result,
831 int BitsToProcess)
832{
833 int l=0,z,i=0;
834
835 z = 1<<(BitsToProcess-1);
836
837 while (i!=BitsToProcess) {
838 if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
839 z=z>>1;
840 i++;
841 }
842 *result=l;
843 (*CurrentBit) = (*CurrentBit) + i;
844}
845
846/* Unicode char 0x00 0x01 makes blinking in some Nokia phones.
847 * We replace single ~ chars into it. When user give double ~, it's replaced
848 * to single ~
849 */
850void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len)
851{
852 int i,current = 0;
853 bool special=false;
854
855 for (i = 0; i < len; i++) {
856 if (special) {
857 if (src[i*2] == 0x00 && src[i*2+1] == '~') {
858 dest[current++]= 0x00;
859 dest[current++]= '~';
860 } else {
861 dest[current++]= 0x00;
862 dest[current++] = 0x01;
863 dest[current++]= src[i*2];
864 dest[current++]= src[i*2+1];
865 }
866 special = false;
867 } else {
868 if (src[i*2] == 0x00 && src[i*2+1] == '~') {
869 special = true;
870 } else {
871 dest[current++]= src[i*2];
872 dest[current++]= src[i*2+1];
873 }
874 }
875 }
876 if (special) {
877 dest[current++]= 0x00;
878 dest[current++]= 0x01;
879 }
880 dest[current++] = 0x00;
881 dest[current++] = 0x00;
882}
883
884void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len)
885{
886 int i=0,current=0;
887
888 for (i=0;i<len;i++) {
889 switch (src[2*i]) {
890 case 0x00:
891 switch (src[2*i+1]) {
892 case 0x01:
893 dest[current++] = 0x00;
894 dest[current++] = '~';
895 break;
896 case '~':
897 dest[current++] = 0x00;
898 dest[current++] = '~';
899 dest[current++] = 0x00;
900 dest[current++] = '~';
901 break;
902 default:
903 dest[current++] = src[i*2];
904 dest[current++] = src[i*2+1];
905 }
906 break;
907 default:
908 dest[current++] = src[i*2];
909 dest[current++] = src[i*2+1];
910 }
911 }
912 dest[current++] = 0x00;
913 dest[current++] = 0x00;
914}
915
916bool mystrncasecmp(unsigned const char *a, unsigned const char *b, int num)
917{
918 int i;
919
920 if (a == NULL || b == NULL) return false;
921
922 num--;
923
924 for (i = 0; i != num; i++) {
925 if (a[i] == 0x00 && b[i] == 0x00) return true;
926 if (a[i] == 0x00 || b[i] == 0x00) return false;
927 if (tolower(a[i]) != tolower(b[i])) return false;
928 }
929 return true;
930}
931
932/* Compares two Unicode strings without regarding to case.
933 * Return true, when they're equal
934 */
935bool mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
936{
937 int i;
938 wchar_t wc,wc2;
939
940 if (a == NULL || b == NULL) return false;
941
942 num--;
943
944 for (i = 0; i != num; i++) {
945 if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) && (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return true;
946 if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) || (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return false;
947 wc = a[i*2+1] | (a[i*2] << 8);
948 wc2 = b[i*2+1] | (b[i*2] << 8);
949 if (mytowlower(wc) != mytowlower(wc2)) return false;
950 }
951 return true;
952}
953
954/* wcscmp in Mandrake 9.0 is wrong */
955bool mywstrncmp(unsigned const char *a, unsigned const char *b, int num)
956{
957 int i=0;
958
959 while (1) {
960 if (a[i*2] != b[i*2] || a[i*2+1] != b[i*2+1]) return false;
961 if (a[i*2] == 0x00 && a[i*2+1] == 0x00) return true;
962 i++;
963 if (num == i) return true;
964 }
965}
966
967/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
968bool myiswspace(unsigned const char *src)
969{
970#ifndef HAVE_ISWSPACE
971 int o;
972 unsigned chardest[10];
973#endif
974 wchar_t wc;
975
976 wc = src[1] | (src[0] << 8);
977
978#ifndef HAVE_ISWSPACE
979 o = DecodeWithUnicodeAlphabet(wc, dest);
980 if (o == 1) {
981 if (isspace(((int)dest[0]))!=0) return true;
982 return false;
983 }
984 return false;
985#else
986 return iswspace(wc);
987#endif
988}
989
990/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
991int mytowlower(wchar_t c)
992{
993#ifndef HAVE_TOWLOWER
994 unsigned char dest[10];
995
996 DecodeWithUnicodeAlphabet(c, dest);
997 return tolower(dest[0]);
998#else
999 return towlower(c);
1000#endif
1001}
1002
1003/*
1004 * Following code is based on wcsstr from the GNU C Library, original
1005 * comment follows:
1006 */
1007/*
1008 * The original strstr() file contains the following comment:
1009 *
1010 * My personal strstr() implementation that beats most other algorithms.
1011 * Until someone tells me otherwise, I assume that this is the
1012 * fastest implementation of strstr() in C.
1013 * I deliberately chose not to comment it. You should have at least
1014 * as much fun trying to understand it, as I had to write it :-).
1015 *
1016 * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
1017
1018unsigned char *mystrstr (const unsigned char *haystack, const unsigned char *needle)
1019{
1020/* One crazy define to convert unicode used in Gammu to standard wchar_t */
1021#define tolowerwchar(x) (mytowlower((wchar_t)( (((&(x))[0] & 0xff) << 8) | (((&(x))[1] & 0xff)) )))
1022 register wchar_t b, c;
1023
1024 if ((b = tolowerwchar(*needle)) != L'\0') {
1025 haystack -= 2; /* possible ANSI violation */
1026 do {
1027 haystack += 2;
1028 if ((c = tolowerwchar(*haystack)) == L'\0')
1029 goto ret0;
1030 } while (c != b);
1031
1032 needle += 2;
1033 if ((c = tolowerwchar(*needle)) == L'\0')
1034 goto foundneedle;
1035 needle += 2;
1036 goto jin;
1037
1038 for (;;) {
1039 register wchar_t a;
1040 register const unsigned char *rhaystack, *rneedle;
1041
1042 do {
1043 haystack += 2;
1044 if ((a = tolowerwchar(*haystack)) == L'\0')
1045 goto ret0;
1046 if (a == b)
1047 break;
1048 haystack += 2;
1049 if ((a = tolowerwchar(*haystack)) == L'\0')
1050 goto ret0;
1051 shloop: ;
1052 } while (a != b);
1053
1054 jin: haystack += 2;
1055 if ((a = tolowerwchar(*haystack)) == L'\0')
1056 goto ret0;
1057
1058 if (a != c)
1059 goto shloop;
1060
1061 rhaystack = haystack + 2;
1062 haystack -= 2;
1063 rneedle = needle;
1064 if (tolowerwchar(*rhaystack) == (a = tolowerwchar(*rneedle)))
1065 do {
1066 if (a == L'\0')
1067 goto foundneedle;
1068 rhaystack += 2;
1069 needle += 2;
1070 if (tolowerwchar(*rhaystack) != (a = tolowerwchar(*needle)))
1071 break ;
1072 if (a == L'\0')
1073 goto foundneedle;
1074 rhaystack += 2;
1075 needle += 2;
1076 } while (tolowerwchar(*rhaystack) == (a = tolowerwchar(*needle)));
1077
1078 needle = rneedle; /* took the register-poor approach */
1079
1080 if (a == L'\0')
1081 break;
1082 }
1083 }
1084foundneedle:
1085 return (unsigned char *)haystack;
1086ret0:
1087 return NULL;
1088#undef tolowerwchar
1089}
1090
1091void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen)
1092{
1093 OutBuffer[0] = 0;
1094 if (Buffer == NULL) return;
1095 while (1) {
1096 if ((*Pos) >= MaxLen) return;
1097 switch (Buffer[*Pos]) {
1098 case 0x00:
1099 return;
1100 case 0x0A:
1101 if (strlen(OutBuffer) != 0) return;
1102 break;
1103 case 0x0D:
1104 if (strlen(OutBuffer) != 0) return;
1105 break;
1106 default :
1107 OutBuffer[strlen(OutBuffer) + 1] = 0;
1108 OutBuffer[strlen(OutBuffer)] = Buffer[*Pos];
1109 }
1110 (*Pos)++;
1111 }
1112}
1113
1114void StringToDouble(char *text, double *d)
1115{
1116 bool before=true;
1117 double multiply = 1;
1118 unsigned int i;
1119
1120 *d = 0;
1121 for (i=0;i<strlen(text);i++) {
1122 if (isdigit(text[i])) {
1123 if (before) {
1124 (*d)=(*d)*10+(text[i]-'0');
1125 } else {
1126 multiply=multiply*0.1;
1127 (*d)=(*d)+(text[i]-'0')*multiply;
1128 }
1129 }
1130 if (text[i]=='.' || text[i]==',') before=false;
1131 }
1132}
1133
1134/* When char can be converted, convert it from Unicode to UTF8 */
1135bool EncodeWithUTF8Alphabet(unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2)
1136{
1137 unsigned charmychar3,mychar4;
1138 int j=0;
1139
1140 if (mychar1>0x00 || mychar2>128) {
1141 mychar3=0x00;
1142 mychar4=128;
1143 while (true) {
1144 if (mychar3==mychar1) {
1145 if (mychar4+64>=mychar2) {
1146 *ret1=j+0xc2;
1147 *ret2=0x80+(mychar2-mychar4);
1148 return true;
1149 }
1150 }
1151 if (mychar4==192) {
1152 mychar3++;
1153 mychar4=0;
1154 } else {
1155 mychar4=mychar4+64;
1156 }
1157 j++;
1158 }
1159 }
1160 return false;
1161}
1162
1163/* Make UTF8 string from Unicode input string */
1164bool EncodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src)
1165{
1166 int i,j=0;
1167 unsigned charmychar1, mychar2;
1168 bool retval = false;
1169
1170 for (i = 0; i < (int)(UnicodeLength(src)); i++) {
1171 if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) {
1172 sprintf(dest+j, "=%02X=%02X",mychar1,mychar2);
1173 j= j+6;
1174 retval = true;
1175 } else {
1176 j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j);
1177 }
1178 }
1179 dest[j++]=0;
1180 return retval;
1181}
1182
1183bool EncodeUTF8(unsigned char *dest, const unsigned char *src)
1184{
1185 int i,j=0;
1186 unsigned charmychar1, mychar2;
1187 bool retval = false;
1188
1189 for (i = 0; i < (int)(UnicodeLength(src)); i++) {
1190 if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) {
1191 sprintf(dest+j, "%c%c",mychar1,mychar2);
1192 j= j+2;
1193 retval = true;
1194 } else {
1195 j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j);
1196 }
1197 }
1198 dest[j++]=0;
1199 return retval;
1200}
1201
1202/* Decode UTF8 char to Unicode char */
1203wchar_t DecodeWithUTF8Alphabet(unsigned char mychar3, unsigned char mychar4)
1204{
1205 unsigned charmychar1, mychar2;
1206 int j;
1207
1208 mychar1=0x00;
1209 mychar2=128;
1210 for(j=0;j<mychar3-0xc2;j++) {
1211 if (mychar2==192) {
1212 mychar1++;
1213 mychar2 = 0;
1214 } else {
1215 mychar2 = mychar2+64;
1216 }
1217 }
1218 mychar2 = mychar2+(mychar4-0x80);
1219 return mychar2 | (mychar1 << 8);
1220}
1221
1222/* Make Unicode string from UTF8 string */
1223void DecodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src, int len)
1224{
1225 int i=0,j=0;
1226 unsigned charmychar1, mychar2;
1227 wchar_t ret;
1228
1229 while (i<=len) {
1230 if (len-6>=i) {
1231 /* Need to have correct chars */
1232 if (src[i] =='=' && DecodeWithHexBinAlphabet(src[i+1])!=-1
1233 && DecodeWithHexBinAlphabet(src[i+2])!=-1 &&
1234 src[i+3]=='=' && DecodeWithHexBinAlphabet(src[i+4])!=-1 &&
1235 DecodeWithHexBinAlphabet(src[i+5])!=-1) {
1236 mychar1= 16*DecodeWithHexBinAlphabet(src[i+1])+DecodeWithHexBinAlphabet(src[i+2]);
1237 mychar2= 16*DecodeWithHexBinAlphabet(src[i+4])+DecodeWithHexBinAlphabet(src[i+5]);
1238 ret = DecodeWithUTF8Alphabet(mychar1,mychar2);
1239 i = i+6;
1240 } else {
1241 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1242 }
1243 } else {
1244 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1245 }
1246 dest[j++] = (ret >> 8) & 0xff;
1247 dest[j++] = ret & 0xff;
1248 }
1249 dest[j++] = 0;
1250 dest[j++] = 0;
1251}
1252
1253void DecodeUTF8(unsigned char *dest, const unsigned char *src, int len)
1254{
1255 int i=0,j=0;
1256 wchar_t ret;
1257
1258 while (i<=len) {
1259 if (len-2>=i) {
1260 if (src[i] >= 0xC2) {
1261 ret = DecodeWithUTF8Alphabet(src[i],src[i+1]);
1262 i = i+2;
1263 } else {
1264 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1265 }
1266 } else {
1267 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1268 }
1269 dest[j++] = (ret >> 8) & 0xff;
1270 dest[j++] = ret & 0xff;
1271 }
1272 dest[j++] = 0;
1273 dest[j++] = 0;
1274}
1275
1276void DecodeUTF7(unsigned char *dest, const unsigned char *src, int len)
1277{
1278 int i=0,j=0,z,p;
1279 wchar_t ret;
1280
1281 while (i<=len) {
1282 if (len-5>=i) {
1283 if (src[i] == '+') {
1284 z=0;
1285 while (src[z+i+1] != '-' && z+i+1<len) z++;
1286 p=DecodeBASE64(src+i+1, dest+j, z);
1287 if (p%2 != 0) p--;
1288 j+=p;
1289 i+=z+2;
1290 } else {
1291 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1292 dest[j++] = (ret >> 8) & 0xff;
1293 dest[j++] = ret & 0xff;
1294 }
1295 } else {
1296 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1297 dest[j++] = (ret >> 8) & 0xff;
1298 dest[j++] = ret & 0xff;
1299 }
1300 }
1301 dest[j++] = 0;
1302 dest[j++] = 0;
1303}
1304
1305/*
1306Bob Trower 08/04/01
1307Copyright (c) Trantor Standard Systems Inc., 2001
1308
1309Permission is hereby granted, free of charge, to any person
1310obtaining a copy of this software and associated
1311documentation files (the "Software"), to deal in the
1312Software without restriction, including without limitation
1313the rights to use, copy, modify, merge, publish, distribute,
1314sublicense, and/or sell copies of the Software, and to
1315permit persons to whom the Software is furnished to do so,
1316subject to the following conditions:
1317
1318The above copyright notice and this permission notice shall
1319be included in all copies or substantial portions of the
1320Software.
1321
1322THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
1323KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
1324WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1325PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
1326OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1327OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1328OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1329SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1330*/
1331
1332static void EncodeBASE64Block(unsigned char in[3], unsigned char out[4], int len)
1333{
1334 /* BASE64 translation Table as described in RFC1113 */
1335 unsigned char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1336
1337 out[0] = cb64[ in[0] >> 2 ];
1338 out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
1339 out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
1340 out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
1341}
1342
1343void EncodeBASE64(const unsigned char *Input, unsigned char *Output, int Length)
1344{
1345 unsigned char in[3], out[4];
1346 int i, pos = 0, len, outpos = 0;
1347
1348 while (pos < Length) {
1349 len = 0;
1350 for (i = 0; i < 3; i++) {
1351 in[i] = 0;
1352 if (pos < Length) {
1353 in[i] = Input[pos];
1354 len++;
1355 pos++;
1356 }
1357 }
1358 if(len) {
1359 EncodeBASE64Block(in, out, len);
1360 for (i = 0; i < 4; i++) Output[outpos++] = out[i];
1361 }
1362 }
1363
1364 Output[outpos++] = 0;
1365}
1366
1367static void DecodeBASE64Block(unsigned char in[4], unsigned char out[3])
1368{
1369 out[0] = (unsigned char) (in[0] << 2 | in[1] >> 4);
1370 out[1] = (unsigned char) (in[1] << 4 | in[2] >> 2);
1371 out[2] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]);
1372}
1373
1374int DecodeBASE64(const unsigned char *Input, unsigned char *Output, int Length)
1375{
1376 unsigned char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
1377 unsigned char in[4], out[3], v;
1378 int i, len, pos = 0, outpos = 0;
1379
1380 while (pos < Length) {
1381 len = 0;
1382 for(i = 0; i < 4; i++) {
1383 v = 0;
1384 while(v == 0) {
1385 if (pos >= Length) break;
1386 v = (unsigned char) Input[pos++];
1387 v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
1388 if (v) v = (unsigned char) ((v == '$') ? 0 : v - 61);
1389 }
1390 if(pos<=Length) {
1391 if (v) {
1392 len++;
1393 in[i] = (unsigned char) (v - 1);
1394 }
1395 }
1396 }
1397 if (len) {
1398 DecodeBASE64Block(in, out);
1399 for(i = 0; i < len - 1; i++) Output[outpos++] = out[i];
1400 }
1401 }
1402 Output[outpos] = 0;
1403 return outpos;
1404}
1405
1406/* How should editor hadle tabs in this file? Add editor commands here.
1407 * vim: noexpandtab sw=8 ts=8 sts=8:
1408 */
1409