+#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;
+}
+
+