+CtxType CTX_VCARD = 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;
+ const char *Str;
+};
+
+vcField VCStr_Ns [] = {
+ {{HKEY("last")}, FlatString, NULL, 0, "Last Name"},
+ {{HKEY("first")}, FlatString, NULL, 0, "First Name"},
+ {{HKEY("middle")}, FlatString, NULL, 0, "Middle Name"},
+ {{HKEY("prefix")}, FlatString, NULL, 0, "Prefix"},
+ {{HKEY("suffix")}, FlatString, NULL, 0, "Suffix"},
+ {{HKEY("")}, TerminateList, NULL, 0, ""}
+};
+
+vcField VCStr_Addrs [] = {
+ {{HKEY("POBox")}, FlatString, NULL, 0, "PO box"},
+ {{HKEY("address")}, FlatString, NULL, 0, "Address"},
+ {{HKEY("address2")}, FlatString, NULL, 0, ""},
+ {{HKEY("city")}, FlatString, NULL, 0, "City"},
+ {{HKEY("state")}, FlatString, NULL, 0, "State"},
+ {{HKEY("zip")}, FlatString, NULL, 0, "ZIP code"},
+ {{HKEY("country")}, FlatString, NULL, 0, "Country"},
+ {{HKEY("")}, TerminateList, NULL, 0, ""}
+};
+
+vcField VCStrE [] = {
+ {{HKEY("version")}, Number, NULL, 0, ""},
+ {{HKEY("rev")}, Number, NULL, 0, ""},
+ {{HKEY("label")}, FlatString, NULL, 0, ""},
+ {{HKEY("uid")}, FlatString, NULL, 0, ""},
+ {{HKEY("n")}, StringCluster, VCStr_Ns, 0, ""}, /* N is name, but only if there's no FN already there */
+ {{HKEY("fn")}, FlatString, NULL, 0, ""}, /* FN (full name) is a true 'display name' field */
+ {{HKEY("title")}, FlatString, NULL, 0, "Title:"},
+ {{HKEY("org")}, FlatString, NULL, 0, "Organization:"},/* organization */
+ {{HKEY("email")}, EmailAddr, NULL, 0, "E-mail:"},
+ {{HKEY("tel")}, PhoneNumber, NULL, 0, "Telephone:"},
+ {{HKEY("adr")}, StringCluster, VCStr_Addrs, 0, "Address:"},
+ {{HKEY("photo")}, Base64BinaryAttachment, NULL, 0, "Photo:"},
+ {{HKEY("tel;home")}, PhoneNumber, NULL, 0, " (home)"},
+ {{HKEY("tel;work")}, PhoneNumber, NULL, 0, " (work)"},
+ {{HKEY("tel;fax")}, PhoneNumber, NULL, 0, " (fax)"},
+ {{HKEY("tel;cell")}, PhoneNumber, NULL, 0, " (cell)"},
+ {{HKEY("email;internet")}, EmailAddr, NULL, 0, "E-mail:"},
+ {{HKEY("")}, TerminateList, NULL, 0, ""}
+};
+
+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);
+
+ 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);
+ }
+}
+
+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);
+ }
+}
+
+int filter_VC_ByType(const char* key, long len, void *Context, StrBuf *Target, WCTemplputParams *TP)
+{
+ long searchType;
+ long type = 0;
+ void *vvcField;
+ int rc = 0;
+
+ memcpy(type, key, sizeof(long));
+ searchType = GetTemplateTokenNumber(Target, TP, 3, 0);/// todo: which?
+
+ if (GetHash(DefineToToken, LKEY(type), &vvcField) &&
+ (vvcField != NULL))
+ {
+ vcField *t = (vcField*) vvcField;
+ if (t && t->Type == searchType) {
+ rc = 1;
+ }
+ }
+ return rc;
+}
+
+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;
+}
+