-rw-r--r-- | gammu/emb/common/misc/cfg.c | 332 | ||||
-rw-r--r-- | gammu/emb/common/misc/cfg.h | 42 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/coding.c | 1409 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/coding.h | 133 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/md5.c | 298 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/md5.h | 6 | ||||
-rw-r--r-- | gammu/emb/common/misc/misc.c | 591 | ||||
-rw-r--r-- | gammu/emb/common/misc/misc.h | 137 |
8 files changed, 2948 insertions, 0 deletions
diff --git a/gammu/emb/common/misc/cfg.c b/gammu/emb/common/misc/cfg.c new file mode 100644 index 0000000..1c74874 --- a/dev/null +++ b/gammu/emb/common/misc/cfg.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /* (c) 2002-2004 by Marcin Wiacek */ | ||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <ctype.h> | ||
7 | #include <errno.h> | ||
8 | #ifndef __OpenBSD__ | ||
9 | # include <wchar.h> | ||
10 | # include <wctype.h> | ||
11 | #endif | ||
12 | |||
13 | #include "../config.h" | ||
14 | #include "coding/coding.h" | ||
15 | #include "cfg.h" | ||
16 | #include "misc.h" | ||
17 | |||
18 | /* | ||
19 | * Read information from file in Windows INI format style | ||
20 | */ | ||
21 | INI_Section *INI_ReadFile(char *FileName, bool Unicode) | ||
22 | { | ||
23 | FILE *f; | ||
24 | bool FFEEUnicode=false; | ||
25 | int level = -1, buffer1used, buffer2used; | ||
26 | int bufferused, i, buffused=1000,buffread=1000, num; | ||
27 | unsigned charch[3], *buffer = NULL; | ||
28 | unsigned char*buffer2 = NULL, *buffer1 = NULL, buff[1000]; | ||
29 | INI_Section *INI_info = NULL, *INI_head = NULL, *heading; | ||
30 | INI_Entry *entry; | ||
31 | |||
32 | f = fopen(FileName,"rb"); | ||
33 | if (f == NULL) return NULL; | ||
34 | |||
35 | num = 0; | ||
36 | while(1) { | ||
37 | /* We read one line from file */ | ||
38 | bufferused = 0; | ||
39 | while (1) { | ||
40 | if (buffused == buffread) { | ||
41 | buffused = fread(buff,1,1000,f); | ||
42 | buffread = 0; | ||
43 | if (buffused == 0) { | ||
44 | free(buffer); free(buffer1); free(buffer2); | ||
45 | fclose(f); | ||
46 | return INI_head; | ||
47 | } | ||
48 | } | ||
49 | if (Unicode) { | ||
50 | if (num == 0) { | ||
51 | if (buffused == buffread) continue; | ||
52 | ch[0] = buff[buffread++]; | ||
53 | num = 1; | ||
54 | } | ||
55 | if (num == 1) { | ||
56 | if (buffused == buffread) continue; | ||
57 | ch[1] = buff[buffread++]; | ||
58 | num = 0; | ||
59 | } | ||
60 | if (level == -1) { | ||
61 | if (ch[0] == 0xFF && ch[1] == 0xFE) FFEEUnicode = true; | ||
62 | level = 0; | ||
63 | continue; | ||
64 | } | ||
65 | if (FFEEUnicode) { | ||
66 | ch[2] = ch[0]; ch[0] = ch[1]; ch[1] = ch[2]; | ||
67 | } | ||
68 | } else { | ||
69 | if (buffused == buffread) continue; | ||
70 | ch[0] = 0; | ||
71 | ch[1] = buff[buffread++]; | ||
72 | if (level == -1) level = 0; | ||
73 | } | ||
74 | if ((ch[0] == 0 && ch[1] == 13) || | ||
75 | (ch[0] == 0 && ch[1] == 10)) { | ||
76 | break; | ||
77 | } | ||
78 | buffer = realloc(buffer,bufferused+2); | ||
79 | buffer[bufferused] = ch[0]; | ||
80 | buffer[bufferused+1] = ch[1]; | ||
81 | bufferused = bufferused + 2; | ||
82 | } | ||
83 | // printf("line \"%s\"\n",DecodeUnicodeConsole(buffer)); | ||
84 | |||
85 | buffer1used = 0; | ||
86 | buffer2used = 0; | ||
87 | if (level == 1) level = 0; | ||
88 | if (level == 3 || level == 4 || level == 5) level = 2; | ||
89 | |||
90 | /* We parse read line */ | ||
91 | for (i=0;i<bufferused/2;i++) { | ||
92 | ch[0] = buffer[i*2]; | ||
93 | ch[1] = buffer[i*2+1]; | ||
94 | if (level == 0) { //search for name of section | ||
95 | if (ch[0] == 0 && ch[1] == '[') level = 1; | ||
96 | if (ch[0] == 0 && ch[1] == ';') break; | ||
97 | if (ch[0] == 0 && ch[1] == '#') break; | ||
98 | continue; | ||
99 | } | ||
100 | if (level == 1) { //section name | ||
101 | if (ch[0] == 0 && ch[1] == ']') { | ||
102 | if (buffer1used == 0) break; | ||
103 | if (Unicode) { | ||
104 | buffer1 = realloc(buffer1,buffer1used+2); | ||
105 | buffer1[buffer1used] = 0; | ||
106 | buffer1[buffer1used+1] = 0; | ||
107 | buffer1used = buffer1used + 2; | ||
108 | } else { | ||
109 | buffer1 = realloc(buffer1,buffer1used+1); | ||
110 | buffer1[buffer1used] = 0x00; | ||
111 | buffer1used = buffer1used + 1; | ||
112 | } | ||
113 | heading = (INI_Section *)malloc(sizeof(*heading)); | ||
114 | if (heading == NULL) { | ||
115 | free(buffer); free(buffer1); free(buffer2); | ||
116 | fclose(f); | ||
117 | return NULL; | ||
118 | } | ||
119 | heading->SectionName = (char *)malloc(buffer1used); | ||
120 | memcpy(heading->SectionName,buffer1,buffer1used); | ||
121 | heading->Prev = INI_info; | ||
122 | heading->Next = NULL; | ||
123 | if (INI_info != NULL) { | ||
124 | INI_info->Next = heading; | ||
125 | } else { | ||
126 | INI_head = heading; | ||
127 | } | ||
128 | INI_info = heading; | ||
129 | INI_info->SubEntries = NULL; | ||
130 | level = 2; | ||
131 | // printf("[%s]\n",DecodeUnicodeConsole(buffer1)); | ||
132 | break; | ||
133 | } | ||
134 | if (Unicode) { | ||
135 | buffer1 = realloc(buffer1,buffer1used+2); | ||
136 | buffer1[buffer1used] = ch[0]; | ||
137 | buffer1[buffer1used+1] = ch[1]; | ||
138 | buffer1used = buffer1used + 2; | ||
139 | } else { | ||
140 | buffer1 = realloc(buffer1,buffer1used+1); | ||
141 | buffer1[buffer1used] = ch[1]; | ||
142 | buffer1used = buffer1used + 1; | ||
143 | } | ||
144 | continue; | ||
145 | } | ||
146 | if (level == 2) { //search for key name | ||
147 | if (ch[0] == 0 && ch[1] == ';') break; | ||
148 | if (ch[0] == 0 && ch[1] == '#') break; | ||
149 | if (ch[0] == 0 && ch[1] == '[') { | ||
150 | level = 1; | ||
151 | continue; | ||
152 | } | ||
153 | if (Unicode) { | ||
154 | if (myiswspace(ch)) continue; | ||
155 | } else { | ||
156 | if (isspace((int) ch[1])) continue; | ||
157 | } | ||
158 | level = 3; | ||
159 | } | ||
160 | if (level == 3) { //key name | ||
161 | if (ch[0] == 0 && ch[1] == '=') { | ||
162 | if (buffer1used == 0) break; | ||
163 | while(1) { | ||
164 | if (Unicode) { | ||
165 | if (!myiswspace(buffer1+(buffer1used-2))) break; | ||
166 | buffer1used = buffer1used - 2; | ||
167 | } else { | ||
168 | if (!isspace((int)buffer1[buffer1used-1])) break; | ||
169 | buffer1used = buffer1used - 1; | ||
170 | } | ||
171 | } | ||
172 | level = 4; | ||
173 | continue; | ||
174 | } | ||
175 | if (Unicode) { | ||
176 | buffer1 = realloc(buffer1,buffer1used+2); | ||
177 | buffer1[buffer1used] = ch[0]; | ||
178 | buffer1[buffer1used+1] = ch[1]; | ||
179 | buffer1used = buffer1used + 2; | ||
180 | } else { | ||
181 | buffer1 = realloc(buffer1,buffer1used+1); | ||
182 | buffer1[buffer1used] = ch[1]; | ||
183 | buffer1used = buffer1used + 1; | ||
184 | } | ||
185 | } | ||
186 | if (level == 4) { //search for key value | ||
187 | if (Unicode) { | ||
188 | if (myiswspace(ch)) continue; | ||
189 | } else { | ||
190 | if (isspace((int) ch[1])) continue; | ||
191 | } | ||
192 | level = 5; | ||
193 | } | ||
194 | if (level == 5) { //key value | ||
195 | if (Unicode) { | ||
196 | buffer2 = realloc(buffer2,buffer2used+2); | ||
197 | buffer2[buffer2used] = ch[0]; | ||
198 | buffer2[buffer2used+1] = ch[1]; | ||
199 | buffer2used = buffer2used + 2; | ||
200 | } else { | ||
201 | buffer2 = realloc(buffer2,buffer2used+1); | ||
202 | buffer2[buffer2used] = ch[1]; | ||
203 | buffer2used = buffer2used + 1; | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | if (level == 5) { | ||
208 | if (buffer2used == 0) continue; | ||
209 | |||
210 | entry = (INI_Entry *)malloc(sizeof(*entry)); | ||
211 | if (entry == NULL) { | ||
212 | free(buffer); free(buffer1); free(buffer2); | ||
213 | fclose(f); | ||
214 | return NULL; | ||
215 | } | ||
216 | if (Unicode) { | ||
217 | buffer1 = realloc(buffer1,buffer1used+2); | ||
218 | buffer1[buffer1used] = 0; | ||
219 | buffer1[buffer1used+1] = 0; | ||
220 | buffer1used = buffer1used + 2; | ||
221 | buffer2 = realloc(buffer2,buffer2used+2); | ||
222 | buffer2[buffer2used] = 0; | ||
223 | buffer2[buffer2used+1] = 0; | ||
224 | buffer2used = buffer2used + 2; | ||
225 | } else { | ||
226 | buffer1 = realloc(buffer1,buffer1used+1); | ||
227 | buffer1[buffer1used] = 0x00; | ||
228 | buffer1used = buffer1used + 1; | ||
229 | buffer2 = realloc(buffer2,buffer2used+1); | ||
230 | buffer2[buffer2used] = 0x00; | ||
231 | buffer2used = buffer2used + 1; | ||
232 | } | ||
233 | // printf("\"%s\"=\"%s\"\n",buffer1,buffer2); | ||
234 | // printf("\"%s\"=",DecodeUnicodeConsole(buffer1)); | ||
235 | // printf("\"%s\"\n",DecodeUnicodeConsole(buffer2)); | ||
236 | |||
237 | entry->EntryName = (char *)malloc(buffer1used); | ||
238 | memcpy(entry->EntryName,buffer1,buffer1used); | ||
239 | |||
240 | entry->EntryValue = (char *)malloc(buffer2used); | ||
241 | memcpy(entry->EntryValue,buffer2,buffer2used); | ||
242 | |||
243 | entry->Prev = NULL; | ||
244 | entry->Next = INI_info->SubEntries; | ||
245 | if (INI_info->SubEntries != NULL) INI_info->SubEntries->Prev = entry; | ||
246 | INI_info->SubEntries = entry; | ||
247 | } | ||
248 | } | ||
249 | free(buffer); free(buffer1); free(buffer2); | ||
250 | fclose(f); | ||
251 | return INI_head; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * Search for key value in file in Windows INI format style | ||
256 | * Returns found value or NULL | ||
257 | */ | ||
258 | unsigned char *INI_GetValue(INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode) | ||
259 | { | ||
260 | INI_Section *sec; | ||
261 | INI_Entry *ent; | ||
262 | |||
263 | if (cfg == NULL || section == NULL || key == NULL) return NULL; | ||
264 | |||
265 | if (Unicode) { | ||
266 | /* Search for section */ | ||
267 | sec = cfg; | ||
268 | while (sec != NULL) { | ||
269 | if (mywstrncasecmp(section, sec->SectionName, 0)) { | ||
270 | /* Search for key inside section */ | ||
271 | ent = sec->SubEntries; | ||
272 | while (ent != NULL) { | ||
273 | if (mywstrncasecmp(key,ent->EntryName,0)) { | ||
274 | return ent->EntryValue; | ||
275 | } | ||
276 | ent = ent->Next; | ||
277 | } | ||
278 | } | ||
279 | sec = sec->Next; | ||
280 | } | ||
281 | } else { | ||
282 | /* Search for section */ | ||
283 | sec = cfg; | ||
284 | while (sec != NULL) { | ||
285 | if (mystrncasecmp(section, sec->SectionName, 0)) { | ||
286 | /* Search for key inside section */ | ||
287 | ent = sec->SubEntries; | ||
288 | while (ent != NULL) { | ||
289 | if (mystrncasecmp(key,ent->EntryName,0)) { | ||
290 | return ent->EntryValue; | ||
291 | } | ||
292 | ent = ent->Next; | ||
293 | } | ||
294 | } | ||
295 | sec = sec->Next; | ||
296 | } | ||
297 | } | ||
298 | return NULL; | ||
299 | } | ||
300 | |||
301 | /* Return last value in specified section */ | ||
302 | INI_Entry *INI_FindLastSectionEntry(INI_Section *file_info, unsigned char *section, bool Unicode) | ||
303 | { | ||
304 | INI_Section *h; | ||
305 | INI_Entry*e; | ||
306 | |||
307 | e = NULL; | ||
308 | /* First find our section */ | ||
309 | for (h = file_info; h != NULL; h = h->Next) { | ||
310 | if (Unicode) { | ||
311 | if (mywstrncasecmp(section, h->SectionName, 0)) { | ||
312 | e = h->SubEntries; | ||
313 | break; | ||
314 | } | ||
315 | } else { | ||
316 | if (mystrncasecmp(section, h->SectionName, 0)) { | ||
317 | e = h->SubEntries; | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | |||
323 | if (e == NULL) return NULL; | ||
324 | |||
325 | /* Goes into last value in section */ | ||
326 | while (e->Next != NULL) e = e->Next; | ||
327 | return e; | ||
328 | } | ||
329 | |||
330 | /* How should editor hadle tabs in this file? Add editor commands here. | ||
331 | * vim: noexpandtab sw=8 ts=8 sts=8: | ||
332 | */ | ||
diff --git a/gammu/emb/common/misc/cfg.h b/gammu/emb/common/misc/cfg.h new file mode 100644 index 0000000..edb9b09 --- a/dev/null +++ b/gammu/emb/common/misc/cfg.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* (c) 2003 by Marcin Wiacek */ | ||
2 | |||
3 | #ifndef _cfg_h | ||
4 | #define _cfg_h | ||
5 | |||
6 | #include "misc.h" | ||
7 | |||
8 | /* -------------------------------- structures ----------------------------- */ | ||
9 | |||
10 | typedef struct _INI_Entry INI_Entry; | ||
11 | |||
12 | /* | ||
13 | * Structure used to save value for single key in INI style file | ||
14 | */ | ||
15 | struct _INI_Entry { | ||
16 | INI_Entry *Next, *Prev; | ||
17 | unsigned char *EntryName; | ||
18 | unsigned char *EntryValue; | ||
19 | }; | ||
20 | |||
21 | typedef struct _INI_Section INI_Section; | ||
22 | |||
23 | /* | ||
24 | * Structure used to save section in INI style file | ||
25 | */ | ||
26 | struct _INI_Section { | ||
27 | INI_Section *Next, *Prev; | ||
28 | INI_Entry *SubEntries; | ||
29 | unsigned char *SectionName; | ||
30 | }; | ||
31 | |||
32 | /* ------------------------- function prototypes --------------------------- */ | ||
33 | |||
34 | INI_Section *INI_ReadFile (char *FileName, bool Unicode); | ||
35 | INI_Entry *INI_FindLastSectionEntry (INI_Section *file_info, unsigned char *section, bool Unicode); | ||
36 | unsigned char *INI_GetValue (INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode); | ||
37 | |||
38 | #endif | ||
39 | |||
40 | /* How should editor hadle tabs in this file? Add editor commands here. | ||
41 | * vim: noexpandtab sw=8 ts=8 sts=8: | ||
42 | */ | ||
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 | |||
19 | unsigned 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 */ | ||
31 | unsigned 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 */ | ||
43 | unsigned 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 | |||
56 | void 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 */ | ||
70 | unsigned 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 | */ | ||
81 | unsigned 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 */ | ||
107 | void 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 | |||
121 | unsigned 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 | |||
129 | int DecodeWithBCDAlphabet(unsigned char value) | ||
130 | { | ||
131 | return 10*(value & 0x0f)+(value >> 4); | ||
132 | } | ||
133 | |||
134 | void 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 | |||
147 | void 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 | |||
166 | int 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 | |||
174 | unsigned 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 | |||
181 | void 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 | |||
210 | void 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 | |||
223 | void 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 | |||
234 | void 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 */ | ||
246 | static 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 | */ | ||
291 | static 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 | |||
305 | void 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 | */ | ||
361 | static 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 | |||
369 | void 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 */ | ||
451 | void 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 | |||
492 | int 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 | |||
536 | int 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 | |||
575 | void 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 | */ | ||
625 | int 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 | |||
673 | void 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 */ | ||
687 | void 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 */ | ||
705 | void 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 | |||
726 | int GetBit(unsigned char *Buffer, int BitNum) | ||
727 | { | ||
728 | return Buffer[BitNum/8] & 1<<(7-(BitNum%8)); | ||
729 | } | ||
730 | |||
731 | int SetBit(unsigned char *Buffer, int BitNum) | ||
732 | { | ||
733 | return Buffer[BitNum/8] |= 1<<(7-(BitNum%8)); | ||
734 | } | ||
735 | |||
736 | int ClearBit(unsigned char *Buffer, int BitNum) | ||
737 | { | ||
738 | return Buffer[BitNum/8] &= 255 - (1 << (7-(BitNum%8))); | ||
739 | } | ||
740 | |||
741 | void 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 | |||
753 | void 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 | |||
782 | void 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 | |||
794 | void 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 | |||
812 | void 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 | */ | ||
850 | void 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 | |||
884 | void 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 | |||
916 | bool 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 | */ | ||
935 | bool 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 */ | ||
955 | bool 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 */ | ||
968 | bool 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 */ | ||
991 | int 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 | |||
1018 | unsigned 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 | } | ||
1084 | foundneedle: | ||
1085 | return (unsigned char *)haystack; | ||
1086 | ret0: | ||
1087 | return NULL; | ||
1088 | #undef tolowerwchar | ||
1089 | } | ||
1090 | |||
1091 | void 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 | |||
1114 | void 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 */ | ||
1135 | bool 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 */ | ||
1164 | bool 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 | |||
1183 | bool 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 */ | ||
1203 | wchar_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 */ | ||
1223 | void 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 | |||
1253 | void 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 | |||
1276 | void 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 | /* | ||
1306 | Bob Trower 08/04/01 | ||
1307 | Copyright (c) Trantor Standard Systems Inc., 2001 | ||
1308 | |||
1309 | Permission is hereby granted, free of charge, to any person | ||
1310 | obtaining a copy of this software and associated | ||
1311 | documentation files (the "Software"), to deal in the | ||
1312 | Software without restriction, including without limitation | ||
1313 | the rights to use, copy, modify, merge, publish, distribute, | ||
1314 | sublicense, and/or sell copies of the Software, and to | ||
1315 | permit persons to whom the Software is furnished to do so, | ||
1316 | subject to the following conditions: | ||
1317 | |||
1318 | The above copyright notice and this permission notice shall | ||
1319 | be included in all copies or substantial portions of the | ||
1320 | Software. | ||
1321 | |||
1322 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | ||
1323 | KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | ||
1324 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
1325 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS | ||
1326 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
1327 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
1328 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
1329 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
1330 | */ | ||
1331 | |||
1332 | static 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 | |||
1343 | void 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 | |||
1367 | static 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 | |||
1374 | int 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 | */ | ||
85 | typedef 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 | |||
107 | void BufferAlign (unsigned char *Destination, int *CurrentBit); | ||
108 | void BufferAlignNumber(int *CurrentBit); | ||
109 | |||
110 | void AddBuffer (unsigned char *Destination, int *CurrentBit, unsigned char *Source, int BitsToProcess); | ||
111 | void AddBufferByte(unsigned char *Destination, int *CurrentBit, unsigned char Source, int BitsToProcess); | ||
112 | |||
113 | void GetBuffer (unsigned char *Source, int *CurrentBit, unsigned char *Destination, int BitsToProcess); | ||
114 | void GetBufferInt (unsigned char *Source, int *CurrentBit, int *integer, int BitsToProcess); | ||
115 | void GetBufferI (unsigned char *Source, int *CurrentBit, int *result, int BitsToProcess); | ||
116 | |||
117 | int GetBit (unsigned char *Buffer, int BitNum); | ||
118 | int SetBit (unsigned char *Buffer, int BitNum); | ||
119 | int ClearBit (unsigned char *Buffer, int BitNum); | ||
120 | |||
121 | /* ---------------------------- Other -------------------------------------- */ | ||
122 | |||
123 | void StringToDouble(char *text, double *d); | ||
124 | |||
125 | bool mystrncasecmp (unsigned const char *a, unsigned const char *b, int num); | ||
126 | |||
127 | void 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 | ||
68 | typedef unsigned long int UINT4; | ||
69 | #endif | ||
70 | |||
71 | /* Data structure for MD5 (Message Digest) computation */ | ||
72 | typedef 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 */ | ||
80 | static 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 */ | ||
128 | static 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 | ||
211 | void 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 | |||
222 | void 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 | |||
254 | void 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 | |||
288 | void 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 | |||
4 | void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum); | ||
5 | |||
6 | #endif | ||
diff --git a/gammu/emb/common/misc/misc.c b/gammu/emb/common/misc/misc.c new file mode 100644 index 0000000..c2f09e4 --- a/dev/null +++ b/gammu/emb/common/misc/misc.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */ | ||
2 | /* Checking used compiler (c) 2002 by Michal Cihar */ | ||
3 | |||
4 | #include <string.h> | ||
5 | #include <ctype.h> | ||
6 | #include <time.h> | ||
7 | #include <stdarg.h> | ||
8 | #include <stdio.h> | ||
9 | #include <locale.h> | ||
10 | #include <sys/timeb.h> | ||
11 | #ifdef WIN32 | ||
12 | # include "windows.h" | ||
13 | #endif | ||
14 | |||
15 | #include "../gsmstate.h" | ||
16 | #include "misc.h" | ||
17 | |||
18 | /* Based on article in Polish PC-Kurier 8/1998 page 104 | ||
19 | * Archive on http://www.pckurier.pl | ||
20 | */ | ||
21 | char *DayOfWeek (int year, int month, int day) | ||
22 | { | ||
23 | int p,q,r,w; | ||
24 | static char DayOfWeekChar[10]; | ||
25 | |||
26 | p=(14-month) / 12; | ||
27 | q=month+12*p-2; | ||
28 | r=year-p; | ||
29 | w=(day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7; | ||
30 | strcpy(DayOfWeekChar,""); | ||
31 | switch (w) { | ||
32 | case 0: strcpy(DayOfWeekChar,"Sun"); break; | ||
33 | case 1: strcpy(DayOfWeekChar,"Mon"); break; | ||
34 | case 2: strcpy(DayOfWeekChar,"Tue"); break; | ||
35 | case 3: strcpy(DayOfWeekChar,"Wed"); break; | ||
36 | case 4: strcpy(DayOfWeekChar,"Thu"); break; | ||
37 | case 5: strcpy(DayOfWeekChar,"Fri"); break; | ||
38 | case 6: strcpy(DayOfWeekChar,"Sat"); break; | ||
39 | } | ||
40 | return DayOfWeekChar; | ||
41 | } | ||
42 | |||
43 | void Fill_GSM_DateTime(GSM_DateTime *Date, time_t timet) | ||
44 | { | ||
45 | struct tm *now; | ||
46 | |||
47 | now = localtime(&timet); | ||
48 | Date->Year= now->tm_year; | ||
49 | Date->Month= now->tm_mon+1; | ||
50 | Date->Day= now->tm_mday; | ||
51 | Date->Hour= now->tm_hour; | ||
52 | Date->Minute= now->tm_min; | ||
53 | Date->Second = now->tm_sec; | ||
54 | } | ||
55 | |||
56 | void GSM_GetCurrentDateTime (GSM_DateTime *Date) | ||
57 | { | ||
58 | Fill_GSM_DateTime(Date, time(NULL)); | ||
59 | if (Date->Year<1900) { | ||
60 | if (Date->Year>90) Date->Year = Date->Year+1900; | ||
61 | else Date->Year = Date->Year+2000; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | time_t Fill_Time_T(GSM_DateTime DT, int TZ) | ||
66 | { | ||
67 | struct tm tm_starttime; | ||
68 | unsigned char buffer[30]; | ||
69 | |||
70 | dbgprintf(" StartTime : %02i-%02i-%04i %02i:%02i:%02i\n", | ||
71 | DT.Day,DT.Month,DT.Year,DT.Hour,DT.Minute,DT.Second); | ||
72 | |||
73 | if (TZ != 0) { | ||
74 | #if defined(WIN32) || defined(__SVR4) | ||
75 | sprintf(buffer,"TZ=PST+%i",TZ); | ||
76 | putenv(buffer); | ||
77 | #else | ||
78 | sprintf(buffer,"PST+%i",TZ); | ||
79 | setenv("TZ",buffer,1); | ||
80 | #endif | ||
81 | } | ||
82 | tzset(); | ||
83 | |||
84 | memset(&tm_starttime, 0, sizeof(tm_starttime)); | ||
85 | tm_starttime.tm_year = DT.Year - 1900; | ||
86 | tm_starttime.tm_mon = DT.Month - 1; | ||
87 | tm_starttime.tm_mday = DT.Day; | ||
88 | tm_starttime.tm_hour = DT.Hour; | ||
89 | tm_starttime.tm_min = DT.Minute; | ||
90 | tm_starttime.tm_sec = DT.Second; | ||
91 | tm_starttime.tm_isdst= 0; | ||
92 | |||
93 | return mktime(&tm_starttime); | ||
94 | } | ||
95 | |||
96 | void GetTimeDifference(unsigned long diff, GSM_DateTime *DT, bool Plus, int multi) | ||
97 | { | ||
98 | time_t t_time; | ||
99 | |||
100 | t_time = Fill_Time_T(*DT,8); | ||
101 | |||
102 | if (Plus) { | ||
103 | t_time += diff*multi; | ||
104 | } else { | ||
105 | t_time -= diff*multi; | ||
106 | } | ||
107 | |||
108 | Fill_GSM_DateTime(DT, t_time); | ||
109 | DT->Year = DT->Year + 1900; | ||
110 | dbgprintf(" EndTime : %02i-%02i-%04i %02i:%02i:%02i\n", | ||
111 | DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second); | ||
112 | } | ||
113 | |||
114 | char *OSDateTime (GSM_DateTime dt, bool TimeZone) | ||
115 | { | ||
116 | struct tm timeptr; | ||
117 | static char retval[200],retval2[200]; | ||
118 | int p,q,r,w; | ||
119 | |||
120 | #ifdef WIN32 | ||
121 | setlocale(LC_ALL, ".OCP"); | ||
122 | #endif | ||
123 | |||
124 | /* Based on article in Polish PC-Kurier 8/1998 page 104 | ||
125 | * Archive on http://www.pckurier.pl | ||
126 | */ | ||
127 | p=(14-dt.Month) / 12; | ||
128 | q=dt.Month+12*p-2; | ||
129 | r=dt.Year-p; | ||
130 | w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7; | ||
131 | |||
132 | timeptr.tm_yday = 0; /* FIXME */ | ||
133 | timeptr.tm_isdst = -1; /* FIXME */ | ||
134 | timeptr.tm_year = dt.Year - 1900; | ||
135 | timeptr.tm_mon = dt.Month - 1; | ||
136 | timeptr.tm_mday = dt.Day; | ||
137 | timeptr.tm_hour = dt.Hour; | ||
138 | timeptr.tm_min = dt.Minute; | ||
139 | timeptr.tm_sec = dt.Second; | ||
140 | timeptr.tm_wday = w; | ||
141 | #ifdef _BSD_SOURCE | ||
142 | timeptr.tm_zone = NULL; | ||
143 | #endif | ||
144 | |||
145 | #ifdef WIN32 | ||
146 | strftime(retval2, 200, "%#c", &timeptr); | ||
147 | #else | ||
148 | strftime(retval2, 200, "%c", &timeptr); | ||
149 | #endif | ||
150 | if (TimeZone) { | ||
151 | if (dt.Timezone >= 0) { | ||
152 | sprintf(retval," +%02i00",dt.Timezone); | ||
153 | } else { | ||
154 | sprintf(retval," -%02i00",dt.Timezone); | ||
155 | } | ||
156 | strcat(retval2,retval); | ||
157 | } | ||
158 | /* If don't have weekday name, include it */ | ||
159 | strftime(retval, 200, "%A", &timeptr); | ||
160 | if (strstr(retval2,retval)==NULL) { | ||
161 | /* Check for abbreviated weekday */ | ||
162 | strftime(retval, 200, "%a", &timeptr); | ||
163 | if (strstr(retval2,retval)==NULL) { | ||
164 | strcat(retval2," ("); | ||
165 | strcat(retval2,retval); | ||
166 | strcat(retval2,")"); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | #ifdef WIN32 | ||
171 | setlocale(LC_ALL, ".ACP"); | ||
172 | #endif | ||
173 | |||
174 | return retval2; | ||
175 | } | ||
176 | |||
177 | char *OSDate (GSM_DateTime dt) | ||
178 | { | ||
179 | struct tm timeptr; | ||
180 | static char retval[200],retval2[200]; | ||
181 | int p,q,r,w; | ||
182 | |||
183 | #ifdef WIN32 | ||
184 | setlocale(LC_ALL, ".OCP"); | ||
185 | #endif | ||
186 | |||
187 | /* Based on article in Polish PC-Kurier 8/1998 page 104 | ||
188 | * Archive on http://www.pckurier.pl | ||
189 | */ | ||
190 | p=(14-dt.Month) / 12; | ||
191 | q=dt.Month+12*p-2; | ||
192 | r=dt.Year-p; | ||
193 | w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7; | ||
194 | |||
195 | timeptr.tm_yday = 0; /* FIXME */ | ||
196 | timeptr.tm_isdst = -1; /* FIXME */ | ||
197 | timeptr.tm_year = dt.Year - 1900; | ||
198 | timeptr.tm_mon = dt.Month - 1; | ||
199 | timeptr.tm_mday = dt.Day; | ||
200 | timeptr.tm_hour = dt.Hour; | ||
201 | timeptr.tm_min = dt.Minute; | ||
202 | timeptr.tm_sec = dt.Second; | ||
203 | timeptr.tm_wday = w; | ||
204 | #ifdef _BSD_SOURCE | ||
205 | timeptr.tm_zone = NULL; | ||
206 | #endif | ||
207 | |||
208 | #ifdef WIN32 | ||
209 | strftime(retval2, 200, "%#x", &timeptr); | ||
210 | #else | ||
211 | strftime(retval2, 200, "%x", &timeptr); | ||
212 | #endif | ||
213 | /* If don't have weekday name, include it */ | ||
214 | strftime(retval, 200, "%A", &timeptr); | ||
215 | if (strstr(retval2,retval)==NULL) { | ||
216 | /* Check also for short name */ | ||
217 | strftime(retval, 200, "%a", &timeptr); | ||
218 | if (strstr(retval2,retval)==NULL) { | ||
219 | strcat(retval2," ("); | ||
220 | strcat(retval2,retval); | ||
221 | strcat(retval2,")"); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | #ifdef WIN32 | ||
226 | setlocale(LC_ALL, ".ACP"); | ||
227 | #endif | ||
228 | |||
229 | return retval2; | ||
230 | } | ||
231 | |||
232 | bool CheckDate(GSM_DateTime *date) | ||
233 | { | ||
234 | /* FIXME: This could also check if day is correct for selected month */ | ||
235 | return date->Year != 0 && | ||
236 | date->Month >= 1 && date->Month <= 12 && | ||
237 | date->Day >= 1 && date->Day <= 31; | ||
238 | } | ||
239 | |||
240 | bool CheckTime(GSM_DateTime *date) | ||
241 | { | ||
242 | return date->Hour <= 23 && date->Hour >= 0 && | ||
243 | date->Minute <= 59 && date->Minute >= 0 && | ||
244 | date->Second <= 59 && date->Second >= 0; | ||
245 | } | ||
246 | |||
247 | int GetLine(FILE *File, char *Line, int count) | ||
248 | { | ||
249 | int num; | ||
250 | |||
251 | if (fgets(Line, count, File) != NULL) { | ||
252 | num = strlen(Line) - 1; | ||
253 | while(1) { | ||
254 | if (Line[num] != '\n' && Line[num] != '\r') break; | ||
255 | if (num == 0) break; | ||
256 | Line[num--] = 0; | ||
257 | } | ||
258 | return strlen(Line); | ||
259 | } | ||
260 | return -1; | ||
261 | } | ||
262 | |||
263 | void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot) | ||
264 | { | ||
265 | int i,number=0,j; | ||
266 | bool whitespace=true, nowwhite; | ||
267 | |||
268 | for (i=0;i<MAX_LINES*2;i++) lines->numbers[i]=0; | ||
269 | |||
270 | for (i=0;i<messagesize;i++) { | ||
271 | nowwhite = false; | ||
272 | for (j=0;j<spaceslen;j++) { | ||
273 | if (whitespaces[j] == message[i]) { | ||
274 | nowwhite = true; | ||
275 | break; | ||
276 | } | ||
277 | } | ||
278 | if (whitespace) { | ||
279 | if (!nowwhite) { | ||
280 | lines->numbers[number]=i; | ||
281 | number++; | ||
282 | whitespace=false; | ||
283 | } | ||
284 | } else { | ||
285 | if (nowwhite) { | ||
286 | lines->numbers[number]=i; | ||
287 | number++; | ||
288 | whitespace=true; | ||
289 | } | ||
290 | |||
291 | } | ||
292 | } | ||
293 | if (eot && !whitespace) lines->numbers[number]=messagesize; | ||
294 | } | ||
295 | |||
296 | char *GetLineString(unsigned char *message, GSM_Lines lines, int start) | ||
297 | { | ||
298 | static char retval[800]; | ||
299 | |||
300 | memcpy(retval,message + lines.numbers[start*2-2],lines.numbers[start*2-2+1]-lines.numbers[start*2-2]); | ||
301 | retval[lines.numbers[start*2-2+1]-lines.numbers[start*2-2]]=0; | ||
302 | |||
303 | return retval; | ||
304 | } | ||
305 | |||
306 | void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start) | ||
307 | { | ||
308 | memcpy(dest,GetLineString(src, lines, start),strlen(GetLineString(src, lines, start))); | ||
309 | dest[strlen(GetLineString(src, lines, start))] = 0; | ||
310 | } | ||
311 | |||
312 | Debug_Info di = {0,NULL,false,""}; | ||
313 | |||
314 | #ifdef DEBUG | ||
315 | #ifdef __GNUC__ | ||
316 | __attribute__((format(printf, 1, 2))) | ||
317 | #endif | ||
318 | int dbgprintf(const char *format, ...) | ||
319 | { | ||
320 | va_list argp; | ||
321 | int result; | ||
322 | static unsigned char nextline[2000]=""; | ||
323 | unsigned char buffer[2000]; | ||
324 | GSM_DateTime date_time; | ||
325 | |||
326 | if (di.df != NULL && (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE)) { | ||
327 | va_start(argp, format); | ||
328 | result = vsprintf(buffer, format, argp); | ||
329 | strcat(nextline, buffer); | ||
330 | if (strstr(buffer, "\n")) { | ||
331 | if (di.dl == DL_TEXTALLDATE) { | ||
332 | GSM_GetCurrentDateTime(&date_time); | ||
333 | fprintf(di.df,"%s %4d/%02d/%02d %02d:%02d:%02d: %s", | ||
334 | DayOfWeek(date_time.Year, date_time.Month, date_time.Day), | ||
335 | date_time.Year, date_time.Month, date_time.Day, | ||
336 | date_time.Hour, date_time.Minute, date_time.Second,nextline); | ||
337 | } else { | ||
338 | fprintf(di.df,"%s",nextline); | ||
339 | } | ||
340 | strcpy(nextline, ""); | ||
341 | } | ||
342 | fflush(di.df); | ||
343 | va_end(argp); | ||
344 | return result; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | #endif | ||
349 | |||
350 | /* assumption: if \n is present it is always the last char, | ||
351 | * string never of the form "......\n..." | ||
352 | */ | ||
353 | #ifdef __GNUC__ | ||
354 | __attribute__((format(printf, 3, 4))) | ||
355 | #endif | ||
356 | int smfprintf(FILE *f, Debug_Level dl, const char *format, ...) | ||
357 | { | ||
358 | va_list argp; | ||
359 | int result=0; | ||
360 | static unsigned char prevline[2000] = "", nextline[2000]=""; | ||
361 | static unsigned int linecount=0; | ||
362 | unsigned char buffer[2000]; | ||
363 | GSM_DateTime date_time; | ||
364 | |||
365 | if (f == NULL) return 0; | ||
366 | va_start(argp, format); | ||
367 | result = vsprintf(buffer, format, argp); | ||
368 | strcat(nextline, buffer); | ||
369 | if (strstr(buffer, "\n")) { | ||
370 | if (ftell(f) < 5000000) { | ||
371 | GSM_GetCurrentDateTime(&date_time); | ||
372 | if (linecount > 0) { | ||
373 | if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) { | ||
374 | fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: <%i> %s", | ||
375 | DayOfWeek(date_time.Year, date_time.Month, date_time.Day), | ||
376 | date_time.Year, date_time.Month, date_time.Day, | ||
377 | date_time.Hour, date_time.Minute, date_time.Second,linecount,prevline); | ||
378 | } else { | ||
379 | fprintf(f,"%s",prevline); | ||
380 | } | ||
381 | } | ||
382 | linecount=0; | ||
383 | if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) { | ||
384 | fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: %s", | ||
385 | DayOfWeek(date_time.Year, date_time.Month, date_time.Day), | ||
386 | date_time.Year, date_time.Month, date_time.Day, | ||
387 | date_time.Hour, date_time.Minute, date_time.Second,nextline); | ||
388 | } else { | ||
389 | fprintf(f,"%s",nextline); | ||
390 | } | ||
391 | strcpy(prevline, nextline); | ||
392 | } | ||
393 | strcpy(nextline, ""); | ||
394 | fflush(f); | ||
395 | } | ||
396 | va_end(argp); | ||
397 | return result; | ||
398 | } | ||
399 | |||
400 | bool GSM_SetDebugLevel(char *info, Debug_Info *di) | ||
401 | { | ||
402 | if (!strcmp(info,"nothing")) {di->dl = 0; return true;} | ||
403 | if (!strcmp(info,"text")) {di->dl = DL_TEXT; return true;} | ||
404 | if (!strcmp(info,"textall")) {di->dl = DL_TEXTALL; return true;} | ||
405 | if (!strcmp(info,"binary")) {di->dl = DL_BINARY; return true;} | ||
406 | if (!strcmp(info,"errors")) {di->dl = DL_TEXTERROR; return true;} | ||
407 | if (!strcmp(info,"textdate")) {di->dl = DL_TEXTDATE; return true;} | ||
408 | if (!strcmp(info,"textalldate")) {di->dl = DL_TEXTALLDATE; return true;} | ||
409 | if (!strcmp(info,"errorsdate")) {di->dl = DL_TEXTERRORDATE; return true;} | ||
410 | return false; | ||
411 | } | ||
412 | |||
413 | /* Dumps a message */ | ||
414 | void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize) | ||
415 | { | ||
416 | int i,j=0,len=16; | ||
417 | unsigned charbuffer[200]; | ||
418 | |||
419 | if (df==NULL || messagesize == 0) return; | ||
420 | |||
421 | smfprintf(df, dl, "\n"); | ||
422 | |||
423 | memset(buffer,0x20,sizeof(buffer)); | ||
424 | buffer[len*5-1]=0; | ||
425 | |||
426 | for (i = 0; i < messagesize; i++) { | ||
427 | sprintf(buffer+j*4,"%02X",message[i]); | ||
428 | buffer[j*4+2] = 0x20; | ||
429 | if (isprint(message[i]) && message[i]!=0x09) { | ||
430 | if (j != len-1) buffer[j*4+2] = message[i]; | ||
431 | buffer[(len-1)*4+j+3] = message[i]; | ||
432 | } else { | ||
433 | buffer[(len-1)*4+j+3] = '.'; | ||
434 | } | ||
435 | if (j != len-1 && i != messagesize-1) buffer[j*4+3] = '|'; | ||
436 | if (j == len-1) { | ||
437 | smfprintf(df, dl, "%s\n", buffer); | ||
438 | memset(buffer,0x20,sizeof(buffer)); | ||
439 | buffer[len*5-1]=0; | ||
440 | j = 0; | ||
441 | } else { | ||
442 | j++; | ||
443 | } | ||
444 | } | ||
445 | if (j != 0) smfprintf(df, dl, "%s\n", buffer); | ||
446 | } | ||
447 | |||
448 | char *GetOS(void) | ||
449 | { | ||
450 | #ifdef WIN32 | ||
451 | OSVERSIONINFOEX Ver; | ||
452 | bool Extended = true; | ||
453 | #endif | ||
454 | static char Buffer[100] = {0x00}; | ||
455 | |||
456 | #ifdef WIN32 | ||
457 | memset(&Ver,sizeof(OSVERSIONINFOEX),0); | ||
458 | Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); | ||
459 | |||
460 | if (!GetVersionEx((OSVERSIONINFO *)&Ver)) { | ||
461 | Extended = false; | ||
462 | Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | ||
463 | if (!GetVersionEx((OSVERSIONINFO *)&Ver)) { | ||
464 | //#ifdef _MSC_VER | ||
465 | // Ver.dwMajorVersion = _winmajor; | ||
466 | // Ver.dwMinorVersion = _winminor; | ||
467 | // Ver.dwBuildNumber = _osver; | ||
468 | //#else | ||
469 | sprintf(Buffer, "Windows"); | ||
470 | return Buffer; | ||
471 | //#endif | ||
472 | } | ||
473 | } | ||
474 | |||
475 | /* ----------------- 9x family ------------------ */ | ||
476 | |||
477 | /* no info about Win95 SP1, Win95 OSR2.1, Win95 OSR2.5.... */ | ||
478 | if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 950) { | ||
479 | sprintf(Buffer,"Win 95"); | ||
480 | } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1111) { | ||
481 | sprintf(Buffer,"Win 95 OSR2.x"); | ||
482 | |||
483 | /* no info about Win98 SP1.... */ | ||
484 | } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 1998) { | ||
485 | sprintf(Buffer,"Win 98"); | ||
486 | } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 2222) { | ||
487 | sprintf(Buffer,"Win 98 SE"); | ||
488 | |||
489 | } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 90 && Ver.dwBuildNumber == 3000) { | ||
490 | sprintf(Buffer,"Win ME"); | ||
491 | |||
492 | /* ---------------- NT family ------------------- */ | ||
493 | |||
494 | } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1381) { | ||
495 | sprintf(Buffer,"Win NT 4.0"); | ||
496 | |||
497 | } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 2195) { | ||
498 | sprintf(Buffer,"Win 2000"); | ||
499 | |||
500 | } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 1 && Ver.dwBuildNumber == 2600) { | ||
501 | sprintf(Buffer,"Win XP"); | ||
502 | #if _MSC_VER > 1200 //6.0 has it undeclared | ||
503 | if (Extended) { | ||
504 | if (Ver.wSuiteMask & VER_SUITE_PERSONAL) { | ||
505 | sprintf(Buffer+strlen(Buffer)," Home"); | ||
506 | } else { | ||
507 | sprintf(Buffer+strlen(Buffer)," Pro"); | ||
508 | } | ||
509 | } | ||
510 | #endif | ||
511 | |||
512 | } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 2) { | ||
513 | sprintf(Buffer,"Win 2003"); | ||
514 | |||
515 | } else { | ||
516 | sprintf(Buffer, "Windows %i.%i.%i",Ver.dwMajorVersion,Ver.dwMinorVersion,Ver.dwBuildNumber); | ||
517 | } | ||
518 | |||
519 | if (Extended && Ver.wServicePackMajor != 0) { | ||
520 | sprintf(Buffer+strlen(Buffer)," SP%i",Ver.wServicePackMajor); | ||
521 | } | ||
522 | #elif defined(linux) || defined(__linux) || defined(__linux__) | ||
523 | sprintf(Buffer, "Linux"); | ||
524 | #elif defined(__FreeBSD__) | ||
525 | sprintf(Buffer, "FreeBSD"); | ||
526 | #elif defined(__NetBSD__) | ||
527 | sprintf(Buffer, "NetBSD"); | ||
528 | #elif defined(__OpenBSD__) | ||
529 | sprintf(Buffer, "OpenBSD"); | ||
530 | #elif defined(__GNU__) | ||
531 | sprintf(Buffer, "GNU/Hurd"); | ||
532 | #elif defined(sun) || defined(__sun) || defined(__sun__) | ||
533 | # ifdef __SVR4 | ||
534 | sprintf(Buffer, "Sun Solaris"); | ||
535 | # else | ||
536 | sprintf(Buffer, "SunOS"); | ||
537 | # endif | ||
538 | #elif defined(hpux) || defined(__hpux) || defined(__hpux__) | ||
539 | sprintf(Buffer, "HP-UX"); | ||
540 | #elif defined(ultrix) || defined(__ultrix) || defined(__ultrix__) | ||
541 | sprintf(Buffer, "DEC Ultrix"); | ||
542 | #elif defined(sgi) || defined(__sgi) | ||
543 | sprintf(Buffer, "SGI Irix"); | ||
544 | #elif defined(__osf__) | ||
545 | sprintf(Buffer, "OSF Unix"); | ||
546 | #elif defined(bsdi) || defined(__bsdi__) | ||
547 | sprintf(Buffer, "BSDI Unix"); | ||
548 | #elif defined(_AIX) | ||
549 | sprintf(Buffer, "AIX Unix"); | ||
550 | #elif defined(_UNIXWARE) | ||
551 | sprintf(Buffer, "SCO Unixware"); | ||
552 | #elif defined(DGUX) | ||
553 | sprintf(Buffer, "DG Unix"); | ||
554 | #elif defined(__QNX__) | ||
555 | sprintf(Buffer, "QNX"); | ||
556 | #endif | ||
557 | return Buffer; | ||
558 | } | ||
559 | |||
560 | char *GetCompiler(void) | ||
561 | { | ||
562 | static char Buffer[100] = {0x00}; | ||
563 | |||
564 | #ifdef WIN32 | ||
565 | # ifdef _MSC_VER | ||
566 | if (_MSC_VER == 1200) { //? | ||
567 | sprintf(Buffer, "MS VC 6.0"); | ||
568 | } else if (_MSC_VER == 1300) { | ||
569 | sprintf(Buffer, "MS VC .NET 2002"); | ||
570 | } else if (_MSC_VER == 1310) { | ||
571 | sprintf(Buffer, "MS VC .NET 2003"); | ||
572 | } else { | ||
573 | sprintf(Buffer, "MS VC %i",_MSC_VER); | ||
574 | } | ||
575 | # elif defined(__BORLANDC__) | ||
576 | sprintf(Buffer, "Borland C++ %i",__BORLANDC__); | ||
577 | # endif | ||
578 | #elif defined(DJGPP) | ||
579 | sprintf(Buffer, "djgpp"); | ||
580 | #elif defined(__GNUC__) | ||
581 | sprintf(Buffer, "gcc %i.%i", __GNUC__, __GNUC_MINOR__); | ||
582 | #elif defined(__SUNPRO_CC) | ||
583 | sprintf(Buffer, "Sun C++ %x", __SUNPRO_CC); | ||
584 | #endif | ||
585 | |||
586 | return Buffer; | ||
587 | } | ||
588 | |||
589 | /* How should editor hadle tabs in this file? Add editor commands here. | ||
590 | * vim: noexpandtab sw=8 ts=8 sts=8: | ||
591 | */ | ||
diff --git a/gammu/emb/common/misc/misc.h b/gammu/emb/common/misc/misc.h new file mode 100644 index 0000000..8b46170 --- a/dev/null +++ b/gammu/emb/common/misc/misc.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* (c) 2002-2004 by Marcin Wiacek */ | ||
2 | |||
3 | #ifndef __misc_h | ||
4 | #define __misc_h | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <time.h> | ||
8 | #ifdef WIN32 | ||
9 | # include <windows.h> | ||
10 | #endif | ||
11 | |||
12 | #include "../config.h" | ||
13 | |||
14 | #ifndef __cplusplus | ||
15 | #ifndef false | ||
16 | # define false 0 | ||
17 | #endif | ||
18 | #ifndef true | ||
19 | # define true !0 | ||
20 | #endif | ||
21 | #ifndef bool | ||
22 | # define boolchar | ||
23 | #endif | ||
24 | #endif /* __cplusplus */ | ||
25 | |||
26 | #ifdef WIN32 | ||
27 | # define my_sleep(x) ((x)<1000 ? Sleep(1) : Sleep((x)/1000)) | ||
28 | #else | ||
29 | # define my_sleep(x) usleep(x) | ||
30 | #endif | ||
31 | |||
32 | #undef MAX | ||
33 | #define MAX(a,b) ((a)>(b) ? (a) : (b)) | ||
34 | #undef MIN | ||
35 | #define MIN(a,b) ((a)<(b) ? (a) : (b)) | ||
36 | |||
37 | /* ------------------------------------------------------------------------- */ | ||
38 | |||
39 | #define MAX_LINES 50 | ||
40 | |||
41 | int GetLine(FILE *File, char *Line, int count); | ||
42 | |||
43 | typedef struct { | ||
44 | int numbers[MAX_LINES*2]; | ||
45 | } GSM_Lines; | ||
46 | |||
47 | void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot); | ||
48 | char *GetLineString(unsigned char *message, GSM_Lines lines, int start); | ||
49 | void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start); | ||
50 | |||
51 | /* ------------------------------------------------------------------------- */ | ||
52 | |||
53 | typedef enum { | ||
54 | DL_BINARY = 1, /* Binary transmission dump */ | ||
55 | DL_TEXT, /* Text transmission dump*/ | ||
56 | DL_TEXTALL, /* Everything */ | ||
57 | DL_TEXTERROR, /* Only errors */ | ||
58 | DL_TEXTDATE, /* Text transmission dump*/ | ||
59 | DL_TEXTALLDATE, /* Everything */ | ||
60 | DL_TEXTERRORDATE /* Only errors */ | ||
61 | } Debug_Level; | ||
62 | |||
63 | typedef struct { | ||
64 | Debug_Leveldl; | ||
65 | FILE *df; | ||
66 | bool use_global; | ||
67 | char *coding; | ||
68 | } Debug_Info; | ||
69 | |||
70 | extern Debug_Infodi; | ||
71 | |||
72 | #ifdef DEBUG | ||
73 | #ifdef __GNUC__ | ||
74 | __attribute__((format(printf, 1, 2))) | ||
75 | #endif | ||
76 | int dbgprintf(const char *format, ...); | ||
77 | #else | ||
78 | # ifndef WIN32 | ||
79 | # define dbgprintf(a...) do { } while (0) | ||
80 | # else | ||
81 | # define dbgprintf | ||
82 | # endif | ||
83 | #endif | ||
84 | |||
85 | #ifdef __GNUC__ | ||
86 | __attribute__((format(printf, 3, 4))) | ||
87 | #endif | ||
88 | int smfprintf(FILE *f, Debug_Level dl, const char *format, ...); | ||
89 | |||
90 | void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize); | ||
91 | |||
92 | bool GSM_SetDebugLevel(char *info, Debug_Info *di); | ||
93 | |||
94 | /* ------------------------------------------------------------------------- */ | ||
95 | |||
96 | /** | ||
97 | * Structure used for saving date and time | ||
98 | */ | ||
99 | typedef struct { | ||
100 | /** | ||
101 | * The difference between local time and GMT in hours | ||
102 | */ | ||
103 | int Timezone; | ||
104 | |||
105 | unsigned int Second; | ||
106 | unsigned int Minute; | ||
107 | unsigned int Hour; | ||
108 | |||
109 | unsigned int Day; | ||
110 | /** | ||
111 | * January = 1, February = 2, etc. | ||
112 | */ | ||
113 | unsigned int Month; | ||
114 | /** | ||
115 | * Complete year number. Not 03, but 2003 | ||
116 | */ | ||
117 | unsigned int Year; | ||
118 | } GSM_DateTime; | ||
119 | |||
120 | void GSM_GetCurrentDateTime (GSM_DateTime *Date); | ||
121 | char *OSDateTime (GSM_DateTime dt, bool TimeZone); | ||
122 | char *OSDate (GSM_DateTime dt); | ||
123 | char *DayOfWeek (int year, int month, int day); | ||
124 | time_t Fill_Time_T (GSM_DateTime DT, int TZ); | ||
125 | void GetTimeDifference (unsigned long diff, GSM_DateTime *DT, bool Plus, int multi); | ||
126 | void Fill_GSM_DateTime (GSM_DateTime *Date, time_t timet); | ||
127 | bool CheckDate (GSM_DateTime *date); | ||
128 | bool CheckTime (GSM_DateTime *date); | ||
129 | |||
130 | char *GetCompiler(void); | ||
131 | char *GetOS(void); | ||
132 | |||
133 | #endif | ||
134 | |||
135 | /* How should editor hadle tabs in this file? Add editor commands here. | ||
136 | * vim: noexpandtab sw=8 ts=8 sts=8: | ||
137 | */ | ||