X-Git-Url: https://code.citadel.org/?p=citadel.git;a=blobdiff_plain;f=webcit%2Fvcard_edit.c;h=27ba6495b61327e0f61cd5465533d9cf30bef4e2;hp=9c8bd3b0c4c76b899883eb610e0df2308d633a7e;hb=b98d9f087b3a24a9549470ab066c2aea187ecfba;hpb=4b4dc864ede7c5d8d956febe4a0afb422b78e7c4 diff --git a/webcit/vcard_edit.c b/webcit/vcard_edit.c index 9c8bd3b0c..27ba6495b 100644 --- a/webcit/vcard_edit.c +++ b/webcit/vcard_edit.c @@ -1,64 +1,362 @@ /* - * Copyright (c) 1996-2011 by the citadel.org team + * 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 as - * published by the Free Software Foundation; either version 3 of the - * License, or (at your option) any later version. + * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #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, + Address, + Street, + Number, + AliasFor, + Base64BinaryAttachment, + UnKnown, + TerminateList +}VCStrEnum; +typedef struct vcField vcField; +struct vcField { + ConstStr STR; + VCStrEnum Type; + vcField *Sub; + long cval; + long parentCVal; + ConstStr Name; +}; + +vcField VCStr_Ns [] = { + {{HKEY("last")}, FlatString, NULL, 0, 0, {HKEY("Last Name")}}, + {{HKEY("first")}, FlatString, NULL, 0, 0, {HKEY("First Name")}}, + {{HKEY("middle")}, FlatString, NULL, 0, 0, {HKEY("Middle Name")}}, + {{HKEY("prefix")}, FlatString, NULL, 0, 0, {HKEY("Prefix")}}, + {{HKEY("suffix")}, FlatString, NULL, 0, 0, {HKEY("Suffix")}}, + {{HKEY("")}, TerminateList, NULL, 0, 0, {HKEY("")}} +}; + +vcField VCStr_Addrs [] = { + {{HKEY("POBox")}, Address, NULL, 0, 0, {HKEY("PO box")}}, + {{HKEY("extadr")}, Address, NULL, 0, 0, {HKEY("Address")}}, + {{HKEY("street")}, Address, NULL, 0, 0, {HKEY("")}}, + {{HKEY("city")}, Address, NULL, 0, 0, {HKEY("City")}}, + {{HKEY("state")}, Address, NULL, 0, 0, {HKEY("State")}}, + {{HKEY("zip")}, Address, NULL, 0, 0, {HKEY("ZIP code")}}, + {{HKEY("country")}, Address, NULL, 0, 0, {HKEY("Country")}}, + {{HKEY("")}, TerminateList, NULL, 0, 0, {HKEY("")}} +}; +vcField VCStrE [] = { + {{HKEY("version")}, Number, NULL, 0, 0, {HKEY("")}}, + {{HKEY("rev")}, Number, NULL, 0, 0, {HKEY("")}}, + {{HKEY("label")}, FlatString, NULL, 0, 0, {HKEY("")}}, + {{HKEY("uid")}, FlatString, NULL, 0, 0, {HKEY("")}}, + {{HKEY("n")}, StringCluster, VCStr_Ns, 0, 0, {HKEY("")}}, /* N is name, but only if there's no FN already there */ + {{HKEY("fn")}, FlatString, NULL, 0, 0, {HKEY("")}}, /* FN (full name) is a true 'display name' field */ + {{HKEY("title")}, FlatString, NULL, 0, 0, {HKEY("Title:")}}, + {{HKEY("org")}, FlatString, NULL, 0, 0, {HKEY("Organization:")}},/* organization */ + {{HKEY("email")}, EmailAddr, NULL, 0, 0, {HKEY("E-mail:")}}, + {{HKEY("tel")}, PhoneNumber, NULL, 0, 0, {HKEY("Telephone:")}}, + {{HKEY("adr")}, StringCluster, VCStr_Addrs, 0, 0, {HKEY("Address:")}}, + {{HKEY("photo")}, Base64BinaryAttachment, NULL, 0, 0, {HKEY("Photo:")}}, + {{HKEY("tel;home")}, PhoneNumber, NULL, 0, 0, {HKEY(" (home)")}}, + {{HKEY("tel;work")}, PhoneNumber, NULL, 0, 0, {HKEY(" (work)")}}, + {{HKEY("tel;fax")}, PhoneNumber, NULL, 0, 0, {HKEY(" (fax)")}}, + {{HKEY("tel;cell")}, PhoneNumber, NULL, 0, 0, {HKEY(" (cell)")}}, + {{HKEY("email;internet")}, EmailAddr, NULL, 0, 0, {HKEY("E-mail:")}}, + {{HKEY("UNKNOWN")}, UnKnown, NULL, 0, 0, {HKEY("")}}, + {{HKEY("")}, TerminateList, NULL, 0, 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("tel_tel")}, - {HKEY("tel_work")}, - {HKEY("tel_home")}, - {HKEY("tel_cell")}, + {HKEY("work")}, + {HKEY("home")}, + {HKEY("cell")}, {HKEY("adr")}, {HKEY("photo")}, {HKEY("version")}, {HKEY("rev")}, - {HKEY("label")} + {HKEY("label")}, + {HKEY("uid")} }; -typedef enum _eVC{ - VC_n, - VC_fn, - VC_title, - VC_org, - VC_email, - VC_tel, - VC_tel_tel, - VC_tel_work, - VC_tel_home, - VC_tel_cell, - VC_adr, - VC_photo, - VC_version, - VC_rev, - VC_label -} eVC; - -HashList *VCToEnum = NULL; + +HashList *DefineToToken = NULL; +HashList *VCTokenToDefine = NULL; +HashList *vcNames = NULL; /* todo: fill with the name strings */ +vcField* vcfUnknown = NULL; + +void RegisterVCardToken(vcField* vf, StrBuf *name, int inTokenCount) +{ + if (vf->Type == UnKnown) { + vcfUnknown = vf; + } + 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, long parentCVal) +{ + int i = 0; + StrBuf *subStr = NewStrBuf(); + while (vf[i].STR.len > 0) { + FlushStrBuf(subStr); + vf[i].cval = (*enumCounter) ++; + vf[i].parentCVal = parentCVal; + 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, vf[i].cval); + } + break; + case PhoneNumber: + break; + case EmailAddr: + break; + case Street: + break; + case Number: + break; + case AliasFor: + break; + case Base64BinaryAttachment: + break; + case TerminateList: + break; + case Address: + break; + case UnKnown: + break; + } + RegisterVCardToken(&vf[i], subStr, i); + i++; + } + FreeStrBuf(&subStr); +} + +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 @@ -143,7 +441,8 @@ wc_mime_attachment *load_vcard(message_summary *Msg) if (VCMime == NULL) return NULL; - MimeLoadData(VCMime); + if (VCMime->Data == NULL) + MimeLoadData(VCMime); return VCMime; } @@ -281,263 +580,20 @@ void fetchname_parsed_vcard(struct vCard *v, char **storename) { -/* - * html print a vcard - * display_vcard() calls this after parsing the textual vCard into - * our 'struct vCard' data object. - * - * Set 'full' to nonzero to display the full card, otherwise it will only - * show a summary line. - * - * This code is a bit ugly, so perhaps an explanation is due: we do this - * in two passes through the vCard fields. On the first pass, we process - * fields we understand, and then render them in a pretty fashion at the - * end. Then we make a second pass, outputting all the fields we don't - * understand in a simple two-column name/value format. - * v the vCard to display - * full display all items of the vcard? - * msgnum Citadel message pointer - */ -void display_parsed_vcard(StrBuf *Target, struct vCard *v, int full, wc_mime_attachment *Mime) -{ - int i, j; - char buf[SIZ]; - char *name; - int is_qp = 0; - int is_b64 = 0; - char *thisname, *thisvalue; - char firsttoken[SIZ]; - int pass; - - char fullname[SIZ]; - char title[SIZ]; - char org[SIZ]; - char phone[SIZ]; - char mailto[SIZ]; - - strcpy(fullname, ""); - strcpy(phone, ""); - strcpy(mailto, ""); - strcpy(title, ""); - strcpy(org, ""); - - if (!full) { - StrBufAppendPrintf(Target, ""); - name = vcard_get_prop(v, "fn", 1, 0, 0); - if (name != NULL) { - StrEscAppend(Target, NULL, name, 0, 0); - } - else if (name = vcard_get_prop(v, "n", 1, 0, 0), name != NULL) { - strcpy(fullname, name); - vcard_n_prettyize(fullname); - StrEscAppend(Target, NULL, fullname, 0, 0); - } - else { - StrBufAppendPrintf(Target, " "); - } - StrBufAppendPrintf(Target, ""); - return; - } - - StrBufAppendPrintf(Target, "
" - ""); - for (pass=1; pass<=2; ++pass) { - - if (v->numprops) for (i=0; i<(v->numprops); ++i) { - int len; - thisname = strdup(v->prop[i].name); - extract_token(firsttoken, thisname, 0, ';', sizeof firsttoken); - - for (j=0; jprop[i].value); - /* if we have some untagged QP, detect it here. */ - if (!is_qp && (strstr(v->prop[i].value, "=?")!=NULL)) - utf8ify_rfc822_string(&v->prop[i].value); - - if (is_qp) { - // %ff can become 6 bytes in utf8 - thisvalue = malloc(len * 2 + 3); - j = CtdlDecodeQuotedPrintable( - thisvalue, v->prop[i].value, - len); - thisvalue[j] = 0; - } - else if (is_b64) { - // ff will become one byte.. - thisvalue = malloc(len + 50); - CtdlDecodeBase64( - thisvalue, v->prop[i].value, - strlen(v->prop[i].value) ); - } - else { - thisvalue = strdup(v->prop[i].value); - } - - /* Various fields we may encounter ***/ - - /* N is name, but only if there's no FN already there */ - if (!strcasecmp(firsttoken, "n")) { - if (IsEmptyStr(fullname)) { - strcpy(fullname, thisvalue); - vcard_n_prettyize(fullname); - } - } - - /* FN (full name) is a true 'display name' field */ - else if (!strcasecmp(firsttoken, "fn")) { - strcpy(fullname, thisvalue); - } - - /* title */ - else if (!strcasecmp(firsttoken, "title")) { - strcpy(title, thisvalue); - } - - /* organization */ - else if (!strcasecmp(firsttoken, "org")) { - strcpy(org, thisvalue); - } - - else if (!strcasecmp(firsttoken, "email")) { - size_t len; - if (!IsEmptyStr(mailto)) strcat(mailto, "
"); - strcat(mailto, - ""); - - strcat(mailto, "\">"); - len = strlen(mailto); - stresc(mailto+len, SIZ - len, thisvalue, 1, 1); - strcat(mailto, ""); - } - else if (!strcasecmp(firsttoken, "tel")) { - if (!IsEmptyStr(phone)) strcat(phone, "
"); - strcat(phone, thisvalue); - for (j=0; j
\n"); - } - } - /* else if (!strcasecmp(firsttoken, "photo") && full && pass == 2) { - // Only output on second pass - StrBufAppendPrintf(Target, "\n"); - } */ - else if (!strcasecmp(firsttoken, "version")) { - /* ignore */ - } - else if (!strcasecmp(firsttoken, "rev")) { - /* ignore */ - } - else if (!strcasecmp(firsttoken, "label")) { - /* ignore */ - } - else { - - /*** Don't show extra fields. They're ugly. - if (pass == 2) { - StrBufAppendPrintf(Target, "\n"); - } - ***/ - } - - free(thisname); - free(thisvalue); - } - - if (pass == 1) { - StrBufAppendPrintf(Target, "" - "\n"); - - if (!IsEmptyStr(phone)) { - StrBufAppendPrintf(Target, "\n", phone); - } - if (!IsEmptyStr(mailto)) { - StrBufAppendPrintf(Target, "\n", mailto); - } - } +void PutVcardItem(HashList *thisVC, vcField *thisField, StrBuf *ThisFieldStr, int is_qp, StrBuf *Swap) +{ + /* if we have some untagged QP, detect it here. */ + if (is_qp || (strstr(ChrPtr(ThisFieldStr), "=?")!=NULL)){ + StrBuf *b; + StrBuf_RFC822_to_Utf8(Swap, ThisFieldStr, NULL, NULL); /* default charset, current charset */ + b = ThisFieldStr; + ThisFieldStr = Swap; + Swap = b; + FlushStrBuf(Swap); } - - StrBufAppendPrintf(Target, "
"); - StrBufAppendPrintf(Target, _("Address:")); - StrBufAppendPrintf(Target, ""); - for (j=0; j"); - else StrBufAppendPrintf(Target, " "); - } - } - StrBufAppendPrintf(Target, "
"); - StrBufAppendPrintf(Target, _("Photo:")); - StrBufAppendPrintf(Target, ""); - StrBufAppendPrintf(Target, "\"Contact",msgnum); - StrBufAppendPrintf(Target, "
"); - StrEscAppend(Target, NULL, thisname, 0, 0); - StrBufAppendPrintf(Target, ""); - StrEscAppend(Target, NULL, thisvalue, 0, 0); - StrBufAppendPrintf(Target, "
" - "" - ""); - StrEscAppend(Target, NULL, fullname, 0, 0); - StrBufAppendPrintf(Target, ""); - if (!IsEmptyStr(title)) { - StrBufAppendPrintf(Target, "
\""); - StrEscAppend(Target, NULL, title, 0, 0); - StrBufAppendPrintf(Target, "
"); - } - if (!IsEmptyStr(org)) { - StrBufAppendPrintf(Target, "
"); - StrEscAppend(Target, NULL, org, 0, 0); - StrBufAppendPrintf(Target, "
"); - } - StrBufAppendPrintf(Target, "
"); - StrBufAppendPrintf(Target, _("Telephone:")); - StrBufAppendPrintf(Target, "%s
"); - StrBufAppendPrintf(Target, _("E-mail:")); - StrBufAppendPrintf(Target, "%s
\n"); + Put(thisVC, LKEY(thisField->cval), ThisFieldStr, HFreeStrBuf); } - /* * html print a vcard * display_vcard() calls this after parsing the textual vCard into @@ -551,44 +607,131 @@ void display_parsed_vcard(StrBuf *Target, struct vCard *v, int full, wc_mime_att * fields we understand, and then render them in a pretty fashion at the * end. Then we make a second pass, outputting all the fields we don't * understand in a simple two-column name/value format. - * v the vCard to display - * full display all items of the vcard? + * v the vCard to parse * msgnum Citadel message pointer */ -void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, int full, wc_mime_attachment *Mime) +void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachment *Mime) { StrBuf *Val = NULL; StrBuf *Swap = NULL; - int i, j; + int i, j, k; char buf[SIZ]; int is_qp = 0; int is_b64 = 0; + int ntokens, len; StrBuf *thisname = NULL; char firsttoken[SIZ]; - void *V; + StrBuf *thisVCToken; + void *vField = NULL; Swap = NewStrBuf (); thisname = NewStrBuf(); + thisVCToken = NewStrBufPlain(NULL, 63); for (i=0; i<(v->numprops); ++i) { + FlushStrBuf(thisVCToken); is_qp = 0; is_b64 = 0; + syslog(LOG_DEBUG, "i: %d oneprop: %s - value: %s", i, v->prop[i].name, v->prop[i].value); StrBufPlain(thisname, v->prop[i].name, -1); StrBufLowerCase(thisname); /*len = */extract_token(firsttoken, ChrPtr(thisname), 0, ';', sizeof firsttoken); - - for (j=0; j 0) { + StrBufAppendBufPlain(thisVCToken, HKEY(";"), 0); + } + StrBufAppendBufPlain(thisVCToken, buf, len, 0); + /* + if (GetHash(VCToEnum, buf, len, &V)) + { + evc[k] = (int) V; + + Put(VC, IKEY(evc), Val, HFreeStrBuf); + + syslog(LOG_DEBUG, "[%ul] -> k: %d %s - %s", evc, k, buf, VCStr[evc[k]].Key); + k++; + } +*/ + + } } - + + vField = NULL; + if ((StrLength(thisVCToken) > 0) && + GetHash(VCTokenToDefine, SKEY(thisVCToken), &vField) && + (vField != NULL)) { + vcField *thisField = (vcField *)vField; + StrBuf *ThisFieldStr = NULL; + syslog(LOG_DEBUG, "got this token: %s, found: %s", ChrPtr(thisVCToken), thisField->STR.Key); + switch (thisField->Type) { + case StringCluster: { + int j = 0; + const char *Pos = NULL; + StrBuf *thisArray = NewStrBufPlain(v->prop[i].value, -1); + StrBuf *Buf = NewStrBufPlain(NULL, StrLength(thisArray)); + while (thisField->Sub[j].STR.len > 0) { + StrBufExtract_NextToken(Buf, thisArray, &Pos, ';'); + ThisFieldStr = NewStrBufDup(Buf); + + PutVcardItem(VC, &thisField->Sub[j], ThisFieldStr, is_qp, Swap); + j++; + } + FreeStrBuf(&thisArray); + FreeStrBuf(&Buf); + } + break; + case Address: + case FlatString: + case PhoneNumber: + case EmailAddr: + case Street: + case Number: + case AliasFor: + /* copy over the payload into a StrBuf */ + ThisFieldStr = NewStrBufPlain(v->prop[i].value, -1); + PutVcardItem(VC, thisField, ThisFieldStr, is_qp, Swap); + + break; + case Base64BinaryAttachment: + case TerminateList: + case UnKnown: + break; + } + + } + else if (StrLength(thisVCToken) > 0) { + /* Add it to the UNKNOWN field... */ + void *pv = NULL; + StrBuf *oldVal; + GetHash(VC, IKEY(vcfUnknown->cval), &pv); + oldVal = (StrBuf*) pv; + if (oldVal == NULL) { + oldVal = NewStrBuf(); + Put(VC, IKEY(vcfUnknown->cval), oldVal, HFreeStrBuf); + } + else { + StrBufAppendBufPlain(oldVal, HKEY("\n"), 0); + } + + StrBufAppendBuf(oldVal, thisVCToken, 0); + StrBufAppendBufPlain(oldVal, HKEY(":"), 0); + StrBufAppendBufPlain(oldVal, v->prop[i].value, -1, 0); + continue; + } + /* copy over the payload into a StrBuf */ Val = NewStrBufPlain(v->prop[i].value, -1); @@ -603,21 +746,22 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, int full, wc_mim } else if (is_b64) { StrBufDecodeBase64(Val); - } - syslog(1, "%s [%s][%s]", +#if 0 + syslog(LOG_DEBUG, "-> firsttoken: %s thisname: %s Value: [%s][%s]", firsttoken, + ChrPtr(thisname), ChrPtr(Val), v->prop[i].value); if (GetHash(VCToEnum, firsttoken, strlen(firsttoken), &V)) { eVC evc = (eVC) V; Put(VC, IKEY(evc), Val, HFreeStrBuf); - syslog(1, "[%ul]\n", evc); + syslog(LOG_DEBUG, "[%ul]\n", evc); Val = NULL; } else - syslog(1, "[]\n"); + syslog(LOG_DEBUG, "[]\n"); /* TODO: check for layer II else @@ -647,18 +791,18 @@ TODO: check for layer II } */ - +#endif FreeStrBuf(&Val); - free(thisname); - thisname = NULL; } - + FreeStrBuf(&thisname); + FreeStrBuf(&Swap); + FreeStrBuf(&thisVCToken); } void tmplput_VCARD_ITEM(StrBuf *Target, WCTemplputParams *TP) { - HashList *VC = CTX; - eVC evc; + HashList *VC = CTX(CTX_VCARD); + int evc; void *vStr; evc = GetTemplateTokenNumber(Target, TP, 0, -1); @@ -674,21 +818,24 @@ void tmplput_VCARD_ITEM(StrBuf *Target, WCTemplputParams *TP) } -void new_vcard (StrBuf *Target, struct vCard *v, int full, wc_mime_attachment *Mime) +void display_one_vcard (StrBuf *Target, struct vCard *v, int full, wc_mime_attachment *Mime) { - HashList *VC; - WCTemplputParams SubTP; + HashList *VC; WCTemplputParams SubTP; memset(&SubTP, 0, sizeof(WCTemplputParams)); - VC = NewHash(0, Flathash); - parse_vcard(Target, v, VC, full, Mime); + VC = NewHash(0, lFlathash); + parse_vcard(Target, v, VC, Mime); - SubTP.Filter.ContextType = CTX_VCARD; - SubTP.Context = VC; + { + WCTemplputParams *TP = NULL; + WCTemplputParams SubTP; + StackContext(TP, &SubTP, VC, CTX_VCARD, 0, NULL); - DoTemplate(HKEY("test_vcard"), Target, &SubTP); + DoTemplate(HKEY("vcard_msg_display"), Target, &SubTP); + UnStackContext(&SubTP); + } DeleteHash(&VC); } @@ -742,11 +889,7 @@ void display_vcard(StrBuf *Target, ((!isalpha(alpha)) && (!isalpha(this_alpha))) ) { -#ifdef XXX_XXX - new_vcard (Target, v, full, Mime); -#else - display_parsed_vcard(Target, v, full, Mime); -#endif + display_one_vcard (Target, v, full, Mime); } vcard_free(v); @@ -876,58 +1019,16 @@ void do_edit_vcard(long msgnum, char *partnum, wc_mime_attachment *VCAtt, const char *return_to, const char *force_room) { + HashList *VC; WCTemplputParams SubTP; + wcsession *WCC = WC; message_summary *Msg = NULL; wc_mime_attachment *VCMime = NULL; struct vCard *v; - int i; - char *key, *value; char whatuser[256]; + VC = NewHash(0, lFlathash); - char lastname[256]; - char firstname[256]; - char middlename[256]; - char prefix[256]; - char suffix[256]; - char pobox[256]; - char extadr[256]; - char street[256]; - char city[256]; - char state[256]; - char zipcode[256]; - char country[256]; - char hometel[256]; - char worktel[256]; - char faxtel[256]; - char mobiletel[256]; - char primary_inetemail[256]; - char other_inetemail[SIZ]; - char extrafields[SIZ]; - char fullname[256]; - char title[256]; - char org[256]; - - lastname[0] = 0; - firstname[0] = 0; - middlename[0] = 0; - prefix[0] = 0; - suffix[0] = 0; - pobox[0] = 0; - extadr[0] = 0; - street[0] = 0; - city[0] = 0; - state[0] = 0; - zipcode[0] = 0; - country[0] = 0; - hometel[0] = 0; - worktel[0] = 0; - faxtel[0] = 0; - mobiletel[0] = 0; - primary_inetemail[0] = 0; - other_inetemail[0] = 0; - title[0] = 0; - org[0] = 0; - extrafields[0] = 0; - fullname[0] = 0; + /* Display the form */ + output_headers(1, 1, 1, 0, 0, 0); safestrncpy(whatuser, "", sizeof whatuser); @@ -951,273 +1052,26 @@ void do_edit_vcard(long msgnum, char *partnum, else { v = VCardLoad(VCAtt->Data); } - - /* Populate the variables for our form */ - i = 0; - while (key = vcard_get_prop(v, "", 0, i, 1), key != NULL) { - char prp[256]; /* property name */ - char prm[256]; /* parameters */ - - value = vcard_get_prop(v, "", 0, i++, 0); - - - extract_token(prp, key, 0, ';', sizeof prp); - safestrncpy(prm, key, sizeof prm); - remove_token(prm, 0, ';'); - if (!strcasecmp(prp, "n")) { - extract_token(lastname, value, 0, ';', sizeof lastname); - extract_token(firstname, value, 1, ';', sizeof firstname); - extract_token(middlename, value, 2, ';', sizeof middlename); - extract_token(prefix, value, 3, ';', sizeof prefix); - extract_token(suffix, value, 4, ';', sizeof suffix); - } - - else if (!strcasecmp(prp, "fn")) { - safestrncpy(fullname, value, sizeof fullname); - } - - else if (!strcasecmp(prp, "title")) { - safestrncpy(title, value, sizeof title); - } + parse_vcard(WCC->WBuf, v, VC, NULL); - else if (!strcasecmp(prp, "org")) { - safestrncpy(org, value, sizeof org); - } - - else if (!strcasecmp(prp, "adr")) { - extract_token(pobox, value, 0, ';', sizeof pobox); - extract_token(extadr, value, 1, ';', sizeof extadr); - extract_token(street, value, 2, ';', sizeof street); - extract_token(city, value, 3, ';', sizeof city); - extract_token(state, value, 4, ';', sizeof state); - extract_token(zipcode, value, 5, ';', sizeof zipcode); - extract_token(country, value, 6, ';', sizeof country); - } - - else if (!strcasecmp(prp, "tel")) { - - if (bmstrcasestr(prm, "home")) { - extract_token(hometel, value, 0, ';', sizeof hometel); - } - else if (bmstrcasestr(prm, "work")) { - extract_token(worktel, value, 0, ';', sizeof worktel); - } - else if (bmstrcasestr(prm, "fax")) { - extract_token(faxtel, value, 0, ';', sizeof faxtel); - } - else if (bmstrcasestr(prm, "cell")) { - extract_token(mobiletel, value, 0, ';', sizeof mobiletel); - } - else { /* Missing or unknown type; put it in the home phone */ - extract_token(hometel, value, 0, ';', sizeof hometel); - } - } - - else if ( (!strcasecmp(prp, "email")) && (bmstrcasestr(prm, "internet")) ) { - if (primary_inetemail[0] == 0) { - safestrncpy(primary_inetemail, value, sizeof primary_inetemail); - } - else { - if (other_inetemail[0] != 0) { - strcat(other_inetemail, "\n"); - } - strcat(other_inetemail, value); - } - } - - /* Unrecognized properties are preserved here so we don't discard them - * just because the vCard was edited with WebCit. - */ - else { - strcat(extrafields, key); - strcat(extrafields, ":"); - strcat(extrafields, value); - strcat(extrafields, "\n"); - } - - } vcard_free(v); } - /* Display the form */ - output_headers(1, 1, 1, 0, 0, 0); - - do_template("box_begin_1"); - StrBufAppendBufPlain(WC->WBuf, _("Edit contact information"), -1, 0); - do_template("box_begin_2"); + memset(&SubTP, 0, sizeof(WCTemplputParams)); - wc_printf("
\n"); - wc_printf("\n", WC->nonce); + { + WCTemplputParams *TP = NULL; + WCTemplputParams SubTP; + StackContext(TP, &SubTP, VC, CTX_VCARD, 0, NULL); - if (force_room != NULL) { - wc_printf("\n"); + DoTemplate(HKEY("vcard_edit"), WCC->WBuf, &SubTP); + UnStackContext(&SubTP); } + DeleteHash(&VC); - wc_printf("
\n"); - - wc_printf("" - "" - "" - "" - "" - "\n", - _("Prefix"), _("First Name"), _("Middle Name"), _("Last Name"), _("Suffix") - ); - wc_printf("", - prefix); - wc_printf("", - firstname); - wc_printf("", - middlename); - wc_printf("", - lastname); - wc_printf("
%s%s%s%s%s
\n", - suffix); - - wc_printf(""); - wc_printf("
"); - - wc_printf(_("Display name:")); - wc_printf("
" - "

\n", - fullname - ); - - wc_printf(_("Title:")); - wc_printf("
" - "

\n", - title - ); - wc_printf(_("Organization:")); - wc_printf("
" - "

\n", - org - ); - - wc_printf("
"); - - wc_printf(""); - wc_printf("\n", - pobox); - wc_printf("\n", - extadr); - wc_printf("\n", - street); - wc_printf("\n", - city); - wc_printf("\n", - state); - wc_printf("\n", - zipcode); - wc_printf("\n", - country); - wc_printf("
"); - wc_printf(_("PO box:")); - wc_printf("" - "
"); - wc_printf(_("Address:")); - wc_printf("" - "
" - "
"); - wc_printf(_("City:")); - wc_printf("" - "
"); - wc_printf(_("State:")); - wc_printf("" - "
"); - wc_printf(_("ZIP code:")); - wc_printf("" - "
"); - wc_printf(_("Country:")); - wc_printf("" - "
\n"); - - wc_printf("
\n"); - - wc_printf("" - "\n", - hometel); - wc_printf("" - "\n", - worktel); - wc_printf("" - "\n", - mobiletel); - wc_printf("" - "
"); - wc_printf(_("Home telephone:")); - wc_printf(""); - wc_printf(_("Work telephone:")); - wc_printf("
"); - wc_printf(_("Mobile telephone:")); - wc_printf(""); - wc_printf(_("Fax number:")); - wc_printf("
\n", - faxtel); - - wc_printf(""); - wc_printf("
"); - - wc_printf("" - "
"); - wc_printf(_("Primary Internet e-mail address")); - wc_printf("
" - "
" - "
"); - wc_printf(_("Internet e-mail aliases")); - wc_printf("
" - "
\n"); - - wc_printf("
\n"); - - wc_printf("\n"); - - wc_printf("\n"); - - wc_printf("
\n" - "" - " " - "" - "
\n", - _("Save changes"), - _("Cancel") - ); - - wc_printf("
\n"); - do_template("box_end"); wDumpContent(1); if (Msg != NULL) { DestroyMessageSummary(Msg); @@ -1245,10 +1099,16 @@ void edit_vcard(void) { void submit_vcard(void) { struct vCard *v; char *serialized_vcard; - char buf[SIZ]; StrBuf *Buf; const StrBuf *ForceRoom; - int i; + HashList* postVcard; + HashPos *it, *itSub; + const char *Key; + long len; + void *pv; + StrBuf *SubStr; + const StrBuf *s; + const char *Pos = NULL; if (!havebstr("ok_button")) { readloop(readnew, eUseDefault); @@ -1280,14 +1140,21 @@ void submit_vcard(void) { } } + postVcard = getSubStruct(HKEY("VC")); + if (postVcard == NULL) { + AppendImportantMessage(_("An error has occurred."), -1); + edit_vcard(); + return;//// more details + } + Buf = NewStrBuf(); - serv_write(HKEY("ENT0 1|||4||||||1\n")); + serv_write(HKEY("ENT0 1|||4\n")); if (!StrBuf_ServGetln(Buf) && (GetServerStatus(Buf, NULL) != 4)) { edit_vcard(); return; } - + /* Make a vCard structure out of the data supplied in the form */ StrBufPrintf(Buf, "begin:vcard\r\n%s\r\nend:vcard\r\n", bstr("extrafields") @@ -1300,41 +1167,100 @@ void submit_vcard(void) { return; } - snprintf(buf, sizeof buf, "%s;%s;%s;%s;%s", - bstr("lastname"), - bstr("firstname"), - bstr("middlename"), - bstr("prefix"), - bstr("suffix") ); - vcard_add_prop(v, "n", buf); - - vcard_add_prop(v, "title", bstr("title")); - vcard_add_prop(v, "fn", bstr("fullname")); - vcard_add_prop(v, "org", bstr("org")); - - snprintf(buf, sizeof buf, "%s;%s;%s;%s;%s;%s;%s", - bstr("pobox"), - bstr("extadr"), - bstr("street"), - bstr("city"), - bstr("state"), - bstr("zipcode"), - bstr("country") ); - vcard_add_prop(v, "adr", buf); - - vcard_add_prop(v, "tel;home", bstr("hometel")); - vcard_add_prop(v, "tel;work", bstr("worktel")); - vcard_add_prop(v, "tel;fax", bstr("faxtel")); - vcard_add_prop(v, "tel;cell", bstr("mobiletel")); - vcard_add_prop(v, "email;internet", bstr("primary_inetemail")); - - for (i=0; iSub != NULL){ + vcField *Sub; + FlushStrBuf(SubStr); + itSub = GetNewHashPos(DefineToToken, 0); + while (GetNextHashPos(DefineToToken, itSub, &len, &Key, &pv) && + (pv != NULL)) + { + Sub = (vcField*) pv; + if (Sub->parentCVal == t->cval) { + if (StrLength(SubStr) > 0) + StrBufAppendBufPlain(SubStr, HKEY(";"), 0); + + + + blen = snprintf(buf, sizeof(buf), "%ld", Sub->cval); + s = SSubBstr(postVcard, buf, blen); + + if ((s != NULL) && (StrLength(s) > 0)) { + /// todo: utf8 qp + StrBufAppendBuf(SubStr, s, 0); + } + } + } + if (StrLength(SubStr) > 0) { + vcard_add_prop(v, t->STR.Key, ChrPtr(SubStr)); + } + DeleteHashPos(&itSub); + } + else if (t->parentCVal == 0) { + blen = snprintf(buf, sizeof(buf), "%ld", t->cval); + s = SSubBstr(postVcard, buf, blen); + + if ((s != NULL) && (StrLength(s) > 0)) { + vcard_add_prop(v, t->STR.Key, ChrPtr(s)); + } + /* + (vvcField != NULL)) + { + vcField *t = (vcField*) vvcField; + if (t->layer == 0) switch (t->Type) { + break; + case StringCluster: + { + + i++; + continue; + } + break; + break; + case EmailAddr: + break; + case Street: + break; + case FlatString: + case PhoneNumber: + case Number: + break; + case AliasFor: + break; + case Base64BinaryAttachment: + break; + case TerminateList: + break; + case Address: + break; + + } +*/ + } + } + DeleteHashPos(&it); + + s = sbstr("other_inetemail"); + if (StrLength(s) > 0) { + FlushStrBuf(SubStr); + while (StrBufSipLine(SubStr, s, &Pos), ((Pos!=StrBufNOTNULL) && (Pos!=NULL)) ) { + if (StrLength(SubStr) > 0) { + vcard_add_prop(v, "email;internet", ChrPtr(SubStr)); + } } } + FreeStrBuf(&SubStr); + + serialized_vcard = vcard_serialize(v); vcard_free(v); if (serialized_vcard == NULL) { @@ -1344,14 +1270,13 @@ void submit_vcard(void) { return; } + printf("%s", serialized_vcard); serv_write(HKEY("Content-type: text/x-vcard; charset=UTF-8\n")); serv_write(HKEY("\n")); serv_printf("%s\r\n", serialized_vcard); serv_write(HKEY("000\n")); free(serialized_vcard); - StrBuf_ServGetln(Buf); - if (!strcmp(bstr("return_to"), "select_user_to_edit")) { select_user_to_edit(NULL); } @@ -1497,7 +1422,7 @@ void ServerStartModule_VCARD (void) { - VCToEnum = NewHash(0, NULL); + ///VCToEnum = NewHash(0, NULL); } @@ -1505,13 +1430,18 @@ void ServerShutdownModule_VCARD (void) { - DeleteHash(&VCToEnum); + DeleteHash(&DefineToToken); + DeleteHash(&vcNames); + DeleteHash(&VCTokenToDefine); + /// DeleteHash(&VCToEnum); } void InitModule_VCARD (void) { + RegisterCTX(CTX_VCARD); + RegisterCTX(CTX_VCARD_TYPE); RegisterReadLoopHandlerset( VIEW_ADDRESSBOOK, vcard_GetParamsGetServerCall, @@ -1524,24 +1454,23 @@ InitModule_VCARD WebcitAddUrlHandler(HKEY("edit_vcard"), "", 0, edit_vcard, 0); WebcitAddUrlHandler(HKEY("submit_vcard"), "", 0, submit_vcard, 0); WebcitAddUrlHandler(HKEY("vcardphoto"), "", 0, display_vcard_photo_img, NEED_URL); - +/* Put(VCToEnum, HKEY("n"), (void*)VC_n, reference_free_handler); Put(VCToEnum, HKEY("fn"), (void*)VC_fn, reference_free_handler); Put(VCToEnum, HKEY("title"), (void*)VC_title, reference_free_handler); Put(VCToEnum, HKEY("org"), (void*)VC_org, reference_free_handler); Put(VCToEnum, HKEY("email"), (void*)VC_email, reference_free_handler); Put(VCToEnum, HKEY("tel"), (void*)VC_tel, reference_free_handler); - Put(VCToEnum, HKEY("tel_tel"), (void*)VC_tel_tel, reference_free_handler); - Put(VCToEnum, HKEY("tel_work"), (void*)VC_tel_work, reference_free_handler); - Put(VCToEnum, HKEY("tel_home"), (void*)VC_tel_home, reference_free_handler); - Put(VCToEnum, HKEY("tel_cell"), (void*)VC_tel_cell, reference_free_handler); + Put(VCToEnum, HKEY("work"), (void*)VC_work, reference_free_handler); + Put(VCToEnum, HKEY("home"), (void*)VC_home, reference_free_handler); + Put(VCToEnum, HKEY("cell"), (void*)VC_cell, reference_free_handler); Put(VCToEnum, HKEY("adr"), (void*)VC_adr, reference_free_handler); Put(VCToEnum, HKEY("photo"), (void*)VC_photo, reference_free_handler); Put(VCToEnum, HKEY("version"), (void*)VC_version, reference_free_handler); Put(VCToEnum, HKEY("rev"), (void*)VC_rev, reference_free_handler); Put(VCToEnum, HKEY("label"), (void*)VC_label, reference_free_handler); - - +*/ +/* RegisterNamespace("VC", 1, 2, tmplput_VCARD_ITEM, NULL, CTX_VCARD); REGISTERTokenParamDefine(VC_n); @@ -1550,15 +1479,42 @@ InitModule_VCARD REGISTERTokenParamDefine(VC_org); REGISTERTokenParamDefine(VC_email); REGISTERTokenParamDefine(VC_tel); - REGISTERTokenParamDefine(VC_tel_tel); - REGISTERTokenParamDefine(VC_tel_work); - REGISTERTokenParamDefine(VC_tel_home); - REGISTERTokenParamDefine(VC_tel_cell); + REGISTERTokenParamDefine(VC_work); + REGISTERTokenParamDefine(VC_home); + REGISTERTokenParamDefine(VC_cell); REGISTERTokenParamDefine(VC_adr); REGISTERTokenParamDefine(VC_photo); REGISTERTokenParamDefine(VC_version); REGISTERTokenParamDefine(VC_rev); REGISTERTokenParamDefine(VC_label); +*/ + { + StrBuf *Prefix = NewStrBufPlain(HKEY("VC:")); + DefineToToken = NewHash(1, lFlathash); + vcNames = NewHash(1, lFlathash); + VCTokenToDefine = NewHash(1, NULL); + autoRegisterTokens(&VCEnumCounter, VCStrE, Prefix, 0, 0); + FreeStrBuf(&Prefix); + } + RegisterCTX(CTX_VCARD); + RegisterNamespace("VC:ITEM", 2, 2, tmpl_vcard_item, preeval_vcard_item, CTX_VCARD); + RegisterNamespace("VC:CTXITEM", 1, 1, tmpl_vcard_context_item, NULL, CTX_VCARD_TYPE); + RegisterNamespace("VC:NAME", 1, 1, tmpl_vcard_name_str, preeval_vcard_name_str, CTX_VCARD); + RegisterNamespace("VC:CTXNAME", 1, 1, tmpl_vcard_context_name_str, NULL, CTX_VCARD_TYPE); + REGISTERTokenParamDefine(FlatString); + REGISTERTokenParamDefine(StringCluster); + REGISTERTokenParamDefine(PhoneNumber); + REGISTERTokenParamDefine(EmailAddr); + REGISTERTokenParamDefine(Street); + REGISTERTokenParamDefine(Number); + REGISTERTokenParamDefine(AliasFor); + REGISTERTokenParamDefine(Base64BinaryAttachment); + REGISTERTokenParamDefine(TerminateList); + REGISTERTokenParamDefine(Address); + + RegisterConditional("VC:HAVE:TYPE", 1, conditional_VC_Havetype, CTX_VCARD); + RegisterFilteredIterator("VC:TYPE", 1, DefineToToken, NULL, NULL, NULL, filter_VC_ByType, CTX_VCARD_TYPE, CTX_VCARD, IT_NOFLAG); + RegisterFilteredIterator("VC:TYPE:ITEMS", 0, NULL, getContextVcard, NULL, NULL, filter_VC_ByContextType, CTX_STRBUF, CTX_VCARD_TYPE, IT_NOFLAG); }