summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service/gsmpbk.c
Unidiff
Diffstat (limited to 'gammu/emb/common/service/gsmpbk.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/service/gsmpbk.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/gammu/emb/common/service/gsmpbk.c b/gammu/emb/common/service/gsmpbk.c
new file mode 100644
index 0000000..05e5cb9
--- a/dev/null
+++ b/gammu/emb/common/service/gsmpbk.c
@@ -0,0 +1,370 @@
1/* (c) 2001-2003 by Marcin Wiacek,... */
2
3#include <string.h>
4
5#include "../misc/coding/coding.h"
6#include "gsmpbk.h"
7#include "gsmmisc.h"
8
9unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry)
10{
11 /* We possibly store here "LastName, FirstName" so allocate enough memory */
12 static char dest[(GSM_PHONEBOOK_TEXT_LENGTH*2+2+1)*2];
13 static char split[] = { '\0', ',', '\0', ' ', '\0', '\0'};
14 int i;
15 int first = -1, last = -1, name = -1;
16 int len = 0;
17
18 for (i = 0; i < entry->EntriesNum; i++) {
19 switch (entry->Entries[i].EntryType) {
20 case PBK_Text_LastName:
21 last = i;
22 break;
23 case PBK_Text_FirstName:
24 first = i;
25 break;
26 case PBK_Text_Name:
27 name = i;
28 break;
29 default:
30 break;
31 }
32 }
33
34 if (name != -1) {
35 CopyUnicodeString(dest, entry->Entries[name].Text);
36 } else {
37 if (last != -1 && first != -1) {
38 len = UnicodeLength(entry->Entries[last].Text);
39 CopyUnicodeString(dest, entry->Entries[last].Text);
40 CopyUnicodeString(dest + 2*len, split);
41 CopyUnicodeString(dest + 2*len + 4, entry->Entries[first].Text);
42 } else if (last != -1) {
43 CopyUnicodeString(dest, entry->Entries[last].Text);
44 } else if (first != -1) {
45 CopyUnicodeString(dest, entry->Entries[first].Text);
46 } else {
47 return NULL;
48 }
49 }
50
51 return dest;
52}
53
54void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group)
55{
56 int i;
57
58 *Name = -1;
59 *Number = -1;
60 *Group = -1;
61 for (i = 0; i < entry->EntriesNum; i++) {
62 switch (entry->Entries[i].EntryType) {
63 case PBK_Number_General : if (*Number == -1) *Number = i; break;
64 case PBK_Text_Name : if (*Name == -1) *Name = i; break;
65 case PBK_Caller_Group : if (*Group == -1) *Group = i; break;
66 default : break;
67 }
68 }
69 if ((*Number) == -1) {
70 for (i = 0; i < entry->EntriesNum; i++) {
71 switch (entry->Entries[i].EntryType) {
72 case PBK_Number_Mobile:
73 case PBK_Number_Work:
74 case PBK_Number_Fax:
75 case PBK_Number_Home:
76 case PBK_Number_Pager:
77 case PBK_Number_Other:
78 *Number = i;
79 break;
80 default:
81 break;
82 }
83 if (*Number != -1) break;
84 }
85 }
86 if ((*Name) == -1) {
87 for (i = 0; i < entry->EntriesNum; i++) {
88 if (entry->Entries[i].EntryType != PBK_Text_LastName) continue;
89 *Name = i;
90 break;
91 }
92 }
93 if ((*Name) == -1) {
94 for (i = 0; i < entry->EntriesNum; i++) {
95 if (entry->Entries[i].EntryType != PBK_Text_FirstName) continue;
96 *Name = i;
97 break;
98 }
99 }
100}
101
102void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version)
103{
104 int Name, Number, Group, i;
105 bool ignore;
106
107 GSM_PhonebookFindDefaultNameNumberGroup(pbk, &Name, &Number, &Group);
108
109 if (Version == Nokia_VCard10) {
110 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%c",13,10);
111 if (Name != -1) {
112 *Length+=sprintf(Buffer+(*Length),"N:%s%c%c",DecodeUnicodeString(pbk->Entries[Name].Text),13,10);
113 }
114 if (Number != -1) {
115 *Length +=sprintf(Buffer+(*Length),"TEL:%s%c%c",DecodeUnicodeString(pbk->Entries[Number].Text),13,10);
116 }
117 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
118 } else if (Version == Nokia_VCard21) {
119 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%cVERSION:2.1%c%c",13,10,13,10);
120 if (Name != -1) {
121 SaveVCALText(Buffer, Length, pbk->Entries[Name].Text, "N");
122 }
123 for (i=0; i < pbk->EntriesNum; i++) {
124 if (i != Name) {
125 ignore = false;
126 switch(pbk->Entries[i].EntryType) {
127 case PBK_Text_Name :
128 case PBK_Date :
129 case PBK_Caller_Group :
130 ignore = true;
131 break;
132 case PBK_Number_General :
133 *Length+=sprintf(Buffer+(*Length),"TEL");
134 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
135 break;
136 case PBK_Number_Mobile :
137 *Length+=sprintf(Buffer+(*Length),"TEL");
138 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
139 *Length+=sprintf(Buffer+(*Length),";CELL");
140 break;
141 case PBK_Number_Work :
142 *Length+=sprintf(Buffer+(*Length),"TEL");
143 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
144 *Length+=sprintf(Buffer+(*Length),";WORK;VOICE");
145 break;
146 case PBK_Number_Fax :
147 *Length+=sprintf(Buffer+(*Length),"TEL");
148 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
149 *Length+=sprintf(Buffer+(*Length),";FAX");
150 break;
151 case PBK_Number_Home :
152 *Length+=sprintf(Buffer+(*Length),"TEL");
153 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
154 *Length+=sprintf(Buffer+(*Length),";HOME;VOICE");
155 break;
156 case PBK_Text_Note :
157 *Length+=sprintf(Buffer+(*Length),"NOTE");
158 break;
159 case PBK_Text_Postal :
160 /* Don't ask why. Nokia phones save postal address
161 * double - once like LABEL, second like ADR
162 */
163 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "LABEL");
164 *Length+=sprintf(Buffer+(*Length),"ADR");
165 break;
166 case PBK_Text_Email :
167 case PBK_Text_Email2 :
168 *Length+=sprintf(Buffer+(*Length),"EMAIL");
169 break;
170 case PBK_Text_URL :
171 *Length+=sprintf(Buffer+(*Length),"URL");
172 break;
173 default :
174 ignore = true;
175 break;
176 }
177 if (!ignore) {
178 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "");
179 }
180 }
181 }
182 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
183 }
184}
185
186GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version)
187{
188 unsigned char Line[2000],Buff[2000];
189 int Level = 0;
190
191 Buff[0] = 0;
192 Pbk->EntriesNum = 0;
193
194 while (1) {
195 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
196 if (strlen(Line) == 0) break;
197 switch (Level) {
198 case 0:
199 if (strstr(Line,"BEGIN:VCARD")) Level = 1;
200 break;
201 case 1:
202 if (strstr(Line,"END:VCARD")) {
203 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
204 return ERR_NONE;
205 }
206 if (ReadVCALText(Line, "N", Buff)) {
207 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
208 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
209 Pbk->EntriesNum++;
210 }
211 if (ReadVCALText(Line, "TEL", Buff) ||
212 ReadVCALText(Line, "TEL;VOICE", Buff) ||
213 ReadVCALText(Line, "TEL;PREF", Buff) ||
214 ReadVCALText(Line, "TEL;PREF;VOICE", Buff)) {
215 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
216 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
217 Pbk->EntriesNum++;
218 }
219 if (ReadVCALText(Line, "TEL;CELL", Buff) ||
220 ReadVCALText(Line, "TEL;CELL;VOICE", Buff) ||
221 ReadVCALText(Line, "TEL;PREF;CELL", Buff) ||
222 ReadVCALText(Line, "TEL;PREF;CELL;VOICE", Buff)) {
223 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
224 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
225 Pbk->EntriesNum++;
226 }
227 if (ReadVCALText(Line, "TEL;WORK", Buff) ||
228 ReadVCALText(Line, "TEL;PREF;WORK", Buff) ||
229 ReadVCALText(Line, "TEL;WORK;VOICE", Buff) ||
230 ReadVCALText(Line, "TEL;PREF;WORK;VOICE", Buff)) {
231 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
233 Pbk->EntriesNum++;
234 }
235 if (ReadVCALText(Line, "TEL;FAX", Buff) ||
236 ReadVCALText(Line, "TEL;PREF;FAX", Buff) ||
237 ReadVCALText(Line, "TEL;FAX;VOICE", Buff) ||
238 ReadVCALText(Line, "TEL;PREF;FAX;VOICE", Buff)) {
239 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
240 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
241 Pbk->EntriesNum++;
242 }
243 if (ReadVCALText(Line, "TEL;HOME", Buff) ||
244 ReadVCALText(Line, "TEL;PREF;HOME", Buff) ||
245 ReadVCALText(Line, "TEL;HOME;VOICE", Buff) ||
246 ReadVCALText(Line, "TEL;PREF;HOME;VOICE", Buff)) {
247 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
248 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
249 Pbk->EntriesNum++;
250 }
251 if (ReadVCALText(Line, "NOTE", Buff)) {
252 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
253 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
254 Pbk->EntriesNum++;
255 }
256 if (ReadVCALText(Line, "ADR", Buff)) {
257 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
258 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
259 Pbk->EntriesNum++;
260 }
261 if (ReadVCALText(Line, "EMAIL", Buff)) {
262 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
263 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
264 Pbk->EntriesNum++;
265 }
266 if (ReadVCALText(Line, "URL", Buff)) {
267 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
268 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
269 Pbk->EntriesNum++;
270 }
271 break;
272 }
273 }
274
275 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
276 return ERR_NONE;
277}
278
279/* -------------- OLD functions (c) by Timo Teras -------------------------- */
280
281#ifndef ENABLE_LGPL
282
283static void ParseVCardLine(char **pos, char *Name, char *Parameters, char *Value)
284{
285 int i;
286
287 Name[0] = Parameters[0] = Value[0] = 0;
288
289 if (**pos == 0) return;
290
291 for (i=0; **pos && **pos != ':' && **pos != ';'; i++, (*pos)++) Name[i] = **pos;
292 Name[i] = 0;
293
294 //dbgprintf("ParseVCardLine: name tag = '%s'\n", Name);
295 if (**pos == ';') {
296 (*pos)++;
297 for (i=0; **pos && **pos != ':'; i++, (*pos)++) Parameters[i] = **pos;
298 Parameters[i] = ';';
299 Parameters[i+1] = 0;
300 //dbgprintf("ParseVCardLine: parameter tag = '%s'\n", Parameters);
301 }
302
303 if (**pos != 0) (*pos)++;
304
305 i=0;
306 while (**pos) {
307 if ((*pos)[0] == '\x0d' && (*pos)[1] == '\x0a') {
308 (*pos) += 2;
309 if (**pos != '\t' && **pos != ' ') break;
310 while (**pos == '\t' || **pos == ' ') (*pos)++;
311 continue;
312 }
313 Value[i++] = **pos;
314 (*pos)++;
315 }
316 Value[i] = 0;
317
318 //dbgprintf("ParseVCardLine: value tag = '%s'\n", Value);
319}
320
321void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk)
322{
323 char *pos = VCard;
324 char Name[32], Parameters[256], Value[1024];
325
326 dbgprintf("Parsing VCard:\n%s\n", VCard);
327
328 ParseVCardLine(&pos, Name, Parameters, Value);
329 if (!mystrncasecmp(Name, "BEGIN", 0) || !mystrncasecmp(Value, "VCARD", 0)) {
330 dbgprintf("No valid VCARD signature\n");
331 return;
332 }
333
334 while (1) {
335 GSM_SubMemoryEntry *pbe = &pbk->Entries[pbk->EntriesNum];
336
337 ParseVCardLine(&pos, Name, Parameters, Value);
338 if (Name[0] == 0x00 ||
339 (mystrncasecmp(Name, "END", 0) && mystrncasecmp(Value, "VCARD", 0)))
340 return;
341
342 if (mystrncasecmp(Name, "N", 0)) {
343 //FIXME: Name is tagged field which should be parsed
344 pbe->EntryType = PBK_Text_Name;
345 EncodeUnicode(pbe->Text, Value, strlen(Value));
346 pbk->EntriesNum++;
347 } else if (mystrncasecmp(Name, "EMAIL", 0)) {
348 pbe->EntryType = PBK_Text_Email;
349 EncodeUnicode(pbe->Text, Value, strlen(Value));
350 pbk->EntriesNum++;
351 } else if (mystrncasecmp(Name, "TEL", 0)) {
352 if (strstr(Parameters, "WORK;"))
353 pbe->EntryType = PBK_Number_Work;
354 else if (strstr(Name, "HOME;"))
355 pbe->EntryType = PBK_Number_Home;
356 else if (strstr(Name, "FAX;"))
357 pbe->EntryType = PBK_Number_Fax;
358 else pbe->EntryType = PBK_Number_General;
359
360 EncodeUnicode(pbe->Text, Value, strlen(Value));
361 pbk->EntriesNum++;
362 }
363 }
364}
365
366#endif
367
368/* How should editor hadle tabs in this file? Add editor commands here.
369 * vim: noexpandtab sw=8 ts=8 sts=8:
370 */