/*
- * Copyright (c) 1996-2012 by the citadel.org team
+ * Copyright (c) 1996-2020 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.
#include "calendar.h"
CtxType CTX_VCARD = CTX_NONE;
+CtxType CTX_VCARD_LIST = CTX_NONE;
CtxType CTX_VCARD_TYPE = CTX_NONE;
long VCEnumCounter = 0;
{HKEY("uid")}
};
+/*
+ * Address book entry (keep it short and sweet, it's just a quickie lookup
+ * which we can use to get to the real meat and bones later)
+ */
+typedef struct _addrbookent {
+ StrBuf *name;
+ HashList *VC;
+ long ab_msgnum; /* message number of address book entry */
+ StrBuf *msgNoStr;
+} addrbookent;
+
+void deleteAbEnt(void *v) {
+ addrbookent *vc = (addrbookent*)v;
+ DeleteHash(&vc->VC);
+ FreeStrBuf(&vc->name);
+ FreeStrBuf(&vc->msgNoStr);
+ free(vc);
+}
HashList *DefineToToken = NULL;
HashList *VCTokenToDefine = NULL;
HashList *vcNames = NULL; /* todo: fill with the name strings */
vcField* vcfUnknown = NULL;
+/******************************************************************************
+ * initialize vcard structure *
+ ******************************************************************************/
+
void RegisterVCardToken(vcField* vf, StrBuf *name, int inTokenCount)
{
if (vf->Type == UnKnown) {
FreeStrBuf(&subStr);
}
+/******************************************************************************
+ * VCard template functions *
+ ******************************************************************************/
+
int preeval_vcard_item(WCTemplateToken *Token)
{
WCTemplputParams TPP;
TP->Tokens = Token;
searchFieldNo = GetTemplateTokenNumber(Target, TP, 0, 0);
if (searchFieldNo >= VCEnumCounter) {
- LogTemplateError(NULL, "VCardItem", ERR_PARM1, TP,
- "Invalid define");
+ LogTemplateError(NULL, "VCardItem", ERR_PARM1, TP, "Invalid define");
return 0;
}
return 1;
{
void *vItem;
long searchFieldNo = GetTemplateTokenNumber(Target, TP, 0, 0);
- HashList *vc = (HashList*) CTX(CTX_VCARD);
- if (GetHash(vc, LKEY(searchFieldNo), &vItem) && (vItem != NULL)) {
+ addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
+ if (GetHash(ab->VC, LKEY(searchFieldNo), &vItem) && (vItem != NULL)) {
StrBufAppendTemplate(Target, TP, (StrBuf*) vItem, 1);
}
}
{
void *vItem;
vcField *t = (vcField*) CTX(CTX_VCARD_TYPE);
- HashList *vc = (HashList*) CTX(CTX_VCARD);
+ addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
if (t == NULL) {
- LogTemplateError(NULL, "VCard item", ERR_NAME, TP,
- "Missing context");
+ LogTemplateError(NULL, "VCard item", ERR_NAME, TP, "Missing context");
return;
}
- if (GetHash(vc, LKEY(t->cval), &vItem) && (vItem != NULL)) {
+ if (GetHash(ab->VC, LKEY(t->cval), &vItem) && (vItem != NULL)) {
StrBufAppendTemplate(Target, TP, (StrBuf*) vItem, 0);
}
else {
}
}
+void tmpl_vcard_msgno(StrBuf *Target, WCTemplputParams *TP)
+{
+ addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
+ if (ab->msgNoStr == NULL) {
+ ab->msgNoStr = NewStrBufPlain(NULL, 64);
+ }
+ StrBufPrintf(ab->msgNoStr, "%ld", ab->ab_msgnum);
+ StrBufAppendTemplate(Target, TP, ab->msgNoStr, 0);
+}
void tmpl_vcard_context_name_str(StrBuf *Target, WCTemplputParams *TP)
{
void *vItem;
long searchType;
long type = 0;
void *v;
- int rc = 0;
vcField *vf = (vcField*) Context;
+ int rc = 0;
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)
+ addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
+ if (GetHash(ab->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);
+ addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
- if ((vf == NULL) || (vc == NULL)) {
+ if ((vf == NULL) || (ab == NULL)) {
LogTemplateError(NULL, "VCard item type", ERR_NAME, TP,
"Need VCard and Vcard type in context");
return NULL;
}
- return vc;
+ return ab->VC;
}
int filter_VC_ByContextType(const char* key, long len, void *Context, StrBuf *Target, WCTemplputParams *TP)
}
}
-
int conditional_VC_Havetype(StrBuf *Target, WCTemplputParams *TP)
{
- HashList *vc = (HashList*) CTX(CTX_VCARD);
+ addrbookent *ab = (addrbookent*) 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) &&
+ HashPos *it = GetNewHashPos(ab->VC, 0);
+ while (GetNextHashPos(ab->VC, it, &len, &Key, &vVCitem) &&
(vVCitem != NULL))
{
void *vvcField;
}
-/*
- * Address book entry (keep it short and sweet, it's just a quickie lookup
- * which we can use to get to the real meat and bones later)
- */
-typedef struct _addrbookent {
- char ab_name[64]; /* name string */
- long ab_msgnum; /* message number of address book entry */
-} addrbookent;
-
-
-/*
- * Record compare function for sorting address book indices
- */
-int abcmp(const void *ab1, const void *ab2) {
- return(strcasecmp(
- (((const addrbookent *)ab1)->ab_name),
- (((const addrbookent *)ab2)->ab_name)
- ));
-}
-
-
-/*
- * Helper function for do_addrbook_view()
- * Converts a name into a three-letter tab label
+/* Returns 1 to suppress the "email" fields in the vCard editor, if we're editing a user's contact info.
+ * Returns 0 to present those fields, if we're editing a vCard in an address book.
*/
-void nametab(char *tabbuf, long len, char *name) {
- stresc(tabbuf, len, name, 0, 0);
- tabbuf[0] = toupper(tabbuf[0]);
- tabbuf[1] = tolower(tabbuf[1]);
- tabbuf[2] = tolower(tabbuf[2]);
- tabbuf[3] = 0;
-}
-
-
-/*
- * If it's an old "Firstname Lastname" style record, try to convert it.
- */
-void lastfirst_firstlast(char *namebuf) {
- char firstname[SIZ];
- char lastname[SIZ];
- int i;
-
- if (namebuf == NULL) return;
- if (strchr(namebuf, ';') != NULL) return;
-
- i = num_tokens(namebuf, ' ');
- if (i < 2) return;
-
- extract_token(lastname, namebuf, i-1, ' ', sizeof lastname);
- remove_token(namebuf, i-1, ' ');
- strcpy(firstname, namebuf);
- sprintf(namebuf, "%s; %s", lastname, firstname);
-}
-
-
-
-wc_mime_attachment *load_vcard(message_summary *Msg)
-{
- HashPos *it;
- StrBuf *FoundCharset = NewStrBuf();
- StrBuf *Error;
- void *vMime;
- const char *Key;
- long len;
- wc_mime_attachment *Mime;
- wc_mime_attachment *VCMime = NULL;
-
- Msg->MsgBody = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
- memset(Msg->MsgBody, 0, sizeof(wc_mime_attachment));
- Msg->MsgBody->msgnum = Msg->msgnum;
-
- load_message(Msg, FoundCharset, &Error);
-
- FreeStrBuf(&FoundCharset);
- /* look up the vcard... */
- it = GetNewHashPos(Msg->AllAttach, 0);
- while (GetNextHashPos(Msg->AllAttach, it, &len, &Key, &vMime) &&
- (vMime != NULL))
- {
- Mime = (wc_mime_attachment*) vMime;
- if ((strcmp(ChrPtr(Mime->ContentType),
- "text/x-vcard") == 0) ||
- (strcmp(ChrPtr(Mime->ContentType),
- "text/vcard") == 0))
- {
- VCMime = Mime;
- break;
- }
- }
- DeleteHashPos(&it);
- if (VCMime == NULL)
- return NULL;
-
- if (VCMime->Data == NULL)
- MimeLoadData(VCMime);
- return VCMime;
-}
-
-
-
-/*
- * Turn a vCard "n" (name) field into something displayable.
- */
-void vcard_n_prettyize(char *name)
-{
- char *original_name;
- int i, j, len;
-
- original_name = strdup(name);
- len = strlen(original_name);
- for (i=0; i<5; ++i) {
- if (len > 0) {
- if (original_name[len-1] == ' ') {
- original_name[--len] = 0;
- }
- if (original_name[len-1] == ';') {
- original_name[--len] = 0;
- }
- }
- }
- strcpy(name, "");
- j=0;
- for (i=0; i<len; ++i) {
- if (original_name[i] == ';') {
- name[j++] = ',';
- name[j++] = ' ';
- }
- else {
- name[j++] = original_name[i];
- }
- }
- name[j] = '\0';
- free(original_name);
+int conditional_VC_SuppressEmailFields(StrBuf *Target, WCTemplputParams *TP)
+{
+ return(atoi(bstr("suppress_email")));
}
-
-
-
-
+/******************************************************************************
+ * parse one VCard *
+ ******************************************************************************/
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;
+ FlushStrBuf(Swap);
StrBuf_RFC822_to_Utf8(Swap, ThisFieldStr, NULL, NULL); /* default charset, current charset */
- b = ThisFieldStr;
- ThisFieldStr = Swap;
- Swap = b;
+ SwapBuffers(Swap, ThisFieldStr);
FlushStrBuf(Swap);
}
Put(thisVC, LKEY(thisField->cval), ThisFieldStr, HFreeStrBuf);
}
-/*
- * 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 parse
- * msgnum Citadel message pointer
- */
+
void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachment *Mime)
{
- StrBuf *Val = NULL;
StrBuf *Swap = NULL;
int i, j, k;
char buf[SIZ];
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);
+ // 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);
+ extract_token(firsttoken, ChrPtr(thisname), 0, ';', sizeof firsttoken);
ntokens = num_tokens(ChrPtr(thisname), ';');
for (j=0, k=0; j < ntokens && k < 10; ++j) {
- ///int evc[10];
-
len = extract_token(buf, ChrPtr(thisname), j, ';', sizeof buf);
if (!strcasecmp(buf, "encoding=quoted-printable")) {
is_qp = 1;
-/* remove_token(thisname, j, ';');*/
}
else if (!strcasecmp(buf, "encoding=base64")) {
is_b64 = 1;
-/* remove_token(thisname, j, ';');*/
}
- else{
+ else {
if (StrLength(thisVCToken) > 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)) {
vcField *thisField = (vcField *)vField;
StrBuf *ThisFieldStr = NULL;
- syslog(LOG_DEBUG, "got this token: %s, found: %s", ChrPtr(thisVCToken), thisField->STR.Key);
+ // syslog(LOG_DEBUG, "got this token: %s, found: %s", ChrPtr(thisVCToken), thisField->STR.Key);
switch (thisField->Type) {
case StringCluster: {
int j = 0;
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++;
}
break;
case Base64BinaryAttachment:
+ ThisFieldStr = NewStrBufPlain(v->prop[i].value, -1);
+ StrBufDecodeBase64(ThisFieldStr);
+ PutVcardItem(VC, thisField, ThisFieldStr, is_qp, Swap);
+ break;
case TerminateList:
case UnKnown:
break;
StrBufAppendBufPlain(oldVal, v->prop[i].value, -1, 0);
continue;
}
-
- /* copy over the payload into a StrBuf */
- Val = NewStrBufPlain(v->prop[i].value, -1);
-
- /* if we have some untagged QP, detect it here. */
- if (is_qp || (strstr(v->prop[i].value, "=?")!=NULL)){
- StrBuf *b;
- StrBuf_RFC822_to_Utf8(Swap, Val, NULL, NULL); /* default charset, current charset */
- b = Val;
- Val = Swap;
- Swap = b;
- FlushStrBuf(Swap);
- }
- else if (is_b64) {
- StrBufDecodeBase64(Val);
- }
-#if 0
- syslog(LOG_DEBUG, "-> firsttoken: %s thisname: %s Value: [%s][%s]",
- firsttoken,
- ChrPtr(thisname),
- ChrPtr(Val),
- v->prop[i].value);
-#endif
- FreeStrBuf(&Val);
}
FreeStrBuf(&thisname);
FreeStrBuf(&Swap);
FreeStrBuf(&thisVCToken);
}
-void tmplput_VCARD_ITEM(StrBuf *Target, WCTemplputParams *TP)
-{
- HashList *VC = CTX(CTX_VCARD);
- int evc;
- void *vStr;
-
- evc = GetTemplateTokenNumber(Target, TP, 0, -1);
- if (evc != -1)
- {
- if (GetHash(VC, IKEY(evc), &vStr))
- {
- StrBufAppendTemplate(Target, TP,
- (StrBuf*) vStr,
- 1);
- }
- }
-
-}
-
-void display_one_vcard (StrBuf *Target, HashList *VC, const char *tp_name, size_t tp_name_len)
+HashList *CtxGetVcardList(StrBuf *Target, WCTemplputParams *TP)
{
- WCTemplputParams *TP = NULL;
- WCTemplputParams SubTP;
-
- memset(&SubTP, 0, sizeof(WCTemplputParams));
- StackContext(TP, &SubTP, VC, CTX_VCARD, 0, NULL);
-
- DoTemplate(tp_name, tp_name_len, Target, &SubTP);
- UnStackContext(&SubTP);
+ HashList *pb = CTX(CTX_VCARD_LIST);
+ return pb;
}
+/******************************************************************************
+ * Extract an embedded photo from a vCard for display on the client *
+ ******************************************************************************/
-/*
- * Render the address book using info we gathered during the scan
- *
- * addrbook the addressbook to render
- * num_ab the number of the addressbook
- */
-void do_addrbook_view(addrbookent *addrbook, int num_ab) {
- int i = 0;
- int displayed = 0;
- int bg = 0;
- static int NAMESPERPAGE = 60;
- int num_pages = 0;
- int tabfirst = 0;
- char tabfirst_label[64];
- int tablast = 0;
- char tablast_label[64];
- char this_tablabel[64];
- int page = 0;
- char **tablabels;
-
- if (num_ab == 0) {
- wc_printf("<br><br><br><div align=\"center\"><i>");
- wc_printf(_("This address book is empty."));
- wc_printf("</i></div>\n");
- return;
- }
-
- if (num_ab > 1) {
- qsort(addrbook, num_ab, sizeof(addrbookent), abcmp);
- }
-
- num_pages = (num_ab / NAMESPERPAGE) + 1;
+void display_vcard_photo_img(void)
+{
+ long msgnum = 0L;
+ StrBuf *vcard;
+ struct vCard *v;
+ char *photosrc;
+ const char *contentType;
+ wcsession *WCC = WC;
- tablabels = malloc(num_pages * sizeof (char *));
- if (tablabels == NULL) {
- wc_printf("<br><br><br><div align=\"center\"><i>");
- wc_printf(_("An internal error has occurred."));
- wc_printf("</i></div>\n");
+ msgnum = StrBufExtract_long(WCC->Hdr->HR.ReqLine, 0, '/');
+
+ vcard = load_mimepart(msgnum,"1");
+ v = VCardLoad(vcard);
+
+ photosrc = vcard_get_prop(v, "PHOTO", 1,0,0);
+ FlushStrBuf(WCC->WBuf);
+ StrBufAppendBufPlain(WCC->WBuf, photosrc, -1, 0);
+ if (StrBufDecodeBase64(WCC->WBuf) <= 0) {
+ FlushStrBuf(WCC->WBuf);
+
+ hprintf("HTTP/1.1 500 %s\n","Unable to get photo");
+ output_headers(0, 0, 0, 0, 0, 0);
+ hprintf("Content-Type: text/plain\r\n");
+ begin_burst();
+ wc_printf(_("Could Not decode vcard photo\n"));
+ end_burst();
return;
}
+ contentType = GuessMimeType(ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
+ http_transmit_thing(contentType, 0);
+ free(v);
+ free(photosrc);
+}
- for (i=0; i<num_pages; ++i) {
- tabfirst = i * NAMESPERPAGE;
- tablast = tabfirst + NAMESPERPAGE - 1;
- if (tablast > (num_ab - 1)) tablast = (num_ab - 1);
- nametab(tabfirst_label, 64, addrbook[tabfirst].ab_name);
- nametab(tablast_label, 64, addrbook[tablast].ab_name);
- sprintf(this_tablabel, "%s - %s", tabfirst_label, tablast_label);
- tablabels[i] = strdup(this_tablabel);
- }
-
- tabbed_dialog(num_pages, tablabels);
- page = (-1);
-
- for (i=0; i<num_ab; ++i) {
+wc_mime_attachment *load_vcard(message_summary *Msg)
+{
+ HashPos *it;
+ StrBuf *FoundCharset = NewStrBuf();
+ StrBuf *Error;
+ void *vMime;
+ const char *Key;
+ long len;
+ wc_mime_attachment *Mime;
+ wc_mime_attachment *VCMime = NULL;
- if ((i / NAMESPERPAGE) != page) { /* New tab */
- page = (i / NAMESPERPAGE);
- if (page > 0) {
- wc_printf("</tr></table>\n");
- end_tab(page-1, num_pages);
- }
- begin_tab(page, num_pages);
- wc_printf("<table border=\"0\" cellspacing=\"0\" cellpadding=\"3\" width=\"100%%\">\n");
- displayed = 0;
- }
+ Msg->MsgBody = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
+ memset(Msg->MsgBody, 0, sizeof(wc_mime_attachment));
+ Msg->MsgBody->msgnum = Msg->msgnum;
- if ((displayed % 4) == 0) {
- if (displayed > 0) {
- wc_printf("</tr>\n");
- }
- bg = 1 - bg;
- wc_printf("<tr bgcolor=\"#%s\">",
- (bg ? "dddddd" : "ffffff")
- );
- }
-
- wc_printf("<td>");
-
- wc_printf("<a href=\"readfwd?startmsg=%ld?is_singlecard=1",
- addrbook[i].ab_msgnum);
- wc_printf("?maxmsgs=1?is_summary=0?alpha=%s\">", bstr("alpha"));
- vcard_n_prettyize(addrbook[i].ab_name);
- escputs(addrbook[i].ab_name);
- wc_printf("</a></td>\n");
- ++displayed;
- }
+ load_message(Msg, FoundCharset, &Error);
- /* Placeholders for empty columns at end */
- if ((num_ab % 4) != 0) {
- for (i=0; i<(4-(num_ab % 4)); ++i) {
- wc_printf("<td> </td>");
+ FreeStrBuf(&FoundCharset);
+ /* look up the vcard... */
+ it = GetNewHashPos(Msg->AllAttach, 0);
+ while (GetNextHashPos(Msg->AllAttach, it, &len, &Key, &vMime) &&
+ (vMime != NULL))
+ {
+ Mime = (wc_mime_attachment*) vMime;
+ if ((strcmp(ChrPtr(Mime->ContentType),
+ "text/x-vcard") == 0) ||
+ (strcmp(ChrPtr(Mime->ContentType),
+ "text/vcard") == 0))
+ {
+ VCMime = Mime;
+ break;
}
}
+ DeleteHashPos(&it);
+ if (VCMime == NULL)
+ return NULL;
- wc_printf("</tr></table>\n");
- end_tab((num_pages-1), num_pages);
-
- begin_tab(num_pages, num_pages);
- /* FIXME there ought to be something here */
- end_tab(num_pages, num_pages);
-
- for (i=0; i<num_pages; ++i) {
- free(tablabels[i]);
- }
- free(tablabels);
+ if (VCMime->Data == NULL)
+ MimeLoadData(VCMime);
+ return VCMime;
}
-
-
-
/*
* Edit the vCard component of a MIME message.
* Supply the message number
wc_mime_attachment *VCAtt,
const char *return_to,
const char *force_room) {
- HashList *VC; WCTemplputParams SubTP;
+ WCTemplputParams SubTP;
wcsession *WCC = WC;
message_summary *Msg = NULL;
wc_mime_attachment *VCMime = NULL;
struct vCard *v;
char whatuser[256];
- VC = NewHash(0, lFlathash);
+ addrbookent ab;
+ memset(&ab, 0, sizeof(addrbookent));
+ ab.VC = NewHash(0, lFlathash);
/* Display the form */
output_headers(1, 1, 1, 0, 0, 0);
Msg->msgnum = msgnum;
VCMime = load_vcard(Msg);
if (VCMime == NULL) {
- convenience_page("770000", _("Error"), "");///TODO: important message
+ convenience_page("770000", _("Error"), "");/*TODO: important message*/
DestroyMessageSummary(Msg);
return;
+ DeleteHash(&ab.VC);
}
v = VCardLoad(VCMime->Data);
v = VCardLoad(VCAtt->Data);
}
- parse_vcard(WCC->WBuf, v, VC, NULL);
+ parse_vcard(WCC->WBuf, v, ab.VC, NULL);
vcard_free(v);
}
memset(&SubTP, 0, sizeof(WCTemplputParams));
-
{
WCTemplputParams *TP = NULL;
WCTemplputParams SubTP;
- StackContext(TP, &SubTP, VC, CTX_VCARD, 0, NULL);
+
+ StackContext(TP, &SubTP, &ab, CTX_VCARD, 0, NULL);
DoTemplate(HKEY("vcard_edit"), WCC->WBuf, &SubTP);
UnStackContext(&SubTP);
}
- DeleteHash(&VC);
+ DeleteHash(&ab.VC);
wDumpContent(1);
do_edit_vcard(msgnum, partnum, NULL, NULL, "", NULL);
}
-
-
/*
* parse edited vcard from the browser
*/
if (postVcard == NULL) {
AppendImportantMessage(_("An error has occurred."), -1);
edit_vcard();
- return;//// more details
+ return;/*/// more details*/
}
Buf = NewStrBuf();
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);
FreeStrBuf(&Buf);
}
-
-
-/*
- * Extract an embedded photo from a vCard for display on the client
- */
-void display_vcard_photo_img(void)
-{
- long msgnum = 0L;
- StrBuf *vcard;
- struct vCard *v;
- char *photosrc;
- const char *contentType;
- wcsession *WCC = WC;
-
- msgnum = StrBufExtract_long(WCC->Hdr->HR.ReqLine, 0, '/');
-
- vcard = load_mimepart(msgnum,"1");
- v = VCardLoad(vcard);
-
- photosrc = vcard_get_prop(v, "PHOTO", 1,0,0);
- FlushStrBuf(WCC->WBuf);
- StrBufAppendBufPlain(WCC->WBuf, photosrc, -1, 0);
- if (StrBufDecodeBase64(WCC->WBuf) <= 0) {
- FlushStrBuf(WCC->WBuf);
-
- hprintf("HTTP/1.1 500 %s\n","Unable to get photo");
- output_headers(0, 0, 0, 0, 0, 0);
- hprintf("Content-Type: text/plain\r\n");
- begin_burst();
- wc_printf(_("Could Not decode vcard photo\n"));
- end_burst();
- return;
- }
- contentType = GuessMimeType(ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
- http_transmit_thing(contentType, 0);
- free(v);
- free(photosrc);
-}
+/******************************************************************************
+ * Render Addressbooks *
+ ******************************************************************************/
typedef struct _vcardview_struct {
long is_singlecard;
- addrbookent *addrbook;
- long num_ab;
+ HashList *addrbook;
} vcardview_struct;
VS->is_singlecard = ibstr("is_singlecard");
if (VS->is_singlecard != 1) {
+ VS->addrbook = NewHash(0, NULL);
if (oper == do_search) {
snprintf(cmd, len, "MSGS SEARCH|%s", bstr("query"));
}
return 200;
}
-
-
-
-
-/*
- * preparse a vcard name
- * display_vcard() calls this after parsing the textual vCard into
- * our 'struct vCard' data object.
- * This gets called instead of display_parsed_vcard() if we are only looking
- * to extract the person's name instead of displaying the card.
- */
-void fetchname_parsed_vcard(struct vCard *v, char **storename) {
- char *name;
- char *prop;
- char buf[SIZ];
- int j, n, len;
- int is_qp = 0;
- int is_b64 = 0;
-
- *storename = NULL;
-
- name = vcard_get_prop(v, "n", 1, 0, 0);
- if (name != NULL) {
- len = strlen(name);
- prop = vcard_get_prop(v, "n", 1, 0, 1);
- n = num_tokens(prop, ';');
-
- for (j=0; j<n; ++j) {
- extract_token(buf, prop, j, ';', sizeof buf);
- if (!strcasecmp(buf, "encoding=quoted-printable")) {
- is_qp = 1;
- }
- if (!strcasecmp(buf, "encoding=base64")) {
- is_b64 = 1;
- }
- }
- if (is_qp) {
- /* %ff can become 6 bytes in utf8 */
- *storename = malloc(len * 2 + 3);
- j = CtdlDecodeQuotedPrintable(
- *storename, name,
- len);
- (*storename)[j] = 0;
- }
- else if (is_b64) {
- /* ff will become one byte.. */
- *storename = malloc(len + 50);
- CtdlDecodeBase64(
- *storename, name,
- len);
- }
- else {
- size_t len;
-
- len = strlen (name);
-
- *storename = malloc(len + 3); /* \0 + eventualy missing ', '*/
- memcpy(*storename, name, len + 1);
- }
- /* vcard_n_prettyize(storename); */
- }
-
-}
-
int vcard_LoadMsgFromServer(SharedMessageStatus *Stat,
void **ViewSpecific,
message_summary* Msg,
int is_new,
int i)
{
+ wcsession *WCC = WC;
+ WCTemplputParams *TP = NULL;
+ WCTemplputParams SubTP;
vcardview_struct *VS;
-// char *ab_name;
- char *namebuf;
-
- namebuf = NULL;
- long len;
- int j;
wc_mime_attachment *VCMime = NULL;
struct vCard *v;
- char *name;
- StrBuf *Buf;
- StrBuf *Buf2;
- char this_alpha = 0;
- HashList *VC;
+ addrbookent* abEntry;
VS = (vcardview_struct*) *ViewSpecific;
v = VCardLoad(VCMime->Data);
if (v == NULL) return 0;
- VC = NewHash(0, lFlathash);
- parse_vcard(WC->WBuf, v, VC, VCMime);
-
- name = vcard_get_prop(v, "n", 1, 0, 0);
- if (name != NULL) {
- Buf = NewStrBufPlain(name, -1);
- Buf2 = NewStrBufPlain(NULL, StrLength(Buf));
- StrBuf_RFC822_to_Utf8(Buf2, Buf, WC->DefaultCharset, NULL);
- this_alpha = ChrPtr(Buf)[0];
- FreeStrBuf(&Buf);
- FreeStrBuf(&Buf2);
+
+ abEntry = (addrbookent*) malloc(sizeof(addrbookent));
+ memset(abEntry, 0, sizeof(addrbookent));
+ abEntry->name = NewStrBuf();
+ abEntry->VC = NewHash(0, lFlathash);
+ abEntry->ab_msgnum = Msg->msgnum;
+
+ parse_vcard(WCC->WBuf, v, abEntry->VC, VCMime);
+
+ memset(&SubTP, 0, sizeof(WCTemplputParams));
+ StackContext(TP, &SubTP, abEntry, CTX_VCARD, 0, NULL);
+
+ // No, don't display the name, it just shits all over the screen
+ // DoTemplate(HKEY("vcard_list_name"), WCC->WBuf, &SubTP);
+
+ UnStackContext(&SubTP);
+
+ if (StrLength(abEntry->name) == 0) {
+ StrBufPlain(abEntry->name, _("(no name)"), -1);
}
- fetchname_parsed_vcard(v, &namebuf);
- DeleteHash(&VC);
+ syslog(LOG_DEBUG, "abEntry->name : %s", ChrPtr(abEntry->name));
vcard_free(v);
+
+ Put(VS->addrbook, SKEY(abEntry->name), abEntry, deleteAbEnt);
+ return 0;
+}
- if (namebuf != NULL) {
- lastfirst_firstlast(namebuf);
- striplt(namebuf);
- len = strlen(namebuf);
- for (j=0; i<len; ++j) {
- if (namebuf[j] != ';') return 0;
- }
- free (namebuf);
- namebuf = strdup(_("(no name)"));
+/*
+ * Render the address book using info we gathered during the scan
+ *
+ * addrbook the addressbook to render
+ * num_ab the number of the addressbook
+ */
+static int NAMESPERPAGE = 60;
+void do_addrbook_view(vcardview_struct* VS) {
+ long i = 0;
+ int num_pages = 0;
+ int tabfirst = 0;
+ int tablast = 0;
+ StrBuf **tablabels;
+ int num_ab = GetCount(VS->addrbook);
+ HashList *headlines;
+ wcsession *WCC = WC;
+
+ WCTemplputParams *TP = NULL;
+ WCTemplputParams SubTP;
+
+ memset(&SubTP, 0, sizeof(WCTemplputParams));
+
+ if (num_ab == 0) {
+ do_template("vcard_list_empty");
+ return;
}
- else {
- namebuf = strdup(_("(no name)"));
+
+ if (num_ab > 1) {
+ SortByHashKey(VS->addrbook, 1);
}
+ num_pages = (GetCount(VS->addrbook) / NAMESPERPAGE) + 1;
- if (namebuf == NULL)
- return 0;
- ++VS->num_ab;
- VS->addrbook = realloc(VS->addrbook,
- (sizeof(addrbookent) * VS->num_ab) );
- safestrncpy(VS->addrbook[VS->num_ab-1].ab_name, namebuf,
- sizeof(VS->addrbook[VS->num_ab-1].ab_name));
- VS->addrbook[VS->num_ab-1].ab_msgnum = Msg->msgnum;
- free(namebuf);
- return 0;
+ tablabels = malloc(num_pages * sizeof (StrBuf *));
+ if (tablabels == NULL) {
+ return;
+ }
+
+ headlines = NewHash(0, lFlathash);
+ for (i=0; i<num_pages; ++i) {
+ void *v1 = NULL;
+ void *v2 = NULL;
+ long hklen1, hklen2;
+ const char *c1, *c2;
+ StrBuf *headline;
+ addrbookent *a1, *a2;
+
+ tabfirst = i * NAMESPERPAGE;
+ tablast = tabfirst + NAMESPERPAGE - 1;
+ if (tablast > (num_ab - 1)) tablast = (num_ab - 1);
+
+ headline = NewStrBufPlain(NULL, StrLength(v1) + StrLength(v2) + 10);
+ if (GetHashAt(VS->addrbook, tabfirst, &hklen1, &c1, &v1)) {
+ a1 = (addrbookent*) v1;
+ StrBufAppendBuf(headline, a1->name, 0);
+ StrBuf_Utf8StrCut(headline, 3);
+ if (GetHashAt(VS->addrbook, tablast, &hklen2, &c2, &v2)) {
+
+ a2 = (addrbookent*) v2;
+ StrBufAppendBufPlain(headline, HKEY(" - "), 0);
+ StrBufAppendBuf(headline, a2->name, 0);
+ StrBuf_Utf8StrCut(headline, 9);
+ }
+ }
+ tablabels[i] = headline;
+ Put(headlines, LKEY(i), headline, HFreeStrBuf);
+ }
+ StrTabbedDialog(WC->WBuf, num_pages, tablabels);
+ StackContext(TP, &SubTP, VS->addrbook, CTX_VCARD_LIST, 0, NULL);
+
+ DoTemplate(HKEY("vcard_list"), WCC->WBuf, &SubTP);
+ UnStackContext(&SubTP);
+ DeleteHash(&headlines);
+ free(tablabels);
+ StrBufAppendBufPlain(WCC->WBuf, HKEY("</div>"), 0);/* closes: id=global */
}
+
int vcard_RenderView_or_Tail(SharedMessageStatus *Stat, void **ViewSpecific, long oper)
{
const StrBuf *Mime;
vcardview_struct *VS;
VS = (vcardview_struct*) *ViewSpecific;
- if (VS->is_singlecard)
- read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime);
- else
- do_addrbook_view(VS->addrbook, VS->num_ab); /* Render the address book */
+ if (VS->is_singlecard) {
+ read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime, NULL);
+ }
+ else {
+ do_addrbook_view(VS); /* Render the address book */
+ }
return 0;
}
VS = (vcardview_struct*) *ViewSpecific;
wDumpContent(1);
- if ((VS != NULL) &&
- (VS->addrbook != NULL))
- free(VS->addrbook);
- if (VS != NULL)
+ if ((VS != NULL) && (VS->addrbook != NULL)) {
+ DeleteHash(&VS->addrbook);
+ }
+ if (VS != NULL) {
free(VS);
+ }
+
return 0;
}
{
wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
wcsession *WCC = WC;
- if (StrLength(Mime->Data) == 0)
+ if (StrLength(Mime->Data) == 0) {
MimeLoadData(Mime);
+ }
if (StrLength(Mime->Data) > 0) {
struct vCard *v;
StrBuf *Buf;
v = VCardLoad(Mime->Data);
if (v != NULL) {
- HashList *VC;
-
- VC = NewHash(0, lFlathash);
- parse_vcard(Target, v, VC, Mime);
- display_one_vcard (Target, VC, HKEY("vcard_msg_display"));
- DeleteHash(&VC);
+ WCTemplputParams *TP = NULL;
+ WCTemplputParams SubTP;
+ addrbookent ab;
+ memset(&ab, 0, sizeof(addrbookent));
+
+ ab.VC = NewHash(0, lFlathash);
+ ab.ab_msgnum = Mime->msgnum;
+
+ parse_vcard(Target, v, ab.VC, Mime);
+
+ memset(&SubTP, 0, sizeof(WCTemplputParams));
+ StackContext(TP, &SubTP, &ab, CTX_VCARD, 0, NULL);
+
+ DoTemplate(HKEY("vcard_msg_display"), Target, &SubTP);
+ UnStackContext(&SubTP);
+ DeleteHash(&ab.VC);
+ vcard_free(v);
}
else {
ServerStartModule_VCARD
(void)
{
- ///VCToEnum = NewHash(0, NULL);
-
}
void
DeleteHash(&DefineToToken);
DeleteHash(&vcNames);
DeleteHash(&VCTokenToDefine);
- /// DeleteHash(&VCToEnum);
}
void
VCTokenToDefine = NewHash(1, NULL);
autoRegisterTokens(&VCEnumCounter, VCStrE, Prefix, 0, 0);
FreeStrBuf(&Prefix);
+
+ REGISTERTokenParamDefine(NAMESPERPAGE);
+
+
RegisterCTX(CTX_VCARD);
+ RegisterCTX(CTX_VCARD_LIST);
RegisterCTX(CTX_VCARD_TYPE);
+
RegisterReadLoopHandlerset(
VIEW_ADDRESSBOOK,
vcard_GetParamsGetServerCall,
NULL,
vcard_LoadMsgFromServer,
vcard_RenderView_or_Tail,
- vcard_Cleanup);
+ vcard_Cleanup,
+ NULL);
+
+ RegisterIterator("MAIL:VCARDS", 0, NULL, CtxGetVcardList, NULL, NULL, CTX_VCARD, CTX_VCARD_LIST, IT_NOFLAG);
+
+
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);
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:MSGNO", 0, 1, tmpl_vcard_msgno, NULL, CTX_VCARD);
RegisterNamespace("VC:CTXNAME", 1, 1, tmpl_vcard_context_name_str, NULL, CTX_VCARD_TYPE);
REGISTERTokenParamDefine(FlatString);
REGISTERTokenParamDefine(StringCluster);
REGISTERTokenParamDefine(TerminateList);
REGISTERTokenParamDefine(Address);
- RegisterConditional("VC:HAVE:TYPE", 1, conditional_VC_Havetype, CTX_VCARD);
+ RegisterConditional("VC:HAVE:TYPE", 1, conditional_VC_Havetype, CTX_VCARD);
+ RegisterConditional("COND:VC:SUPPRESS_EMAIL_FIELDS", 1, conditional_VC_SuppressEmailFields, 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);
RegisterMimeRenderer(HKEY("text/x-vcard"), render_MIME_VCard, 1, 201);
RegisterMimeRenderer(HKEY("text/vcard"), render_MIME_VCard, 1, 200);
}
-