summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/misc/coding
Unidiff
Diffstat (limited to 'gammu/emb/common/misc/coding') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/misc/coding/coding.c1409
-rw-r--r--gammu/emb/common/misc/coding/coding.h133
-rw-r--r--gammu/emb/common/misc/coding/md5.c298
-rw-r--r--gammu/emb/common/misc/coding/md5.h6
4 files changed, 1846 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
diff --git a/gammu/emb/common/misc/coding/coding.h b/gammu/emb/common/misc/coding/coding.h
new file mode 100644
index 0000000..d0c334d
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/coding.h
@@ -0,0 +1,133 @@
1/* (c) 2002-2004 by Marcin Wiacek and others */
2
3#ifndef __coding_h
4#define __coding_h
5
6#include <stdlib.h>
7
8#include "../misc.h"
9
10#ifdef __OpenBSD__
11 typedef int wint_t;
12#endif
13
14/* ---------------------------- Unicode ------------------------------------ */
15 bool mywstrncasecmp (unsigned const char *a, unsigned const char *b, int num);
16 unsigned char *mystrstr (unsigned const char *haystack, unsigned const char *needle);
17 bool mywstrncmp (unsigned const char *a, unsigned const char *b, int num);
18 bool myiswspace (unsigned const char *src);
19 int mytowlower (wchar_t c);
20
21 unsigned int EncodeWithUnicodeAlphabet(const unsigned char *value, wchar_t *dest);
22 unsigned int DecodeWithUnicodeAlphabet(wchar_t value, unsigned char *dest);
23
24 unsigned int UnicodeLength (const unsigned char *str);
25 unsigned char *DecodeUnicodeString (const unsigned char *src);
26 unsigned char *DecodeUnicodeConsole (const unsigned char *src);
27 void DecodeUnicode (const unsigned char *src, unsigned char *dest);
28 void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len);
29
30 void CopyUnicodeString (unsigned char *Dest, unsigned char *Source);
31 void ReverseUnicodeString (unsigned char *String);
32
33 void ReadUnicodeFile (unsigned char *Dest, unsigned char *Source);
34
35 void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len);
36 void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len);
37
38/* ------------------------------- BCD ------------------------------------- */
39 unsigned char EncodeWithBCDAlphabet (int value);
40 int DecodeWithBCDAlphabet (unsigned char value);
41
42 void DecodeBCD (unsigned char *dest, const unsigned char *src, int len);
43 void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill);
44
45/* ------------------------------ UTF7 ------------------------------------- */
46 void DecodeUTF7 (unsigned char *dest, const unsigned char *src, int len);
47
48/* ------------------------------ UTF8 ------------------------------------- */
49 wchar_t DecodeWithUTF8Alphabet (unsigned char mychar3, unsigned char mychar4);
50 bool EncodeWithUTF8Alphabet (unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2);
51
52 bool EncodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src);
53 void DecodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src, int len);
54
55 bool EncodeUTF8 (unsigned char *dest, const unsigned char *src);
56 void DecodeUTF8 (unsigned char *dest, const unsigned char *src, int len);
57
58/* ------------------------------- BASE64 ---------------------------------- */
59 void EncodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length);
60 int DecodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length);
61
62/* ----------------------------- HexBin ------------------------------------ */
63 void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len);
64 void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len);
65
66/* ----------------------------- HexUnicode -------------------------------- */
67 void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len);
68 void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len);
69
70/* ---------------------- DefaultAlphabet for SMS -------------------------- */
71 void EncodeDefault (unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet);
72 void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet);
73 void FindDefaultAlphabetLen (const unsigned char *src, int *srclen, int *smslen, int maxlen);
74
75 int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output, int length);
76 int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length,
77 unsigned char *input, unsigned char *output);
78
79/* ----------------- Phone numbers according to GSM specs ------------------ */
80
81/**
82 * Enum to handle types of phones numbers like
83 * specified in GSM 03.40 section 9.1.2.5
84 */
85typedef enum {
86 /**
87 * Unknown number type
88 */
89 NUMBER_UNKNOWN = 0x81,
90 /**
91 * International number (full number with code of country)
92 */
93 NUMBER_INTERNATIONAL= 0x91,
94 /**
95 * Alphanumeric number (with chars too)
96 */
97 NUMBER_ALPHANUMERIC= 0xD0
98
99 /* specification give also other values */
100} GSM_NumberType;
101
102 void GSM_UnpackSemiOctetNumber(unsigned char *retval, unsigned char *Number, bool semioctet);
103 int GSM_PackSemiOctetNumber (unsigned char *Number, unsigned char *Output, bool semioctet);
104
105/* ---------------------------- Bits --------------------------------------- */
106
107void BufferAlign (unsigned char *Destination, int *CurrentBit);
108void BufferAlignNumber(int *CurrentBit);
109
110 void AddBuffer (unsigned char *Destination, int *CurrentBit, unsigned char *Source, int BitsToProcess);
111void AddBufferByte(unsigned char *Destination, int *CurrentBit, unsigned char Source, int BitsToProcess);
112
113void GetBuffer (unsigned char *Source, int *CurrentBit, unsigned char *Destination, int BitsToProcess);
114void GetBufferInt (unsigned char *Source, int *CurrentBit, int *integer, int BitsToProcess);
115void GetBufferI (unsigned char *Source, int *CurrentBit, int *result, int BitsToProcess);
116
117int GetBit (unsigned char *Buffer, int BitNum);
118int SetBit (unsigned char *Buffer, int BitNum);
119int ClearBit (unsigned char *Buffer, int BitNum);
120
121/* ---------------------------- Other -------------------------------------- */
122
123 void StringToDouble(char *text, double *d);
124
125bool mystrncasecmp (unsigned const char *a, unsigned const char *b, int num);
126
127void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen);
128
129#endif
130
131/* How should editor hadle tabs in this file? Add editor commands here.
132 * vim: noexpandtab sw=8 ts=8 sts=8:
133 */
diff --git a/gammu/emb/common/misc/coding/md5.c b/gammu/emb/common/misc/coding/md5.c
new file mode 100644
index 0000000..30fe33f
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/md5.c
@@ -0,0 +1,298 @@
1/* Taken from ReHash (see http://www.reichlsoft.de.vu/) and released
2 * under GPL/LGPL with permission from ReHash author
3 * Dominik Reichl <dominik.reichl@t-online.de>, Germany
4 */
5
6/*
7 **********************************************************************
8 ** MD5.cpp **
9 ** **
10 ** - Style modified by Tony Ray, January 2001 **
11 ** Added support for randomizing initialization constants **
12 ** - Style modified by Dominik Reichl, April 2003 **
13 ** Optimized code **
14 ** **
15 ** MD5.c **
16 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
17 ** Created: 2/17/90 RLR **
18 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
19 **********************************************************************
20 */
21
22/*
23 **********************************************************************
24 ** MD5.h -- Header file for implementation of MD5 **
25 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
26 ** Created: 2/17/90 RLR **
27 ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
28 ** Revised (for MD5): RLR 4/27/91 **
29 ** -- G modified to have y&~z instead of y&z **
30 ** -- FF, GG, HH modified to add in last register done **
31 ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
32 ** -- distinct additive constant for each step **
33 ** -- round 4 added, working mod 7 **
34 **********************************************************************
35 */
36
37/*
38 **********************************************************************
39 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
40 ** **
41 ** License to copy and use this software is granted provided that **
42 ** it is identified as the "RSA Data Security, Inc. MD5 Message **
43 ** Digest Algorithm" in all material mentioning or referencing this **
44 ** software or this function. **
45 ** **
46 ** License is also granted to make and use derivative works **
47 ** provided that such works are identified as "derived from the RSA **
48 ** Data Security, Inc. MD5 Message Digest Algorithm" in all **
49 ** material mentioning or referencing the derived work. **
50 ** **
51 ** RSA Data Security, Inc. makes no representations concerning **
52 ** either the merchantability of this software or the suitability **
53 ** of this software for any particular purpose. It is provided "as **
54 ** is" without express or implied warranty of any kind. **
55 ** **
56 ** These notices must be retained in any copies of any part of this **
57 ** documentation and/or software. **
58 **********************************************************************
59 */
60
61#include <stdio.h>
62#include <stdlib.h>
63
64#include "md5.h"
65
66/* Typedef a 32 bit type */
67#ifndef UINT4
68typedef unsigned long int UINT4;
69#endif
70
71/* Data structure for MD5 (Message Digest) computation */
72typedef struct {
73 UINT4 i[2]; /* Number of _bits_ handled mod 2^64 */
74 UINT4 buf[4]; /* Scratch buffer */
75 unsigned char in[64]; /* Input buffer */
76 unsigned char digest[16]; /* Actual digest after MD5Final call */
77} MD5_CTX;
78
79/* Padding */
80static unsigned char MD5_PADDING[64] = {
81 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
89};
90
91/* MD5_F, MD5_G and MD5_H are basic MD5 functions: selection, majority, parity */
92#define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
93#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
94#define MD5_H(x, y, z) ((x) ^ (y) ^ (z))
95#define MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
96
97/* ROTATE_LEFT rotates x left n bits */
98#ifndef ROTATE_LEFT
99#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
100#endif
101
102/* MD5_FF, MD5_GG, MD5_HH, and MD5_II transformations for rounds 1, 2, 3, and 4 */
103/* Rotation is separate from addition to prevent recomputation */
104#define MD5_FF(a, b, c, d, x, s, ac) {(a) += MD5_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
105#define MD5_GG(a, b, c, d, x, s, ac) {(a) += MD5_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
106#define MD5_HH(a, b, c, d, x, s, ac) {(a) += MD5_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
107#define MD5_II(a, b, c, d, x, s, ac) {(a) += MD5_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
108
109/* Constants for transformation */
110#define MD5_S11 7 /* Round 1 */
111#define MD5_S12 12
112#define MD5_S13 17
113#define MD5_S14 22
114#define MD5_S21 5 /* Round 2 */
115#define MD5_S22 9
116#define MD5_S23 14
117#define MD5_S24 20
118#define MD5_S31 4 /* Round 3 */
119#define MD5_S32 11
120#define MD5_S33 16
121#define MD5_S34 23
122#define MD5_S41 6 /* Round 4 */
123#define MD5_S42 10
124#define MD5_S43 15
125#define MD5_S44 21
126
127/* Basic MD5 step. MD5_Transform buf based on in */
128static void MD5_Transform (UINT4 *buf, UINT4 *in)
129{
130 UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
131
132 /* Round 1 */
133 MD5_FF ( a, b, c, d, in[ 0], MD5_S11, (UINT4) 3614090360u); /* 1 */
134 MD5_FF ( d, a, b, c, in[ 1], MD5_S12, (UINT4) 3905402710u); /* 2 */
135 MD5_FF ( c, d, a, b, in[ 2], MD5_S13, (UINT4) 606105819u); /* 3 */
136 MD5_FF ( b, c, d, a, in[ 3], MD5_S14, (UINT4) 3250441966u); /* 4 */
137 MD5_FF ( a, b, c, d, in[ 4], MD5_S11, (UINT4) 4118548399u); /* 5 */
138 MD5_FF ( d, a, b, c, in[ 5], MD5_S12, (UINT4) 1200080426u); /* 6 */
139 MD5_FF ( c, d, a, b, in[ 6], MD5_S13, (UINT4) 2821735955u); /* 7 */
140 MD5_FF ( b, c, d, a, in[ 7], MD5_S14, (UINT4) 4249261313u); /* 8 */
141 MD5_FF ( a, b, c, d, in[ 8], MD5_S11, (UINT4) 1770035416u); /* 9 */
142 MD5_FF ( d, a, b, c, in[ 9], MD5_S12, (UINT4) 2336552879u); /* 10 */
143 MD5_FF ( c, d, a, b, in[10], MD5_S13, (UINT4) 4294925233u); /* 11 */
144 MD5_FF ( b, c, d, a, in[11], MD5_S14, (UINT4) 2304563134u); /* 12 */
145 MD5_FF ( a, b, c, d, in[12], MD5_S11, (UINT4) 1804603682u); /* 13 */
146 MD5_FF ( d, a, b, c, in[13], MD5_S12, (UINT4) 4254626195u); /* 14 */
147 MD5_FF ( c, d, a, b, in[14], MD5_S13, (UINT4) 2792965006u); /* 15 */
148 MD5_FF ( b, c, d, a, in[15], MD5_S14, (UINT4) 1236535329u); /* 16 */
149
150 /* Round 2 */
151 MD5_GG ( a, b, c, d, in[ 1], MD5_S21, (UINT4) 4129170786u); /* 17 */
152 MD5_GG ( d, a, b, c, in[ 6], MD5_S22, (UINT4) 3225465664u); /* 18 */
153 MD5_GG ( c, d, a, b, in[11], MD5_S23, (UINT4) 643717713u); /* 19 */
154 MD5_GG ( b, c, d, a, in[ 0], MD5_S24, (UINT4) 3921069994u); /* 20 */
155 MD5_GG ( a, b, c, d, in[ 5], MD5_S21, (UINT4) 3593408605u); /* 21 */
156 MD5_GG ( d, a, b, c, in[10], MD5_S22, (UINT4) 38016083u); /* 22 */
157 MD5_GG ( c, d, a, b, in[15], MD5_S23, (UINT4) 3634488961u); /* 23 */
158 MD5_GG ( b, c, d, a, in[ 4], MD5_S24, (UINT4) 3889429448u); /* 24 */
159 MD5_GG ( a, b, c, d, in[ 9], MD5_S21, (UINT4) 568446438u); /* 25 */
160 MD5_GG ( d, a, b, c, in[14], MD5_S22, (UINT4) 3275163606u); /* 26 */
161 MD5_GG ( c, d, a, b, in[ 3], MD5_S23, (UINT4) 4107603335u); /* 27 */
162 MD5_GG ( b, c, d, a, in[ 8], MD5_S24, (UINT4) 1163531501u); /* 28 */
163 MD5_GG ( a, b, c, d, in[13], MD5_S21, (UINT4) 2850285829u); /* 29 */
164 MD5_GG ( d, a, b, c, in[ 2], MD5_S22, (UINT4) 4243563512u); /* 30 */
165 MD5_GG ( c, d, a, b, in[ 7], MD5_S23, (UINT4) 1735328473u); /* 31 */
166 MD5_GG ( b, c, d, a, in[12], MD5_S24, (UINT4) 2368359562u); /* 32 */
167
168 /* Round 3 */
169 MD5_HH ( a, b, c, d, in[ 5], MD5_S31, (UINT4) 4294588738u); /* 33 */
170 MD5_HH ( d, a, b, c, in[ 8], MD5_S32, (UINT4) 2272392833u); /* 34 */
171 MD5_HH ( c, d, a, b, in[11], MD5_S33, (UINT4) 1839030562u); /* 35 */
172 MD5_HH ( b, c, d, a, in[14], MD5_S34, (UINT4) 4259657740u); /* 36 */
173 MD5_HH ( a, b, c, d, in[ 1], MD5_S31, (UINT4) 2763975236u); /* 37 */
174 MD5_HH ( d, a, b, c, in[ 4], MD5_S32, (UINT4) 1272893353u); /* 38 */
175 MD5_HH ( c, d, a, b, in[ 7], MD5_S33, (UINT4) 4139469664u); /* 39 */
176 MD5_HH ( b, c, d, a, in[10], MD5_S34, (UINT4) 3200236656u); /* 40 */
177 MD5_HH ( a, b, c, d, in[13], MD5_S31, (UINT4) 681279174u); /* 41 */
178 MD5_HH ( d, a, b, c, in[ 0], MD5_S32, (UINT4) 3936430074u); /* 42 */
179 MD5_HH ( c, d, a, b, in[ 3], MD5_S33, (UINT4) 3572445317u); /* 43 */
180 MD5_HH ( b, c, d, a, in[ 6], MD5_S34, (UINT4) 76029189u); /* 44 */
181 MD5_HH ( a, b, c, d, in[ 9], MD5_S31, (UINT4) 3654602809u); /* 45 */
182 MD5_HH ( d, a, b, c, in[12], MD5_S32, (UINT4) 3873151461u); /* 46 */
183 MD5_HH ( c, d, a, b, in[15], MD5_S33, (UINT4) 530742520u); /* 47 */
184 MD5_HH ( b, c, d, a, in[ 2], MD5_S34, (UINT4) 3299628645u); /* 48 */
185
186 /* Round 4 */
187 MD5_II ( a, b, c, d, in[ 0], MD5_S41, (UINT4) 4096336452u); /* 49 */
188 MD5_II ( d, a, b, c, in[ 7], MD5_S42, (UINT4) 1126891415u); /* 50 */
189 MD5_II ( c, d, a, b, in[14], MD5_S43, (UINT4) 2878612391u); /* 51 */
190 MD5_II ( b, c, d, a, in[ 5], MD5_S44, (UINT4) 4237533241u); /* 52 */
191 MD5_II ( a, b, c, d, in[12], MD5_S41, (UINT4) 1700485571u); /* 53 */
192 MD5_II ( d, a, b, c, in[ 3], MD5_S42, (UINT4) 2399980690u); /* 54 */
193 MD5_II ( c, d, a, b, in[10], MD5_S43, (UINT4) 4293915773u); /* 55 */
194 MD5_II ( b, c, d, a, in[ 1], MD5_S44, (UINT4) 2240044497u); /* 56 */
195 MD5_II ( a, b, c, d, in[ 8], MD5_S41, (UINT4) 1873313359u); /* 57 */
196 MD5_II ( d, a, b, c, in[15], MD5_S42, (UINT4) 4264355552u); /* 58 */
197 MD5_II ( c, d, a, b, in[ 6], MD5_S43, (UINT4) 2734768916u); /* 59 */
198 MD5_II ( b, c, d, a, in[13], MD5_S44, (UINT4) 1309151649u); /* 60 */
199 MD5_II ( a, b, c, d, in[ 4], MD5_S41, (UINT4) 4149444226u); /* 61 */
200 MD5_II ( d, a, b, c, in[11], MD5_S42, (UINT4) 3174756917u); /* 62 */
201 MD5_II ( c, d, a, b, in[ 2], MD5_S43, (UINT4) 718787259u); /* 63 */
202 MD5_II ( b, c, d, a, in[ 9], MD5_S44, (UINT4) 3951481745u); /* 64 */
203
204 buf[0] += a;
205 buf[1] += b;
206 buf[2] += c;
207 buf[3] += d;
208}
209
210// Set pseudoRandomNumber to zero for RFC MD5 implementation
211void MD5Init (MD5_CTX *mdContext, unsigned long pseudoRandomNumber)
212{
213 mdContext->i[0] = mdContext->i[1] = (UINT4)0;
214
215 /* Load magic initialization constants */
216 mdContext->buf[0] = (UINT4)0x67452301 + (pseudoRandomNumber * 11);
217 mdContext->buf[1] = (UINT4)0xefcdab89 + (pseudoRandomNumber * 71);
218 mdContext->buf[2] = (UINT4)0x98badcfe + (pseudoRandomNumber * 37);
219 mdContext->buf[3] = (UINT4)0x10325476 + (pseudoRandomNumber * 97);
220}
221
222void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
223{
224 UINT4 in[16];
225 int mdi = 0;
226 unsigned int i = 0, ii = 0;
227
228 /* Compute number of bytes mod 64 */
229 mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
230
231 /* Update number of bits */
232 if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) mdContext->i[1]++;
233 mdContext->i[0] += ((UINT4)inLen << 3);
234 mdContext->i[1] += ((UINT4)inLen >> 29);
235
236 while (inLen--) {
237 /* Add new character to buffer, increment mdi */
238 mdContext->in[mdi++] = *inBuf++;
239
240 /* Transform if necessary */
241 if (mdi == 0x40) {
242 for (i = 0, ii = 0; i < 16; i++, ii += 4)
243 in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
244 (((UINT4)mdContext->in[ii+2]) << 16) |
245 (((UINT4)mdContext->in[ii+1]) << 8) |
246 ((UINT4)mdContext->in[ii]);
247
248 MD5_Transform (mdContext->buf, in);
249 mdi = 0;
250 }
251 }
252}
253
254void MD5Final (MD5_CTX *mdContext)
255{
256 UINT4 in[16];
257 int mdi = 0;
258 unsigned int i = 0, ii = 0, padLen = 0;
259
260 /* Save number of bits */
261 in[14] = mdContext->i[0];
262 in[15] = mdContext->i[1];
263
264 /* Compute number of bytes mod 64 */
265 mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
266
267 /* Pad out to 56 mod 64 */
268 padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
269 MD5Update (mdContext, MD5_PADDING, padLen);
270
271 /* Append length in bits and transform */
272 for (i = 0, ii = 0; i < 14; i++, ii += 4)
273 in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
274 (((UINT4)mdContext->in[ii+2]) << 16) |
275 (((UINT4)mdContext->in[ii+1]) << 8) |
276 ((UINT4)mdContext->in[ii]);
277 MD5_Transform (mdContext->buf, in);
278
279 /* Store buffer in digest */
280 for (i = 0, ii = 0; i < 4; i++, ii += 4) {
281 mdContext->digest[ii] = (unsigned char)( mdContext->buf[i] & 0xFF);
282 mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
283 mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
284 mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
285 }
286}
287
288void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum)
289{
290 int i;
291 MD5_CTX m_md5;
292
293 MD5Init(&m_md5, 0);
294 MD5Update(&m_md5, buffer, length);
295 MD5Final(&m_md5);
296
297 for (i = 0; i < 16; i++) sprintf(checksum+i*2,"%02X", m_md5.digest[i]);
298}
diff --git a/gammu/emb/common/misc/coding/md5.h b/gammu/emb/common/misc/coding/md5.h
new file mode 100644
index 0000000..9da9229
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/md5.h
@@ -0,0 +1,6 @@
1#ifndef __md5_h
2#define __md5_h
3
4void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum);
5
6#endif