Gammu internals  1.38.0
gsmpbk.c
Go to the documentation of this file.
1 /* (c) 2001-2005 by Marcin Wiacek, Michal Cihar... */
2 
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdarg.h>
6 #include <ctype.h>
7 
8 #include <gammu-misc.h>
9 #include <gammu-bitmap.h>
10 
11 #include "../misc/coding/coding.h"
12 #include "../debug.h"
13 #include "gsmpbk.h"
14 #include "gsmmisc.h"
15 
17  if (strcmp(s, "ME") == 0) return MEM_ME;
18  else if (strcmp(s, "SM") == 0) return MEM_SM;
19  else if (strcmp(s, "ON") == 0) return MEM_ON;
20  else if (strcmp(s, "DC") == 0) return MEM_DC;
21  else if (strcmp(s, "RC") == 0) return MEM_RC;
22  else if (strcmp(s, "MC") == 0) return MEM_MC;
23  else if (strcmp(s, "MT") == 0) return MEM_MT;
24  else if (strcmp(s, "FD") == 0) return MEM_FD;
25  else if (strcmp(s, "VM") == 0) return MEM_VM;
26  else if (strcmp(s, "SL") == 0) return MEM_SL;
27  else if (strcmp(s, "QD") == 0) return MEM_QD;
28  else {
29  return 0;
30  }
31 }
32 
33 unsigned char *GSM_PhonebookGetEntryName (const GSM_MemoryEntry *entry)
34 {
35  /* We possibly store here "LastName, FirstName" so allocate enough memory */
36  static char dest[(GSM_PHONEBOOK_TEXT_LENGTH*2+2+1)*2];
37  static char split[] = { '\0', ',', '\0', ' ', '\0', '\0'};
38  int i;
39  int first = -1, last = -1, name = -1;
40  int len = 0;
41 
42  for (i = 0; i < entry->EntriesNum; i++) {
43  switch (entry->Entries[i].EntryType) {
44  case PBK_Text_LastName:
45  last = i;
46  break;
47  case PBK_Text_FirstName:
48  first = i;
49  break;
50  case PBK_Text_Name:
51  name = i;
52  break;
53  default:
54  break;
55  }
56  }
57 
58  if (name != -1) {
59  CopyUnicodeString(dest, entry->Entries[name].Text);
60  } else {
61  if (last != -1 && first != -1) {
62  len = UnicodeLength(entry->Entries[last].Text);
63  CopyUnicodeString(dest, entry->Entries[last].Text);
64  CopyUnicodeString(dest + 2*len, split);
65  CopyUnicodeString(dest + 2*len + 4, entry->Entries[first].Text);
66  } else if (last != -1) {
67  CopyUnicodeString(dest, entry->Entries[last].Text);
68  } else if (first != -1) {
69  CopyUnicodeString(dest, entry->Entries[first].Text);
70  } else {
71  return NULL;
72  }
73  }
74 
75  return dest;
76 }
77 
78 void GSM_PhonebookFindDefaultNameNumberGroup(const GSM_MemoryEntry *entry, int *Name, int *Number, int *Group)
79 {
80  int i;
81 
82  *Name = -1;
83  *Number = -1;
84  *Group = -1;
85  for (i = 0; i < entry->EntriesNum; i++) {
86  switch (entry->Entries[i].EntryType) {
87  case PBK_Number_General : if (*Number == -1) *Number = i; break;
88  case PBK_Text_Name : if (*Name == -1) *Name = i; break;
89  case PBK_Caller_Group : if (*Group == -1) *Group = i; break;
90  default : break;
91  }
92  }
93  if ((*Number) == -1) {
94  for (i = 0; i < entry->EntriesNum; i++) {
95  switch (entry->Entries[i].EntryType) {
96  case PBK_Number_Mobile:
97  case PBK_Number_General:
98  case PBK_Number_Fax:
99  case PBK_Number_Pager:
100  case PBK_Number_Other:
101  *Number = i;
102  break;
103  default:
104  break;
105  }
106  if (*Number != -1) break;
107  }
108  }
109  if ((*Name) == -1) {
110  for (i = 0; i < entry->EntriesNum; i++) {
111  if (entry->Entries[i].EntryType != PBK_Text_LastName) continue;
112  *Name = i;
113  break;
114  }
115  }
116  if ((*Name) == -1) {
117  for (i = 0; i < entry->EntriesNum; i++) {
118  if (entry->Entries[i].EntryType != PBK_Text_FirstName) continue;
119  *Name = i;
120  break;
121  }
122  }
123 }
124 
125 
126 GSM_Error GSM_EncodeVCARD(GSM_Debug_Info *di, char *Buffer, const size_t buff_len, size_t *Length, GSM_MemoryEntry *pbk, const gboolean header, const GSM_VCardVersion Version)
127 {
128  int Name, Number, Group, i;
129  int firstname = -1, secondname = -1, lastname = -1;
130  int address = -1, city = -1, state = -1, zip = -1, country = -1;
131  int workaddress = -1, workcity = -1, workstate = -1, workzip = -1, workcountry = -1;
132  unsigned char buffer[1024];
133  int pos;
134  gboolean ignore;
135  GSM_Error error;
136  GSM_BinaryPicture *bitmap;
137 
138  GSM_PhonebookFindDefaultNameNumberGroup(pbk, &Name, &Number, &Group);
139 
140  if (header) {
141  error = VC_StoreLine(Buffer, buff_len, Length, "BEGIN:VCARD");
142  if (error != ERR_NONE) return error;
143  }
144  if (Version == Nokia_VCard10 || Version == SonyEricsson_VCard10) {
145  if (Name != -1) {
146  error = VC_StoreLine(Buffer, buff_len, Length, "N:%s",
147  DecodeUnicodeString(pbk->Entries[Name].Text));
148  if (error != ERR_NONE) return error;
149  }
150  if (Number != -1) {
151  error = VC_StoreLine(Buffer, buff_len, Length, "TEL:%s",
152  DecodeUnicodeString(pbk->Entries[Number].Text));
153  if (error != ERR_NONE) return error;
154  }
155  } else if (Version == Nokia_VCard21 || Version == SonyEricsson_VCard21_Phone || Version == SonyEricsson_VCard21) {
156  if (header) {
157  error = VC_StoreLine(Buffer, buff_len, Length, "VERSION:2.1");
158  if (error != ERR_NONE) return error;
159  }
160 
161  if (Version != SonyEricsson_VCard21_Phone) {
162  error = VC_StoreLine(Buffer, buff_len, Length, "X-GAMMU-LOCATION:%d", pbk->Location);
163  if (error != ERR_NONE) return error;
164 
165  error = VC_StoreLine(Buffer, buff_len, Length, "X-GAMMU-MEMORY:%s", GSM_MemoryTypeToString(pbk->MemoryType));
166  if (error != ERR_NONE) return error;
167  }
168 
169  for (i=0; i < pbk->EntriesNum; i++) {
170  ignore = FALSE;
171  pbk->Entries[i].AddError = ERR_NONE;
172  switch(pbk->Entries[i].EntryType) {
173  case PBK_Text_Name:
174  error = VC_Store(Buffer, buff_len, Length, "N");
175  if (error != ERR_NONE) return error;
176  break;
177  case PBK_Text_NickName:
178  error = VC_Store(Buffer, buff_len, Length, "NICKNAME");
179  if (error != ERR_NONE) return error;
180  break;
181  case PBK_Text_FormalName:
182  error = VC_Store(Buffer, buff_len, Length, "FN");
183  if (error != ERR_NONE) return error;
184  break;
185  case PBK_Text_NamePrefix:
186  error = VC_Store(Buffer, buff_len, Length, "X-NAME-PREFIX");
187  if (error != ERR_NONE) return error;
188  break;
189  case PBK_Text_NameSuffix:
190  error = VC_Store(Buffer, buff_len, Length, "X-NAME-SUFFIX");
191  if (error != ERR_NONE) return error;
192  break;
193  case PBK_Text_FirstName:
194  firstname = i;
195  ignore = TRUE;
196  break;
197  case PBK_Text_SecondName:
198  secondname = i;
199  ignore = TRUE;
200  break;
201  case PBK_Text_LastName:
202  lastname = i;
203  ignore = TRUE;
204  break;
206  if (pbk->Entries[i].Location == PBK_Location_Work) {
207  workaddress = i;
208  } else {
209  address = i;
210  }
211  ignore = TRUE;
212  break;
213  case PBK_Text_City:
214  if (pbk->Entries[i].Location == PBK_Location_Work) {
215  workcity = i;
216  } else {
217  city = i;
218  }
219  ignore = TRUE;
220  break;
221  case PBK_Text_State:
222  if (pbk->Entries[i].Location == PBK_Location_Work) {
223  workstate = i;
224  } else {
225  state = i;
226  }
227  ignore = TRUE;
228  break;
229  case PBK_Text_Zip:
230  if (pbk->Entries[i].Location == PBK_Location_Work) {
231  workzip = i;
232  } else {
233  zip = i;
234  }
235  ignore = TRUE;
236  break;
237  case PBK_Text_Country:
238  if (pbk->Entries[i].Location == PBK_Location_Work) {
239  workcountry = i;
240  } else {
241  country = i;
242  }
243  ignore = TRUE;
244  break;
245  case PBK_Date:
246  error = VC_StoreDate(Buffer, buff_len, Length, &(pbk->Entries[i].Date), "BDAY");
247  if (error != ERR_NONE) return error;
248  ignore = TRUE;
249  break;
250  case PBK_LastModified:
251  error = VC_StoreDateTime(Buffer, buff_len, Length, &(pbk->Entries[i].Date), "LAST-MODIFIED");
252  if (error != ERR_NONE) return error;
253  ignore = TRUE;
254  break;
255  case PBK_Number_General:
256  case PBK_Number_Video:
257  case PBK_Number_Other:
258  case PBK_Number_Pager:
259  case PBK_Number_Mobile :
260  case PBK_Number_Fax :
261  case PBK_Number_Messaging :
262  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
263  ignore = TRUE;
264  break;
265  }
266  error = VC_Store(Buffer, buff_len, Length, "TEL");
267  if (error != ERR_NONE) return error;
268 
269  if (Version != SonyEricsson_VCard21 && Number == i) {
270  error = VC_Store(Buffer, buff_len, Length, ";PREF");
271  if (error != ERR_NONE) return error;
272  }
273  switch (pbk->Entries[i].Location) {
274  case PBK_Location_Home:
275  error = VC_Store(Buffer, buff_len, Length, ";HOME");
276  if (error != ERR_NONE) return error;
277  break;
278  case PBK_Location_Work:
279  error = VC_Store(Buffer, buff_len, Length, ";WORK");
280  if (error != ERR_NONE) return error;
281  break;
283  break;
284  }
285  switch (pbk->Entries[i].EntryType) {
286  case PBK_Number_Other:
287  error = VC_Store(Buffer, buff_len, Length, ";OTHER");
288  if (error != ERR_NONE) return error;
289  break;
290  case PBK_Number_Pager:
291  error = VC_Store(Buffer, buff_len, Length, ";PAGER");
292  if (error != ERR_NONE) return error;
293  break;
294  case PBK_Number_Mobile:
295  error = VC_Store(Buffer, buff_len, Length, ";CELL");
296  if (error != ERR_NONE) return error;
297  break;
298  case PBK_Number_Fax:
299  error = VC_Store(Buffer, buff_len, Length, ";FAX");
300  if (error != ERR_NONE) return error;
301  break;
303  error = VC_Store(Buffer, buff_len, Length, ";MSG");
304  if (error != ERR_NONE) return error;
305  break;
306  case PBK_Number_Video:
307  error = VC_Store(Buffer, buff_len, Length, ";VIDEO");
308  if (error != ERR_NONE) return error;
309  break;
310  default:
311  break;
312  }
313  break;
314  case PBK_Text_Note :
315  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
316  ignore = TRUE;
317  break;
318  }
319  error = VC_Store(Buffer, buff_len, Length, "NOTE");
320  if (error != ERR_NONE) return error;
321  break;
322  case PBK_Text_Postal :
323  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
324  ignore = TRUE;
325  break;
326  }
327  /* Don't ask why. Nokia phones save postal address
328  * double - once like LABEL, second like ADR
329  */
330  error = VC_StoreText(Buffer, buff_len, Length, pbk->Entries[i].Text, "LABEL", FALSE);
331  if (error != ERR_NONE) return error;
332  if (pbk->Entries[i].Location == PBK_Location_Work) {
333  error = VC_Store(Buffer, buff_len, Length, "ADR;WORK");
334  } else if (pbk->Entries[i].Location == PBK_Location_Home) {
335  error = VC_Store(Buffer, buff_len, Length, "ADR;HOME");
336  } else {
337  error = VC_Store(Buffer, buff_len, Length, "ADR");
338  }
339  if (error != ERR_NONE) return error;
340  break;
341  case PBK_Text_Email :
342  case PBK_Text_Email2 :
343  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
344  ignore = TRUE;
345  break;
346  }
347  error = VC_Store(Buffer, buff_len, Length, "EMAIL");
348  if (error != ERR_NONE) return error;
349  break;
350  case PBK_Text_URL :
351  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
352  ignore = TRUE;
353  break;
354  }
355  error = VC_Store(Buffer, buff_len, Length, "URL");
356  if (error != ERR_NONE) return error;
357  break;
358  case PBK_Text_LUID :
359  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
360  ignore = TRUE;
361  break;
362  }
363  error = VC_Store(Buffer, buff_len, Length, "X-IRMC-LUID");
364  if (error != ERR_NONE) return error;
365  break;
366  case PBK_Text_VOIP :
367  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
368  ignore = TRUE;
369  break;
370  }
371  error = VC_Store(Buffer, buff_len, Length, "X-SIP;VOIP");
372  if (error != ERR_NONE) return error;
373  break;
374  case PBK_Text_SWIS :
375  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
376  ignore = TRUE;
377  break;
378  }
379  error = VC_Store(Buffer, buff_len, Length, "X-SIP;SWIS");
380  if (error != ERR_NONE) return error;
381  break;
382  case PBK_Text_WVID :
383  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
384  ignore = TRUE;
385  break;
386  }
387  error = VC_Store(Buffer, buff_len, Length, "X-WV-ID");
388  if (error != ERR_NONE) return error;
389  break;
390  case PBK_Text_SIP :
391  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
392  ignore = TRUE;
393  break;
394  }
395  error = VC_Store(Buffer, buff_len, Length, "X-SIP");
396  if (error != ERR_NONE) return error;
397  break;
398  case PBK_Text_DTMF :
399  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
400  ignore = TRUE;
401  break;
402  }
403  error = VC_Store(Buffer, buff_len, Length, "X-DTMF");
404  if (error != ERR_NONE) return error;
405  break;
406  case PBK_PushToTalkID:
407  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
408  ignore = TRUE;
409  break;
410  }
411  error = VC_Store(Buffer, buff_len, Length, "X-SIP;POC");
412  if (error != ERR_NONE) return error;
413  break;
414  case PBK_Text_JobTitle:
415  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
416  ignore = TRUE;
417  break;
418  }
419  error = VC_Store(Buffer, buff_len, Length, "TITLE");
420  if (error != ERR_NONE) return error;
421  break;
422  case PBK_Text_Company:
423  if (UnicodeLength(pbk->Entries[i].Text) == 0) {
424  ignore = TRUE;
425  break;
426  }
427  error = VC_Store(Buffer, buff_len, Length, "ORG");
428  if (error != ERR_NONE) return error;
429  break;
430  case PBK_Photo:
431  bitmap = &(pbk->Entries[i].Picture);
432  error = VC_Store(Buffer, buff_len, Length, "PHOTO;TYPE=");
433  if (error != ERR_NONE) return error;
434  switch (bitmap->Type) {
435  case PICTURE_BMP:
436  error = VC_Store(Buffer, buff_len, Length, "BMP;");
437  break;
438  case PICTURE_GIF:
439  error = VC_Store(Buffer, buff_len, Length, "GIF;");
440  break;
441  case PICTURE_JPG:
442  error = VC_Store(Buffer, buff_len, Length, "JPEG;");
443  break;
444  case PICTURE_ICN:
445  error = VC_Store(Buffer, buff_len, Length, "ICO;");
446  break;
447  case PICTURE_PNG:
448  error = VC_Store(Buffer, buff_len, Length, "PNG;");
449  break;
450  default:
451  smfprintf(di, "Unknown picture format: %d\n", bitmap->Type);
452  error = VC_Store(Buffer, buff_len, Length, "UNKNOWN;");
453  break;
454  }
455  if (error != ERR_NONE) return error;
456  error = VC_Store(Buffer, buff_len, Length, "ENCODING=BASE64:");
457  if (error != ERR_NONE) return error;
458  error = VC_StoreBase64(Buffer, buff_len, Length, bitmap->Buffer, bitmap->Length);
459  if (error != ERR_NONE) return error;
460  ignore = TRUE;
461  break;
462  case PBK_Caller_Group:
463  error = VC_StoreLine(Buffer, buff_len, Length, "X-CALLER-GROUP:%d", pbk->Entries[i].Number);
464  if (error != ERR_NONE) return error;
465  ignore = TRUE;
466  break;
467  case PBK_Private:
468  error = VC_StoreLine(Buffer, buff_len, Length, "X-PRIVATE:%d", pbk->Entries[i].Number);
469  if (error != ERR_NONE) return error;
470  ignore = TRUE;
471  break;
472  /* Not supported fields */
473  case PBK_Category:
474  case PBK_RingtoneID:
475  case PBK_PictureID:
476  case PBK_Text_UserID:
477  case PBK_CallLength:
478  case PBK_Text_Custom1:
479  case PBK_Text_Custom2:
480  case PBK_Text_Custom3:
481  case PBK_Text_Custom4:
484  ignore = TRUE;
485  break;
486  }
487  if (!ignore) {
488  error = VC_StoreText(Buffer, buff_len, Length, pbk->Entries[i].Text, "", FALSE);
489  if (error != ERR_NONE) return error;
490  }
491  }
492  /* Save name if it is composed from parts */
493  if (firstname != -1 || secondname != -1 || lastname != -1) {
494  pos = 0;
495  if (lastname != -1) {
496  CopyUnicodeString(buffer + 2*pos, pbk->Entries[lastname].Text);
497  pos += UnicodeLength(pbk->Entries[lastname].Text);
498  }
499  buffer[2*pos] = 0;
500  buffer[2*pos + 1] = ';';
501  pos++;
502  if (firstname != -1) {
503  CopyUnicodeString(buffer + 2*pos, pbk->Entries[firstname].Text);
504  pos += UnicodeLength(pbk->Entries[firstname].Text);
505  }
506  if (secondname != -1) {
507  buffer[2*pos] = 0;
508  buffer[2*pos + 1] = ' ';
509  pos++;
510  CopyUnicodeString(buffer + 2*pos, pbk->Entries[secondname].Text);
511  pos += UnicodeLength(pbk->Entries[secondname].Text);
512  }
513  buffer[2*pos] = 0;
514  buffer[2*pos + 1] = 0;
515  error = VC_StoreText(Buffer, buff_len, Length, buffer, "N", FALSE);
516  if (error != ERR_NONE) return error;
517  }
518  /* Save workaddress if it is composed from parts */
519  if (workaddress != -1 || workcity != -1 || workstate != -1 || workzip != -1 || workcountry != -1) {
520  pos = 0;
521  buffer[2*pos] = 0;
522  buffer[2*pos + 1] = ';';
523  pos++;
524  buffer[2*pos] = 0;
525  buffer[2*pos + 1] = ';';
526  pos++;
527  if (workaddress != -1) {
528  CopyUnicodeString(buffer + 2*pos, pbk->Entries[workaddress].Text);
529  pos += UnicodeLength(pbk->Entries[workaddress].Text);
530  }
531  buffer[2*pos] = 0;
532  buffer[2*pos + 1] = ';';
533  pos++;
534  if (workcity != -1) {
535  CopyUnicodeString(buffer + 2*pos, pbk->Entries[workcity].Text);
536  pos += UnicodeLength(pbk->Entries[workcity].Text);
537  }
538  buffer[2*pos] = 0;
539  buffer[2*pos + 1] = ';';
540  pos++;
541  if (workstate != -1) {
542  CopyUnicodeString(buffer + 2*pos, pbk->Entries[workstate].Text);
543  pos += UnicodeLength(pbk->Entries[workstate].Text);
544  }
545  buffer[2*pos] = 0;
546  buffer[2*pos + 1] = ';';
547  pos++;
548  if (workzip != -1) {
549  CopyUnicodeString(buffer + 2*pos, pbk->Entries[workzip].Text);
550  pos += UnicodeLength(pbk->Entries[workzip].Text);
551  }
552  buffer[2*pos] = 0;
553  buffer[2*pos + 1] = ';';
554  pos++;
555  if (workcountry != -1) {
556  CopyUnicodeString(buffer + 2*pos, pbk->Entries[workcountry].Text);
557  pos += UnicodeLength(pbk->Entries[workcountry].Text);
558  }
559  buffer[2*pos] = 0;
560  buffer[2*pos + 1] = 0;
561  error = VC_StoreText(Buffer, buff_len, Length, buffer, "ADR;WORK", FALSE);
562  if (error != ERR_NONE) return error;
563  }
564  /* Save address if it is composed from parts */
565  if (address != -1 || city != -1 || state != -1 || zip != -1 || country != -1) {
566  pos = 0;
567  buffer[2*pos] = 0;
568  buffer[2*pos + 1] = ';';
569  pos++;
570  buffer[2*pos] = 0;
571  buffer[2*pos + 1] = ';';
572  pos++;
573  if (address != -1) {
574  CopyUnicodeString(buffer + 2*pos, pbk->Entries[address].Text);
575  pos += UnicodeLength(pbk->Entries[address].Text);
576  }
577  buffer[2*pos] = 0;
578  buffer[2*pos + 1] = ';';
579  pos++;
580  if (city != -1) {
581  CopyUnicodeString(buffer + 2*pos, pbk->Entries[city].Text);
582  pos += UnicodeLength(pbk->Entries[city].Text);
583  }
584  buffer[2*pos] = 0;
585  buffer[2*pos + 1] = ';';
586  pos++;
587  if (state != -1) {
588  CopyUnicodeString(buffer + 2*pos, pbk->Entries[state].Text);
589  pos += UnicodeLength(pbk->Entries[state].Text);
590  }
591  buffer[2*pos] = 0;
592  buffer[2*pos + 1] = ';';
593  pos++;
594  if (zip != -1) {
595  CopyUnicodeString(buffer + 2*pos, pbk->Entries[zip].Text);
596  pos += UnicodeLength(pbk->Entries[zip].Text);
597  }
598  buffer[2*pos] = 0;
599  buffer[2*pos + 1] = ';';
600  pos++;
601  if (country != -1) {
602  CopyUnicodeString(buffer + 2*pos, pbk->Entries[country].Text);
603  pos += UnicodeLength(pbk->Entries[country].Text);
604  }
605  buffer[2*pos] = 0;
606  buffer[2*pos + 1] = 0;
607  error = VC_StoreText(Buffer, buff_len, Length, buffer, "ADR;HOME", FALSE);
608  if (error != ERR_NONE) return error;
609  }
610  } else {
611  return ERR_NOTSUPPORTED;
612  }
613  if (header) {
614  error = VC_StoreLine(Buffer, buff_len, Length, "END:VCARD");
615  if (error != ERR_NONE) return error;
616  }
617  return ERR_NONE;
618 }
619 
620 void GSM_TweakInternationalNumber(unsigned char *Number, const GSM_NumberType numType)
621 {
622  /* Checks if International number needs to be corrected */
623  char* pos; /* current position in the buffer */
624  char buf[500]; /* Taken from DecodeUnicodeString(). How to get length of the encoded unicode string? There may be embedded 0s. */
625 
627  sprintf(buf+1,"%s",DecodeUnicodeString(Number)); /* leave 1 free char before the number, we'll need it */
628  /* International number may be without + (e.g. (Sony)Ericsson)
629  we can add it, but must handle numbers in the form:
630  NNNNNN N - any digit (char)
631  *code#NNNNNN any number of Ns
632  *[*]code*NNNNNN[...]
633  other combinations (like *code1*code2*number#)
634  will have to be added if found in real life
635  Or does somebody know the exact allowed syntax
636  from some standard?
637  */
638  pos=buf+1;
639  if (*pos=='*') { /* Code? Skip it. */
640  /* probably with code */
641  while (*pos=='*') { /* skip leading asterisks */
642  *(pos-1)=*pos; /* shift the chars by one */
643  pos++;
644  }
645  while ((*pos!='*')&&(*pos!='#')) { /* skip code - anything except * or # */
646  *(pos-1)=*pos;
647  pos++;
648  }
649  *(pos-1)=*pos; /* shift the last delimiter */
650  pos++;
651  }
652  /* check the guessed location, if + is correctly there */
653  if (*pos=='+') {
654  /* yes, just shift the rest of the string */
655  while (*pos) {
656  *(pos-1) = *pos;
657  pos++;
658  }
659  *(pos-1)=0; /* kill the last char, which now got doubled */
660  } else {
661  /* no, insert + and exit, no more shifting */
662  *(pos-1)='+';
663  }
664  EncodeUnicode(Number,buf,strlen(buf));
665  }
666 }
667 
668 
669 #define CHECK_NUM_ENTRIES { \
670  if (Pbk->EntriesNum >= GSM_PHONEBOOK_ENTRIES) { error = ERR_MOREMEMORY; goto vcard_done; } \
671  Pbk->Entries[Pbk->EntriesNum].AddError = ERR_NONE; \
672 }
673 
677 GSM_Error GSM_DecodeVCARD(GSM_Debug_Info *di, char *Buffer, size_t *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version)
678 {
679  char Buff[20000];
680  int Level = 0;
681  char *s;
682  int pos;
683  int version = 1;
684  GSM_Error error;
685  char *Line = NULL;
686  GSM_EntryLocation location;
687 
688  Buff[0] = 0;
689  Pbk->EntriesNum = 0;
690  if (Version != SonyEricsson_VCard21_Phone) {
691  Pbk->Location = 0;
692  Pbk->MemoryType = MEM_MT;
693  }
694 
695  while (1) {
696  free(Line);
697  Line = NULL;
698  error = GSM_GetVCSLine(&Line, Buffer, Pos, strlen(Buffer), TRUE);
699  if (error != ERR_NONE) goto vcard_done;
700  if (strlen(Line) == 0) break;
701  switch (Level) {
702  case 0:
703  if (strstr(Line,"BEGIN:VCARD")) Level = 1;
704  break;
705  case 1:
707  if (strstr(Line,"END:VCARD")) {
708  goto vcard_complete;
709  }
710  if (strstr(Line, "VERSION:") != NULL) {
711  version = atoi(Line + 8);
712  dbgprintf(di, "vCard version %d\n", version);
713  }
714  if (ReadVCALText(Line, "N", Buff, (version >= 3), NULL)) {
715  pos = 0;
716  s = VCALGetTextPart(Buff, &pos);
717  if (s == NULL) {
718  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
721  Pbk->EntriesNum++;
722  continue;
723  } else {
724  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
725  /* Skip empty name */
726  if (UnicodeLength(Pbk->Entries[Pbk->EntriesNum].Text) > 0) {
729  Pbk->EntriesNum++;
730  }
731 
732  s = VCALGetTextPart(Buff, &pos);
733  if (s == NULL) continue;
735  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
738  Pbk->EntriesNum++;
739  continue;
740  }
741  }
742  if (strncmp(Line, "PHOTO;JPEG;BASE64:", 18) == 0 ||
743  strncmp(Line, "PHOTO;BASE64;JPEG:", 18) == 0 ||
744  strncmp(Line, "PHOTO;TYPE=JPEG;BASE64:", 23) == 0 ||
745  strncmp(Line, "PHOTO;BASE64;TYPE=JPEG:", 23) == 0 ||
746  strncmp(Line, "PHOTO;TYPE=JPEG;ENCODING=BASE64:", 32) == 0 ||
747  strncmp(Line, "PHOTO;ENCODING=BASE64;TYPE=JPEG:", 32) == 0 ||
748  strncmp(Line, "PHOTO;JPEG;ENCODING=BASE64:", 27) == 0 ||
749  strncmp(Line, "PHOTO;ENCODING=BASE64;JPEG:", 27) == 0) {
750  /* Find : (it should be there we matched it above) */
751  s = strchr(Line, ':');
752  s++;
753  /* Skip whitespace */
754  while (isspace((int)*s) && *s) s++;
755 
756  Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Photo;
759 
760  /* We allocate here more memory than is actually required */
761  Pbk->Entries[Pbk->EntriesNum].Picture.Buffer = (unsigned char *)malloc(strlen(s));
762  if (Pbk->Entries[Pbk->EntriesNum].Picture.Buffer == NULL)
763  return ERR_MOREMEMORY;
764 
765  Pbk->Entries[Pbk->EntriesNum].Picture.Length =
766  DecodeBASE64(s, Pbk->Entries[Pbk->EntriesNum].Picture.Buffer, strlen(s));
767  Pbk->EntriesNum++;
768  continue;
769  }
770 
771  if (ReadVCALText(Line, "TEL", Buff, (version >= 3), &location) ||
772  ReadVCALText(Line, "TEL;VOICE", Buff, (version >= 3), &location) ||
773  ReadVCALText(Line, "TEL;MAIN", Buff, (version >= 3), &location)) {
774  if (Buff[1] == '+') {
776  }
777  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
779  Pbk->Entries[Pbk->EntriesNum].Location = location;
780  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
781  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
782  Pbk->EntriesNum++;
783  continue;
784  }
785  if (ReadVCALText(Line, "TEL;VIDEO", Buff, (version >= 3), &location)) {
786  if (Buff[1] == '+') {
788  }
789  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
791  Pbk->Entries[Pbk->EntriesNum].Location = location;
792  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
793  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
794  Pbk->EntriesNum++;
795  continue;
796  }
797  if (ReadVCALText(Line, "TEL;CELL", Buff, (version >= 3), &location) ||
798  ReadVCALText(Line, "TEL;CELL;VOICE", Buff, (version >= 3), &location)) {
799  if (Buff[1] == '+') {
801  }
802  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
804  Pbk->Entries[Pbk->EntriesNum].Location = location;
805  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
806  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
807  Pbk->EntriesNum++;
808  continue;
809  }
810  if (ReadVCALText(Line, "TEL;OTHER", Buff, (version >= 3), &location) ||
811  ReadVCALText(Line, "TEL;OTHER;VOICE", Buff, (version >= 3), &location)) {
812  if (Buff[1] == '+') {
814  }
815  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
817  Pbk->Entries[Pbk->EntriesNum].Location = location;
818  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
819  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
820  Pbk->EntriesNum++;
821  continue;
822  }
823  if (ReadVCALText(Line, "TEL;PAGER", Buff, (version >= 3), &location) ||
824  ReadVCALText(Line, "TEL;PAGER;VOICE", Buff, (version >= 3), &location)) {
825  if (Buff[1] == '+') {
827  }
828  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
830  Pbk->Entries[Pbk->EntriesNum].Location = location;
831  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
832  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
833  Pbk->EntriesNum++;
834  continue;
835  }
836  if (ReadVCALText(Line, "TEL;MSG", Buff, (version >= 3), &location) ||
837  ReadVCALText(Line, "TEL;MSG;VOICE", Buff, (version >= 3), &location)) {
838  if (Buff[1] == '+') {
840  }
841  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
843  Pbk->Entries[Pbk->EntriesNum].Location = location;
844  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
845  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
846  Pbk->EntriesNum++;
847  continue;
848  }
849  /* FAX + VOICE looks like nonsense */
850  if (ReadVCALText(Line, "TEL;FAX", Buff, (version >= 3), &location) ||
851  ReadVCALText(Line, "TEL;FAX;VOICE", Buff, (version >= 3), &location)) {
852  if (Buff[1] == '+') {
854  }
855  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
857  Pbk->Entries[Pbk->EntriesNum].Location = location;
858  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
859  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
860  Pbk->EntriesNum++;
861  continue;
862  }
863  if (ReadVCALText(Line, "TITLE", Buff, (version >= 3), &location)) {
864  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
866  Pbk->Entries[Pbk->EntriesNum].Location = location;
867  Pbk->EntriesNum++;
868  continue;
869  }
870  if (ReadVCALText(Line, "NOTE", Buff, (version >= 3), &location)) {
871  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
873  Pbk->Entries[Pbk->EntriesNum].Location = location;
874  Pbk->EntriesNum++;
875  continue;
876  }
877  if (ReadVCALText(Line, "LABEL", Buff, (version >= 3), &location) ||
878  ReadVCALText(Line, "ADR", Buff, (version >= 3), &location)) {
879  pos = 0;
880  s = VCALGetTextPart(Buff, &pos); /* PO box, ignore for now */
881  if (s == NULL) {
882  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
884  Pbk->Entries[Pbk->EntriesNum].Location = location;
885  Pbk->EntriesNum++;
886  continue;
887  } else {
888  s = VCALGetTextPart(Buff, &pos); /* Don't know ... */
889 
890  s = VCALGetTextPart(Buff, &pos);
891  if (s == NULL) continue;
892  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
894  Pbk->Entries[Pbk->EntriesNum].Location = location;
895  Pbk->EntriesNum++;
897 
898  s = VCALGetTextPart(Buff, &pos);
899  if (s == NULL) continue;
900  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
902  Pbk->Entries[Pbk->EntriesNum].Location = location;
903  Pbk->EntriesNum++;
905 
906  s = VCALGetTextPart(Buff, &pos);
907  if (s == NULL) continue;
908  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
910  Pbk->Entries[Pbk->EntriesNum].Location = location;
911  Pbk->EntriesNum++;
913 
914  s = VCALGetTextPart(Buff, &pos);
915  if (s == NULL) continue;
916  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
918  Pbk->Entries[Pbk->EntriesNum].Location = location;
919  Pbk->EntriesNum++;
921 
922  s = VCALGetTextPart(Buff, &pos);
923  if (s == NULL) continue;
924  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s);
926  Pbk->Entries[Pbk->EntriesNum].Location = location;
927  Pbk->EntriesNum++;
928  continue;
929  }
930  }
931  if (ReadVCALText(Line, "EMAIL", Buff, (version >= 3), &location) ||
932  ReadVCALText(Line, "EMAIL;OTHER", Buff, (version >= 3), &location) ||
933  ReadVCALText(Line, "EMAIL;INTERNET", Buff, (version >= 3), &location)) {
934  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
936  Pbk->Entries[Pbk->EntriesNum].Location = location;
937  Pbk->EntriesNum++;
938  continue;
939  }
940  if (ReadVCALText(Line, "X-IRMC-LUID", Buff, (version >= 3), &location)) {
941  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
943  Pbk->Entries[Pbk->EntriesNum].Location = location;
944  Pbk->EntriesNum++;
945  continue;
946  }
947  if (ReadVCALText(Line, "X-DTMF", Buff, (version >= 3), &location)) {
948  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
950  Pbk->Entries[Pbk->EntriesNum].Location = location;
951  Pbk->EntriesNum++;
952  continue;
953  }
954  if (ReadVCALText(Line, "X-SIP", Buff, (version >= 3), &location)) {
955  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
957  Pbk->Entries[Pbk->EntriesNum].Location = location;
958  Pbk->EntriesNum++;
959  continue;
960  }
961  if (ReadVCALText(Line, "X-SIP;VOIP", Buff, (version >= 3), &location)) {
962  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
964  Pbk->Entries[Pbk->EntriesNum].Location = location;
965  Pbk->EntriesNum++;
966  continue;
967  }
968  if (ReadVCALText(Line, "X-WV-ID", Buff, (version >= 3), &location)) {
969  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
971  Pbk->Entries[Pbk->EntriesNum].Location = location;
972  Pbk->EntriesNum++;
973  continue;
974  }
975  if (ReadVCALText(Line, "X-SIP;SWIS", Buff, (version >= 3), &location)) {
976  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
978  Pbk->Entries[Pbk->EntriesNum].Location = location;
979  Pbk->EntriesNum++;
980  continue;
981  }
982  if (ReadVCALText(Line, "X-SIP;POC", Buff, (version >= 3), &location)) {
983  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
985  Pbk->Entries[Pbk->EntriesNum].Location = location;
986  Pbk->EntriesNum++;
987  continue;
988  }
989  if (ReadVCALText(Line, "URL", Buff, (version >= 3), &location)) {
990  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
992  Pbk->Entries[Pbk->EntriesNum].Location = location;
993  Pbk->EntriesNum++;
994  continue;
995  }
996  if (ReadVCALText(Line, "ORG", Buff, (version >= 3), &location)) {
997  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
999  Pbk->Entries[Pbk->EntriesNum].Location = location;
1000  Pbk->EntriesNum++;
1001  continue;
1002  }
1003  if (ReadVCALText(Line, "NICKNAME", Buff, (version >= 3), &location)) {
1004  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
1006  Pbk->Entries[Pbk->EntriesNum].Location = location;
1007  Pbk->EntriesNum++;
1008  continue;
1009  }
1010  if (ReadVCALText(Line, "FN", Buff, (version >= 3), &location)) {
1011  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
1013  Pbk->Entries[Pbk->EntriesNum].Location = location;
1014  Pbk->EntriesNum++;
1015  continue;
1016  }
1017  if (ReadVCALText(Line, "X-NAME-PREFIX", Buff, (version >= 3), &location)) {
1018  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
1020  Pbk->Entries[Pbk->EntriesNum].Location = location;
1021  Pbk->EntriesNum++;
1022  continue;
1023  }
1024  if (ReadVCALText(Line, "X-NAME-SUFFIX", Buff, (version >= 3), &location)) {
1025  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
1027  Pbk->Entries[Pbk->EntriesNum].Location = location;
1028  Pbk->EntriesNum++;
1029  continue;
1030  }
1031  if (ReadVCALText(Line, "CATEGORIES", Buff, (version >= 3), &location)) {
1032  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
1033  Pbk->Entries[Pbk->EntriesNum].Number = -1;
1035  Pbk->Entries[Pbk->EntriesNum].Location = location;
1036  Pbk->EntriesNum++;
1037  continue;
1038  }
1039  if (ReadVCALText(Line, "BDAY", Buff, (version >= 3), NULL)) {
1040  if (ReadVCALDateTime(DecodeUnicodeString(Buff), &Pbk->Entries[Pbk->EntriesNum].Date)) {
1041  Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Date;
1043  Pbk->EntriesNum++;
1044  continue;
1045  }
1046  }
1047  if (ReadVCALText(Line, "LAST-MODIFIED", Buff, (version >= 3), NULL)) {
1048  if (ReadVCALDateTime(DecodeUnicodeString(Buff), &Pbk->Entries[Pbk->EntriesNum].Date)) {
1051  Pbk->EntriesNum++;
1052  continue;
1053  }
1054  }
1055  if (ReadVCALText(Line, "X-PRIVATE", Buff, (version >= 3), NULL)) {
1056  Pbk->Entries[Pbk->EntriesNum].Number = atoi(DecodeUnicodeString(Buff));
1057  Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Private;
1059  Pbk->EntriesNum++;
1060  continue;
1061  }
1062  if (ReadVCALText(Line, "X-CALLER-GROUP", Buff, (version >= 3), NULL)) {
1063  Pbk->Entries[Pbk->EntriesNum].Number = atoi(DecodeUnicodeString(Buff));
1066  Pbk->EntriesNum++;
1067  continue;
1068  }
1069  if (ReadVCALText(Line, "X-GAMMU-LOCATION", Buff, (version >= 3), NULL)) {
1070  Pbk->Location = atoi(DecodeUnicodeString(Buff));
1071  }
1072  if (ReadVCALText(Line, "X-GAMMU-MEMORY", Buff, (version >= 3), NULL)) {
1074  }
1075  break;
1076  }
1077  }
1078 
1079 vcard_complete:
1080  if (Pbk->EntriesNum == 0) error = ERR_EMPTY;
1081  else error = ERR_NONE;
1082 
1083 vcard_done:
1084  free(Line);
1085  Line=NULL;
1086  return error;
1087 }
1088 
1090 {
1091  int i;
1092 
1093  for (i = 0; i < Entry->EntriesNum; i++) {
1094  switch (Entry->Entries[i].EntryType) {
1095  case PBK_Photo:
1096  free(Entry->Entries[i].Picture.Buffer);
1097  Entry->Entries[i].Picture.Buffer = NULL;
1098  Entry->Entries[i].Picture.Length = 0;
1099  break;
1100  default:
1101  break;
1102  }
1103  }
1104 }
1105 
1106 /* How should editor hadle tabs in this file? Add editor commands here.
1107  * vim: noexpandtab sw=8 ts=8 sts=8:
1108  */
void GSM_TweakInternationalNumber(unsigned char *Number, const GSM_NumberType numType)
Definition: gsmpbk.c:620
GSM_Error GSM_EncodeVCARD(GSM_Debug_Info *di, char *Buffer, const size_t buff_len, size_t *Length, GSM_MemoryEntry *pbk, const gboolean header, const GSM_VCardVersion Version)
Definition: gsmpbk.c:126
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void GSM_PhonebookFindDefaultNameNumberGroup(const GSM_MemoryEntry *entry, int *Name, int *Number, int *Group)
Definition: gsmpbk.c:78
unsigned char * VCALGetTextPart(unsigned char *Buff, int *pos)
Definition: gsmmisc.c:436
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
GSM_Error GSM_GetVCSLine(char **OutBuffer, char *Buffer, size_t *Pos, size_t MaxLen, gboolean MergeLines)
Definition: coding.c:1656
GSM_MemoryType MemoryType
Definition: gammu-memory.h:415
#define GSM_PHONEBOOK_TEXT_LENGTH
Definition: gammu-limits.h:91
GSM_EntryLocation
Definition: gammu-memory.h:348
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
GSM_Error
Definition: gammu-error.h:23
GSM_BinaryPicture_Types Type
Definition: gammu-bitmap.h:44
void GSM_FreeMemoryEntry(GSM_MemoryEntry *Entry)
Definition: gsmpbk.c:1089
unsigned char * Buffer
Definition: gammu-bitmap.h:45
#define GSM_MemoryTypeToString(x)
Definition: gammu-memory.h:95
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
#define CHECK_NUM_ENTRIES
Definition: gsmpbk.c:669
GSM_BinaryPicture Picture
Definition: gammu-memory.h:403
GSM_Error VC_StoreLine(char *Buffer, const size_t buff_len, size_t *Pos, const char *format,...)
Definition: gsmmisc.c:187
GSM_EntryType EntryType
Definition: gammu-memory.h:372
gboolean ReadVCALDateTime(const char *Buffer, GSM_DateTime *dt)
Definition: gsmmisc.c:254
GSM_Error VC_Store(char *Buffer, const size_t buff_len, size_t *Pos, const char *format,...)
Definition: gsmmisc.c:208
GSM_NumberType
Definition: coding.h:81
unsigned char Text[(GSM_PHONEBOOK_TEXT_LENGTH+1) *2]
Definition: gammu-memory.h:399
int gboolean
Definition: gammu-types.h:23
GSM_MemoryType
Definition: gammu-memory.h:31
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
#define FALSE
Definition: gammu-types.h:25
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
GSM_Error GSM_DecodeVCARD(GSM_Debug_Info *di, char *Buffer, size_t *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version)
Definition: gsmpbk.c:677
unsigned char * GSM_PhonebookGetEntryName(const GSM_MemoryEntry *entry)
Definition: gsmpbk.c:33
GSM_DateTime Date
Definition: gammu-memory.h:380
gboolean ReadVCALText(char *Buffer, const char *Start, unsigned char *Value, const gboolean UTF8, GSM_EntryLocation *location)
Definition: gsmmisc.c:468
#define dbgprintf
Definition: debug.h:72
GSM_EntryLocation Location
Definition: gammu-memory.h:376
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240
#define TRUE
Definition: gammu-types.h:28
GSM_VCardVersion
Definition: gammu-memory.h:602
GSM_MemoryType GSM_StringToMemoryType(const char *s)
Definition: gsmpbk.c:16
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
int DecodeBASE64(const char *Input, unsigned char *Output, const size_t Length)
Definition: coding.c:2149
GSM_SubMemoryEntry Entries[GSM_PHONEBOOK_ENTRIES]
Definition: gammu-memory.h:427