author | zautrix <zautrix> | 2004-08-07 17:24:40 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-08-07 17:24:40 (UTC) |
commit | 88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22 (patch) (side-by-side diff) | |
tree | 6331418973714243beb674abc87692277b83869d /gammu/emb/common/misc | |
parent | ef8a09ce74ad3f0a51484d03fdf009bd5b3677bf (diff) | |
download | kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.zip kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.gz kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.bz2 |
Initial revision
-rw-r--r-- | gammu/emb/common/misc/cfg.c | 332 | ||||
-rw-r--r-- | gammu/emb/common/misc/cfg.h | 42 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/coding.c | 1409 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/coding.h | 133 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/md5.c | 298 | ||||
-rw-r--r-- | gammu/emb/common/misc/coding/md5.h | 6 | ||||
-rw-r--r-- | gammu/emb/common/misc/misc.c | 591 | ||||
-rw-r--r-- | gammu/emb/common/misc/misc.h | 137 |
8 files changed, 2948 insertions, 0 deletions
diff --git a/gammu/emb/common/misc/cfg.c b/gammu/emb/common/misc/cfg.c new file mode 100644 index 0000000..1c74874 --- a/dev/null +++ b/gammu/emb/common/misc/cfg.c @@ -0,0 +1,332 @@ +/* (c) 2002-2004 by Marcin Wiacek */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#ifndef __OpenBSD__ +# include <wchar.h> +# include <wctype.h> +#endif + +#include "../config.h" +#include "coding/coding.h" +#include "cfg.h" +#include "misc.h" + +/* + * Read information from file in Windows INI format style + */ +INI_Section *INI_ReadFile(char *FileName, bool Unicode) +{ + FILE *f; + bool FFEEUnicode=false; + int level = -1, buffer1used, buffer2used; + int bufferused, i, buffused=1000,buffread=1000, num; + unsigned char ch[3], *buffer = NULL; + unsigned char *buffer2 = NULL, *buffer1 = NULL, buff[1000]; + INI_Section *INI_info = NULL, *INI_head = NULL, *heading; + INI_Entry *entry; + + f = fopen(FileName,"rb"); + if (f == NULL) return NULL; + + num = 0; + while(1) { + /* We read one line from file */ + bufferused = 0; + while (1) { + if (buffused == buffread) { + buffused = fread(buff,1,1000,f); + buffread = 0; + if (buffused == 0) { + free(buffer); free(buffer1); free(buffer2); + fclose(f); + return INI_head; + } + } + if (Unicode) { + if (num == 0) { + if (buffused == buffread) continue; + ch[0] = buff[buffread++]; + num = 1; + } + if (num == 1) { + if (buffused == buffread) continue; + ch[1] = buff[buffread++]; + num = 0; + } + if (level == -1) { + if (ch[0] == 0xFF && ch[1] == 0xFE) FFEEUnicode = true; + level = 0; + continue; + } + if (FFEEUnicode) { + ch[2] = ch[0]; ch[0] = ch[1]; ch[1] = ch[2]; + } + } else { + if (buffused == buffread) continue; + ch[0] = 0; + ch[1] = buff[buffread++]; + if (level == -1) level = 0; + } + if ((ch[0] == 0 && ch[1] == 13) || + (ch[0] == 0 && ch[1] == 10)) { + break; + } + buffer = realloc(buffer,bufferused+2); + buffer[bufferused] = ch[0]; + buffer[bufferused+1] = ch[1]; + bufferused = bufferused + 2; + } +// printf("line \"%s\"\n",DecodeUnicodeConsole(buffer)); + + buffer1used = 0; + buffer2used = 0; + if (level == 1) level = 0; + if (level == 3 || level == 4 || level == 5) level = 2; + + /* We parse read line */ + for (i=0;i<bufferused/2;i++) { + ch[0] = buffer[i*2]; + ch[1] = buffer[i*2+1]; + if (level == 0) { //search for name of section + if (ch[0] == 0 && ch[1] == '[') level = 1; + if (ch[0] == 0 && ch[1] == ';') break; + if (ch[0] == 0 && ch[1] == '#') break; + continue; + } + if (level == 1) { //section name + if (ch[0] == 0 && ch[1] == ']') { + if (buffer1used == 0) break; + if (Unicode) { + buffer1 = realloc(buffer1,buffer1used+2); + buffer1[buffer1used] = 0; + buffer1[buffer1used+1] = 0; + buffer1used = buffer1used + 2; + } else { + buffer1 = realloc(buffer1,buffer1used+1); + buffer1[buffer1used] = 0x00; + buffer1used = buffer1used + 1; + } + heading = (INI_Section *)malloc(sizeof(*heading)); + if (heading == NULL) { + free(buffer); free(buffer1); free(buffer2); + fclose(f); + return NULL; + } + heading->SectionName = (char *)malloc(buffer1used); + memcpy(heading->SectionName,buffer1,buffer1used); + heading->Prev = INI_info; + heading->Next = NULL; + if (INI_info != NULL) { + INI_info->Next = heading; + } else { + INI_head = heading; + } + INI_info = heading; + INI_info->SubEntries = NULL; + level = 2; +// printf("[%s]\n",DecodeUnicodeConsole(buffer1)); + break; + } + if (Unicode) { + buffer1 = realloc(buffer1,buffer1used+2); + buffer1[buffer1used] = ch[0]; + buffer1[buffer1used+1] = ch[1]; + buffer1used = buffer1used + 2; + } else { + buffer1 = realloc(buffer1,buffer1used+1); + buffer1[buffer1used] = ch[1]; + buffer1used = buffer1used + 1; + } + continue; + } + if (level == 2) { //search for key name + if (ch[0] == 0 && ch[1] == ';') break; + if (ch[0] == 0 && ch[1] == '#') break; + if (ch[0] == 0 && ch[1] == '[') { + level = 1; + continue; + } + if (Unicode) { + if (myiswspace(ch)) continue; + } else { + if (isspace((int) ch[1])) continue; + } + level = 3; + } + if (level == 3) { //key name + if (ch[0] == 0 && ch[1] == '=') { + if (buffer1used == 0) break; + while(1) { + if (Unicode) { + if (!myiswspace(buffer1+(buffer1used-2))) break; + buffer1used = buffer1used - 2; + } else { + if (!isspace((int)buffer1[buffer1used-1])) break; + buffer1used = buffer1used - 1; + } + } + level = 4; + continue; + } + if (Unicode) { + buffer1 = realloc(buffer1,buffer1used+2); + buffer1[buffer1used] = ch[0]; + buffer1[buffer1used+1] = ch[1]; + buffer1used = buffer1used + 2; + } else { + buffer1 = realloc(buffer1,buffer1used+1); + buffer1[buffer1used] = ch[1]; + buffer1used = buffer1used + 1; + } + } + if (level == 4) { //search for key value + if (Unicode) { + if (myiswspace(ch)) continue; + } else { + if (isspace((int) ch[1])) continue; + } + level = 5; + } + if (level == 5) { //key value + if (Unicode) { + buffer2 = realloc(buffer2,buffer2used+2); + buffer2[buffer2used] = ch[0]; + buffer2[buffer2used+1] = ch[1]; + buffer2used = buffer2used + 2; + } else { + buffer2 = realloc(buffer2,buffer2used+1); + buffer2[buffer2used] = ch[1]; + buffer2used = buffer2used + 1; + } + } + } + if (level == 5) { + if (buffer2used == 0) continue; + + entry = (INI_Entry *)malloc(sizeof(*entry)); + if (entry == NULL) { + free(buffer); free(buffer1); free(buffer2); + fclose(f); + return NULL; + } + if (Unicode) { + buffer1 = realloc(buffer1,buffer1used+2); + buffer1[buffer1used] = 0; + buffer1[buffer1used+1] = 0; + buffer1used = buffer1used + 2; + buffer2 = realloc(buffer2,buffer2used+2); + buffer2[buffer2used] = 0; + buffer2[buffer2used+1] = 0; + buffer2used = buffer2used + 2; + } else { + buffer1 = realloc(buffer1,buffer1used+1); + buffer1[buffer1used] = 0x00; + buffer1used = buffer1used + 1; + buffer2 = realloc(buffer2,buffer2used+1); + buffer2[buffer2used] = 0x00; + buffer2used = buffer2used + 1; + } +// printf("\"%s\"=\"%s\"\n",buffer1,buffer2); +// printf("\"%s\"=",DecodeUnicodeConsole(buffer1)); +// printf("\"%s\"\n",DecodeUnicodeConsole(buffer2)); + + entry->EntryName = (char *)malloc(buffer1used); + memcpy(entry->EntryName,buffer1,buffer1used); + + entry->EntryValue = (char *)malloc(buffer2used); + memcpy(entry->EntryValue,buffer2,buffer2used); + + entry->Prev = NULL; + entry->Next = INI_info->SubEntries; + if (INI_info->SubEntries != NULL) INI_info->SubEntries->Prev = entry; + INI_info->SubEntries = entry; + } + } + free(buffer); free(buffer1); free(buffer2); + fclose(f); + return INI_head; +} + +/* + * Search for key value in file in Windows INI format style + * Returns found value or NULL + */ +unsigned char *INI_GetValue(INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode) +{ + INI_Section *sec; + INI_Entry *ent; + + if (cfg == NULL || section == NULL || key == NULL) return NULL; + + if (Unicode) { + /* Search for section */ + sec = cfg; + while (sec != NULL) { + if (mywstrncasecmp(section, sec->SectionName, 0)) { + /* Search for key inside section */ + ent = sec->SubEntries; + while (ent != NULL) { + if (mywstrncasecmp(key,ent->EntryName,0)) { + return ent->EntryValue; + } + ent = ent->Next; + } + } + sec = sec->Next; + } + } else { + /* Search for section */ + sec = cfg; + while (sec != NULL) { + if (mystrncasecmp(section, sec->SectionName, 0)) { + /* Search for key inside section */ + ent = sec->SubEntries; + while (ent != NULL) { + if (mystrncasecmp(key,ent->EntryName,0)) { + return ent->EntryValue; + } + ent = ent->Next; + } + } + sec = sec->Next; + } + } + return NULL; +} + +/* Return last value in specified section */ +INI_Entry *INI_FindLastSectionEntry(INI_Section *file_info, unsigned char *section, bool Unicode) +{ + INI_Section *h; + INI_Entry *e; + + e = NULL; + /* First find our section */ + for (h = file_info; h != NULL; h = h->Next) { + if (Unicode) { + if (mywstrncasecmp(section, h->SectionName, 0)) { + e = h->SubEntries; + break; + } + } else { + if (mystrncasecmp(section, h->SectionName, 0)) { + e = h->SubEntries; + break; + } + } + } + + if (e == NULL) return NULL; + + /* Goes into last value in section */ + while (e->Next != NULL) e = e->Next; + return e; +} + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ 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 @@ +/* (c) 2003 by Marcin Wiacek */ + +#ifndef _cfg_h +#define _cfg_h + +#include "misc.h" + +/* -------------------------------- structures ----------------------------- */ + +typedef struct _INI_Entry INI_Entry; + +/* + * Structure used to save value for single key in INI style file + */ +struct _INI_Entry { + INI_Entry *Next, *Prev; + unsigned char *EntryName; + unsigned char *EntryValue; +}; + +typedef struct _INI_Section INI_Section; + +/* + * Structure used to save section in INI style file + */ +struct _INI_Section { + INI_Section *Next, *Prev; + INI_Entry *SubEntries; + unsigned char *SectionName; +}; + +/* ------------------------- function prototypes --------------------------- */ + +INI_Section *INI_ReadFile (char *FileName, bool Unicode); +INI_Entry *INI_FindLastSectionEntry (INI_Section *file_info, unsigned char *section, bool Unicode); +unsigned char *INI_GetValue (INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode); + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ 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 @@ +/* (c) 2002-2004 by Marcin Wiacek, Michal Cihar and others */ +/* based on some work from MyGnokii and Gnokii */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <locale.h> +#ifndef __OpenBSD__ +# include <wctype.h> +#endif +#ifdef WIN32 +# include "windows.h" +#endif + +#include "../misc.h" +#include "coding.h" + +unsigned int UnicodeLength(const unsigned char *str) +{ + unsigned int len = 0; + + if (str == NULL) return 0; + + while(str[len*2] != 0 || str[len*2+1] != 0) len++; + + return len; +} + +/* Convert Unicode char saved in src to dest */ +unsigned int EncodeWithUnicodeAlphabet(const unsigned char *src, wchar_t *dest) +{ + char retval; + + switch (retval = mbtowc(dest, src, MB_CUR_MAX)) { + case -1 : + case 0 : return 1; + default : return retval; + } +} + +/* Convert Unicode char saved in src to dest */ +unsigned int DecodeWithUnicodeAlphabet(wchar_t src, unsigned char *dest) +{ + int retval; + + switch (retval = wctomb(dest, src)) { + case -1: + *dest = '?'; + return 1; + default: + return retval; + } +} + +void DecodeUnicode (const unsigned char *src, unsigned char *dest) +{ + int i=0,o=0; + wchar_t wc; + + while (src[(2*i)+1]!=0x00 || src[2*i]!=0x00) { + wc = src[(2*i)+1] | (src[2*i] << 8); + o += DecodeWithUnicodeAlphabet(wc, dest + o); + i++; + } + dest[o]=0; +} + +/* Decode Unicode string and return as function result */ +unsigned char *DecodeUnicodeString (const unsigned char *src) +{ + static char dest[500]; + + DecodeUnicode(src,dest); + return dest; +} + +/* Decode Unicode string to UTF8 or other console charset + * and return as function result + */ +unsigned char *DecodeUnicodeConsole(const unsigned char *src) +{ + static char dest[500]; + + if (di.coding[0] != 0) { + if (!strcmp(di.coding,"utf8")) { + EncodeUTF8(dest, src); + } else { +#ifdef WIN32 + setlocale(LC_ALL, di.coding); +#endif + DecodeUnicode(src,dest); + } + } else { +#ifdef WIN32 + setlocale(LC_ALL, ".OCP"); +#endif + DecodeUnicode(src,dest); +#ifdef WIN32 + setlocale(LC_ALL, ".ACP"); +#endif + } + return dest; +} + +/* Encode string to Unicode. Len is number of input chars */ +void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len) +{ + int i_len = 0, o_len; + wchar_t wc; + + for (o_len = 0; i_len < len; o_len++) { + i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc); + dest[o_len*2] = (wc >> 8) & 0xff; + dest[(o_len*2)+1] = wc & 0xff; + } + dest[o_len*2] = 0; + dest[(o_len*2)+1] = 0; +} + +unsigned char EncodeWithBCDAlphabet(int value) +{ + div_t division; + + division=div(value,10); + return ( ( (value-division.quot*10) & 0x0f) << 4) | (division.quot & 0xf); +} + +int DecodeWithBCDAlphabet(unsigned char value) +{ + return 10*(value & 0x0f)+(value >> 4); +} + +void DecodeBCD (unsigned char *dest, const unsigned char *src, int len) +{ + int i,current=0,digit; + + for (i = 0; i < len; i++) { + digit=src[i] & 0x0f; + if (digit<10) dest[current++]=digit + '0'; + digit=src[i] >> 4; + if (digit<10) dest[current++]=digit + '0'; + } + dest[current++]=0; +} + +void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill) +{ + int i,current=0; + + for (i = 0; i < len; i++) { + if (i & 0x01) { + dest[current]=dest[current] | ((src[i]-'0') << 4); + current++; + } else { + dest[current]=src[i]-'0'; + } + } + + /* When fill is set: if number consist of odd number of digits, + we fill last bits in last byte with 0x0f + */ + if (fill && (len & 0x01)) dest[current]=dest[current] | 0xf0; +} + +int DecodeWithHexBinAlphabet (unsigned char mychar) +{ + if (mychar>='A' && mychar<='F') return mychar-'A'+10; + if (mychar>='a' && mychar<='f') return mychar-'a'+10; + if (mychar>='0' && mychar<='9') return mychar-'0'; + return -1; +} + +unsigned char EncodeWithHexBinAlphabet (int digit) +{ + if (digit >= 0 && digit <= 9) return '0'+(digit); + if (digit >=10 && digit <=15) return 'A'+(digit-10); + return 0; +} + +void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len) +{ + int i,current=0; + bool first = false; + + if (len != 0 && src[0] == '0' && src[1] == '0') { + first = true; + } else if (len != 0 && src[2] == '0' && src[3] == '0') { + first = false; + } else { + first = (10 * (src[0] - '0') + (src[1] - '0')) < (10 * (src[2] - '0')+ (src[3] - '0')); + } + for (i = 0; i < len/4 ; i++) { + if (first) { + dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+ + DecodeWithHexBinAlphabet(src[i*4+1]); + dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+ + DecodeWithHexBinAlphabet(src[i*4+3]); + } else { + dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+ + DecodeWithHexBinAlphabet(src[i*4+3]); + dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+ + DecodeWithHexBinAlphabet(src[i*4+1]); + } + } + dest[current++] = 0; + dest[current++] = 0; +} + +void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len) +{ + int i,current=0; + + for (i = 0; i < len; i++) { + dest[current++] = EncodeWithHexBinAlphabet(src[2*i] >> 0x04); + dest[current++] = EncodeWithHexBinAlphabet(src[2*i] & 0x0f); + dest[current++] = EncodeWithHexBinAlphabet(src[2*i+1] >> 0x04); + dest[current++] = EncodeWithHexBinAlphabet(src[2*i+1] & 0x0f); + } + dest[current++] = 0; +} + +void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len) +{ + int i,current=0; + + for (i = 0; i < len/2 ; i++) { + dest[current++] = DecodeWithHexBinAlphabet(src[i*2])*16+ + DecodeWithHexBinAlphabet(src[i*2+1]); + } + dest[current++] = 0; +} + +void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len) +{ + int i,current=0; + + for (i = 0; i < len; i++) { + dest[current++] = EncodeWithHexBinAlphabet(src[i] >> 0x04); + dest[current++] = EncodeWithHexBinAlphabet(src[i] & 0x0f); + } + dest[current++] = 0; +} + +/* ETSI GSM 03.38, section 6.2.1: Default alphabet for SMS messages */ +static unsigned char GSM_DefaultAlphabetUnicode[128+1][2] = +{ + {0x00,0x40},{0x00,0xa3},{0x00,0x24},{0x00,0xA5}, + {0x00,0xE8},{0x00,0xE9},{0x00,0xF9},{0x00,0xEC},/*0x08*/ + {0x00,0xF2},{0x00,0xC7},{0x00,'\n'},{0x00,0xD8}, + {0x00,0xF8},{0x00,'\r'},{0x00,0xC5},{0x00,0xE5}, + {0x03,0x94},{0x00,0x5f},{0x03,0xA6},{0x03,0x93}, + {0x03,0x9B},{0x03,0xA9},{0x03,0xA0},{0x03,0xA8}, + {0x03,0xA3},{0x03,0x98},{0x03,0x9E},{0x00,0xb9}, + {0x00,0xC6},{0x00,0xE6},{0x00,0xDF},{0x00,0xC9},/*0x20*/ + {0x00,' ' },{0x00,'!' },{0x00,'\"'},{0x00,'#' }, + {0x00,0xA4},{0x00,'%' },{0x00,'&' },{0x00,'\''}, + {0x00,'(' },{0x00,')' },{0x00,'*' },{0x00,'+' }, + {0x00,',' },{0x00,'-' },{0x00,'.' },{0x00,'/' },/*0x30*/ + {0x00,'0' },{0x00,'1' },{0x00,'2' },{0x00,'3' }, + {0x00,'4' },{0x00,'5' },{0x00,'6' },{0x00,'7' }, + {0x00,'8' },{0x00,'9' },{0x00,':' },{0x00,';' }, + {0x00,'<' },{0x00,'=' },{0x00,'>' },{0x00,'?' },/*0x40*/ + {0x00,0xA1},{0x00,'A' },{0x00,'B' },{0x00,'C' }, + {0x00,'D' },{0x00,'E' },{0x00,'F' },{0x00,'G' }, + {0x00,'H' },{0x00,'I' },{0x00,'J' },{0x00,'K' }, + {0x00,'L' },{0x00,'M' },{0x00,'N' },{0x00,'O' }, + {0x00,'P' },{0x00,'Q' },{0x00,'R' },{0x00,'S' }, + {0x00,'T' },{0x00,'U' },{0x00,'V' },{0x00,'W' }, + {0x00,'X' },{0x00,'Y' },{0x00,'Z' },{0x00,0xC4}, + {0x00,0xD6},{0x00,0xD1},{0x00,0xDC},{0x00,0xA7}, + {0x00,0xBF},{0x00,'a' },{0x00,'b' },{0x00,'c' }, + {0x00,'d' },{0x00,'e' },{0x00,'f' },{0x00,'g' }, + {0x00,'h' },{0x00,'i' },{0x00,'j' },{0x00,'k' }, + {0x00,'l' },{0x00,'m' },{0x00,'n' },{0x00,'o' }, + {0x00,'p' },{0x00,'q' },{0x00,'r' },{0x00,'s' }, + {0x00,'t' },{0x00,'u' },{0x00,'v' },{0x00,'w' }, + {0x00,'x' },{0x00,'y' },{0x00,'z' },{0x00,0xE4}, + {0x00,0xF6},{0x00,0xF1},{0x00,0xFC},{0x00,0xE0}, + {0x00,0x00} +}; + +/* ETSI GSM 3.38 + * Some sequences of 2 default alphabet chars (for example, + * 0x1b, 0x65) are visible as one single additional char (for example, + * 0x1b, 0x65 gives Euro char saved in Unicode as 0x20, 0xAC) + * This table contains: + * 1. two first chars means sequence of chars from GSM default alphabet + * 2. two second is target (encoded) char saved in Unicode + */ +static unsigned char GSM_DefaultAlphabetCharsExtension[][4] = +{ + {0x1b,0x14,0x00,0x5e}, /* ^ */ + {0x1b,0x28,0x00,0x7b}, /* { */ + {0x1b,0x29,0x00,0x7d}, /* } */ + {0x1b,0x2f,0x00,0x5c}, /* \ */ + {0x1b,0x3c,0x00,0x5b}, /* [ */ + {0x1b,0x3d,0x00,0x7E}, /* ~ */ + {0x1b,0x3e,0x00,0x5d}, /* ] */ + {0x1b,0x40,0x00,0x7C}, /* | */ + {0x1b,0x65,0x20,0xAC}, /* Euro */ + {0x00,0x00,0x00,0x00} +}; + +void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet) +{ + int i,current=0,j; + bool FoundSpecial = false; + +#ifdef DEBUG + if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, src, len); +#endif + + for (i = 0; i < len; i++) { + FoundSpecial = false; + if ((i < (len-1)) && UseExtensions) { + j=0; + while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) { + if (GSM_DefaultAlphabetCharsExtension[j][0]==src[i] && + GSM_DefaultAlphabetCharsExtension[j][1]==src[i+1]) { + FoundSpecial = true; + dest[current++] = GSM_DefaultAlphabetCharsExtension[j][2]; + dest[current++] = GSM_DefaultAlphabetCharsExtension[j][3]; + i++; + break; + } + j++; + } + } + if (ExtraAlphabet!=NULL && !FoundSpecial) { + j = 0; + while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) { + if (ExtraAlphabet[j] == src[i]) { + dest[current++] = ExtraAlphabet[j+1]; + dest[current++] = ExtraAlphabet[j+2]; + FoundSpecial = true; + break; + } + j=j+3; + } + } + if (!FoundSpecial) { + dest[current++] = GSM_DefaultAlphabetUnicode[src[i]][0]; + dest[current++] = GSM_DefaultAlphabetUnicode[src[i]][1]; + } + } + dest[current++]=0; + dest[current++]=0; +#ifdef DEBUG + if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, UnicodeLength(dest)*2); +#endif +} + +/* There are many national chars with "adds". In phone they're normally + * changed to "plain" Latin chars. We have such functionality too. + * This table is automatically created from convert.txt file (see + * /docs/developers) using --makeconverttable. It contains such chars + * to replace in order: + * 1. original char (Unicode) 2. destination char (Unicode) + */ +static unsigned char ConvertTable[] = +"\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"\ +"\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"\ +"\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"\ +"\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"\ +"\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"\ +"\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"; + +void EncodeDefault(unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet) +{ + int i,current=0,j,z; + char ret; + bool FoundSpecial,FoundNormal; + +#ifdef DEBUG + if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, src, (*len)*2); +#endif + + for (i = 0; i < *len; i++) { + FoundSpecial = false; + j = 0; + while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00 && UseExtensions) { + if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] && + src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) { + dest[current++] = GSM_DefaultAlphabetCharsExtension[j][0]; + dest[current++] = GSM_DefaultAlphabetCharsExtension[j][1]; + FoundSpecial = true; + break; + } + j++; + } + if (!FoundSpecial) { + ret = '?'; + FoundNormal = false; + j = 0; + while (GSM_DefaultAlphabetUnicode[j][1]!=0x00) { + if (src[i*2] == GSM_DefaultAlphabetUnicode[j][0] && + src[i*2+1] == GSM_DefaultAlphabetUnicode[j][1]) { + ret = j; + FoundNormal = true; + break; + } + j++; + } + if (ExtraAlphabet!=NULL && !FoundNormal) { + j = 0; + while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) { + if (ExtraAlphabet[j+1] == src[i*2] && + ExtraAlphabet[j+2] == src[i*2 + 1]) { + ret = ExtraAlphabet[j]; + FoundSpecial = true; + break; + } + j=j+3; + } + } + if (!FoundNormal && !FoundSpecial) { + j = 0; + FoundNormal = false; + while (ConvertTable[j*4] != 0x00 || + ConvertTable[j*4+1] != 0x00) { + if (src[i*2] == ConvertTable[j*4] && + src[i*2+1] == ConvertTable[j*4+1]) { + z = 0; + while (GSM_DefaultAlphabetUnicode[z][1]!=0x00) { + if (ConvertTable[j*4+2] == GSM_DefaultAlphabetUnicode[z][0] && + ConvertTable[j*4+3] == GSM_DefaultAlphabetUnicode[z][1]) { + ret = z; + FoundNormal = true; + break; + } + z++; + } + if (FoundNormal) break; + } + j++; + } + } + dest[current++]=ret; + } + } + dest[current]=0; +#ifdef DEBUG + if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, current); +#endif + + *len = current; +} + +/* You don't have to use ConvertTable here - 1 char is replaced there by 1 char */ +void FindDefaultAlphabetLen(const unsigned char *src, int *srclen, int *smslen, int maxlen) +{ + int current=0,j,i; + bool FoundSpecial; + + i = 0; + while (src[i*2] != 0x00 || src[i*2+1] != 0x00) { + FoundSpecial = false; + j = 0; + while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) { + if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] && + src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) { + FoundSpecial = true; + if (current+2 > maxlen) { + *srclen = i; + *smslen = current; + return; + } + current+=2; + break; + } + j++; + } + if (!FoundSpecial) { + if (current+1 > maxlen) { + *srclen = i; + *smslen = current; + return; + } + current++; + } + i++; + } + *srclen = i; + *smslen = current; +} + +#ifndef ENABLE_LGPL +# define ByteMask ((1 << Bits) - 1) +#endif + +int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length, + unsigned char *input, unsigned char *output) +{ +#ifndef ENABLE_LGPL + /* (c) by Pavel Janik and Pawel Kot */ + + unsigned char *OUTPUT = output; /* Current pointer to the output buffer */ + unsigned char *INPUT = input; /* Current pointer to the input buffer */ + unsigned char Rest = 0x00; + int Bits; + + Bits = offset ? offset : 7; + + while ((INPUT - input) < in_length) { + + *OUTPUT = ((*INPUT & ByteMask) << (7 - Bits)) | Rest; + Rest = *INPUT >> Bits; + + /* If we don't start from 0th bit, we shouldn't go to the + next char. Under *OUTPUT we have now 0 and under Rest - + _first_ part of the char. */ + if ((INPUT != input) || (Bits == 7)) OUTPUT++; + INPUT++; + + if ((OUTPUT - output) >= out_length) break; + + /* After reading 7 octets we have read 7 full characters but + we have 7 bits as well. This is the next character */ + if (Bits == 1) { + *OUTPUT = Rest; + OUTPUT++; + Bits = 7; + Rest = 0x00; + } else { + Bits--; + } + } + + return OUTPUT - output; +#else + return 0; +#endif +} + +int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output, int length) +{ +#ifndef ENABLE_LGPL + /* (c) by Pavel Janik and Pawel Kot */ + + unsigned char *OUTPUT = output; /* Current pointer to the output buffer */ + unsigned char *INPUT = input; /* Current pointer to the input buffer */ + int Bits; /* Number of bits directly copied to + * the output buffer */ + Bits = (7 + offset) % 8; + + /* If we don't begin with 0th bit, we will write only a part of the + first octet */ + if (offset) { + *OUTPUT = 0x00; + OUTPUT++; + } + + while ((INPUT - input) < length) { + unsigned char Byte = *INPUT; + + *OUTPUT = Byte >> (7 - Bits); + /* If we don't write at 0th bit of the octet, we should write + a second part of the previous octet */ + if (Bits != 7) + *(OUTPUT-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1); + + Bits--; + + if (Bits == -1) Bits = 7; else OUTPUT++; + + INPUT++; + } + return (OUTPUT - output); +#else + return 0; +#endif +} + +void GSM_UnpackSemiOctetNumber(unsigned char *retval, unsigned char *Number, bool semioctet) +{ + unsigned char Buffer[50] = ""; + int length = Number[0]; + + if (semioctet) { + /* Convert number of semioctets to number of chars */ + if (length % 2) length++; + length=length / 2 + 1; + } + + /*without leading byte with format of number*/ + length--; + + switch (Number[1]) { + case NUMBER_ALPHANUMERIC: + if (length > 6) length++; + dbgprintf("Alphanumeric number, length %i\n",length); + GSM_UnpackEightBitsToSeven(0, length, length, Number+2, Buffer); + Buffer[length]=0; + break; + case NUMBER_INTERNATIONAL: + dbgprintf("International number\n"); + Buffer[0]='+'; + DecodeBCD(Buffer+1,Number+2, length); + break; + default: + dbgprintf("Default number %02x\n",Number[1]); + DecodeBCD (Buffer, Number+2, length); + break; + } + + EncodeUnicode(retval,Buffer,strlen(Buffer)); +} + +/** + * Packing some phone numbers (SMSC, SMS destination and others) + * + * See GSM 03.40 9.1.1: + * 1 byte - length of number given in semioctets or bytes (when given in + * bytes, includes one byte for byte with number format). + * Returned by function (set semioctet to true, if want result + * in semioctets). + * 1 byte - format of number (see GSM_NumberType in coding.h). Returned + * in unsigned char *Output. + * n bytes - 2n or 2n-1 semioctets with number. Returned in unsigned char + * *Output. + * + * 1 semioctet = 4 bits = half of byte + */ +int GSM_PackSemiOctetNumber(unsigned char *Number, unsigned char *Output, bool semioctet) +{ + unsigned char format, buffer[50]; + int length, i; + + length=UnicodeLength(Number); + memcpy(buffer,DecodeUnicodeString(Number),length+1); + + /* Checking for format number */ + format = NUMBER_UNKNOWN; + for (i=0;i<length;i++) { + /* first byte is '+'. Number can be international */ + if (i==0 && buffer[i]=='+') { + format=NUMBER_INTERNATIONAL; + } else { + /*char is not number. It must be alphanumeric*/ + if (!isdigit(buffer[i])) format=NUMBER_ALPHANUMERIC; + } + } + + /** + * First byte is used for saving type of number. See GSM 03.40 + * section 9.1.2.5 + */ + Output[0]=format; + + /* After number type we will have number. GSM 03.40 section 9.1.2 */ + switch (format) { + case NUMBER_ALPHANUMERIC: + length=GSM_PackSevenBitsToEight(0, buffer, Output+1, strlen(buffer))*2; + if (strlen(buffer)==7) length--; + break; + case NUMBER_INTERNATIONAL: + length--; + EncodeBCD (Output+1, buffer+1, length, true); + break; + default: + EncodeBCD (Output+1, buffer, length, true); + break; + } + + if (semioctet) return length; + + /* Convert number of semioctets to number of chars */ + if (length % 2) length++; + return length / 2 + 1; +} + +void CopyUnicodeString(unsigned char *Dest, unsigned char *Source) +{ + int j = 0; + + while (Source[j]!=0x00 || Source[j+1]!=0x00) { + Dest[j] = Source[j]; + Dest[j+1] = Source[j+1]; + j=j+2; + } + Dest[j] = 0; + Dest[j+1] = 0; +} + +/* Changes minor/major order in Unicode string */ +void ReverseUnicodeString(unsigned char *String) +{ + int j = 0; + unsigned char byte1, byte2; + + while (String[j]!=0x00 || String[j+1]!=0x00) { + byte1 = String[j]; + byte2 = String[j+1]; + String[j+1] = byte1; + String[j] = byte2; + j=j+2; + } + String[j] = 0; + String[j+1] = 0; +} + +/* All input is in Unicode. First char can show Unicode minor/major order. + Output is Unicode string in Gammu minor/major order */ +void ReadUnicodeFile(unsigned char *Dest, unsigned char *Source) +{ + int j = 0, current = 0; + + if (Source[0] == 0xFF && Source[1] == 0xFE) j = 2; + if (Source[0] == 0xFE && Source[1] == 0xFF) j = 2; + + while (Source[j]!=0x00 || Source[j+1]!=0x00) { + if (Source[0] == 0xFF) { + Dest[current++] = Source[j+1]; + Dest[current++] = Source[j]; + } else { + Dest[current++] = Source[j]; + Dest[current++] = Source[j+1]; + } + j=j+2; + } + Dest[current++] = 0; + Dest[current++] = 0; +} + +int GetBit(unsigned char *Buffer, int BitNum) +{ + return Buffer[BitNum/8] & 1<<(7-(BitNum%8)); +} + +int SetBit(unsigned char *Buffer, int BitNum) +{ + return Buffer[BitNum/8] |= 1<<(7-(BitNum%8)); +} + +int ClearBit(unsigned char *Buffer, int BitNum) +{ + return Buffer[BitNum/8] &= 255 - (1 << (7-(BitNum%8))); +} + +void BufferAlign(unsigned char *Destination, int *CurrentBit) +{ + int i=0; + + while(((*CurrentBit) + i) % 8 != 0) { + ClearBit(Destination, (*CurrentBit)+i); + i++; + } + + (*CurrentBit) = (*CurrentBit) + i; +} + +void BufferAlignNumber(int *CurrentBit) +{ + int i=0; + + while(((*CurrentBit) + i) % 8 != 0) { + i++; + } + + (*CurrentBit) = (*CurrentBit) + i; +} + +void AddBuffer(unsigned char *Destination, + int *CurrentBit, + unsigned char *Source, + int BitsToProcess) +{ + int i=0; + + while (i!=BitsToProcess) { + if (GetBit(Source, i)) { + SetBit(Destination, (*CurrentBit)+i); + } else { + ClearBit(Destination, (*CurrentBit)+i); + } + i++; + } + (*CurrentBit) = (*CurrentBit) + BitsToProcess; +} + +void AddBufferByte(unsigned char *Destination, + int *CurrentBit, + unsigned char Source, + int BitsToProcess) +{ + unsigned char Byte; + + Byte = Source; + + AddBuffer(Destination, CurrentBit, &Byte, BitsToProcess); +} + +void GetBuffer(unsigned char *Source, + int *CurrentBit, + unsigned char *Destination, + int BitsToProcess) +{ + int i=0; + + while (i!=BitsToProcess) { + if (GetBit(Source, (*CurrentBit)+i)) { + SetBit(Destination, i); + } else { + ClearBit(Destination, i); + } + i++; + } + (*CurrentBit) = (*CurrentBit) + BitsToProcess; +} + +void GetBufferInt(unsigned char *Source, + int *CurrentBit, + int *integer, + int BitsToProcess) +{ + int l=0,z=128,i=0; + + while (i!=BitsToProcess) { + if (GetBit(Source, (*CurrentBit)+i)) l=l+z; + z=z/2; + i++; + } + *integer=l; + (*CurrentBit) = (*CurrentBit) + i; +} + +void GetBufferI(unsigned char *Source, + int *CurrentBit, + int *result, + int BitsToProcess) +{ + int l=0,z,i=0; + + z = 1<<(BitsToProcess-1); + + while (i!=BitsToProcess) { + if (GetBit(Source, (*CurrentBit)+i)) l=l+z; + z=z>>1; + i++; + } + *result=l; + (*CurrentBit) = (*CurrentBit) + i; +} + +/* Unicode char 0x00 0x01 makes blinking in some Nokia phones. + * We replace single ~ chars into it. When user give double ~, it's replaced + * to single ~ + */ +void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len) +{ + int i,current = 0; + bool special=false; + + for (i = 0; i < len; i++) { + if (special) { + if (src[i*2] == 0x00 && src[i*2+1] == '~') { + dest[current++] = 0x00; + dest[current++] = '~'; + } else { + dest[current++] = 0x00; + dest[current++] = 0x01; + dest[current++] = src[i*2]; + dest[current++] = src[i*2+1]; + } + special = false; + } else { + if (src[i*2] == 0x00 && src[i*2+1] == '~') { + special = true; + } else { + dest[current++] = src[i*2]; + dest[current++] = src[i*2+1]; + } + } + } + if (special) { + dest[current++] = 0x00; + dest[current++] = 0x01; + } + dest[current++] = 0x00; + dest[current++] = 0x00; +} + +void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len) +{ + int i=0,current=0; + + for (i=0;i<len;i++) { + switch (src[2*i]) { + case 0x00: + switch (src[2*i+1]) { + case 0x01: + dest[current++] = 0x00; + dest[current++] = '~'; + break; + case '~': + dest[current++] = 0x00; + dest[current++] = '~'; + dest[current++] = 0x00; + dest[current++] = '~'; + break; + default: + dest[current++] = src[i*2]; + dest[current++] = src[i*2+1]; + } + break; + default: + dest[current++] = src[i*2]; + dest[current++] = src[i*2+1]; + } + } + dest[current++] = 0x00; + dest[current++] = 0x00; +} + +bool mystrncasecmp(unsigned const char *a, unsigned const char *b, int num) +{ + int i; + + if (a == NULL || b == NULL) return false; + + num--; + + for (i = 0; i != num; i++) { + if (a[i] == 0x00 && b[i] == 0x00) return true; + if (a[i] == 0x00 || b[i] == 0x00) return false; + if (tolower(a[i]) != tolower(b[i])) return false; + } + return true; +} + +/* Compares two Unicode strings without regarding to case. + * Return true, when they're equal + */ +bool mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num) +{ + int i; + wchar_t wc,wc2; + + if (a == NULL || b == NULL) return false; + + num--; + + for (i = 0; i != num; i++) { + if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) && (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return true; + if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) || (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return false; + wc = a[i*2+1] | (a[i*2] << 8); + wc2 = b[i*2+1] | (b[i*2] << 8); + if (mytowlower(wc) != mytowlower(wc2)) return false; + } + return true; +} + +/* wcscmp in Mandrake 9.0 is wrong */ +bool mywstrncmp(unsigned const char *a, unsigned const char *b, int num) +{ + int i=0; + + while (1) { + if (a[i*2] != b[i*2] || a[i*2+1] != b[i*2+1]) return false; + if (a[i*2] == 0x00 && a[i*2+1] == 0x00) return true; + i++; + if (num == i) return true; + } +} + +/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */ +bool myiswspace(unsigned const char *src) +{ +#ifndef HAVE_ISWSPACE + int o; + unsigned char dest[10]; +#endif + wchar_t wc; + + wc = src[1] | (src[0] << 8); + +#ifndef HAVE_ISWSPACE + o = DecodeWithUnicodeAlphabet(wc, dest); + if (o == 1) { + if (isspace(((int)dest[0]))!=0) return true; + return false; + } + return false; +#else + return iswspace(wc); +#endif +} + +/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */ +int mytowlower(wchar_t c) +{ +#ifndef HAVE_TOWLOWER + unsigned char dest[10]; + + DecodeWithUnicodeAlphabet(c, dest); + return tolower(dest[0]); +#else + return towlower(c); +#endif +} + +/* + * Following code is based on wcsstr from the GNU C Library, original + * comment follows: + */ +/* + * The original strstr() file contains the following comment: + * + * My personal strstr() implementation that beats most other algorithms. + * Until someone tells me otherwise, I assume that this is the + * fastest implementation of strstr() in C. + * I deliberately chose not to comment it. You should have at least + * as much fun trying to understand it, as I had to write it :-). + * + * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */ + +unsigned char *mystrstr (const unsigned char *haystack, const unsigned char *needle) +{ +/* One crazy define to convert unicode used in Gammu to standard wchar_t */ +#define tolowerwchar(x) (mytowlower((wchar_t)( (((&(x))[0] & 0xff) << 8) | (((&(x))[1] & 0xff)) ))) + register wchar_t b, c; + + if ((b = tolowerwchar(*needle)) != L'\0') { + haystack -= 2; /* possible ANSI violation */ + do { + haystack += 2; + if ((c = tolowerwchar(*haystack)) == L'\0') + goto ret0; + } while (c != b); + + needle += 2; + if ((c = tolowerwchar(*needle)) == L'\0') + goto foundneedle; + needle += 2; + goto jin; + + for (;;) { + register wchar_t a; + register const unsigned char *rhaystack, *rneedle; + + do { + haystack += 2; + if ((a = tolowerwchar(*haystack)) == L'\0') + goto ret0; + if (a == b) + break; + haystack += 2; + if ((a = tolowerwchar(*haystack)) == L'\0') + goto ret0; +shloop: ; + } while (a != b); + +jin: haystack += 2; + if ((a = tolowerwchar(*haystack)) == L'\0') + goto ret0; + + if (a != c) + goto shloop; + + rhaystack = haystack + 2; + haystack -= 2; + rneedle = needle; + if (tolowerwchar(*rhaystack) == (a = tolowerwchar(*rneedle))) + do { + if (a == L'\0') + goto foundneedle; + rhaystack += 2; + needle += 2; + if (tolowerwchar(*rhaystack) != (a = tolowerwchar(*needle))) + break ; + if (a == L'\0') + goto foundneedle; + rhaystack += 2; + needle += 2; + } while (tolowerwchar(*rhaystack) == (a = tolowerwchar(*needle))); + + needle = rneedle; /* took the register-poor approach */ + + if (a == L'\0') + break; + } + } +foundneedle: + return (unsigned char *)haystack; +ret0: + return NULL; +#undef tolowerwchar +} + +void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen) +{ + OutBuffer[0] = 0; + if (Buffer == NULL) return; + while (1) { + if ((*Pos) >= MaxLen) return; + switch (Buffer[*Pos]) { + case 0x00: + return; + case 0x0A: + if (strlen(OutBuffer) != 0) return; + break; + case 0x0D: + if (strlen(OutBuffer) != 0) return; + break; + default : + OutBuffer[strlen(OutBuffer) + 1] = 0; + OutBuffer[strlen(OutBuffer)] = Buffer[*Pos]; + } + (*Pos)++; + } +} + +void StringToDouble(char *text, double *d) +{ + bool before=true; + double multiply = 1; + unsigned int i; + + *d = 0; + for (i=0;i<strlen(text);i++) { + if (isdigit(text[i])) { + if (before) { + (*d)=(*d)*10+(text[i]-'0'); + } else { + multiply=multiply*0.1; + (*d)=(*d)+(text[i]-'0')*multiply; + } + } + if (text[i]=='.' || text[i]==',') before=false; + } +} + +/* When char can be converted, convert it from Unicode to UTF8 */ +bool EncodeWithUTF8Alphabet(unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2) +{ + unsigned char mychar3,mychar4; + int j=0; + + if (mychar1>0x00 || mychar2>128) { + mychar3=0x00; + mychar4=128; + while (true) { + if (mychar3==mychar1) { + if (mychar4+64>=mychar2) { + *ret1=j+0xc2; + *ret2=0x80+(mychar2-mychar4); + return true; + } + } + if (mychar4==192) { + mychar3++; + mychar4=0; + } else { + mychar4=mychar4+64; + } + j++; + } + } + return false; +} + +/* Make UTF8 string from Unicode input string */ +bool EncodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src) +{ + int i,j=0; + unsigned char mychar1, mychar2; + bool retval = false; + + for (i = 0; i < (int)(UnicodeLength(src)); i++) { + if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) { + sprintf(dest+j, "=%02X=%02X",mychar1,mychar2); + j = j+6; + retval = true; + } else { + j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j); + } + } + dest[j++]=0; + return retval; +} + +bool EncodeUTF8(unsigned char *dest, const unsigned char *src) +{ + int i,j=0; + unsigned char mychar1, mychar2; + bool retval = false; + + for (i = 0; i < (int)(UnicodeLength(src)); i++) { + if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) { + sprintf(dest+j, "%c%c",mychar1,mychar2); + j = j+2; + retval = true; + } else { + j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j); + } + } + dest[j++]=0; + return retval; +} + +/* Decode UTF8 char to Unicode char */ +wchar_t DecodeWithUTF8Alphabet(unsigned char mychar3, unsigned char mychar4) +{ + unsigned char mychar1, mychar2; + int j; + + mychar1=0x00; + mychar2=128; + for(j=0;j<mychar3-0xc2;j++) { + if (mychar2==192) { + mychar1++; + mychar2 = 0; + } else { + mychar2 = mychar2+64; + } + } + mychar2 = mychar2+(mychar4-0x80); + return mychar2 | (mychar1 << 8); +} + +/* Make Unicode string from UTF8 string */ +void DecodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src, int len) +{ + int i=0,j=0; + unsigned char mychar1, mychar2; + wchar_t ret; + + while (i<=len) { + if (len-6>=i) { + /* Need to have correct chars */ + if (src[i] =='=' && DecodeWithHexBinAlphabet(src[i+1])!=-1 + && DecodeWithHexBinAlphabet(src[i+2])!=-1 && + src[i+3]=='=' && DecodeWithHexBinAlphabet(src[i+4])!=-1 && + DecodeWithHexBinAlphabet(src[i+5])!=-1) { + mychar1 = 16*DecodeWithHexBinAlphabet(src[i+1])+DecodeWithHexBinAlphabet(src[i+2]); + mychar2 = 16*DecodeWithHexBinAlphabet(src[i+4])+DecodeWithHexBinAlphabet(src[i+5]); + ret = DecodeWithUTF8Alphabet(mychar1,mychar2); + i = i+6; + } else { + i+=EncodeWithUnicodeAlphabet(&src[i], &ret); + } + } else { + i+=EncodeWithUnicodeAlphabet(&src[i], &ret); + } + dest[j++] = (ret >> 8) & 0xff; + dest[j++] = ret & 0xff; + } + dest[j++] = 0; + dest[j++] = 0; +} + +void DecodeUTF8(unsigned char *dest, const unsigned char *src, int len) +{ + int i=0,j=0; + wchar_t ret; + + while (i<=len) { + if (len-2>=i) { + if (src[i] >= 0xC2) { + ret = DecodeWithUTF8Alphabet(src[i],src[i+1]); + i = i+2; + } else { + i+=EncodeWithUnicodeAlphabet(&src[i], &ret); + } + } else { + i+=EncodeWithUnicodeAlphabet(&src[i], &ret); + } + dest[j++] = (ret >> 8) & 0xff; + dest[j++] = ret & 0xff; + } + dest[j++] = 0; + dest[j++] = 0; +} + +void DecodeUTF7(unsigned char *dest, const unsigned char *src, int len) +{ + int i=0,j=0,z,p; + wchar_t ret; + + while (i<=len) { + if (len-5>=i) { + if (src[i] == '+') { + z=0; + while (src[z+i+1] != '-' && z+i+1<len) z++; + p=DecodeBASE64(src+i+1, dest+j, z); + if (p%2 != 0) p--; + j+=p; + i+=z+2; + } else { + i+=EncodeWithUnicodeAlphabet(&src[i], &ret); + dest[j++] = (ret >> 8) & 0xff; + dest[j++] = ret & 0xff; + } + } else { + i+=EncodeWithUnicodeAlphabet(&src[i], &ret); + dest[j++] = (ret >> 8) & 0xff; + dest[j++] = ret & 0xff; + } + } + dest[j++] = 0; + dest[j++] = 0; +} + +/* +Bob Trower 08/04/01 +Copyright (c) Trantor Standard Systems Inc., 2001 + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall +be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +static void EncodeBASE64Block(unsigned char in[3], unsigned char out[4], int len) +{ + /* BASE64 translation Table as described in RFC1113 */ + unsigned char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + out[0] = cb64[ in[0] >> 2 ]; + out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; + out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); + out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '='); +} + +void EncodeBASE64(const unsigned char *Input, unsigned char *Output, int Length) +{ + unsigned char in[3], out[4]; + int i, pos = 0, len, outpos = 0; + + while (pos < Length) { + len = 0; + for (i = 0; i < 3; i++) { + in[i] = 0; + if (pos < Length) { + in[i] = Input[pos]; + len++; + pos++; + } + } + if(len) { + EncodeBASE64Block(in, out, len); + for (i = 0; i < 4; i++) Output[outpos++] = out[i]; + } + } + + Output[outpos++] = 0; +} + +static void DecodeBASE64Block(unsigned char in[4], unsigned char out[3]) +{ + out[0] = (unsigned char) (in[0] << 2 | in[1] >> 4); + out[1] = (unsigned char) (in[1] << 4 | in[2] >> 2); + out[2] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]); +} + +int DecodeBASE64(const unsigned char *Input, unsigned char *Output, int Length) +{ + unsigned char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; + unsigned char in[4], out[3], v; + int i, len, pos = 0, outpos = 0; + + while (pos < Length) { + len = 0; + for(i = 0; i < 4; i++) { + v = 0; + while(v == 0) { + if (pos >= Length) break; + v = (unsigned char) Input[pos++]; + v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]); + if (v) v = (unsigned char) ((v == '$') ? 0 : v - 61); + } + if(pos<=Length) { + if (v) { + len++; + in[i] = (unsigned char) (v - 1); + } + } + } + if (len) { + DecodeBASE64Block(in, out); + for(i = 0; i < len - 1; i++) Output[outpos++] = out[i]; + } + } + Output[outpos] = 0; + return outpos; +} + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ + 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 @@ +/* (c) 2002-2004 by Marcin Wiacek and others */ + +#ifndef __coding_h +#define __coding_h + +#include <stdlib.h> + +#include "../misc.h" + +#ifdef __OpenBSD__ +typedef int wint_t; +#endif + +/* ---------------------------- Unicode ------------------------------------ */ +bool mywstrncasecmp (unsigned const char *a, unsigned const char *b, int num); +unsigned char *mystrstr (unsigned const char *haystack, unsigned const char *needle); +bool mywstrncmp (unsigned const char *a, unsigned const char *b, int num); +bool myiswspace (unsigned const char *src); +int mytowlower (wchar_t c); + +unsigned int EncodeWithUnicodeAlphabet (const unsigned char *value, wchar_t *dest); +unsigned int DecodeWithUnicodeAlphabet (wchar_t value, unsigned char *dest); + +unsigned int UnicodeLength (const unsigned char *str); +unsigned char *DecodeUnicodeString (const unsigned char *src); +unsigned char *DecodeUnicodeConsole (const unsigned char *src); +void DecodeUnicode (const unsigned char *src, unsigned char *dest); +void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len); + +void CopyUnicodeString (unsigned char *Dest, unsigned char *Source); +void ReverseUnicodeString (unsigned char *String); + +void ReadUnicodeFile (unsigned char *Dest, unsigned char *Source); + +void DecodeUnicodeSpecialNOKIAChars (unsigned char *dest, const unsigned char *src, int len); +void EncodeUnicodeSpecialNOKIAChars (unsigned char *dest, const unsigned char *src, int len); + +/* ------------------------------- BCD ------------------------------------- */ +unsigned char EncodeWithBCDAlphabet (int value); +int DecodeWithBCDAlphabet (unsigned char value); + +void DecodeBCD (unsigned char *dest, const unsigned char *src, int len); +void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill); + +/* ------------------------------ UTF7 ------------------------------------- */ +void DecodeUTF7 (unsigned char *dest, const unsigned char *src, int len); + +/* ------------------------------ UTF8 ------------------------------------- */ +wchar_t DecodeWithUTF8Alphabet (unsigned char mychar3, unsigned char mychar4); +bool EncodeWithUTF8Alphabet (unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2); + +bool EncodeUTF8QuotedPrintable (unsigned char *dest, const unsigned char *src); +void DecodeUTF8QuotedPrintable (unsigned char *dest, const unsigned char *src, int len); + +bool EncodeUTF8 (unsigned char *dest, const unsigned char *src); +void DecodeUTF8 (unsigned char *dest, const unsigned char *src, int len); + +/* ------------------------------- BASE64 ---------------------------------- */ +void EncodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length); +int DecodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length); + +/* ----------------------------- HexBin ------------------------------------ */ +void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len); +void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len); + +/* ----------------------------- HexUnicode -------------------------------- */ +void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len); +void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len); + +/* ---------------------- DefaultAlphabet for SMS -------------------------- */ +void EncodeDefault (unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet); +void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet); +void FindDefaultAlphabetLen (const unsigned char *src, int *srclen, int *smslen, int maxlen); + +int GSM_PackSevenBitsToEight (int offset, unsigned char *input, unsigned char *output, int length); +int GSM_UnpackEightBitsToSeven (int offset, int in_length, int out_length, + unsigned char *input, unsigned char *output); + +/* ----------------- Phone numbers according to GSM specs ------------------ */ + +/** + * Enum to handle types of phones numbers like + * specified in GSM 03.40 section 9.1.2.5 + */ +typedef enum { + /** + * Unknown number type + */ + NUMBER_UNKNOWN = 0x81, + /** + * International number (full number with code of country) + */ + NUMBER_INTERNATIONAL = 0x91, + /** + * Alphanumeric number (with chars too) + */ + NUMBER_ALPHANUMERIC = 0xD0 + + /* specification give also other values */ +} GSM_NumberType; + +void GSM_UnpackSemiOctetNumber (unsigned char *retval, unsigned char *Number, bool semioctet); +int GSM_PackSemiOctetNumber (unsigned char *Number, unsigned char *Output, bool semioctet); + +/* ---------------------------- Bits --------------------------------------- */ + +void BufferAlign (unsigned char *Destination, int *CurrentBit); +void BufferAlignNumber(int *CurrentBit); + +void AddBuffer (unsigned char *Destination, int *CurrentBit, unsigned char *Source, int BitsToProcess); +void AddBufferByte(unsigned char *Destination, int *CurrentBit, unsigned char Source, int BitsToProcess); + +void GetBuffer (unsigned char *Source, int *CurrentBit, unsigned char *Destination, int BitsToProcess); +void GetBufferInt (unsigned char *Source, int *CurrentBit, int *integer, int BitsToProcess); +void GetBufferI (unsigned char *Source, int *CurrentBit, int *result, int BitsToProcess); + +int GetBit (unsigned char *Buffer, int BitNum); +int SetBit (unsigned char *Buffer, int BitNum); +int ClearBit (unsigned char *Buffer, int BitNum); + +/* ---------------------------- Other -------------------------------------- */ + +void StringToDouble (char *text, double *d); + +bool mystrncasecmp (unsigned const char *a, unsigned const char *b, int num); + +void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen); + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ 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 @@ +/* Taken from ReHash (see http://www.reichlsoft.de.vu/) and released + * under GPL/LGPL with permission from ReHash author + * Dominik Reichl <dominik.reichl@t-online.de>, Germany + */ + +/* + ********************************************************************** + ** MD5.cpp ** + ** ** + ** - Style modified by Tony Ray, January 2001 ** + ** Added support for randomizing initialization constants ** + ** - Style modified by Dominik Reichl, April 2003 ** + ** Optimized code ** + ** ** + ** MD5.c ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** MD5.h -- Header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "md5.h" + +/* Typedef a 32 bit type */ +#ifndef UINT4 +typedef unsigned long int UINT4; +#endif + +/* Data structure for MD5 (Message Digest) computation */ +typedef struct { + UINT4 i[2]; /* Number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* Scratch buffer */ + unsigned char in[64]; /* Input buffer */ + unsigned char digest[16]; /* Actual digest after MD5Final call */ +} MD5_CTX; + +/* Padding */ +static unsigned char MD5_PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* MD5_F, MD5_G and MD5_H are basic MD5 functions: selection, majority, parity */ +#define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#ifndef ROTATE_LEFT +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#endif + +/* MD5_FF, MD5_GG, MD5_HH, and MD5_II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#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); } +#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); } +#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); } +#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); } + +/* Constants for transformation */ +#define MD5_S11 7 /* Round 1 */ +#define MD5_S12 12 +#define MD5_S13 17 +#define MD5_S14 22 +#define MD5_S21 5 /* Round 2 */ +#define MD5_S22 9 +#define MD5_S23 14 +#define MD5_S24 20 +#define MD5_S31 4 /* Round 3 */ +#define MD5_S32 11 +#define MD5_S33 16 +#define MD5_S34 23 +#define MD5_S41 6 /* Round 4 */ +#define MD5_S42 10 +#define MD5_S43 15 +#define MD5_S44 21 + +/* Basic MD5 step. MD5_Transform buf based on in */ +static void MD5_Transform (UINT4 *buf, UINT4 *in) +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + MD5_FF ( a, b, c, d, in[ 0], MD5_S11, (UINT4) 3614090360u); /* 1 */ + MD5_FF ( d, a, b, c, in[ 1], MD5_S12, (UINT4) 3905402710u); /* 2 */ + MD5_FF ( c, d, a, b, in[ 2], MD5_S13, (UINT4) 606105819u); /* 3 */ + MD5_FF ( b, c, d, a, in[ 3], MD5_S14, (UINT4) 3250441966u); /* 4 */ + MD5_FF ( a, b, c, d, in[ 4], MD5_S11, (UINT4) 4118548399u); /* 5 */ + MD5_FF ( d, a, b, c, in[ 5], MD5_S12, (UINT4) 1200080426u); /* 6 */ + MD5_FF ( c, d, a, b, in[ 6], MD5_S13, (UINT4) 2821735955u); /* 7 */ + MD5_FF ( b, c, d, a, in[ 7], MD5_S14, (UINT4) 4249261313u); /* 8 */ + MD5_FF ( a, b, c, d, in[ 8], MD5_S11, (UINT4) 1770035416u); /* 9 */ + MD5_FF ( d, a, b, c, in[ 9], MD5_S12, (UINT4) 2336552879u); /* 10 */ + MD5_FF ( c, d, a, b, in[10], MD5_S13, (UINT4) 4294925233u); /* 11 */ + MD5_FF ( b, c, d, a, in[11], MD5_S14, (UINT4) 2304563134u); /* 12 */ + MD5_FF ( a, b, c, d, in[12], MD5_S11, (UINT4) 1804603682u); /* 13 */ + MD5_FF ( d, a, b, c, in[13], MD5_S12, (UINT4) 4254626195u); /* 14 */ + MD5_FF ( c, d, a, b, in[14], MD5_S13, (UINT4) 2792965006u); /* 15 */ + MD5_FF ( b, c, d, a, in[15], MD5_S14, (UINT4) 1236535329u); /* 16 */ + + /* Round 2 */ + MD5_GG ( a, b, c, d, in[ 1], MD5_S21, (UINT4) 4129170786u); /* 17 */ + MD5_GG ( d, a, b, c, in[ 6], MD5_S22, (UINT4) 3225465664u); /* 18 */ + MD5_GG ( c, d, a, b, in[11], MD5_S23, (UINT4) 643717713u); /* 19 */ + MD5_GG ( b, c, d, a, in[ 0], MD5_S24, (UINT4) 3921069994u); /* 20 */ + MD5_GG ( a, b, c, d, in[ 5], MD5_S21, (UINT4) 3593408605u); /* 21 */ + MD5_GG ( d, a, b, c, in[10], MD5_S22, (UINT4) 38016083u); /* 22 */ + MD5_GG ( c, d, a, b, in[15], MD5_S23, (UINT4) 3634488961u); /* 23 */ + MD5_GG ( b, c, d, a, in[ 4], MD5_S24, (UINT4) 3889429448u); /* 24 */ + MD5_GG ( a, b, c, d, in[ 9], MD5_S21, (UINT4) 568446438u); /* 25 */ + MD5_GG ( d, a, b, c, in[14], MD5_S22, (UINT4) 3275163606u); /* 26 */ + MD5_GG ( c, d, a, b, in[ 3], MD5_S23, (UINT4) 4107603335u); /* 27 */ + MD5_GG ( b, c, d, a, in[ 8], MD5_S24, (UINT4) 1163531501u); /* 28 */ + MD5_GG ( a, b, c, d, in[13], MD5_S21, (UINT4) 2850285829u); /* 29 */ + MD5_GG ( d, a, b, c, in[ 2], MD5_S22, (UINT4) 4243563512u); /* 30 */ + MD5_GG ( c, d, a, b, in[ 7], MD5_S23, (UINT4) 1735328473u); /* 31 */ + MD5_GG ( b, c, d, a, in[12], MD5_S24, (UINT4) 2368359562u); /* 32 */ + + /* Round 3 */ + MD5_HH ( a, b, c, d, in[ 5], MD5_S31, (UINT4) 4294588738u); /* 33 */ + MD5_HH ( d, a, b, c, in[ 8], MD5_S32, (UINT4) 2272392833u); /* 34 */ + MD5_HH ( c, d, a, b, in[11], MD5_S33, (UINT4) 1839030562u); /* 35 */ + MD5_HH ( b, c, d, a, in[14], MD5_S34, (UINT4) 4259657740u); /* 36 */ + MD5_HH ( a, b, c, d, in[ 1], MD5_S31, (UINT4) 2763975236u); /* 37 */ + MD5_HH ( d, a, b, c, in[ 4], MD5_S32, (UINT4) 1272893353u); /* 38 */ + MD5_HH ( c, d, a, b, in[ 7], MD5_S33, (UINT4) 4139469664u); /* 39 */ + MD5_HH ( b, c, d, a, in[10], MD5_S34, (UINT4) 3200236656u); /* 40 */ + MD5_HH ( a, b, c, d, in[13], MD5_S31, (UINT4) 681279174u); /* 41 */ + MD5_HH ( d, a, b, c, in[ 0], MD5_S32, (UINT4) 3936430074u); /* 42 */ + MD5_HH ( c, d, a, b, in[ 3], MD5_S33, (UINT4) 3572445317u); /* 43 */ + MD5_HH ( b, c, d, a, in[ 6], MD5_S34, (UINT4) 76029189u); /* 44 */ + MD5_HH ( a, b, c, d, in[ 9], MD5_S31, (UINT4) 3654602809u); /* 45 */ + MD5_HH ( d, a, b, c, in[12], MD5_S32, (UINT4) 3873151461u); /* 46 */ + MD5_HH ( c, d, a, b, in[15], MD5_S33, (UINT4) 530742520u); /* 47 */ + MD5_HH ( b, c, d, a, in[ 2], MD5_S34, (UINT4) 3299628645u); /* 48 */ + + /* Round 4 */ + MD5_II ( a, b, c, d, in[ 0], MD5_S41, (UINT4) 4096336452u); /* 49 */ + MD5_II ( d, a, b, c, in[ 7], MD5_S42, (UINT4) 1126891415u); /* 50 */ + MD5_II ( c, d, a, b, in[14], MD5_S43, (UINT4) 2878612391u); /* 51 */ + MD5_II ( b, c, d, a, in[ 5], MD5_S44, (UINT4) 4237533241u); /* 52 */ + MD5_II ( a, b, c, d, in[12], MD5_S41, (UINT4) 1700485571u); /* 53 */ + MD5_II ( d, a, b, c, in[ 3], MD5_S42, (UINT4) 2399980690u); /* 54 */ + MD5_II ( c, d, a, b, in[10], MD5_S43, (UINT4) 4293915773u); /* 55 */ + MD5_II ( b, c, d, a, in[ 1], MD5_S44, (UINT4) 2240044497u); /* 56 */ + MD5_II ( a, b, c, d, in[ 8], MD5_S41, (UINT4) 1873313359u); /* 57 */ + MD5_II ( d, a, b, c, in[15], MD5_S42, (UINT4) 4264355552u); /* 58 */ + MD5_II ( c, d, a, b, in[ 6], MD5_S43, (UINT4) 2734768916u); /* 59 */ + MD5_II ( b, c, d, a, in[13], MD5_S44, (UINT4) 1309151649u); /* 60 */ + MD5_II ( a, b, c, d, in[ 4], MD5_S41, (UINT4) 4149444226u); /* 61 */ + MD5_II ( d, a, b, c, in[11], MD5_S42, (UINT4) 3174756917u); /* 62 */ + MD5_II ( c, d, a, b, in[ 2], MD5_S43, (UINT4) 718787259u); /* 63 */ + MD5_II ( b, c, d, a, in[ 9], MD5_S44, (UINT4) 3951481745u); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +// Set pseudoRandomNumber to zero for RFC MD5 implementation +void MD5Init (MD5_CTX *mdContext, unsigned long pseudoRandomNumber) +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants */ + mdContext->buf[0] = (UINT4)0x67452301 + (pseudoRandomNumber * 11); + mdContext->buf[1] = (UINT4)0xefcdab89 + (pseudoRandomNumber * 71); + mdContext->buf[2] = (UINT4)0x98badcfe + (pseudoRandomNumber * 37); + mdContext->buf[3] = (UINT4)0x10325476 + (pseudoRandomNumber * 97); +} + +void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) +{ + UINT4 in[16]; + int mdi = 0; + unsigned int i = 0, ii = 0; + + /* Compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { + /* Add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* Transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + + MD5_Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void MD5Final (MD5_CTX *mdContext) +{ + UINT4 in[16]; + int mdi = 0; + unsigned int i = 0, ii = 0, padLen = 0; + + /* Save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* Compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* Pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, MD5_PADDING, padLen); + + /* Append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + MD5_Transform (mdContext->buf, in); + + /* Store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)( mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } +} + +void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum) +{ + int i; + MD5_CTX m_md5; + + MD5Init(&m_md5, 0); + MD5Update(&m_md5, buffer, length); + MD5Final(&m_md5); + + for (i = 0; i < 16; i++) sprintf(checksum+i*2,"%02X", m_md5.digest[i]); +} 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 @@ +#ifndef __md5_h +#define __md5_h + +void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum); + +#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 @@ +/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */ +/* Checking used compiler (c) 2002 by Michal Cihar */ + +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <stdarg.h> +#include <stdio.h> +#include <locale.h> +#include <sys/timeb.h> +#ifdef WIN32 +# include "windows.h" +#endif + +#include "../gsmstate.h" +#include "misc.h" + +/* Based on article in Polish PC-Kurier 8/1998 page 104 + * Archive on http://www.pckurier.pl + */ +char *DayOfWeek (int year, int month, int day) +{ + int p,q,r,w; + static char DayOfWeekChar[10]; + + p=(14-month) / 12; + q=month+12*p-2; + r=year-p; + w=(day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7; + strcpy(DayOfWeekChar,""); + switch (w) { + case 0: strcpy(DayOfWeekChar,"Sun"); break; + case 1: strcpy(DayOfWeekChar,"Mon"); break; + case 2: strcpy(DayOfWeekChar,"Tue"); break; + case 3: strcpy(DayOfWeekChar,"Wed"); break; + case 4: strcpy(DayOfWeekChar,"Thu"); break; + case 5: strcpy(DayOfWeekChar,"Fri"); break; + case 6: strcpy(DayOfWeekChar,"Sat"); break; + } + return DayOfWeekChar; +} + +void Fill_GSM_DateTime(GSM_DateTime *Date, time_t timet) +{ + struct tm *now; + + now = localtime(&timet); + Date->Year = now->tm_year; + Date->Month = now->tm_mon+1; + Date->Day = now->tm_mday; + Date->Hour = now->tm_hour; + Date->Minute = now->tm_min; + Date->Second = now->tm_sec; +} + +void GSM_GetCurrentDateTime (GSM_DateTime *Date) +{ + Fill_GSM_DateTime(Date, time(NULL)); + if (Date->Year<1900) { + if (Date->Year>90) Date->Year = Date->Year+1900; + else Date->Year = Date->Year+2000; + } +} + +time_t Fill_Time_T(GSM_DateTime DT, int TZ) +{ + struct tm tm_starttime; + unsigned char buffer[30]; + + dbgprintf(" StartTime : %02i-%02i-%04i %02i:%02i:%02i\n", + DT.Day,DT.Month,DT.Year,DT.Hour,DT.Minute,DT.Second); + + if (TZ != 0) { +#if defined(WIN32) || defined(__SVR4) + sprintf(buffer,"TZ=PST+%i",TZ); + putenv(buffer); +#else + sprintf(buffer,"PST+%i",TZ); + setenv("TZ",buffer,1); +#endif + } + tzset(); + + memset(&tm_starttime, 0, sizeof(tm_starttime)); + tm_starttime.tm_year = DT.Year - 1900; + tm_starttime.tm_mon = DT.Month - 1; + tm_starttime.tm_mday = DT.Day; + tm_starttime.tm_hour = DT.Hour; + tm_starttime.tm_min = DT.Minute; + tm_starttime.tm_sec = DT.Second; + tm_starttime.tm_isdst = 0; + + return mktime(&tm_starttime); +} + +void GetTimeDifference(unsigned long diff, GSM_DateTime *DT, bool Plus, int multi) +{ + time_t t_time; + + t_time = Fill_Time_T(*DT,8); + + if (Plus) { + t_time += diff*multi; + } else { + t_time -= diff*multi; + } + + Fill_GSM_DateTime(DT, t_time); + DT->Year = DT->Year + 1900; + dbgprintf(" EndTime : %02i-%02i-%04i %02i:%02i:%02i\n", + DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second); +} + +char *OSDateTime (GSM_DateTime dt, bool TimeZone) +{ + struct tm timeptr; + static char retval[200],retval2[200]; + int p,q,r,w; + +#ifdef WIN32 + setlocale(LC_ALL, ".OCP"); +#endif + + /* Based on article in Polish PC-Kurier 8/1998 page 104 + * Archive on http://www.pckurier.pl + */ + p=(14-dt.Month) / 12; + q=dt.Month+12*p-2; + r=dt.Year-p; + w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7; + + timeptr.tm_yday = 0; /* FIXME */ + timeptr.tm_isdst = -1; /* FIXME */ + timeptr.tm_year = dt.Year - 1900; + timeptr.tm_mon = dt.Month - 1; + timeptr.tm_mday = dt.Day; + timeptr.tm_hour = dt.Hour; + timeptr.tm_min = dt.Minute; + timeptr.tm_sec = dt.Second; + timeptr.tm_wday = w; +#ifdef _BSD_SOURCE + timeptr.tm_zone = NULL; +#endif + +#ifdef WIN32 + strftime(retval2, 200, "%#c", &timeptr); +#else + strftime(retval2, 200, "%c", &timeptr); +#endif + if (TimeZone) { + if (dt.Timezone >= 0) { + sprintf(retval," +%02i00",dt.Timezone); + } else { + sprintf(retval," -%02i00",dt.Timezone); + } + strcat(retval2,retval); + } + /* If don't have weekday name, include it */ + strftime(retval, 200, "%A", &timeptr); + if (strstr(retval2,retval)==NULL) { + /* Check for abbreviated weekday */ + strftime(retval, 200, "%a", &timeptr); + if (strstr(retval2,retval)==NULL) { + strcat(retval2," ("); + strcat(retval2,retval); + strcat(retval2,")"); + } + } + +#ifdef WIN32 + setlocale(LC_ALL, ".ACP"); +#endif + + return retval2; +} + +char *OSDate (GSM_DateTime dt) +{ + struct tm timeptr; + static char retval[200],retval2[200]; + int p,q,r,w; + +#ifdef WIN32 + setlocale(LC_ALL, ".OCP"); +#endif + + /* Based on article in Polish PC-Kurier 8/1998 page 104 + * Archive on http://www.pckurier.pl + */ + p=(14-dt.Month) / 12; + q=dt.Month+12*p-2; + r=dt.Year-p; + w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7; + + timeptr.tm_yday = 0; /* FIXME */ + timeptr.tm_isdst = -1; /* FIXME */ + timeptr.tm_year = dt.Year - 1900; + timeptr.tm_mon = dt.Month - 1; + timeptr.tm_mday = dt.Day; + timeptr.tm_hour = dt.Hour; + timeptr.tm_min = dt.Minute; + timeptr.tm_sec = dt.Second; + timeptr.tm_wday = w; +#ifdef _BSD_SOURCE + timeptr.tm_zone = NULL; +#endif + +#ifdef WIN32 + strftime(retval2, 200, "%#x", &timeptr); +#else + strftime(retval2, 200, "%x", &timeptr); +#endif + /* If don't have weekday name, include it */ + strftime(retval, 200, "%A", &timeptr); + if (strstr(retval2,retval)==NULL) { + /* Check also for short name */ + strftime(retval, 200, "%a", &timeptr); + if (strstr(retval2,retval)==NULL) { + strcat(retval2," ("); + strcat(retval2,retval); + strcat(retval2,")"); + } + } + +#ifdef WIN32 + setlocale(LC_ALL, ".ACP"); +#endif + + return retval2; +} + +bool CheckDate(GSM_DateTime *date) +{ + /* FIXME: This could also check if day is correct for selected month */ + return date->Year != 0 && + date->Month >= 1 && date->Month <= 12 && + date->Day >= 1 && date->Day <= 31; +} + +bool CheckTime(GSM_DateTime *date) +{ + return date->Hour <= 23 && date->Hour >= 0 && + date->Minute <= 59 && date->Minute >= 0 && + date->Second <= 59 && date->Second >= 0; +} + +int GetLine(FILE *File, char *Line, int count) +{ + int num; + + if (fgets(Line, count, File) != NULL) { + num = strlen(Line) - 1; + while(1) { + if (Line[num] != '\n' && Line[num] != '\r') break; + if (num == 0) break; + Line[num--] = 0; + } + return strlen(Line); + } + return -1; +} + +void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot) +{ + int i,number=0,j; + bool whitespace=true, nowwhite; + + for (i=0;i<MAX_LINES*2;i++) lines->numbers[i]=0; + + for (i=0;i<messagesize;i++) { + nowwhite = false; + for (j=0;j<spaceslen;j++) { + if (whitespaces[j] == message[i]) { + nowwhite = true; + break; + } + } + if (whitespace) { + if (!nowwhite) { + lines->numbers[number]=i; + number++; + whitespace=false; + } + } else { + if (nowwhite) { + lines->numbers[number]=i; + number++; + whitespace=true; + } + + } + } + if (eot && !whitespace) lines->numbers[number]=messagesize; +} + +char *GetLineString(unsigned char *message, GSM_Lines lines, int start) +{ + static char retval[800]; + + memcpy(retval,message + lines.numbers[start*2-2],lines.numbers[start*2-2+1]-lines.numbers[start*2-2]); + retval[lines.numbers[start*2-2+1]-lines.numbers[start*2-2]]=0; + + return retval; +} + +void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start) +{ + memcpy(dest,GetLineString(src, lines, start),strlen(GetLineString(src, lines, start))); + dest[strlen(GetLineString(src, lines, start))] = 0; +} + +Debug_Info di = {0,NULL,false,""}; + +#ifdef DEBUG +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif +int dbgprintf(const char *format, ...) +{ + va_list argp; + int result; + static unsigned char nextline[2000]=""; + unsigned char buffer[2000]; + GSM_DateTime date_time; + + if (di.df != NULL && (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE)) { + va_start(argp, format); + result = vsprintf(buffer, format, argp); + strcat(nextline, buffer); + if (strstr(buffer, "\n")) { + if (di.dl == DL_TEXTALLDATE) { + GSM_GetCurrentDateTime(&date_time); + fprintf(di.df,"%s %4d/%02d/%02d %02d:%02d:%02d: %s", + DayOfWeek(date_time.Year, date_time.Month, date_time.Day), + date_time.Year, date_time.Month, date_time.Day, + date_time.Hour, date_time.Minute, date_time.Second,nextline); + } else { + fprintf(di.df,"%s",nextline); + } + strcpy(nextline, ""); + } + fflush(di.df); + va_end(argp); + return result; + } + return 0; +} +#endif + +/* assumption: if \n is present it is always the last char, + * string never of the form "......\n..." + */ +#ifdef __GNUC__ +__attribute__((format(printf, 3, 4))) +#endif +int smfprintf(FILE *f, Debug_Level dl, const char *format, ...) +{ + va_list argp; + int result=0; + static unsigned char prevline[2000] = "", nextline[2000]=""; + static unsigned int linecount=0; + unsigned char buffer[2000]; + GSM_DateTime date_time; + + if (f == NULL) return 0; + va_start(argp, format); + result = vsprintf(buffer, format, argp); + strcat(nextline, buffer); + if (strstr(buffer, "\n")) { + if (ftell(f) < 5000000) { + GSM_GetCurrentDateTime(&date_time); + if (linecount > 0) { + if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) { + fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: <%i> %s", + DayOfWeek(date_time.Year, date_time.Month, date_time.Day), + date_time.Year, date_time.Month, date_time.Day, + date_time.Hour, date_time.Minute, date_time.Second,linecount,prevline); + } else { + fprintf(f,"%s",prevline); + } + } + linecount=0; + if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) { + fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: %s", + DayOfWeek(date_time.Year, date_time.Month, date_time.Day), + date_time.Year, date_time.Month, date_time.Day, + date_time.Hour, date_time.Minute, date_time.Second,nextline); + } else { + fprintf(f,"%s",nextline); + } + strcpy(prevline, nextline); + } + strcpy(nextline, ""); + fflush(f); + } + va_end(argp); + return result; +} + +bool GSM_SetDebugLevel(char *info, Debug_Info *di) +{ + if (!strcmp(info,"nothing")) {di->dl = 0; return true;} + if (!strcmp(info,"text")) {di->dl = DL_TEXT; return true;} + if (!strcmp(info,"textall")) {di->dl = DL_TEXTALL; return true;} + if (!strcmp(info,"binary")) {di->dl = DL_BINARY; return true;} + if (!strcmp(info,"errors")) {di->dl = DL_TEXTERROR; return true;} + if (!strcmp(info,"textdate")) {di->dl = DL_TEXTDATE; return true;} + if (!strcmp(info,"textalldate")) {di->dl = DL_TEXTALLDATE; return true;} + if (!strcmp(info,"errorsdate")) {di->dl = DL_TEXTERRORDATE; return true;} + return false; +} + +/* Dumps a message */ +void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize) +{ + int i,j=0,len=16; + unsigned char buffer[200]; + + if (df==NULL || messagesize == 0) return; + + smfprintf(df, dl, "\n"); + + memset(buffer,0x20,sizeof(buffer)); + buffer[len*5-1]=0; + + for (i = 0; i < messagesize; i++) { + sprintf(buffer+j*4,"%02X",message[i]); + buffer[j*4+2] = 0x20; + if (isprint(message[i]) && message[i]!=0x09) { + if (j != len-1) buffer[j*4+2] = message[i]; + buffer[(len-1)*4+j+3] = message[i]; + } else { + buffer[(len-1)*4+j+3] = '.'; + } + if (j != len-1 && i != messagesize-1) buffer[j*4+3] = '|'; + if (j == len-1) { + smfprintf(df, dl, "%s\n", buffer); + memset(buffer,0x20,sizeof(buffer)); + buffer[len*5-1]=0; + j = 0; + } else { + j++; + } + } + if (j != 0) smfprintf(df, dl, "%s\n", buffer); +} + +char *GetOS(void) +{ +#ifdef WIN32 + OSVERSIONINFOEX Ver; + bool Extended = true; +#endif + static char Buffer[100] = {0x00}; + +#ifdef WIN32 + memset(&Ver,sizeof(OSVERSIONINFOEX),0); + Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if (!GetVersionEx((OSVERSIONINFO *)&Ver)) { + Extended = false; + Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO *)&Ver)) { +//#ifdef _MSC_VER
+// Ver.dwMajorVersion = _winmajor; +// Ver.dwMinorVersion = _winminor; +// Ver.dwBuildNumber = _osver; +//#else + sprintf(Buffer, "Windows"); + return Buffer; +//#endif + } + } + + /* ----------------- 9x family ------------------ */ + + /* no info about Win95 SP1, Win95 OSR2.1, Win95 OSR2.5.... */ + if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 950) { + sprintf(Buffer,"Win 95"); + } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1111) { + sprintf(Buffer,"Win 95 OSR2.x"); + + /* no info about Win98 SP1.... */ + } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 1998) { + sprintf(Buffer,"Win 98"); + } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 2222) { + sprintf(Buffer,"Win 98 SE"); + + } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 90 && Ver.dwBuildNumber == 3000) { + sprintf(Buffer,"Win ME"); + + /* ---------------- NT family ------------------- */ + + } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1381) { + sprintf(Buffer,"Win NT 4.0"); + + } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 2195) { + sprintf(Buffer,"Win 2000"); + + } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 1 && Ver.dwBuildNumber == 2600) { + sprintf(Buffer,"Win XP"); +#if _MSC_VER > 1200 //6.0 has it undeclared
+ if (Extended) { + if (Ver.wSuiteMask & VER_SUITE_PERSONAL) { + sprintf(Buffer+strlen(Buffer)," Home"); + } else { + sprintf(Buffer+strlen(Buffer)," Pro"); + } + }
+#endif + + } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 2) { + sprintf(Buffer,"Win 2003"); + + } else { + sprintf(Buffer, "Windows %i.%i.%i",Ver.dwMajorVersion,Ver.dwMinorVersion,Ver.dwBuildNumber); + } + + if (Extended && Ver.wServicePackMajor != 0) { + sprintf(Buffer+strlen(Buffer)," SP%i",Ver.wServicePackMajor); + } +#elif defined(linux) || defined(__linux) || defined(__linux__) + sprintf(Buffer, "Linux"); +#elif defined(__FreeBSD__) + sprintf(Buffer, "FreeBSD"); +#elif defined(__NetBSD__) + sprintf(Buffer, "NetBSD"); +#elif defined(__OpenBSD__) + sprintf(Buffer, "OpenBSD"); +#elif defined(__GNU__) + sprintf(Buffer, "GNU/Hurd"); +#elif defined(sun) || defined(__sun) || defined(__sun__) +# ifdef __SVR4 + sprintf(Buffer, "Sun Solaris"); +# else + sprintf(Buffer, "SunOS"); +# endif +#elif defined(hpux) || defined(__hpux) || defined(__hpux__) + sprintf(Buffer, "HP-UX"); +#elif defined(ultrix) || defined(__ultrix) || defined(__ultrix__) + sprintf(Buffer, "DEC Ultrix"); +#elif defined(sgi) || defined(__sgi) + sprintf(Buffer, "SGI Irix"); +#elif defined(__osf__) + sprintf(Buffer, "OSF Unix"); +#elif defined(bsdi) || defined(__bsdi__) + sprintf(Buffer, "BSDI Unix"); +#elif defined(_AIX) + sprintf(Buffer, "AIX Unix"); +#elif defined(_UNIXWARE) + sprintf(Buffer, "SCO Unixware"); +#elif defined(DGUX) + sprintf(Buffer, "DG Unix"); +#elif defined(__QNX__) + sprintf(Buffer, "QNX"); +#endif + return Buffer; +} + +char *GetCompiler(void) +{ + static char Buffer[100] = {0x00}; + +#ifdef WIN32 +# ifdef _MSC_VER + if (_MSC_VER == 1200) { //? + sprintf(Buffer, "MS VC 6.0"); + } else if (_MSC_VER == 1300) { + sprintf(Buffer, "MS VC .NET 2002"); + } else if (_MSC_VER == 1310) { + sprintf(Buffer, "MS VC .NET 2003"); + } else { + sprintf(Buffer, "MS VC %i",_MSC_VER); + } +# elif defined(__BORLANDC__) + sprintf(Buffer, "Borland C++ %i",__BORLANDC__); +# endif +#elif defined(DJGPP) + sprintf(Buffer, "djgpp"); +#elif defined(__GNUC__) + sprintf(Buffer, "gcc %i.%i", __GNUC__, __GNUC_MINOR__); +#elif defined(__SUNPRO_CC) + sprintf(Buffer, "Sun C++ %x", __SUNPRO_CC); +#endif + + return Buffer; +} + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ 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 @@ +/* (c) 2002-2004 by Marcin Wiacek */ + +#ifndef __misc_h +#define __misc_h + +#include <stdio.h> +#include <time.h> +#ifdef WIN32 +# include <windows.h> +#endif + +#include "../config.h" + +#ifndef __cplusplus +#ifndef false +# define false 0 +#endif +#ifndef true +# define true !0 +#endif +#ifndef bool +# define bool char +#endif +#endif /* __cplusplus */ + +#ifdef WIN32 +# define my_sleep(x) ((x)<1000 ? Sleep(1) : Sleep((x)/1000)) +#else +# define my_sleep(x) usleep(x) +#endif + +#undef MAX +#define MAX(a,b) ((a)>(b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a)<(b) ? (a) : (b)) + +/* ------------------------------------------------------------------------- */ + +#define MAX_LINES 50 + +int GetLine(FILE *File, char *Line, int count); + +typedef struct { + int numbers[MAX_LINES*2]; +} GSM_Lines; + +void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot); +char *GetLineString(unsigned char *message, GSM_Lines lines, int start); +void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start); + +/* ------------------------------------------------------------------------- */ + +typedef enum { + DL_BINARY = 1, /* Binary transmission dump */ + DL_TEXT, /* Text transmission dump */ + DL_TEXTALL, /* Everything */ + DL_TEXTERROR, /* Only errors */ + DL_TEXTDATE, /* Text transmission dump */ + DL_TEXTALLDATE, /* Everything */ + DL_TEXTERRORDATE /* Only errors */ +} Debug_Level; + +typedef struct { + Debug_Level dl; + FILE *df; + bool use_global; + char *coding; +} Debug_Info; + +extern Debug_Info di; + +#ifdef DEBUG +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif +int dbgprintf(const char *format, ...); +#else +# ifndef WIN32 +# define dbgprintf(a...) do { } while (0) +# else +# define dbgprintf +# endif +#endif + +#ifdef __GNUC__ +__attribute__((format(printf, 3, 4))) +#endif +int smfprintf(FILE *f, Debug_Level dl, const char *format, ...); + +void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize); + +bool GSM_SetDebugLevel(char *info, Debug_Info *di); + +/* ------------------------------------------------------------------------- */ + +/** + * Structure used for saving date and time + */ +typedef struct { + /** + * The difference between local time and GMT in hours + */ + int Timezone; + + unsigned int Second; + unsigned int Minute; + unsigned int Hour; + + unsigned int Day; + /** + * January = 1, February = 2, etc. + */ + unsigned int Month; + /** + * Complete year number. Not 03, but 2003 + */ + unsigned int Year; +} GSM_DateTime; + +void GSM_GetCurrentDateTime (GSM_DateTime *Date); +char *OSDateTime (GSM_DateTime dt, bool TimeZone); +char *OSDate (GSM_DateTime dt); +char *DayOfWeek (int year, int month, int day); +time_t Fill_Time_T (GSM_DateTime DT, int TZ); +void GetTimeDifference (unsigned long diff, GSM_DateTime *DT, bool Plus, int multi); +void Fill_GSM_DateTime (GSM_DateTime *Date, time_t timet); +bool CheckDate (GSM_DateTime *date); +bool CheckTime (GSM_DateTime *date); + +char *GetCompiler(void); +char *GetOS(void); + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ |