/* (c) 2001-2005 by Marcin Wiacek, Michal Cihar... */ #include #include #include #include "../misc/coding/coding.h" #include "gsmpbk.h" #include "gsmmisc.h" unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry) { /* We possibly store here "LastName, FirstName" so allocate enough memory */ static char dest[(GSM_PHONEBOOK_TEXT_LENGTH*2+2+1)*2]; static char split[] = { '\0', ',', '\0', ' ', '\0', '\0'}; int i; int first = -1, last = -1, name = -1; int len = 0; for (i = 0; i < entry->EntriesNum; i++) { switch (entry->Entries[i].EntryType) { case PBK_Text_LastName: last = i; break; case PBK_Text_FirstName: first = i; break; case PBK_Text_Name: name = i; break; default: break; } } if (name != -1) { CopyUnicodeString(dest, entry->Entries[name].Text); } else { if (last != -1 && first != -1) { len = UnicodeLength(entry->Entries[last].Text); CopyUnicodeString(dest, entry->Entries[last].Text); CopyUnicodeString(dest + 2*len, split); CopyUnicodeString(dest + 2*len + 4, entry->Entries[first].Text); } else if (last != -1) { CopyUnicodeString(dest, entry->Entries[last].Text); } else if (first != -1) { CopyUnicodeString(dest, entry->Entries[first].Text); } else { return NULL; } } return dest; } void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group) { int i; *Name = -1; *Number = -1; *Group = -1; for (i = 0; i < entry->EntriesNum; i++) { switch (entry->Entries[i].EntryType) { case PBK_Number_General : if (*Number == -1) *Number = i; break; case PBK_Text_Name : if (*Name == -1) *Name = i; break; case PBK_Caller_Group : if (*Group == -1) *Group = i; break; default : break; } } if ((*Number) == -1) { for (i = 0; i < entry->EntriesNum; i++) { switch (entry->Entries[i].EntryType) { case PBK_Number_Mobile: case PBK_Number_Work: case PBK_Number_Fax: case PBK_Number_Home: case PBK_Number_Pager: case PBK_Number_Other: *Number = i; break; default: break; } if (*Number != -1) break; } } if ((*Name) == -1) { for (i = 0; i < entry->EntriesNum; i++) { if (entry->Entries[i].EntryType != PBK_Text_LastName) continue; *Name = i; break; } } if ((*Name) == -1) { for (i = 0; i < entry->EntriesNum; i++) { if (entry->Entries[i].EntryType != PBK_Text_FirstName) continue; *Name = i; break; } } } void GSM_EncodeVCARD(char *Buffer, size_t *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version) { int Name, Number, Group, i; int firstname = -1, lastname = -1; int address = -1, city = -1, state = -1, zip = -1, country = -1; int workaddress = -1, workcity = -1, workstate = -1, workzip = -1, workcountry = -1; unsigned char buffer[1024]; int pos; bool ignore; GSM_PhonebookFindDefaultNameNumberGroup(pbk, &Name, &Number, &Group); if (Version == Nokia_VCard10) { if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%c",13,10); if (Name != -1) { *Length+=sprintf(Buffer+(*Length),"N:%s%c%c",DecodeUnicodeString(pbk->Entries[Name].Text),13,10); } if (Number != -1) { *Length +=sprintf(Buffer+(*Length),"TEL:%s%c%c",DecodeUnicodeString(pbk->Entries[Number].Text),13,10); } if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10); } else if (Version == Nokia_VCard21 || Version == SonyEricsson_VCard21) { if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%cVERSION:2.1%c%c",13,10,13,10); for (i=0; i < pbk->EntriesNum; i++) { ignore = false; pbk->Entries[i].AddError = ERR_NONE; switch(pbk->Entries[i].EntryType) { case PBK_Text_Name: *Length+=sprintf(Buffer+(*Length),"N"); break; case PBK_Text_NickName: *Length+=sprintf(Buffer+(*Length),"NICKNAME"); break; case PBK_Text_FormalName: *Length+=sprintf(Buffer+(*Length),"FN"); break; case PBK_Text_FirstName: firstname = i; ignore = true; break; case PBK_Text_LastName: lastname = i; ignore = true; break; case PBK_Text_StreetAddress: address = i; ignore = true; break; case PBK_Text_City: city = i; ignore = true; break; case PBK_Text_State: state = i; ignore = true; break; case PBK_Text_Zip: zip = i; ignore = true; break; case PBK_Text_Country: country = i; ignore = true; break; case PBK_Text_WorkStreetAddress: workaddress = i; ignore = true; break; case PBK_Text_WorkCity: workcity = i; ignore = true; break; case PBK_Text_WorkState: workstate = i; ignore = true; break; case PBK_Text_WorkZip: workzip = i; ignore = true; break; case PBK_Text_WorkCountry: workcountry = i; ignore = true; break; case PBK_Date: SaveVCALDate(Buffer, Length, &(pbk->Entries[i].Date), "BDAY"); ignore = true; break; case PBK_LastModified: SaveVCALDateTime(Buffer, Length, &(pbk->Entries[i].Date), "LAST-MODIFIED"); ignore = true; break; case PBK_Number_General: if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); break; case PBK_Number_Other: if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); *Length+=sprintf(Buffer+(*Length),";OTHER"); break; case PBK_Number_Pager: if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); *Length+=sprintf(Buffer+(*Length),";PAGER"); break; case PBK_Number_Mobile : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); *Length+=sprintf(Buffer+(*Length),";CELL"); break; case PBK_Number_Work : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); *Length+=sprintf(Buffer+(*Length),";WORK"); break; case PBK_Number_Fax : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); *Length+=sprintf(Buffer+(*Length),";FAX"); break; case PBK_Number_Home : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TEL"); if (Version != SonyEricsson_VCard21 && Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF"); *Length+=sprintf(Buffer+(*Length),";HOME"); break; case PBK_Text_Note : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"NOTE"); break; case PBK_Text_Postal : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } /* Don't ask why. Nokia phones save postal address * double - once like LABEL, second like ADR */ SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "LABEL", false); *Length+=sprintf(Buffer+(*Length),"ADR;HOME"); break; case PBK_Text_WorkPostal : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"ADR;WORK"); break; case PBK_Text_Email : case PBK_Text_Email2 : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"EMAIL"); break; case PBK_Text_URL : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"URL"); break; case PBK_Text_LUID : if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"X-IRMC-LUID"); break; case PBK_Text_JobTitle: if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"TITLE"); break; case PBK_Text_Company: if (UnicodeLength(pbk->Entries[i].Text) == 0) { ignore = true; break; } *Length+=sprintf(Buffer+(*Length),"ORG"); break; /* Not supported fields */ case PBK_Caller_Group: case PBK_Category: case PBK_Private: case PBK_RingtoneID: case PBK_PictureID: case PBK_Text_UserID: case PBK_CallLength: case PBK_Text_Custom1: case PBK_Text_Custom2: case PBK_Text_Custom3: case PBK_Text_Custom4: case PBK_Text_PictureName: case PBK_PushToTalkID: pbk->Entries[i].AddError = ERR_NOTSUPPORTED; ignore = true; break; } if (!ignore) { SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "", false); } } /* Save name if it is composed from parts */ if (firstname != -1 || lastname != -1) { pos = 0; if (lastname != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[lastname].Text); pos += UnicodeLength(pbk->Entries[lastname].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (firstname != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[firstname].Text); pos += UnicodeLength(pbk->Entries[firstname].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = 0; SaveVCALText(Buffer, Length, buffer, "N", false); } /* Save workaddress if it is composed from parts */ if (workaddress != -1 || workcity != -1 || workstate != -1 || workzip != -1 || workcountry != -1) { pos = 0; buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (workaddress != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[workaddress].Text); pos += UnicodeLength(pbk->Entries[workaddress].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (workcity != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[workcity].Text); pos += UnicodeLength(pbk->Entries[workcity].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (workstate != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[workstate].Text); pos += UnicodeLength(pbk->Entries[workstate].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (workzip != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[workzip].Text); pos += UnicodeLength(pbk->Entries[workzip].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (workcountry != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[workcountry].Text); pos += UnicodeLength(pbk->Entries[workcountry].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = 0; SaveVCALText(Buffer, Length, buffer, "ADR;WORK", false); } /* Save address if it is composed from parts */ if (address != -1 || city != -1 || state != -1 || zip != -1 || country != -1) { pos = 0; buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (address != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[address].Text); pos += UnicodeLength(pbk->Entries[address].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (city != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[city].Text); pos += UnicodeLength(pbk->Entries[city].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (state != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[state].Text); pos += UnicodeLength(pbk->Entries[state].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (zip != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[zip].Text); pos += UnicodeLength(pbk->Entries[zip].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = ';'; pos++; if (country != -1) { CopyUnicodeString(buffer + 2*pos, pbk->Entries[country].Text); pos += UnicodeLength(pbk->Entries[country].Text); } buffer[2*pos] = 0; buffer[2*pos + 1] = 0; SaveVCALText(Buffer, Length, buffer, "ADR;HOME", false); } if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10); } } void GSM_TweakInternationalNumber(unsigned char *Number, const GSM_NumberType numType) { /* Checks if International number needs to be corrected */ char* pos; /* current position in the buffer */ char buf[500]; /* Taken from DecodeUnicodeString(). How to get length of the encoded unicode string? There may be embedded 0s. */ if (numType == NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN || numType + 1 == NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN) { sprintf(buf+1,"%s",DecodeUnicodeString(Number)); /* leave 1 free char before the number, we'll need it */ /* International number may be without + (e.g. (Sony)Ericsson) we can add it, but must handle numbers in the form: NNNNNN N - any digit (char) *code#NNNNNN any number of Ns *[*]code*NNNNNN[...] other combinations (like *code1*code2*number#) will have to be added if found in real life Or does somebody know the exact allowed syntax from some standard? */ pos=buf+1; if (*pos=='*') { /* Code? Skip it. */ /* probably with code */ while (*pos=='*') { /* skip leading asterisks */ *(pos-1)=*pos; /* shift the chars by one */ pos++; } while ((*pos!='*')&&(*pos!='#')) { /* skip code - anything except * or # */ *(pos-1)=*pos; pos++; } *(pos-1)=*pos; /* shift the last delimiter */ pos++; } /* check the guessed location, if + is correctly there */ if (*pos=='+') { /* yes, just shift the rest of the string */ while (*pos) { *(pos-1) = *pos; pos++; } *(pos-1)=0; /* kill the last char, which now got doubled */ } else { /* no, insert + and exit, no more shifting */ *(pos-1)='+'; } EncodeUnicode(Number,buf,strlen(buf)); } } /** * \bug We should avoid using static buffers here. */ GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version UNUSED) { unsigned char Line[20000],Buff[20000]; int Level = 0; unsigned char *s; int pos; Buff[0] = 0; Pbk->EntriesNum = 0; while (1) { MyGetLine(Buffer, Pos, Line, strlen(Buffer), true); if (strlen(Line) == 0) break; switch (Level) { case 0: if (strstr(Line,"BEGIN:VCARD")) Level = 1; break; case 1: if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; if (strstr(Line,"END:VCARD")) { if (Pbk->EntriesNum == 0) return ERR_EMPTY; return ERR_NONE; } if (ReadVCALText(Line, "N", Buff, false)) { pos = 0; s = VCALGetTextPart(Buff, &pos); if (s == NULL) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name; Pbk->EntriesNum++; } else { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); /* Skip empty name */ if (UnicodeLength(Pbk->Entries[Pbk->EntriesNum].Text) > 0) { Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_LastName; Pbk->EntriesNum++; } s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_FirstName; Pbk->EntriesNum++; } } if (ReadVCALText(Line, "TEL", Buff, false) || ReadVCALText(Line, "TEL;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=VOICE", Buff, false)) { if (Buff[1] == '+') { GSM_TweakInternationalNumber(Buff, NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN); } CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General; Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0; Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0; Pbk->EntriesNum++; } if (ReadVCALText(Line, "TEL;CELL", Buff, false) || ReadVCALText(Line, "TEL;CELL;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=CELL", Buff, false) || ReadVCALText(Line, "TEL;TYPE=CELL,VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=CELL;TYPE=VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=CELL;VOICE", Buff, false)) { if (Buff[1] == '+') { GSM_TweakInternationalNumber(Buff, NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN); } CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile; Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0; Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0; Pbk->EntriesNum++; } if (ReadVCALText(Line, "TEL;WORK", Buff, false) || ReadVCALText(Line, "TEL;TYPE=WORK", Buff, false) || ReadVCALText(Line, "TEL;WORK;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=WORK;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=WORK;TYPE=VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=WORK,VOICE", Buff, false)) { if (Buff[1] == '+') { GSM_TweakInternationalNumber(Buff, NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN); } CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work; Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0; Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0; Pbk->EntriesNum++; } if (ReadVCALText(Line, "TEL;OTHER", Buff, false) || ReadVCALText(Line, "TEL;TYPE=OTHER", Buff, false) || ReadVCALText(Line, "TEL;OTHER;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=OTHER;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=OTHER;TYPE=VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=OTHER,VOICE", Buff, false)) { if (Buff[1] == '+') { GSM_TweakInternationalNumber(Buff, NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN); } CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Other; Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0; Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0; Pbk->EntriesNum++; } /* FAX + VOICE looks like nonsense */ if (ReadVCALText(Line, "TEL;FAX", Buff, false) || ReadVCALText(Line, "TEL;TYPE=FAX", Buff, false) || ReadVCALText(Line, "TEL;FAX;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=FAX;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=FAX;TYPE=VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=FAX,VOICE", Buff, false)) { if (Buff[1] == '+') { GSM_TweakInternationalNumber(Buff, NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN); } CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax; Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0; Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0; Pbk->EntriesNum++; } if (ReadVCALText(Line, "TEL;HOME", Buff, false) || ReadVCALText(Line, "TEL;TYPE=HOME", Buff, false) || ReadVCALText(Line, "TEL;HOME;VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=HOME,VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=HOME;TYPE=VOICE", Buff, false) || ReadVCALText(Line, "TEL;TYPE=HOME;VOICE", Buff, false)) { if (Buff[1] == '+') { GSM_TweakInternationalNumber(Buff, NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN); } CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home; Pbk->Entries[Pbk->EntriesNum].SMSList[0] = 0; Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0; Pbk->EntriesNum++; } if (ReadVCALText(Line, "TITLE", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_JobTitle; Pbk->EntriesNum++; } if (ReadVCALText(Line, "NOTE", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note; Pbk->EntriesNum++; } if (ReadVCALText(Line, "LABEL", Buff, false) || ReadVCALText(Line, "ADR", Buff, false) || ReadVCALText(Line, "ADR;HOME", Buff, false)) { pos = 0; s = VCALGetTextPart(Buff, &pos); /* PO box, ignore for now */ if (s == NULL) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal; Pbk->EntriesNum++; } else { s = VCALGetTextPart(Buff, &pos); /* Don't know ... */ s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_StreetAddress; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_City; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_State; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Zip; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Country; Pbk->EntriesNum++; } } if (ReadVCALText(Line, "ADR;WORK", Buff, false)) { pos = 0; s = VCALGetTextPart(Buff, &pos); /* PO box, ignore for now */ if (s == NULL) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_WorkPostal; Pbk->EntriesNum++; } else { s = VCALGetTextPart(Buff, &pos); /* Don't know ... */ s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_WorkStreetAddress; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_WorkCity; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_WorkState; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_WorkZip; Pbk->EntriesNum++; if (Pbk->EntriesNum == GSM_PHONEBOOK_ENTRIES) return ERR_MOREMEMORY; s = VCALGetTextPart(Buff, &pos); if (s == NULL) continue; CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text, s); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_WorkCountry; Pbk->EntriesNum++; } } if (ReadVCALText(Line, "EMAIL", Buff, false) || ReadVCALText(Line, "EMAIL;TYPE=OTHER", Buff, false) || ReadVCALText(Line, "EMAIL;INTERNET", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email; Pbk->EntriesNum++; } if (ReadVCALText(Line, "X-IRMC-LUID", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_LUID; Pbk->EntriesNum++; } if (ReadVCALText(Line, "URL", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL; Pbk->EntriesNum++; } if (ReadVCALText(Line, "ORG", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Company; Pbk->EntriesNum++; } if (ReadVCALText(Line, "NICKNAME", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_NickName; Pbk->EntriesNum++; } if (ReadVCALText(Line, "FN", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_FormalName; Pbk->EntriesNum++; } if (ReadVCALText(Line, "CATEGORIES", Buff, false)) { CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff); Pbk->Entries[Pbk->EntriesNum].Number = -1; Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Category; Pbk->EntriesNum++; } if (ReadVCALText(Line, "BDAY", Buff, false)) { if (ReadVCALDateTime(DecodeUnicodeString(Buff), &Pbk->Entries[Pbk->EntriesNum].Date)) { Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Date; Pbk->EntriesNum++; } } if (ReadVCALText(Line, "LAST-MODIFIED", Buff, false)) { if (ReadVCALDateTime(DecodeUnicodeString(Buff), &Pbk->Entries[Pbk->EntriesNum].Date)) { Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_LastModified; Pbk->EntriesNum++; } } break; } } if (Pbk->EntriesNum == 0) return ERR_EMPTY; return ERR_NONE; } /* How should editor hadle tabs in this file? Add editor commands here. * vim: noexpandtab sw=8 ts=8 sts=8: */