Imported gammu 0.90.7
[gammu.git] / common / service / gsmpbk.c
blobf07199e1f030f76d4f6bdcffca6098c1504d6f44
2 #include <string.h>
4 #include "../misc/coding/coding.h"
5 #include "gsmpbk.h"
6 #include "gsmmisc.h"
8 unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry)
10 /* We possibly store here "LastName, FirstName" so allocate enough memory */
11 static char dest[(GSM_PHONEBOOK_TEXT_LENGTH*2+2+1)*2];
12 static char split[] = { '\0', ',', '\0', ' ', '\0', '\0'};
13 int i;
14 int first = -1, last = -1, name = -1;
15 int len = 0;
17 for (i = 0; i < entry->EntriesNum; i++) {
18 switch (entry->Entries[i].EntryType) {
19 case PBK_Text_LastName:
20 last = i;
21 break;
22 case PBK_Text_FirstName:
23 first = i;
24 break;
25 case PBK_Text_Name:
26 name = i;
27 break;
28 default:
29 break;
33 if (name != -1) {
34 CopyUnicodeString(dest, entry->Entries[name].Text);
35 } else {
36 if (last != -1 && first != -1) {
37 len = UnicodeLength(entry->Entries[last].Text);
38 CopyUnicodeString(dest, entry->Entries[last].Text);
39 CopyUnicodeString(dest + 2*len, split);
40 CopyUnicodeString(dest + 2*len + 4, entry->Entries[first].Text);
41 } else if (last != -1) {
42 CopyUnicodeString(dest, entry->Entries[last].Text);
43 } else if (first != -1) {
44 CopyUnicodeString(dest, entry->Entries[first].Text);
45 } else {
46 return NULL;
50 return dest;
53 void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group)
55 int i;
57 *Name = -1;
58 *Number = -1;
59 *Group = -1;
60 for (i = 0; i < entry->EntriesNum; i++) {
61 switch (entry->Entries[i].EntryType) {
62 case PBK_Number_General : if (*Number == -1) *Number = i; break;
63 case PBK_Text_Name : if (*Name == -1) *Name = i; break;
64 case PBK_Caller_Group : if (*Group == -1) *Group = i; break;
65 default : break;
68 if ((*Number) == -1) {
69 for (i = 0; i < entry->EntriesNum; i++) {
70 switch (entry->Entries[i].EntryType) {
71 case PBK_Number_Mobile:
72 case PBK_Number_Work:
73 case PBK_Number_Fax:
74 case PBK_Number_Home:
75 case PBK_Number_Pager:
76 case PBK_Number_Other:
77 if (*Number == -1) *Number = i;
78 break;
79 default:
80 break;
84 if ((*Name) == -1) {
85 for (i = 0; i < entry->EntriesNum; i++) {
86 switch (entry->Entries[i].EntryType) {
87 case PBK_Text_LastName:
88 if (*Name == -1) *Name = i;
89 break;
90 default:
91 break;
95 if ((*Name) == -1) {
96 for (i = 0; i < entry->EntriesNum; i++) {
97 switch (entry->Entries[i].EntryType) {
98 case PBK_Text_FirstName:
99 if (*Name == -1) *Name = i;
100 break;
101 default:
102 break;
108 void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version)
110 int Name, Number, Group, i;
111 bool ignore;
113 GSM_PhonebookFindDefaultNameNumberGroup(pbk, &Name, &Number, &Group);
115 if (Version == Nokia_VCard10) {
116 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%c",13,10);
117 if (Name != -1) {
118 *Length+=sprintf(Buffer+(*Length),"N:%s%c%c",DecodeUnicodeString(pbk->Entries[Name].Text),13,10);
120 if (Number != -1) {
121 *Length +=sprintf(Buffer+(*Length),"TEL:%s%c%c",DecodeUnicodeString(pbk->Entries[Number].Text),13,10);
123 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
124 } else if (Version == Nokia_VCard21) {
125 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%cVERSION:2.1%c%c",13,10,13,10);
126 if (Name != -1) {
127 SaveVCALText(Buffer, Length, pbk->Entries[Name].Text, "N");
129 for (i=0; i < pbk->EntriesNum; i++) {
130 if (i != Name) {
131 ignore = false;
132 switch(pbk->Entries[i].EntryType) {
133 case PBK_Text_Name :
134 case PBK_Date :
135 case PBK_Caller_Group :
136 ignore = true;
137 break;
138 case PBK_Number_General :
139 *Length+=sprintf(Buffer+(*Length),"TEL");
140 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
141 break;
142 case PBK_Number_Mobile :
143 *Length+=sprintf(Buffer+(*Length),"TEL");
144 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
145 *Length+=sprintf(Buffer+(*Length),";CELL");
146 break;
147 case PBK_Number_Work :
148 *Length+=sprintf(Buffer+(*Length),"TEL");
149 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
150 *Length+=sprintf(Buffer+(*Length),";WORK;VOICE");
151 break;
152 case PBK_Number_Fax :
153 *Length+=sprintf(Buffer+(*Length),"TEL");
154 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
155 *Length+=sprintf(Buffer+(*Length),";FAX");
156 break;
157 case PBK_Number_Home :
158 *Length+=sprintf(Buffer+(*Length),"TEL");
159 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
160 *Length+=sprintf(Buffer+(*Length),";HOME;VOICE");
161 break;
162 case PBK_Text_Note :
163 *Length+=sprintf(Buffer+(*Length),"NOTE");
164 break;
165 case PBK_Text_Postal :
166 /* Don't ask why. Nokia phones save postal address
167 * double - once like LABEL, second like ADR
169 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "LABEL");
170 *Length+=sprintf(Buffer+(*Length),"ADR");
171 break;
172 case PBK_Text_Email :
173 case PBK_Text_Email2 :
174 *Length+=sprintf(Buffer+(*Length),"EMAIL");
175 break;
176 case PBK_Text_URL :
177 *Length+=sprintf(Buffer+(*Length),"URL");
178 break;
179 default :
180 ignore = true;
181 break;
183 if (!ignore) {
184 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "");
188 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
192 GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version)
194 unsigned char Line[2000],Buff[2000];
195 int Level = 0;
197 Buff[0] = 0;
198 Pbk->EntriesNum = 0;
200 while (1) {
201 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
202 if (strlen(Line) == 0) break;
203 switch (Level) {
204 case 0:
205 if (strstr(Line,"BEGIN:VCARD")) Level = 1;
206 break;
207 case 1:
208 if (strstr(Line,"END:VCARD")) {
209 if (Pbk->EntriesNum == 0) return GE_EMPTY;
210 return GE_NONE;
212 if (ReadVCALText(Line, "N", Buff)) {
213 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
214 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
215 Pbk->EntriesNum++;
217 if (ReadVCALText(Line, "TEL", Buff) ||
218 ReadVCALText(Line, "TEL;VOICE", Buff) ||
219 ReadVCALText(Line, "TEL;PREF", Buff) ||
220 ReadVCALText(Line, "TEL;PREF;VOICE", Buff)) {
221 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
222 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
223 Pbk->EntriesNum++;
225 if (ReadVCALText(Line, "TEL;CELL", Buff) ||
226 ReadVCALText(Line, "TEL;CELL;VOICE", Buff) ||
227 ReadVCALText(Line, "TEL;PREF;CELL", Buff) ||
228 ReadVCALText(Line, "TEL;PREF;CELL;VOICE", Buff)) {
229 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
230 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
231 Pbk->EntriesNum++;
233 if (ReadVCALText(Line, "TEL;WORK", Buff) ||
234 ReadVCALText(Line, "TEL;PREF;WORK", Buff) ||
235 ReadVCALText(Line, "TEL;WORK;VOICE", Buff) ||
236 ReadVCALText(Line, "TEL;PREF;WORK;VOICE", Buff)) {
237 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
238 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
239 Pbk->EntriesNum++;
241 if (ReadVCALText(Line, "TEL;FAX", Buff) ||
242 ReadVCALText(Line, "TEL;PREF;FAX", Buff) ||
243 ReadVCALText(Line, "TEL;FAX;VOICE", Buff) ||
244 ReadVCALText(Line, "TEL;PREF;FAX;VOICE", Buff)) {
245 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
246 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
247 Pbk->EntriesNum++;
249 if (ReadVCALText(Line, "TEL;HOME", Buff) ||
250 ReadVCALText(Line, "TEL;PREF;HOME", Buff) ||
251 ReadVCALText(Line, "TEL;HOME;VOICE", Buff) ||
252 ReadVCALText(Line, "TEL;PREF;HOME;VOICE", Buff)) {
253 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
254 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
255 Pbk->EntriesNum++;
257 if (ReadVCALText(Line, "NOTE", Buff)) {
258 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
259 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
260 Pbk->EntriesNum++;
262 if (ReadVCALText(Line, "ADR", Buff)) {
263 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
264 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
265 Pbk->EntriesNum++;
267 if (ReadVCALText(Line, "EMAIL", Buff)) {
268 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
269 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
270 Pbk->EntriesNum++;
272 if (ReadVCALText(Line, "URL", Buff)) {
273 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
274 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
275 Pbk->EntriesNum++;
277 break;
281 if (Pbk->EntriesNum == 0) return GE_EMPTY;
282 return GE_NONE;
285 /* -------------------------------- OLD ------------------------------------ */
287 static void ParseVCardLine(char **pos, char *Name, char *Parameters, char *Value)
289 int i;
291 Name[0] = Parameters[0] = Value[0] = 0;
293 if (**pos == 0) return;
295 for (i=0; **pos && **pos != ':' && **pos != ';'; i++, (*pos)++) Name[i] = **pos;
296 Name[i] = 0;
298 //dbgprintf("ParseVCardLine: name tag = '%s'\n", Name);
299 if (**pos == ';') {
300 (*pos)++;
301 for (i=0; **pos && **pos != ':'; i++, (*pos)++) Parameters[i] = **pos;
302 Parameters[i] = ';';
303 Parameters[i+1] = 0;
304 //dbgprintf("ParseVCardLine: parameter tag = '%s'\n", Parameters);
307 if (**pos != 0) (*pos)++;
309 i=0;
310 while (**pos) {
311 if ((*pos)[0] == '\x0d' && (*pos)[1] == '\x0a') {
312 (*pos) += 2;
313 if (**pos != '\t' && **pos != ' ') break;
314 while (**pos == '\t' || **pos == ' ') (*pos)++;
315 continue;
317 Value[i++] = **pos;
318 (*pos)++;
320 Value[i] = 0;
322 //dbgprintf("ParseVCardLine: value tag = '%s'\n", Value);
325 void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk)
327 char *pos = VCard;
328 char Name[32], Parameters[256], Value[1024];
330 dbgprintf("Parsing VCard:\n%s\n", VCard);
332 ParseVCardLine(&pos, Name, Parameters, Value);
333 if (!mystrncasecmp(Name, "BEGIN", 0) || !mystrncasecmp(Value, "VCARD", 0)) {
334 dbgprintf("No valid VCARD signature\n");
335 return;
338 while (1) {
339 GSM_SubMemoryEntry *pbe = &pbk->Entries[pbk->EntriesNum];
341 ParseVCardLine(&pos, Name, Parameters, Value);
342 if (Name[0] == 0x00 ||
343 (mystrncasecmp(Name, "END", 0) && mystrncasecmp(Value, "VCARD", 0)))
344 return;
346 if (mystrncasecmp(Name, "N", 0)) {
347 //FIXME: Name is tagged field which should be parsed
348 pbe->EntryType = PBK_Text_Name;
349 EncodeUnicode(pbe->Text, Value, strlen(Value));
350 pbk->EntriesNum++;
351 } else if (mystrncasecmp(Name, "EMAIL", 0)) {
352 pbe->EntryType = PBK_Text_Email;
353 EncodeUnicode(pbe->Text, Value, strlen(Value));
354 pbk->EntriesNum++;
355 } else if (mystrncasecmp(Name, "TEL", 0)) {
356 if (strstr(Parameters, "WORK;"))
357 pbe->EntryType = PBK_Number_Work;
358 else if (strstr(Name, "HOME;"))
359 pbe->EntryType = PBK_Number_Home;
360 else if (strstr(Name, "FAX;"))
361 pbe->EntryType = PBK_Number_Fax;
362 else pbe->EntryType = PBK_Number_General;
364 EncodeUnicode(pbe->Text, Value, strlen(Value));
365 pbk->EntriesNum++;
370 /* How should editor hadle tabs in this file? Add editor commands here.
371 * vim: noexpandtab sw=8 ts=8 sts=8: