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