X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fvcard_edit.c;h=8345d003fa9524cac5ad58f1d6a11cb9c5c2d1ba;hb=f9555db58209352cc9ae4537f36ced11d9dbee8b;hp=d9537cb42c4586479f835fb689b04abdb787091f;hpb=0af85763b23dfbefdc9faee3b62651046084ae22;p=citadel.git diff --git a/webcit/vcard_edit.c b/webcit/vcard_edit.c index d9537cb42..8345d003f 100644 --- a/webcit/vcard_edit.c +++ b/webcit/vcard_edit.c @@ -1,10 +1,351 @@ /* - * $Id$ + * Copyright (c) 1996-2012 by the citadel.org team + * + * This program is open source software. You can redistribute it and/or + * modify it under the terms of the GNU General Public License, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #include "webcit.h" +#include "webserver.h" #include "calendar.h" +CtxType CTX_VCARD = CTX_NONE; +CtxType CTX_VCARD_TYPE = CTX_NONE; +long VCEnumCounter = 0; + +typedef enum _VCStrEnum { + FlatString, + StringCluster, + PhoneNumber, + EmailAddr, + Street, + Number, + AliasFor, + Base64BinaryAttachment, + TerminateList +}VCStrEnum; +typedef struct vcField vcField; +struct vcField { + ConstStr STR; + VCStrEnum Type; + vcField *Sub; + long cval; + ConstStr Name; +}; + +vcField VCStr_Ns [] = { + {{HKEY("last")}, FlatString, NULL, 0, {HKEY("Last Name")}}, + {{HKEY("first")}, FlatString, NULL, 0, {HKEY("First Name")}}, + {{HKEY("middle")}, FlatString, NULL, 0, {HKEY("Middle Name")}}, + {{HKEY("prefix")}, FlatString, NULL, 0, {HKEY("Prefix")}}, + {{HKEY("suffix")}, FlatString, NULL, 0, {HKEY("Suffix")}}, + {{HKEY("")}, TerminateList, NULL, 0, {HKEY("")}} +}; + +vcField VCStr_Addrs [] = { + {{HKEY("POBox")}, FlatString, NULL, 0, {HKEY("PO box")}}, + {{HKEY("address")}, FlatString, NULL, 0, {HKEY("Address")}}, + {{HKEY("address2")}, FlatString, NULL, 0, {HKEY("")}}, + {{HKEY("city")}, FlatString, NULL, 0, {HKEY("City")}}, + {{HKEY("state")}, FlatString, NULL, 0, {HKEY("State")}}, + {{HKEY("zip")}, FlatString, NULL, 0, {HKEY("ZIP code")}}, + {{HKEY("country")}, FlatString, NULL, 0, {HKEY("Country")}}, + {{HKEY("")}, TerminateList, NULL, 0, {HKEY("")}} +}; + +vcField VCStrE [] = { + {{HKEY("version")}, Number, NULL, 0, {HKEY("")}}, + {{HKEY("rev")}, Number, NULL, 0, {HKEY("")}}, + {{HKEY("label")}, FlatString, NULL, 0, {HKEY("")}}, + {{HKEY("uid")}, FlatString, NULL, 0, {HKEY("")}}, + {{HKEY("n")}, StringCluster, VCStr_Ns, 0, {HKEY("")}}, /* N is name, but only if there's no FN already there */ + {{HKEY("fn")}, FlatString, NULL, 0, {HKEY("")}}, /* FN (full name) is a true 'display name' field */ + {{HKEY("title")}, FlatString, NULL, 0, {HKEY("Title:")}}, + {{HKEY("org")}, FlatString, NULL, 0, {HKEY("Organization:")}},/* organization */ + {{HKEY("email")}, EmailAddr, NULL, 0, {HKEY("E-mail:")}}, + {{HKEY("tel")}, PhoneNumber, NULL, 0, {HKEY("Telephone:")}}, + {{HKEY("adr")}, StringCluster, VCStr_Addrs, 0, {HKEY("Address:")}}, + {{HKEY("photo")}, Base64BinaryAttachment, NULL, 0, {HKEY("Photo:")}}, + {{HKEY("tel;home")}, PhoneNumber, NULL, 0, {HKEY(" (home)")}}, + {{HKEY("tel;work")}, PhoneNumber, NULL, 0, {HKEY(" (work)")}}, + {{HKEY("tel;fax")}, PhoneNumber, NULL, 0, {HKEY(" (fax)")}}, + {{HKEY("tel;cell")}, PhoneNumber, NULL, 0, {HKEY(" (cell)")}}, + {{HKEY("email;internet")}, EmailAddr, NULL, 0, {HKEY("E-mail:")}}, + {{HKEY("")}, TerminateList, NULL, 0, {HKEY("")}} +}; + +ConstStr VCStr [] = { + {HKEY("")}, + {HKEY("n")}, /* N is name, but only if there's no FN already there */ + {HKEY("fn")}, /* FN (full name) is a true 'display name' field */ + {HKEY("title")}, /* title */ + {HKEY("org")}, /* organization */ + {HKEY("email")}, + {HKEY("tel")}, + {HKEY("work")}, + {HKEY("home")}, + {HKEY("cell")}, + {HKEY("adr")}, + {HKEY("photo")}, + {HKEY("version")}, + {HKEY("rev")}, + {HKEY("label")}, + {HKEY("uid")} +}; + + +HashList *DefineToToken = NULL; +HashList *VCTokenToDefine = NULL; +HashList *vcNames = NULL; /* todo: fill with the name strings */ + + +void RegisterVCardToken(vcField* vf, StrBuf *name, int inTokenCount) +{ + RegisterTokenParamDefine(SKEY(name), vf->cval); + Put(DefineToToken, LKEY(vf->cval), vf, reference_free_handler); + Put(vcNames, LKEY(vf->cval), NewStrBufPlain(CKEY(vf->Name)), HFreeStrBuf); + + syslog(LOG_DEBUG, "Token: %s -> %ld, %d", + ChrPtr(name), + vf->cval, + inTokenCount); + +} + +void autoRegisterTokens(long *enumCounter, vcField* vf, StrBuf *BaseStr, int layer) +{ + int i = 0; + while (vf[i].STR.len > 0) { + StrBuf *subStr = NewStrBuf(); + vf[i].cval = (*enumCounter) ++; + StrBufAppendBuf(subStr, BaseStr, 0); + if (StrLength(subStr) > 0) { + StrBufAppendBufPlain(subStr, HKEY("."), 0); + } + StrBufAppendBufPlain(subStr, CKEY(vf[i].STR), 0); + if (layer == 0) { + Put(VCTokenToDefine, CKEY(vf[i].STR), &vf[i], reference_free_handler); + } + switch (vf[i].Type) { + case FlatString: + break; + case StringCluster: + { + autoRegisterTokens(enumCounter, vf[i].Sub, subStr, 1); + i++; + continue; + } + break; + case PhoneNumber: + break; + case EmailAddr: + break; + case Street: + break; + case Number: + break; + case AliasFor: + break; + case Base64BinaryAttachment: + break; + case TerminateList: + break; + } + RegisterVCardToken(&vf[i], subStr, i); + i++; + } +} + +int preeval_vcard_item(WCTemplateToken *Token) +{ + WCTemplputParams TPP; + WCTemplputParams *TP; + int searchFieldNo; + StrBuf *Target = NULL; + + memset(&TPP, 0, sizeof(WCTemplputParams)); + TP = &TPP; + TP->Tokens = Token; + searchFieldNo = GetTemplateTokenNumber(Target, TP, 0, 0); + if (searchFieldNo >= VCEnumCounter) { + LogTemplateError(NULL, "VCardItem", ERR_PARM1, TP, + "Invalid define"); + return 0; + } + return 1; +} + +void tmpl_vcard_item(StrBuf *Target, WCTemplputParams *TP) +{ + void *vItem; + long searchFieldNo = GetTemplateTokenNumber(Target, TP, 0, 0); + HashList *vc = (HashList*) CTX(CTX_VCARD); + if (GetHash(vc, LKEY(searchFieldNo), &vItem) && (vItem != NULL)) { + StrBufAppendTemplate(Target, TP, (StrBuf*) vItem, 1); + } +} + +void tmpl_vcard_context_item(StrBuf *Target, WCTemplputParams *TP) +{ + void *vItem; + vcField *t = (vcField*) CTX(CTX_VCARD_TYPE); + HashList *vc = (HashList*) CTX(CTX_VCARD); + + if (t == NULL) { + LogTemplateError(NULL, "VCard item", ERR_NAME, TP, + "Missing context"); + return; + } + + if (GetHash(vc, LKEY(t->cval), &vItem) && (vItem != NULL)) { + StrBufAppendTemplate(Target, TP, (StrBuf*) vItem, 0); + } + else { + LogTemplateError(NULL, "VCard item", ERR_NAME, TP, + "Doesn't have that key - did you miss to filter in advance?"); + } +} +int preeval_vcard_name_str(WCTemplateToken *Token) +{ + WCTemplputParams TPP; + WCTemplputParams *TP; + int searchFieldNo; + StrBuf *Target = NULL; + + memset(&TPP, 0, sizeof(WCTemplputParams)); + TP = &TPP; + TP->Tokens = Token; + searchFieldNo = GetTemplateTokenNumber(Target, TP, 0, 0); + if (searchFieldNo >= VCEnumCounter) { + LogTemplateError(NULL, "VCardName", ERR_PARM1, TP, + "Invalid define"); + return 0; + } + return 1; +} + +void tmpl_vcard_name_str(StrBuf *Target, WCTemplputParams *TP) +{ + void *vItem; + long searchFieldNo = GetTemplateTokenNumber(Target, TP, 0, 0); + /* todo: get descriptive string for this vcard type */ + if (GetHash(vcNames, LKEY(searchFieldNo), &vItem) && (vItem != NULL)) { + StrBufAppendTemplate(Target, TP, (StrBuf*) vItem, 1); + } + else { + LogTemplateError(NULL, "VCard item type", ERR_NAME, TP, + "No i18n string for this."); + return; + } +} + +void tmpl_vcard_context_name_str(StrBuf *Target, WCTemplputParams *TP) +{ + void *vItem; + vcField *t = (vcField*) CTX(CTX_VCARD_TYPE); + + if (t == NULL) { + LogTemplateError(NULL, "VCard item type", ERR_NAME, TP, + "Missing context"); + return; + } + + if (GetHash(vcNames, LKEY(t->cval), &vItem) && (vItem != NULL)) { + StrBufAppendTemplate(Target, TP, (StrBuf*) vItem, 1); + } + else { + LogTemplateError(NULL, "VCard item type", ERR_NAME, TP, + "No i18n string for this."); + return; + } +} + +int filter_VC_ByType(const char* key, long len, void *Context, StrBuf *Target, WCTemplputParams *TP) +{ + long searchType; + long type = 0; + void *v; + int rc = 0; + vcField *vf = (vcField*) Context; + + memcpy(&type, key, sizeof(long)); + searchType = GetTemplateTokenNumber(Target, TP, IT_ADDT_PARAM(0), 0); + + if (vf->Type == searchType) { + HashList *vc = (HashList*) CTX(CTX_VCARD); + if (GetHash(vc, LKEY(vf->cval), &v) && v != NULL) + return 1; + } + return rc; +} + + + + +HashList *getContextVcard(StrBuf *Target, WCTemplputParams *TP) +{ + vcField *vf = (vcField*) CTX(CTX_VCARD_TYPE); + HashList *vc = (HashList*) CTX(CTX_VCARD); + + if ((vf == NULL) || (vc == NULL)) { + LogTemplateError(NULL, "VCard item type", ERR_NAME, TP, + "Need VCard and Vcard type in context"); + + return NULL; + } + return vc; +} + +int filter_VC_ByContextType(const char* key, long len, void *Context, StrBuf *Target, WCTemplputParams *TP) +{ + long searchType; + vcField *vf = (vcField*) CTX(CTX_VCARD_TYPE); + + memcpy(&searchType, key, sizeof(long)); + + if (vf->cval == searchType) { + return 1; + } + else { + return 0; + } +} + + +int conditional_VC_Havetype(StrBuf *Target, WCTemplputParams *TP) +{ + HashList *vc = (HashList*) CTX(CTX_VCARD); + long HaveFieldType = GetTemplateTokenNumber(Target, TP, 2, 0); + int rc = 0; + void *vVCitem; + const char *Key; + long len; + HashPos *it = GetNewHashPos(vc, 0); + while (GetNextHashPos(vc, it, &len, &Key, &vVCitem) && + (vVCitem != NULL)) + { + void *vvcField; + long type = 0; + memcpy(&type, Key, sizeof(long)); + if (GetHash(DefineToToken, LKEY(type), &vvcField) && + (vvcField != NULL)) + { + vcField *t = (vcField*) vvcField; + if (t && t->Type == HaveFieldType) { + rc = 1; + break; + } + } + } + DeleteHashPos(&it); + return rc; +} + /* * Record compare function for sorting address book indices */ @@ -88,7 +429,8 @@ wc_mime_attachment *load_vcard(message_summary *Msg) if (VCMime == NULL) return NULL; - MimeLoadData(VCMime); + if (VCMime->Data == NULL) + MimeLoadData(VCMime); return VCMime; } @@ -197,7 +539,7 @@ void fetchname_parsed_vcard(struct vCard *v, char **storename) { } } if (is_qp) { - // %ff can become 6 bytes in utf8 + /* %ff can become 6 bytes in utf8 */ *storename = malloc(len * 2 + 3); j = CtdlDecodeQuotedPrintable( *storename, name, @@ -205,7 +547,7 @@ void fetchname_parsed_vcard(struct vCard *v, char **storename) { (*storename)[j] = 0; } else if (is_b64) { - // ff will become one byte.. + /* ff will become one byte.. */ *storename = malloc(len + 50); CtdlDecodeBase64( *storename, name, @@ -267,7 +609,7 @@ void display_parsed_vcard(StrBuf *Target, struct vCard *v, int full, wc_mime_att strcpy(org, ""); if (!full) { - StrBufAppendPrintf(Target, "