Gammu internals  1.33.90
gsmmisc.c
Go to the documentation of this file.
1 /* (c) 2002-2005 by Marcin Wiacek and Michal Cihar */
2 
3 #include <gammu-config.h>
4 
5 #include <string.h>
6 #include <stdlib.h>
7 #include <sys/stat.h>
8 
9 #include <gammu-keys.h>
10 #include <gammu-debug.h>
11 
12 #include "../misc/coding/coding.h"
13 #include "../debug.h"
14 #include "gsmmisc.h"
15 
16 #include "../../helper/string.h"
17 
19  char whatchar;
20  int whatcode;
21 };
22 
23 static struct keys_table_position Keys[] = {
24  {'m',GSM_KEY_MENU}, {'M',GSM_KEY_MENU},
25  {'n',GSM_KEY_NAMES}, {'N',GSM_KEY_NAMES},
26  {'p',GSM_KEY_POWER}, {'P',GSM_KEY_POWER},
27  {'u',GSM_KEY_UP}, {'U',GSM_KEY_UP},
28  {'d',GSM_KEY_DOWN}, {'D',GSM_KEY_DOWN},
30  {'1',GSM_KEY_1}, {'2',GSM_KEY_2}, {'3',GSM_KEY_3},
31  {'4',GSM_KEY_4}, {'5',GSM_KEY_5}, {'6',GSM_KEY_6},
32  {'7',GSM_KEY_7}, {'8',GSM_KEY_8}, {'9',GSM_KEY_9},
33  {'*',GSM_KEY_ASTERISK}, {'0',GSM_KEY_0}, {'#',GSM_KEY_HASH},
34  {'g',GSM_KEY_GREEN}, {'G',GSM_KEY_GREEN},
35  {'r',GSM_KEY_RED}, {'R',GSM_KEY_RED},
36  {'<',GSM_KEY_LEFT}, {'>',GSM_KEY_RIGHT},
37  {'[',GSM_KEY_SOFT1}, {']',GSM_KEY_SOFT2},
38  {'h',GSM_KEY_HEADSET}, {'H',GSM_KEY_HEADSET},
39  {'c',GSM_KEY_CLEAR}, {'C',GSM_KEY_CLEAR},
41  {'f',GSM_KEY_CAMERA}, {'F',GSM_KEY_CAMERA},
43  {'m',GSM_KEY_MEDIA}, {'M',GSM_KEY_MEDIA},
44  {'d',GSM_KEY_DESKTOP}, {'D',GSM_KEY_DESKTOP},
45  {'@',GSM_KEY_RETURN},
46  {' ',0}
47 };
48 
49 GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, size_t *Length)
50 {
51  int i,j;
52  char key;
53 
54  for (i=0;i<(int)(strlen(text));i++) {
55  key = text[i];
56  KeyCode[i] = GSM_KEY_NONE;
57  j = 0;
58  while (Keys[j].whatchar!=' ') {
59  if (Keys[j].whatchar==key) {
60  KeyCode[i]=Keys[j].whatcode;
61  break;
62  }
63  j++;
64  }
65  if (KeyCode[i] == GSM_KEY_NONE) {
66  *Length = i;
67  return ERR_NOTSUPPORTED;
68  }
69  }
70  *Length = i;
71  return ERR_NONE;
72 }
73 
74 GSM_Error GSM_ReadFile(const char *FileName, GSM_File *File)
75 {
76  int i = 1000;
77  FILE *file;
78  struct stat fileinfo;
79 
80  if (FileName[0] == 0x00) return ERR_UNKNOWN;
81  file = fopen(FileName,"rb");
82  if (file == NULL) return ERR_CANTOPENFILE;
83 
84  free(File->Buffer);
85  File->Buffer = NULL;
86  File->Used = 0;
87  while (i == 1000) {
88  File->Buffer = (unsigned char *)realloc(File->Buffer,File->Used + 1000);
89  i = fread(File->Buffer+File->Used,1,1000,file);
90  File->Used = File->Used + i;
91  }
92  File->Buffer = (unsigned char *)realloc(File->Buffer,File->Used + 1);
93  /* Make it 0 terminated, in case it is needed somewhere (we don't count this to length) */
94  File->Buffer[File->Used] = 0;
95  fclose(file);
96 
97  File->Level = 0;
99  File->Protected = FALSE;
100  File->Hidden = FALSE;
101  File->System = FALSE;
102  File->ReadOnly = FALSE; /* @todo TODO get this from permissions? */
103  File->Folder = FALSE;
104 
105  File->ModifiedEmpty = TRUE;
106  if (stat(FileName,&fileinfo) == 0) {
107  File->ModifiedEmpty = FALSE;
108  dbgprintf(NULL, "File info read correctly\n");
109  /* st_mtime is time of last modification of file */
110  Fill_GSM_DateTime(&File->Modified, fileinfo.st_mtime);
111  dbgprintf(NULL, "FillTime: %s\n", OSDate(File->Modified));
112  }
113 
114  return ERR_NONE;
115 }
116 
117 static void GSM_JADFindLine(GSM_File *File, const char *Name, char *Value)
118 {
119  unsigned char Line[2000];
120  size_t Pos = 0;
121 
122  Value[0] = 0;
123 
124  while (1) {
125  if (MyGetLine(File->Buffer, &Pos, Line, File->Used, sizeof(Line), FALSE) != ERR_NONE) break;
126  if (strlen(Line) == 0) break;
127  if (!strncmp(Line,Name,strlen(Name))) {
128  Pos = strlen(Name);
129  while (Line[Pos] == 0x20) Pos++;
130  strcpy(Value,Line+Pos);
131  return;
132  }
133  }
134 }
135 
136 GSM_Error GSM_JADFindData(GSM_File *File, char *Vendor, char *Name, char *JAR, char *Version, int *Size)
137 {
138  char Size2[200];
139 
140  GSM_JADFindLine(File, "MIDlet-Vendor:", Vendor);
141  if (Vendor[0] == 0x00) return ERR_FILENOTSUPPORTED;
142  dbgprintf(NULL, "Vendor: \"%s\"\n",Vendor);
143 
144  GSM_JADFindLine(File, "MIDlet-Name:", Name);
145  if (Name[0] == 0x00) return ERR_FILENOTSUPPORTED;
146  dbgprintf(NULL, "Name: \"%s\"\n",Name);
147 
148  GSM_JADFindLine(File, "MIDlet-Jar-URL:", JAR);
149  if (JAR[0] == 0x00) return ERR_FILENOTSUPPORTED;
150  dbgprintf(NULL, "JAR file URL: \"%s\"\n",JAR);
151 
152  GSM_JADFindLine(File, "MIDlet-Jar-Size:", Size2);
153  *Size = -1;
154  if (Size2[0] == 0x00) return ERR_FILENOTSUPPORTED;
155  dbgprintf(NULL, "JAR size: \"%s\"\n",Size2);
156  (*Size) = atoi(Size2);
157 
158  GSM_JADFindLine(File, "MIDlet-Version:", Version);
159  dbgprintf(NULL, "Version: \"%s\"\n",Version);
160 
161  return ERR_NONE;
162 }
163 
165 {
166  File->Type = GSM_File_Other;
167  if (File->Used > 2) {
168  if (memcmp(File->Buffer, "BM",2)==0) {
169  File->Type = GSM_File_Image_BMP;
170  } else if (memcmp(File->Buffer, "GIF",3)==0) {
171  File->Type = GSM_File_Image_GIF;
172  } else if (File->Buffer[0] == 0x00 && File->Buffer[1] == 0x00) {
173  File->Type = GSM_File_Image_WBMP;
174  } else if (memcmp(File->Buffer+1, "PNG",3)==0) {
175  File->Type = GSM_File_Image_PNG;
176  } else if (File->Buffer[0] == 0xFF && File->Buffer[1] == 0xD8) {
177  File->Type = GSM_File_Image_JPG;
178  } else if (memcmp(File->Buffer, "MThd",4)==0) {
179  File->Type = GSM_File_Sound_MIDI;
180  } else if (File->Buffer[0] == 0x00 && File->Buffer[1] == 0x02) {
181  File->Type = GSM_File_Sound_NRT;
182  }
183  }
184 }
185 
186 PRINTF_STYLE(4, 5)
187 GSM_Error VC_StoreLine(char *Buffer, const size_t buff_len, size_t *Pos, const char *format, ...)
188 {
189  va_list argp;
190  int result;
191 
192  va_start(argp, format);
193  result = vsnprintf(Buffer + (*Pos), buff_len - *Pos - 1, format, argp);
194  va_end(argp);
195 
196  *Pos += result;
197  if (*Pos >= buff_len - 1) return ERR_MOREMEMORY;
198 
199  result = snprintf(Buffer + (*Pos), buff_len - *Pos - 1, "%c%c", 13, 10);
200 
201  *Pos += result;
202  if (*Pos >= buff_len - 1) return ERR_MOREMEMORY;
203 
204  return ERR_NONE;
205 }
206 
207 PRINTF_STYLE(4, 5)
208 GSM_Error VC_Store(char *Buffer, const size_t buff_len, size_t *Pos, const char *format, ...)
209 {
210  va_list argp;
211  int result;
212 
213  va_start(argp, format);
214  result = vsnprintf(Buffer + (*Pos), buff_len - *Pos - 1, format, argp);
215  va_end(argp);
216 
217  *Pos += result;
218  if (*Pos >= buff_len - 1) return ERR_MOREMEMORY;
219 
220  return ERR_NONE;
221 }
222 
223 
224 GSM_Error VC_StoreDateTime(char *Buffer, const size_t buff_len, size_t *Pos, const GSM_DateTime *Date, const char *Start)
225 {
226  GSM_Error error;
227 
228  if (Start != NULL) {
229  error = VC_Store(Buffer, buff_len, Pos, "%s:", Start);
230  if (error != ERR_NONE) return error;
231  }
232  error = VC_StoreLine(Buffer, buff_len, Pos,
233  "%04d%02d%02dT%02d%02d%02d%s",
234  Date->Year, Date->Month, Date->Day,
235  Date->Hour, Date->Minute, Date->Second,
236  Date->Timezone == 0 ? "Z" : "");
237  return error;
238 }
239 
240 GSM_Error VC_StoreDate(char *Buffer, const size_t buff_len, size_t *Pos, const GSM_DateTime *Date, const char *Start)
241 {
242  GSM_Error error;
243 
244  if (Start != NULL) {
245  error = VC_Store(Buffer, buff_len, Pos, "%s:", Start);
246  if (error != ERR_NONE) return error;
247  }
248  error = VC_StoreLine(Buffer, buff_len, Pos,
249  "%04d%02d%02d",
250  Date->Year, Date->Month, Date->Day);
251  return error;
252 }
253 
254 gboolean ReadVCALDateTime(const char *Buffer, GSM_DateTime *dt)
255 {
256  time_t timestamp;
257  char year[5]="", month[3]="", day[3]="", hour[3]="", minute[3]="", second[3]="";
258 
259  memset(dt,0,sizeof(GSM_DateTime));
260 
261  /* YYYY-MM-DD is invalid, though used */
262  if (sscanf(Buffer, "%d-%d-%d", &dt->Year, &dt->Month, &dt->Day) == 3) {
263  goto checkdt;
264  }
265 
266  if (strlen(Buffer) < 8) {
267  return FALSE;
268  }
269 
270  strncpy(year, Buffer, 4);
271  strncpy(month, Buffer+4, 2);
272  strncpy(day, Buffer+6, 2);
273  dt->Year = atoi(year);
274  dt->Month = atoi(month);
275  dt->Day = atoi(day);
276 
277  if (Buffer[8] == 'T') {
278  if (strlen(Buffer + 9) < 6) return FALSE;
279 
280  strncpy(hour, Buffer+9, 2);
281  strncpy(minute, Buffer+11, 2);
282  strncpy(second, Buffer+13, 2);
283  dt->Hour = atoi(hour);
284  dt->Minute = atoi(minute);
285  dt->Second = atoi(second);
286 
290  if (Buffer[15] == 'Z') dt->Timezone = 0; /* Z = ZULU = GMT */
291  }
292 checkdt:
293 
294  if (!CheckTime(dt)) {
295  dbgprintf(NULL, "incorrect date %d-%d-%d %d:%d:%d\n",dt->Day,dt->Month,dt->Year,dt->Hour,dt->Minute,dt->Second);
296  return FALSE;
297  }
298  if (dt->Year!=0) {
299  if (!CheckDate(dt)) {
300  dbgprintf(NULL, "incorrect date %d-%d-%d %d:%d:%d\n",dt->Day,dt->Month,dt->Year,dt->Hour,dt->Minute,dt->Second);
301  return FALSE;
302  }
303  }
304 
305  if (dt->Timezone != 0) {
306  timestamp = Fill_Time_T(*dt) + dt->Timezone;
307  Fill_GSM_DateTime(dt, timestamp);
308  }
309 
310  return TRUE;
311 }
312 
313 gboolean ReadVCALInt(char *Buffer, const char *Start, int *Value)
314 {
315  unsigned char buff[200];
316 
317  *Value = 0;
318 
319  strcpy(buff,Start);
320  strcat(buff,":");
321  if (!strncmp(Buffer,buff,strlen(buff))) {
322  int lstart = strlen(Start);
323  int lvalue = strlen(Buffer)-(lstart+1);
324  strncpy(buff,Buffer+lstart+1,lvalue);
325  strncpy(buff+lvalue,"\0",1);
326  if (sscanf(buff,"%i",Value)) {
327  dbgprintf(NULL, "ReadVCalInt is \"%i\"\n",*Value);
328  return TRUE;
329  }
330  }
331  return FALSE;
332 }
333 
334 
335 gboolean ReadVCALDate(char *Buffer, const char *Start, GSM_DateTime *Date, gboolean *is_date_only)
336 {
337  char fullstart[200];
338  unsigned char datestring[200];
339 
340  if (!ReadVCALText(Buffer, Start, datestring, FALSE, NULL)) {
341  fullstart[0] = 0;
342  strcat(fullstart, Start);
343  strcat(fullstart, ";VALUE=DATE");
344  if (!ReadVCALText(Buffer, fullstart, datestring, FALSE, NULL)) {
345  return FALSE;
346  }
347  *is_date_only = TRUE;
348  }
349 
350  if (ReadVCALDateTime(DecodeUnicodeString(datestring), Date)) {
351  dbgprintf(NULL, "ReadVCALDateTime is %s\n", OSDate(*Date));
352  *is_date_only = FALSE;
353  return TRUE;
354  }
355 
356  return FALSE;
357 }
358 
359 
360 GSM_Error VC_StoreText(char *Buffer, const size_t buff_len, size_t *Pos, const unsigned char *Text, const char *Start, const gboolean UTF8)
361 {
362  char *buffer=NULL;
363  size_t len=0;
364  GSM_Error error;
365 
366  len = UnicodeLength(Text);
367 
368  if (len == 0) return ERR_NONE;
369 
370  /* Need to be big enough to store quoted printable */
371  buffer = (char *)malloc(len * 8);
372  if (buffer == NULL) return ERR_MOREMEMORY;
373 
374  if (UTF8) {
375  EncodeUTF8(buffer, Text);
376  error = VC_StoreLine(Buffer, buff_len, Pos, "%s:%s", Start, buffer);
377  } else {
378  EncodeUTF8QuotedPrintable(buffer,Text);
379  if (UnicodeLength(Text) == strlen(buffer)) {
380  /* Text is plain ASCII */
381  error = VC_StoreLine(Buffer, buff_len, Pos, "%s:%s", Start, buffer);
382  } else {
383  error = VC_StoreLine(Buffer, buff_len, Pos, "%s;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:%s", Start, buffer);
384  }
385  }
386 
387  free(buffer);
388  buffer=NULL;
389  return error;
390 }
391 
392 GSM_Error VC_StoreBase64(char *Buffer, const size_t buff_len, size_t *Pos, const unsigned char *data, const size_t length)
393 {
394  char *buffer=NULL, *pos=NULL, linebuffer[80]={0};
395  size_t len=0, current=0;
396  char spacer[2]={0};
397  GSM_Error error;
398 
399  /*
400  * Need to be big enough to store base64 (what is *4/3, but *2 is safer
401  * and we don't have to care about rounding and padding).
402  */
403  buffer = (char *)malloc(length * 2);
404  if (buffer == NULL) return ERR_MOREMEMORY;
405 
406  spacer[0] = 0;
407  spacer[1] = 0;
408 
409 
410  EncodeBASE64(data, buffer, length);
411 
412  len = strlen(buffer);
413  pos = buffer;
414 
415  /* Write at most 76 chars per line */
416  while (len > 0) {
417  current = MIN(len, 76);
418  strncpy(linebuffer, pos, current);
419  linebuffer[current] = 0;
420  error = VC_StoreLine(Buffer, buff_len, Pos, "%s%s", spacer, linebuffer);
421  if (error != ERR_NONE) {
422  free(buffer);
423  buffer=NULL;
424  return error;
425  }
426  spacer[0] = ' ';
427  len -= current;
428  pos += current;
429  }
430 
431  free(buffer);
432  buffer=NULL;
433  return ERR_NONE;
434 }
435 
436 unsigned char *VCALGetTextPart(unsigned char *Buff, int *pos)
437 {
438  static unsigned char tmp[1000];
439  unsigned char *start;
440 
441  start = Buff + *pos;
442  while (Buff[*pos] != 0 || Buff[*pos + 1] != 0) {
443  if (Buff[*pos] == 0 && Buff[*pos + 1] == ';') {
444  Buff[*pos + 1] = 0;
445  CopyUnicodeString(tmp, start);
446  Buff[*pos + 1] = ';';
447  *pos += 2;
448  return tmp;
449  }
450  *pos += 2;
451  }
452  if (start == Buff || (start[0] == 0 && start[1] == 0)) return NULL;
453  CopyUnicodeString(tmp, start);
454  return tmp;
455 }
456 
468 gboolean ReadVCALText(char *Buffer, const char *Start, unsigned char *Value, const gboolean UTF8, GSM_EntryLocation *location)
469 {
470  char *line = NULL;
471  char **tokens = NULL;
472  char *charset = NULL;
473  char *begin, *pos, *end, *end2;
474  gboolean quoted_printable = FALSE;
475  size_t numtokens, token;
476  size_t i, j, len;
477  gboolean found;
478  gboolean ret = FALSE;
479 
480  /* Initialize output */
481  Value[0] = 0x00;
482  Value[1] = 0x00;
483 
484  /* Count number of tokens */
485  len = strlen(Start);
486  numtokens = 1;
487  for (i = 0; i < len; i++) {
488  if (Start[i] == ';') {
489  numtokens++;
490  }
491  }
492 
493  /* Allocate memory */
494  line = strdup(Start);
495  if (line == NULL) {
496  dbgprintf(NULL, "Could not alloc!\n");
497  goto fail;
498  }
499  tokens = (char **)malloc(sizeof(char *) * numtokens);
500  if (tokens == NULL) {
501  dbgprintf(NULL, "Could not alloc!\n");
502  goto fail;
503  }
504 
505  /* Parse Start to vCard tokens (separated by ;) */
506  token = 0;
507  begin = line;
508  for (i = 0; i < len; i++) {
509  if (line[i] == ';') {
510  tokens[token++] = begin;
511  begin = line + i + 1;
512  line[i] = 0;
513  }
514  }
515  /* Store last token */
516  tokens[token] = begin;
517 
518  /* Compare first token, it must be in place */
519  pos = Buffer;
520  len = strlen(tokens[0]);
521  if (strncasecmp(pos, tokens[0], len) != 0) {
522  goto fail;
523  }
524  /* Advance position */
525  pos += len;
526  /* No need to check this token anymore */
527  tokens[0][0] = 0;
528  /* Initialize location */
529  if (location != NULL) {
530  *location = PBK_Location_Unknown;
531  }
532 
533  /* Check remaining tokens */
534  while (*pos != ':') {
535  if (*pos == ';') {
536  pos++;
537  } else {
538  dbgprintf(NULL, "Could not parse! (stopped at string: %s)\n", pos);
539  goto fail;
540  }
541  found = FALSE;
542  for (token = 0; token < numtokens; token++) {
543  len = strlen(tokens[token]);
544  /* Skip already matched tokens */
545  if (len == 0) {
546  continue;
547  }
548  if (strncasecmp(pos, tokens[token], len) == 0) {
549  dbgprintf(NULL, "Found %s\n", tokens[token]);
550  /* Advance position */
551  pos += len;
552  /* We need to check one token less */
553  tokens[token][0] = 0;
554  found = TRUE;
555  break;
556  }
557  }
558  if (!found) {
559  if (strncasecmp(pos, "ENCODING=QUOTED-PRINTABLE", 25) == 0) {
560  quoted_printable = TRUE;
561  /* Advance position */
562  pos += 25;
563  found = TRUE;
564  } else if (strncasecmp(pos, "CHARSET=", 8) == 0) {
565  /* Advance position */
566  pos += 8;
567  /* Grab charset */
568  end = strchr(pos, ':');
569  end2 = strchr(pos, ';');
570  if (end == NULL && end2 == NULL) {
571  dbgprintf(NULL, "Could not read charset!\n");
572  goto fail;
573  } else if (end == NULL) {
574  end = end2;
575  } else if (end2 != NULL && end2 < end) {
576  end = end2;
577  }
578  /* We basically want strndup, but it is not portable */
579  charset = strdup(pos);
580  if (charset == NULL) {
581  dbgprintf(NULL, "Could not alloc!\n");
582  goto fail;
583  }
584  charset[end - pos] = 0;
585 
586  pos = end;
587  found = TRUE;
588  } else if (strncasecmp(pos, "TZID=", 5) == 0) {
589  /* @todo: We ignore time zone for now */
590  /* Advance position */
591  pos += 5;
592  /* Go behind value */
593  end = strchr(pos, ':');
594  end2 = strchr(pos, ';');
595  if (end == NULL && end2 == NULL) {
596  dbgprintf(NULL, "Could not read timezone!\n");
597  goto fail;
598  } else if (end == NULL) {
599  end = end2;
600  } else if (end2 != NULL && end2 < end) {
601  end = end2;
602  }
603  pos = end;
604  found = TRUE;
605  } else if (strncasecmp(pos, "TYPE=", 5) == 0) {
606  /* We ignore TYPE= prefix */
607  pos += 5;
608 
609  /* Now process types, which should be comma separated */
610  while (*pos != ':' && *pos != ';') {
611  found = FALSE;
612 
613  /* Go through tokens to match */
614  for (token = 0; token < numtokens; token++) {
615  len = strlen(tokens[token]);
616  /* Skip already matched tokens */
617  if (len == 0) {
618  continue;
619  }
620  if (strncasecmp(pos, tokens[token], len) == 0) {
621  dbgprintf(NULL, "Found %s\n", tokens[token]);
622  /* Advance position */
623  pos += len;
624  /* We need to check one token less */
625  tokens[token][0] = 0;
626  found = TRUE;
627  break;
628  }
629  }
630 
631  if (!found) {
632  if (strncasecmp(pos, "PREF", 4) == 0) {
633  /* We ignore pref token */
634  pos += 4;
635  found = TRUE;
636  } else if (strncasecmp(pos, "WORK", 4) == 0) {
637  /* We ignore work token */
638  pos += 4;
639  found = TRUE;
640  if (location != NULL) {
641  *location = PBK_Location_Work;
642  }
643  } else if (strncasecmp(pos, "HOME", 4) == 0) {
644  /* We ignore home token */
645  pos += 4;
646  found = TRUE;
647  if (location != NULL) {
648  *location = PBK_Location_Home;
649  }
650  } else {
651  dbgprintf(NULL, "%s not found! (%s)\n", Start, pos);
652  goto fail;
653  }
654  }
655 
656  if (*pos == ';' || *pos == ':') {
657  dbgprintf(NULL, "End of TYPE= string\n");
658  break;
659  } else if (*pos == ',') {
660  /* Advance past separator */
661  pos++;
662  } else {
663  dbgprintf(NULL, "Could not parse TYPE=! (stopped at string: %s)\n", pos);
664  goto fail;
665  }
666 
667  }
668  } else if (strncasecmp(pos, "PREF", 4) == 0) {
669  /* We ignore pref token */
670  pos += 4;
671  found = TRUE;
672  } else if (location && strncasecmp(pos, "WORK", 4) == 0) {
673  /* We ignore pref token */
674  pos += 4;
675  found = TRUE;
676  *location = PBK_Location_Work;
677  } else if (location && strncasecmp(pos, "HOME", 4) == 0) {
678  /* We ignore pref token */
679  pos += 4;
680  found = TRUE;
681  *location = PBK_Location_Home;
682  }
683  if (!found) {
684  dbgprintf(NULL, "%s not found!\n", Start);
685  goto fail;
686  }
687  }
688  }
689  /* Skip : */
690  pos++;
691  /* Length of rest */
692  len = strlen(pos);
693 
694  /* Did we match all our tokens? */
695  for (token = 0; token < numtokens; token++) {
696  if (strlen(tokens[token]) > 0) {
697  dbgprintf(NULL, "All tokens did not match!\n");
698  goto fail;
699  }
700  }
701 
702  /* Decode the text */
703  if (charset == NULL) {
704  if (quoted_printable) {
705  if (UTF8) {
706  DecodeUTF8QuotedPrintable(Value, pos, len);
707  } else {
708  DecodeISO88591QuotedPrintable(Value, pos, len);
709  }
710  } else {
711  if (UTF8) {
712  DecodeUTF8(Value, pos, len);
713  } else {
714  DecodeISO88591(Value, pos, len);
715  }
716  }
717  } else {
718  if (strcasecmp(charset, "UTF-8") == 0||
719  strcasecmp(charset, "\"UTF-8\"") == 0
720  ) {
721  if (quoted_printable) {
722  DecodeUTF8QuotedPrintable(Value, pos, len);
723  } else {
724  DecodeUTF8(Value, pos, len);
725  }
726  } else if (strcasecmp(charset, "UTF-7") == 0||
727  strcasecmp(charset, "\"UTF-7\"") == 0
728  ) {
729  if (quoted_printable) {
730  dbgprintf(NULL, "Unsupported charset: %s\n", charset);
731  goto fail;
732  } else {
733  DecodeUTF7(Value, pos, len);
734  }
735  } else {
736  dbgprintf(NULL, "Unsupported charset: %s\n", charset);
737  goto fail;
738  }
739  }
740 
741  /* Postprocess escaped chars */
742  len = UnicodeLength(Value);
743  for (i = 0; i < len; i++) {
744  if (Value[(2 * i)] == 0 && Value[(2 * i) + 1] == '\\') {
745  j = i + 1;
746  if (Value[(2 * j)] == 0 && (
747  Value[(2 * j) + 1] == 'n' ||
748  Value[(2 * j) + 1] == 'N')
749  ) {
750  Value[(2 * i) + 1] = '\n';
751  } else if (Value[(2 * j)] == 0 && (
752  Value[(2 * j) + 1] == 'r' ||
753  Value[(2 * j) + 1] == 'R')
754  ) {
755  Value[(2 * i) + 1] = '\r';
756  } else if (Value[(2 * j)] == 0 && Value[(2 * j) + 1] == '\\') {
757  Value[(2 * i) + 1] = '\\';
758  } else if (Value[(2 * j)] == 0 && Value[(2 * j) + 1] == ';') {
759  Value[(2 * i) + 1] = ';';
760  } else if (Value[(2 * j)] == 0 && Value[(2 * j) + 1] == ',') {
761  Value[(2 * i) + 1] = ',';
762  } else {
763  /* We ignore unknown for now */
764  continue;
765  }
766  /* Shift the string */
767  memmove(Value + (2 * j), Value + (2 * j) + 2, 2 * (len + 1 - j));
768  len--;
769  }
770  }
771 
772  ret = TRUE;
773  dbgprintf(NULL, "ReadVCalText(%s) is \"%s\"\n", Start, DecodeUnicodeConsole(Value));
774 fail:
775  free(line);
776  line=NULL;
777  free(tokens);
778  tokens=NULL;
779  free(charset);
780  charset=NULL;
781  return ret;
782 }
783 
785 {
786  bat->BatteryPercent = -1;
787  bat->ChargeState = 0;
788  bat->BatteryType = 0;
789  bat->BatteryVoltage = -1;
790  bat->ChargeVoltage = -1;
791  bat->ChargeCurrent = -1;
792  bat->PhoneCurrent = -1;
793  bat->BatteryTemperature = -1;
794  bat->PhoneTemperature = -1;
795  bat->BatteryCapacity = -1;
796 }
797 
798 /* How should editor hadle tabs in this file? Add editor commands here.
799  * vim: noexpandtab sw=8 ts=8 sts=8:
800  */
void DecodeUTF8QuotedPrintable(unsigned char *dest, const char *src, int len)
Definition: coding.c:1586
char * DecodeUnicodeConsole(const unsigned char *src)
Definition: coding.c:248
GSM_ChargeState ChargeState
Definition: gammu-info.h:240
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:237
unsigned char * VCALGetTextPart(unsigned char *Buff, int *pos)
Definition: gsmmisc.c:436
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:901
static struct keys_table_position Keys[]
Definition: gsmmisc.c:23
int Level
Definition: gammu-file.h:78
char * OSDate(GSM_DateTime dt)
Definition: misc.c:304
GSM_EntryLocation
Definition: gammu-memory.h:344
GSM_Error VC_StoreDateTime(char *Buffer, const size_t buff_len, size_t *Pos, const GSM_DateTime *Date, const char *Start)
Definition: gsmmisc.c:224
GSM_Error VC_StoreText(char *Buffer, const size_t buff_len, size_t *Pos, const unsigned char *Text, const char *Start, const gboolean UTF8)
Definition: gsmmisc.c:360
gboolean EncodeUTF8QuotedPrintable(char *dest, const unsigned char *src)
Definition: coding.c:1490
void EncodeBASE64(const unsigned char *Input, char *Output, const size_t Length)
Definition: coding.c:1791
GSM_Error
Definition: gammu-error.h:19
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
gboolean ReadVCALDate(char *Buffer, const char *Start, GSM_DateTime *Date, gboolean *is_date_only)
Definition: gsmmisc.c:335
gboolean Folder
Definition: gammu-file.h:74
gboolean ReadOnly
Definition: gammu-file.h:107
unsigned char * Buffer
Definition: gammu-file.h:90
#define PRINTF_STYLE(f, a)
Definition: gammu-misc.h:88
GSM_FileType Type
Definition: gammu-file.h:82
GSM_Error VC_StoreLine(char *Buffer, const size_t buff_len, size_t *Pos, const char *format,...)
Definition: gsmmisc.c:187
gboolean Protected
Definition: gammu-file.h:103
size_t Used
Definition: gammu-file.h:66
gboolean ReadVCALDateTime(const char *Buffer, GSM_DateTime *dt)
Definition: gsmmisc.c:254
gboolean System
Definition: gammu-file.h:115
void GSM_ClearBatteryCharge(GSM_BatteryCharge *bat)
Definition: gsmmisc.c:784
GSM_Error VC_Store(char *Buffer, const size_t buff_len, size_t *Pos, const char *format,...)
Definition: gsmmisc.c:208
static void GSM_JADFindLine(GSM_File *File, const char *Name, char *Value)
Definition: gsmmisc.c:117
void Fill_GSM_DateTime(GSM_DateTime *Date, time_t timet)
Definition: misc.c:168
int gboolean
Definition: gammu-types.h:19
gboolean ReadVCALInt(char *Buffer, const char *Start, int *Value)
Definition: gsmmisc.c:313
#define FALSE
Definition: gammu-types.h:21
GSM_Error VC_StoreBase64(char *Buffer, const size_t buff_len, size_t *Pos, const unsigned char *data, const size_t length)
Definition: gsmmisc.c:392
void DecodeISO88591(unsigned char *dest, const char *src, int len)
Definition: coding.c:274
void DecodeUTF8(unsigned char *dest, const char *src, int len)
Definition: coding.c:1621
GSM_DateTime Modified
Definition: gammu-file.h:94
void DecodeUTF7(unsigned char *dest, const unsigned char *src, int len)
Definition: coding.c:1724
gboolean CheckTime(GSM_DateTime *date)
Definition: misc.c:362
gboolean ModifiedEmpty
Definition: gammu-file.h:98
GSM_Error GSM_ReadFile(const char *FileName, GSM_File *File)
Definition: gsmmisc.c:74
gboolean ReadVCALText(char *Buffer, const char *Start, unsigned char *Value, const gboolean UTF8, GSM_EntryLocation *location)
Definition: gsmmisc.c:468
GSM_KeyCode
Definition: gammu-keys.h:26
#define dbgprintf
Definition: debug.h:72
time_t Fill_Time_T(GSM_DateTime DT)
Definition: misc.c:187
#define MIN(a, b)
Definition: gammu-misc.h:66
gboolean EncodeUTF8(char *dest, const unsigned char *src)
Definition: coding.c:1520
#define TRUE
Definition: gammu-types.h:24
void DecodeISO88591QuotedPrintable(unsigned char *dest, const unsigned char *src, int len)
Definition: coding.c:1564
void GSM_IdentifyFileFormat(GSM_File *File)
Definition: gsmmisc.c:164
gboolean CheckDate(GSM_DateTime *date)
Definition: misc.c:348
GSM_Error MyGetLine(char *Buffer, size_t *Pos, char *OutBuffer, size_t MaxLen, size_t MaxOutLen, gboolean MergeLines)
Definition: coding.c:1294
GSM_Error GSM_JADFindData(GSM_File *File, char *Vendor, char *Name, char *JAR, char *Version, int *Size)
Definition: gsmmisc.c:136
GSM_Error VC_StoreDate(char *Buffer, const size_t buff_len, size_t *Pos, const GSM_DateTime *Date, const char *Start)
Definition: gsmmisc.c:240
gboolean Hidden
Definition: gammu-file.h:111
GSM_BatteryType BatteryType
Definition: gammu-info.h:272
GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, size_t *Length)
Definition: gsmmisc.c:49