Gammu internals  1.38.0
backldif.c
Go to the documentation of this file.
1 /* (c) 2003-2004 by Marcin Wiacek */
2 
3 #include <string.h>
4 #include <ctype.h>
5 
6 #include <gammu-config.h>
7 
8 #include "../../misc/coding/coding.h"
9 #include "../../debug.h"
10 #include "../gsmlogo.h"
11 #include "../gsmmisc.h"
12 #include "backldif.h"
13 
14 #ifdef GSM_ENABLE_BACKUP
15 
16 static void SaveLDIFText(FILE *file, const char *Name, const unsigned char *Value)
17 {
18  unsigned char Buffer[1000],Buffer2[1000];
19 
20  if (EncodeUTF8(Buffer, Value)) {
21  EncodeBASE64(Buffer, Buffer2, strlen(Buffer));
22  fprintf(file,"%s:: %s%c%c",Name,Buffer2,13,10);
23  } else {
24  fprintf(file,"%s: %s%c%c",Name,DecodeUnicodeString(Value),13,10);
25  }
26 }
27 
28 GSM_Error SaveLDIF(const char *FileName, GSM_Backup *backup)
29 {
30  int i, j;
31  FILE *file;
32  gboolean had_dn = FALSE;
33  int firstname = -1, lastname = -1;
34  unsigned char Text[(GSM_PHONEBOOK_TEXT_LENGTH + 1) * 4];
35  size_t pos;
36 
37  file = fopen(FileName, "wb");
38  if (file == NULL) return ERR_CANTOPENFILE;
39 
40  i=0;
41  while (backup->PhonePhonebook[i]!=NULL) {
42  for (j=0;j<backup->PhonePhonebook[i]->EntriesNum;j++) {
43  switch (backup->PhonePhonebook[i]->Entries[j].EntryType) {
44  case PBK_Text_Name:
45  SaveLDIFText(file, "dn", backup->PhonePhonebook[i]->Entries[j].Text);
46  had_dn = TRUE;
47  break;
48  case PBK_Text_FirstName:
49  firstname = j;
50  break;
51  case PBK_Text_LastName:
52  lastname = j;
53  break;
54  default:
55  break;
56  }
57  }
58  /* Save name if it is composed from parts */
59  if (!had_dn && (firstname != -1 || lastname != -1)) {
60  pos = 0;
61 
62  if (firstname != -1) {
63  CopyUnicodeString(Text + 2 * pos, backup->PhonePhonebook[i]->Entries[firstname].Text);
64  pos += UnicodeLength(backup->PhonePhonebook[i]->Entries[firstname].Text);
65  }
66  Text[2*pos] = 0;
67  Text[2*pos + 1] = 0;
68  pos++;
69 
70  if (lastname != -1) {
71  if (firstname != -1) {
72  Text[2*(pos - 1) + 1] = ' ';
73  }
74  CopyUnicodeString(Text + 2 * pos, backup->PhonePhonebook[i]->Entries[lastname].Text);
75  pos += UnicodeLength(backup->PhonePhonebook[i]->Entries[lastname].Text);
76  }
77  Text[2*pos] = 0;
78  Text[2*pos + 1] = 0;
79 
80  SaveLDIFText(file, "dn", Text);
81  }
82  fprintf(file, "objectclass: top%c%c",13,10);
83  fprintf(file, "objectclass: person%c%c",13,10);
84  fprintf(file, "objectclass: organizationalPerson%c%c",13,10);
85  fprintf(file, "objectclass: inetOrgPerson%c%c",13,10);
86  fprintf(file, "objectclass: mozillaAbPersonObsolete%c%c",13,10);
87  for (j=0;j<backup->PhonePhonebook[i]->EntriesNum;j++) {
88  switch (backup->PhonePhonebook[i]->Entries[j].EntryType) {
89  case PBK_Text_Postal:
90  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Home) {
91  SaveLDIFText(file, "homePostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
92  } else if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
93  /* This does not conform to standard, but I think it's better to have it saved */
94  SaveLDIFText(file, "workPostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
95  } else {
96  SaveLDIFText(file, "postalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
97  }
98  break;
99  case PBK_Text_URL:
100  SaveLDIFText(file, "homeurl", backup->PhonePhonebook[i]->Entries[j].Text);
101  break;
102  case PBK_Text_Name:
103  /* Handled above */
104  break;
105  case PBK_Text_Note:
106  SaveLDIFText(file, "Description", backup->PhonePhonebook[i]->Entries[j].Text);
107  break;
108  case PBK_Number_Mobile:
109  SaveLDIFText(file, "mobile", backup->PhonePhonebook[i]->Entries[j].Text);
110  break;
111  case PBK_Number_Pager:
112  SaveLDIFText(file, "pager", backup->PhonePhonebook[i]->Entries[j].Text);
113  break;
115  SaveLDIFText(file, "messaging", backup->PhonePhonebook[i]->Entries[j].Text);
116  break;
117  case PBK_Number_Fax:
118  /* facsimileTelephoneNumber */
119  SaveLDIFText(file, "fax", backup->PhonePhonebook[i]->Entries[j].Text);
120  break;
121  case PBK_Number_General:
122  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Home) {
123  SaveLDIFText(file, "homePhone", backup->PhonePhonebook[i]->Entries[j].Text);
124  } else if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
125  /* not exist in Mozilla 1.4 win32 */
126  SaveLDIFText(file, "workPhone", backup->PhonePhonebook[i]->Entries[j].Text);
127  } else {
128  /* work in Mozilla 1.4 win32 */
129  SaveLDIFText(file, "telephoneNumber", backup->PhonePhonebook[i]->Entries[j].Text);
130  }
131  break;
132  case PBK_Text_Email:
133  SaveLDIFText(file, "mail", backup->PhonePhonebook[i]->Entries[j].Text);
134  break;
135  case PBK_Text_Email2:
136  SaveLDIFText(file, "mozillaSecondEmail", backup->PhonePhonebook[i]->Entries[j].Text);
137  break;
138  case PBK_Text_Custom1:
139  SaveLDIFText(file, "custom1", backup->PhonePhonebook[i]->Entries[j].Text);
140  break;
141  case PBK_Text_Custom2:
142  SaveLDIFText(file, "custom2", backup->PhonePhonebook[i]->Entries[j].Text);
143  break;
144  case PBK_Text_Custom3:
145  SaveLDIFText(file, "custom3", backup->PhonePhonebook[i]->Entries[j].Text);
146  break;
147  case PBK_Text_Custom4:
148  SaveLDIFText(file, "custom4", backup->PhonePhonebook[i]->Entries[j].Text);
149  break;
150  case PBK_Text_LUID:
151  SaveLDIFText(file, "luid", backup->PhonePhonebook[i]->Entries[j].Text);
152  break;
153  case PBK_Text_Company:
154  SaveLDIFText(file, "o", backup->PhonePhonebook[i]->Entries[j].Text);
155  break;
156  case PBK_Text_JobTitle:
157  SaveLDIFText(file, "title", backup->PhonePhonebook[i]->Entries[j].Text);
158  break;
160  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
161  SaveLDIFText(file, "workPostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
162  } else {
163  SaveLDIFText(file, "homePostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
164  }
165  break;
166  case PBK_Text_City:
167  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
168  SaveLDIFText(file, "workLocalityName", backup->PhonePhonebook[i]->Entries[j].Text);
169  } else {
170  SaveLDIFText(file, "mozillaHomeLocalityName", backup->PhonePhonebook[i]->Entries[j].Text);
171  }
172  break;
173  case PBK_Text_State:
174  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
175  SaveLDIFText(file, "workState", backup->PhonePhonebook[i]->Entries[j].Text);
176  } else {
177  SaveLDIFText(file, "mozillaHomeState", backup->PhonePhonebook[i]->Entries[j].Text);
178  }
179  break;
180  case PBK_Text_Zip:
181  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
182  SaveLDIFText(file, "workPostalCode", backup->PhonePhonebook[i]->Entries[j].Text);
183  } else {
184  SaveLDIFText(file, "mozillaHomePostalCode", backup->PhonePhonebook[i]->Entries[j].Text);
185  }
186  break;
187  case PBK_Text_Country:
188  if (backup->PhonePhonebook[i]->Entries[j].Location == PBK_Location_Work) {
189  SaveLDIFText(file, "workCountryName", backup->PhonePhonebook[i]->Entries[j].Text);
190  } else {
191  SaveLDIFText(file, "mozillaHomeCountryName", backup->PhonePhonebook[i]->Entries[j].Text);
192  }
193  break;
194  case PBK_Text_LastName:
195  SaveLDIFText(file, "sn", backup->PhonePhonebook[i]->Entries[j].Text);
196  break;
197  case PBK_Text_FirstName:
198  SaveLDIFText(file, "givenName", backup->PhonePhonebook[i]->Entries[j].Text);
199  break;
200  case PBK_Text_NickName:
201  SaveLDIFText(file, "nickname", backup->PhonePhonebook[i]->Entries[j].Text);
202  break;
203  case PBK_Text_SecondName:
204  SaveLDIFText(file, "nickname", backup->PhonePhonebook[i]->Entries[j].Text);
205  break;
206  case PBK_Text_FormalName:
207  SaveLDIFText(file, "cn", backup->PhonePhonebook[i]->Entries[j].Text);
208  break;
209  case PBK_Number_Other:
210  case PBK_Number_Video:
211  case PBK_Text_VOIP:
212  case PBK_Text_SIP:
213  case PBK_Text_DTMF:
214  case PBK_Text_SWIS:
215  case PBK_Text_WVID:
216  case PBK_Text_NamePrefix:
217  case PBK_Text_NameSuffix:
218  case PBK_Caller_Group:
219  case PBK_RingtoneID:
220  case PBK_PictureID:
221  case PBK_Date:
222  case PBK_LastModified:
223  case PBK_Text_UserID:
224  case PBK_Category:
225  case PBK_Private:
226  case PBK_CallLength:
228  case PBK_PushToTalkID:
229  case PBK_Photo:
230  dbgprintf(NULL, "Feature missed\n");
231  break;
232  }
233  }
234  fprintf(file, "%c%c",13,10);
235  i++;
236  }
237  fclose(file);
238  return ERR_NONE;
239 }
240 
241 static gboolean ReadLDIFText(const char *Buffer, const char *Start, char *Value)
242 {
243  unsigned char Buffer2[1000],buff[200];
244  int i;
245 
246  Value[0] = 0x00;
247 
248  strcpy(buff,Start);
249  strcat(buff,":: ");
250  if (!strncmp(Buffer,buff,strlen(buff))) {
251  i = DecodeBASE64(Buffer+strlen(Start)+3, Buffer2, strlen(Buffer)-(strlen(Start)+3));
252  dbgprintf(NULL, "Text after DecodeBASE64 is \"%s\"\n",Buffer2);
253  DecodeUTF8(Value, Buffer2, i);
254  dbgprintf(NULL, "Text after DecodeUTF8 is \"%s\"\n",DecodeUnicodeString(Value));
255  return TRUE;
256  }
257  strcpy(buff,Start);
258  strcat(buff,": ");
259  if (!strncmp(Buffer,buff,strlen(buff))) {
260  EncodeUnicode(Value,Buffer+strlen(Start)+2,strlen(Buffer)-(strlen(Start)+2));
261  dbgprintf(NULL, "Text after EncodeUnicode is \"%s\"\n",DecodeUnicodeString(Value));
262  return TRUE;
263  }
264  return FALSE;
265 }
266 
267 GSM_Error GSM_DecodeLDIFEntry(char *Buffer, size_t *Pos, GSM_MemoryEntry *Pbk)
268 {
269  unsigned char Line[2000],Buff[2000],Buff2[2000];
270  int Level = 0;
271  GSM_Error error;
272 
273  Buff[0] = 0;
274  Pbk->EntriesNum = 0;
275 
276  while (1) {
277  error = MyGetLine(Buffer, Pos, Line, strlen(Buffer), sizeof(Line), FALSE);
278  if (error != ERR_NONE) return error;
279  if (strlen(Line) == 0) break;
280  Pbk->Entries[Pbk->EntriesNum].AddError = ERR_NONE;
281  Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0;
282  Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
283  switch (Level) {
284  case 0:
285  if (ReadLDIFText(Line, "objectclass", Buff)) {
286  sprintf(Buff2,"%s",DecodeUnicodeString(Buff));
287  if (!strcmp("mozillaAbPersonObsolete",Buff2)) {
288  dbgprintf(NULL, "level1\n");
289  Level = 1;
290  }
291  }
292  break;
293  case 1:
294  if (ReadLDIFText(Line, "dn", Buff)) {
295  dbgprintf(NULL, "entries num is %i\n",Pbk->EntriesNum);
296  if (Pbk->EntriesNum == 0) return ERR_EMPTY;
297  return ERR_NONE;
298  }
299  if (ReadLDIFText(Line, "givenName", Buff)) {
300  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
303  Pbk->EntriesNum++;
304  }
305  if (ReadLDIFText(Line, "sn", Buff)) {
306  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
309  Pbk->EntriesNum++;
310  }
311  if (ReadLDIFText(Line, "telephoneNumber", Buff)) {
312  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
315  Pbk->EntriesNum++;
316  }
317  if (ReadLDIFText(Line, "mobile", Buff)) {
318  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
321  Pbk->EntriesNum++;
322  }
323  if (ReadLDIFText(Line, "pager", Buff)) {
324  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
327  Pbk->EntriesNum++;
328  }
329  if (ReadLDIFText(Line, "messaging", Buff)) {
330  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
333  Pbk->EntriesNum++;
334  }
335  if (ReadLDIFText(Line, "workPhone", Buff)) {
336  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
339  Pbk->EntriesNum++;
340  }
341  if (ReadLDIFText(Line, "fax", Buff)) {
342  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
345  Pbk->EntriesNum++;
346  }
347  if (ReadLDIFText(Line, "homePhone",Buff)) {
348  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
351  Pbk->EntriesNum++;
352  }
353  if (ReadLDIFText(Line, "Description", Buff)) {
354  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
357  Pbk->EntriesNum++;
358  }
359  if (ReadLDIFText(Line, "homePostalAddress", Buff)) {
360  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
363  Pbk->EntriesNum++;
364  }
365  if (ReadLDIFText(Line, "mozillaHomeLocalityName", Buff)) {
366  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
369  Pbk->EntriesNum++;
370  }
371  if (ReadLDIFText(Line, "mozillaHomeState", Buff)) {
372  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
375  Pbk->EntriesNum++;
376  }
377  if (ReadLDIFText(Line, "mozillaHomePostalCode", Buff)) {
378  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
381  Pbk->EntriesNum++;
382  }
383  if (ReadLDIFText(Line, "mozillaHomeCountryName", Buff)) {
384  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
387  Pbk->EntriesNum++;
388  }
389  if (ReadLDIFText(Line, "workPostalAddress", Buff)) {
390  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
393  Pbk->EntriesNum++;
394  }
395  if (ReadLDIFText(Line, "workLocalityName", Buff)) {
396  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
399  Pbk->EntriesNum++;
400  }
401  if (ReadLDIFText(Line, "workState", Buff)) {
402  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
405  Pbk->EntriesNum++;
406  }
407  if (ReadLDIFText(Line, "workPostalCode", Buff)) {
408  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
411  Pbk->EntriesNum++;
412  }
413  if (ReadLDIFText(Line, "workCountryName", Buff)) {
414  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
417  Pbk->EntriesNum++;
418  }
419  if (ReadLDIFText(Line, "mail", Buff)) {
420  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
423  Pbk->EntriesNum++;
424  }
425  if (ReadLDIFText(Line, "mozillaSecondEmail", Buff)) {
426  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
429  Pbk->EntriesNum++;
430  }
431  if (ReadLDIFText(Line, "homeurl", Buff)) {
432  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
435  Pbk->EntriesNum++;
436  }
437  if (ReadLDIFText(Line, "luid", Buff)) {
438  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
441  Pbk->EntriesNum++;
442  }
443  if (ReadLDIFText(Line, "custom1", Buff)) {
444  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
447  Pbk->EntriesNum++;
448  }
449  if (ReadLDIFText(Line, "custom2", Buff)) {
450  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
453  Pbk->EntriesNum++;
454  }
455  if (ReadLDIFText(Line, "custom3", Buff)) {
456  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
459  Pbk->EntriesNum++;
460  }
461  if (ReadLDIFText(Line, "custom4", Buff)) {
462  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
465  Pbk->EntriesNum++;
466  }
467  if (ReadLDIFText(Line, "o", Buff)) {
468  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
471  Pbk->EntriesNum++;
472  }
473  if (ReadLDIFText(Line, "title", Buff)) {
474  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
477  Pbk->EntriesNum++;
478  }
479  if (ReadLDIFText(Line, "nickname", Buff)) {
480  CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
483  Pbk->EntriesNum++;
484  }
485  break;
486  }
487  if (Pbk->EntriesNum >= GSM_PHONEBOOK_ENTRIES) {
488  return ERR_MOREMEMORY;
489  }
490  }
491 
492  dbgprintf(NULL, "entries num is %i\n",Pbk->EntriesNum);
493  if (Pbk->EntriesNum == 0) return ERR_EMPTY;
494  return ERR_NONE;
495 }
496 
497 GSM_Error LoadLDIF(const char *FileName, GSM_Backup *backup)
498 {
499  GSM_File File;
500  GSM_Error error;
501  GSM_MemoryEntry Pbk;
502  int numPbk = 0;
503  size_t Pos = 0;
504 
505  File.Buffer = NULL;
506  error = GSM_ReadFile(FileName, &File);
507  if (error != ERR_NONE) return error;
508 
509  while (1) {
510  error = GSM_DecodeLDIFEntry(File.Buffer, &Pos, &Pbk);
511  if (error == ERR_EMPTY) {
512  error = ERR_NONE;
513  break;
514  }
515  if (error != ERR_NONE) break;
516  if (numPbk < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
517  backup->PhonePhonebook[numPbk] = (GSM_MemoryEntry *)malloc(sizeof(GSM_MemoryEntry));
518  if (backup->PhonePhonebook[numPbk] == NULL) {
519  error = ERR_MOREMEMORY;
520  break;
521  }
522  backup->PhonePhonebook[numPbk + 1] = NULL;
523  } else {
524  dbgprintf(NULL, "Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
525  error = ERR_MOREMEMORY;
526  break;
527  }
528  memcpy(backup->PhonePhonebook[numPbk],&Pbk,sizeof(GSM_MemoryEntry));
529  backup->PhonePhonebook[numPbk]->Location = numPbk + 1;
530  backup->PhonePhonebook[numPbk]->MemoryType = MEM_ME;
531  numPbk++;
532  }
533 
534  free(File.Buffer);
535  File.Buffer=NULL;
536  return error;
537 }
538 
539 #endif
540 
541 /* How should editor hadle tabs in this file? Add editor commands here.
542  * vim: noexpandtab sw=8 ts=8 sts=8:
543  */
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
#define GSM_PHONEBOOK_TEXT_LENGTH
Definition: gammu-limits.h:91
#define GSM_PHONEBOOK_ENTRIES
Definition: gammu-limits.h:98
void EncodeBASE64(const unsigned char *Input, char *Output, const size_t Length)
Definition: coding.c:2118
GSM_Error
Definition: gammu-error.h:23
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
unsigned char * Buffer
Definition: gammu-file.h:94
GSM_EntryType EntryType
Definition: gammu-memory.h:372
unsigned char Text[(GSM_PHONEBOOK_TEXT_LENGTH+1) *2]
Definition: gammu-memory.h:399
int gboolean
Definition: gammu-types.h:23
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
#define FALSE
Definition: gammu-types.h:25
void DecodeUTF8(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:1947
GSM_Error GSM_ReadFile(const char *FileName, GSM_File *File)
Definition: gsmmisc.c:74
#define dbgprintf
Definition: debug.h:72
GSM_EntryLocation Location
Definition: gammu-memory.h:376
gboolean EncodeUTF8(char *dest, const unsigned char *src)
Definition: coding.c:1835
#define TRUE
Definition: gammu-types.h:28
GSM_Error MyGetLine(char *Buffer, size_t *Pos, char *OutBuffer, size_t MaxLen, size_t MaxOutLen, gboolean MergeLines)
Definition: coding.c:1580
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