CONF STOREVAL fix off-by-one string termination
[citadel.git] / webcit / vcard_edit.c
index f94841f9ac7caf062ec408cf5d4f93f50a9101d9..e08a227feb7aafbe201c583cfae377edc31c4535 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996-2012 by the citadel.org team
+ * Copyright (c) 1996-2021 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.
@@ -11,7 +11,7 @@
  */
 
 #include "webcit.h"
-#include "webserver.h"
+
 #include "calendar.h"
 
 CtxType CTX_VCARD = CTX_NONE;
@@ -127,6 +127,10 @@ 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) {
@@ -192,6 +196,10 @@ void autoRegisterTokens(long *enumCounter, vcField* vf, StrBuf *BaseStr, int lay
        FreeStrBuf(&subStr);
 }
 
+/******************************************************************************
+ *               VCard template functions                                     *
+ ******************************************************************************/
+
 int preeval_vcard_item(WCTemplateToken *Token)
 {
        WCTemplputParams TPP;
@@ -204,8 +212,7 @@ int preeval_vcard_item(WCTemplateToken *Token)
        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;
@@ -228,8 +235,7 @@ void tmpl_vcard_context_item(StrBuf *Target, WCTemplputParams *TP)
        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;
        }
 
@@ -310,23 +316,21 @@ int filter_VC_ByType(const char* key, long len, void *Context, StrBuf *Target, W
        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) {
                addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
-               if (GetHash(ab->VC, LKEY(vf->cval), &v) && v != NULL)
+               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);
@@ -356,7 +360,6 @@ int filter_VC_ByContextType(const char* key, long len, void *Context, StrBuf *Ta
        }
 }
 
-
 int conditional_VC_Havetype(StrBuf *Target, WCTemplputParams *TP)
 {
        addrbookent *ab = (addrbookent*) CTX(CTX_VCARD);
@@ -386,47 +389,19 @@ int conditional_VC_Havetype(StrBuf *Target, WCTemplputParams *TP)
        return rc;
 }
 
-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;
+/* 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.
+ */
+int conditional_VC_SuppressEmailFields(StrBuf *Target, WCTemplputParams *TP)
+{      
+       return(atoi(bstr("suppress_email")));
+}
 
-       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;
-}
+/******************************************************************************
+ *              parse one VCard                                               *
+ ******************************************************************************/
 
 void PutVcardItem(HashList *thisVC, vcField *thisField, StrBuf *ThisFieldStr, int is_qp, StrBuf *Swap)
 {
@@ -460,11 +435,11 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachme
                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) {
                        len = extract_token(buf, ChrPtr(thisname), j, ';', sizeof buf);
@@ -474,7 +449,7 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachme
                        else if (!strcasecmp(buf, "encoding=base64")) {
                                is_b64 = 1;
                        }
-                       else{
+                       else {
                                if (StrLength(thisVCToken) > 0) {
                                        StrBufAppendBufPlain(thisVCToken, HKEY(";"), 0);
                                }
@@ -488,7 +463,7 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachme
                    (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;
@@ -498,7 +473,6 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachme
                                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++;
                                }
@@ -554,46 +528,16 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachme
        FreeStrBuf(&thisVCToken);
 }
 
-void tmplput_VCARD_ITEM(StrBuf *Target, WCTemplputParams *TP)
-{
-       addrbookent *ab = CTX(CTX_VCARD);
-       int evc;
-       void *vStr;
-
-       evc = GetTemplateTokenNumber(Target, TP, 0, -1);
-       if (evc != -1)
-       {
-               if (GetHash(ab->VC, IKEY(evc), &vStr))
-               {
-                       StrBufAppendTemplate(Target, TP,
-                                            (StrBuf*) vStr,
-                                            1);
-               }
-       }
-       
-}
-
 HashList *CtxGetVcardList(StrBuf *Target, WCTemplputParams *TP)
 {
        HashList *pb = CTX(CTX_VCARD_LIST);
        return pb;
 }
 
-void display_one_vcard (StrBuf *Target, addrbookent *ab, const char *tp_name, size_t tp_name_len)
-{
-       WCTemplputParams *TP = NULL;
-       WCTemplputParams SubTP;
+/******************************************************************************
+ * Extract an embedded photo from a vCard for display on the client           *
+ ******************************************************************************/
 
-        memset(&SubTP, 0, sizeof(WCTemplputParams));    
-       StackContext(TP, &SubTP, ab, CTX_VCARD, 0, NULL);
-
-       DoTemplate(tp_name, tp_name_len, Target, &SubTP);
-       UnStackContext(&SubTP);
-}
-
-/*
- * Extract an embedded photo from a vCard for display on the client
- */
 void display_vcard_photo_img(void)
 {
        long msgnum = 0L;
@@ -601,18 +545,17 @@ void display_vcard_photo_img(void)
        struct vCard *v;
        char *photosrc;
        const char *contentType;
-       wcsession *WCC = WC;
 
-       msgnum = StrBufExtract_long(WCC->Hdr->HR.ReqLine, 0, '/');
+       msgnum = StrBufExtract_long(WC->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);
+       FlushStrBuf(WC->WBuf);
+       StrBufAppendBufPlain(WC->WBuf, photosrc, -1, 0);
+       if (StrBufDecodeBase64(WC->WBuf) <= 0) {
+               FlushStrBuf(WC->WBuf);
                
                hprintf("HTTP/1.1 500 %s\n","Unable to get photo");
                output_headers(0, 0, 0, 0, 0, 0);
@@ -622,12 +565,54 @@ void display_vcard_photo_img(void)
                end_burst();
                return;
        }
-       contentType = GuessMimeType(ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
+       contentType = GuessMimeType(ChrPtr(WC->WBuf), StrLength(WC->WBuf));
        http_transmit_thing(contentType, 0);
        free(v);
        free(photosrc);
 }
 
+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;
+}
+
 /*
  * Edit the vCard component of a MIME message.  
  * Supply the message number
@@ -640,7 +625,6 @@ void do_edit_vcard(long msgnum, char *partnum,
                   const char *return_to, 
                   const char *force_room) {
        WCTemplputParams SubTP;
-       wcsession *WCC = WC;
        message_summary *Msg = NULL;
        wc_mime_attachment *VCMime = NULL;
        struct vCard *v;
@@ -676,7 +660,7 @@ void do_edit_vcard(long msgnum, char *partnum,
                        v = VCardLoad(VCAtt->Data);
                }
 
-               parse_vcard(WCC->WBuf, v, ab.VC, NULL);
+               parse_vcard(WC->WBuf, v, ab.VC, NULL);
        
        
                vcard_free(v);
@@ -689,7 +673,7 @@ void do_edit_vcard(long msgnum, char *partnum,
 
                StackContext(TP, &SubTP, &ab, CTX_VCARD, 0, NULL);
 
-               DoTemplate(HKEY("vcard_edit"), WCC->WBuf, &SubTP);
+               DoTemplate(HKEY("vcard_edit"), WC->WBuf, &SubTP);
                UnStackContext(&SubTP);
        }
        DeleteHash(&ab.VC);
@@ -880,7 +864,9 @@ void submit_vcard(void) {
        FreeStrBuf(&Buf);
 }
 
-
+/******************************************************************************
+ *              Render Addressbooks                                           *
+ ******************************************************************************/
 
 typedef struct _vcardview_struct {
        long is_singlecard;
@@ -922,6 +908,8 @@ int vcard_LoadMsgFromServer(SharedMessageStatus *Stat,
                            int is_new, 
                            int i)
 {
+       WCTemplputParams *TP = NULL;
+       WCTemplputParams SubTP;
        vcardview_struct *VS;
        wc_mime_attachment *VCMime = NULL;
        struct vCard *v;
@@ -942,14 +930,23 @@ int vcard_LoadMsgFromServer(SharedMessageStatus *Stat,
        abEntry->name = NewStrBuf();
        abEntry->VC = NewHash(0, lFlathash);
        abEntry->ab_msgnum = Msg->msgnum;
+
        parse_vcard(WC->WBuf, v, abEntry->VC, VCMime);
 
-       display_one_vcard(abEntry->name, abEntry, HKEY("vcard_list_name"));
+        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"), WC->WBuf, &SubTP);
+
+       UnStackContext(&SubTP);
 
        if (StrLength(abEntry->name) == 0) {
                StrBufPlain(abEntry->name, _("(no name)"), -1);
        }
 
+       syslog(LOG_DEBUG, "abEntry->name : %s", ChrPtr(abEntry->name));
+
        vcard_free(v);
        
        Put(VS->addrbook, SKEY(abEntry->name), abEntry, deleteAbEnt);
@@ -972,7 +969,6 @@ void do_addrbook_view(vcardview_struct* VS) {
        StrBuf **tablabels;
        int num_ab = GetCount(VS->addrbook);
        HashList *headlines;
-       wcsession *WCC = WC;
 
        WCTemplputParams *TP = NULL;
        WCTemplputParams SubTP;
@@ -1027,11 +1023,10 @@ void do_addrbook_view(vcardview_struct* VS) {
        StrTabbedDialog(WC->WBuf, num_pages, tablabels);
        StackContext(TP, &SubTP, VS->addrbook, CTX_VCARD_LIST, 0, NULL);
 
-       DoTemplate(HKEY("vcard_list"), WCC->WBuf, &SubTP);
+       DoTemplate(HKEY("vcard_list"), WC->WBuf, &SubTP);
        UnStackContext(&SubTP);
        DeleteHash(&headlines);
        free(tablabels);
-       StrBufAppendBufPlain(WCC->WBuf, HKEY("</div>"), 0);/* closes: id=global */
 }
 
 
@@ -1042,10 +1037,12 @@ int vcard_RenderView_or_Tail(SharedMessageStatus *Stat, void **ViewSpecific, lon
        vcardview_struct *VS;
 
        VS = (vcardview_struct*) *ViewSpecific;
-       if (VS->is_singlecard)
-               read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime);
-       else
+       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;
 }
 
@@ -1055,11 +1052,12 @@ int vcard_Cleanup(void **ViewSpecific)
 
        VS = (vcardview_struct*) *ViewSpecific;
        wDumpContent(1);
-       if ((VS != NULL) && 
-           (VS->addrbook != NULL))
+       if ((VS != NULL) && (VS->addrbook != NULL)) {
                DeleteHash(&VS->addrbook);
-       if (VS != NULL) 
+       }
+       if (VS != NULL)  {
                free(VS);
+       }
 
        return 0;
 }
@@ -1067,19 +1065,19 @@ int vcard_Cleanup(void **ViewSpecific)
 void render_MIME_VCard(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
 {
        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;
 
                Buf = NewStrBuf();
                /** If it's my vCard I can edit it */
-               if (    (!strcasecmp(ChrPtr(WCC->CurRoom.name), USERCONFIGROOM))
-                       || ((StrLength(WCC->CurRoom.name) > 11) &&
-                           (!strcasecmp(&(ChrPtr(WCC->CurRoom.name)[11]), USERCONFIGROOM)))
-                       || (WCC->CurRoom.view == VIEW_ADDRESSBOOK)
+               if (    (!strcasecmp(ChrPtr(WC->CurRoom.name), USERCONFIGROOM))
+                       || ((StrLength(WC->CurRoom.name) > 11) &&
+                           (!strcasecmp(&(ChrPtr(WC->CurRoom.name)[11]), USERCONFIGROOM)))
+                       || (WC->CurRoom.view == VIEW_ADDRESSBOOK)
                        ) {
                        StrBufAppendPrintf(Buf, "<a href=\"edit_vcard?msgnum=%ld?partnum=%s\">",
                                Mime->msgnum, ChrPtr(Mime->PartNum));
@@ -1091,6 +1089,8 @@ void render_MIME_VCard(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharse
                v = VCardLoad(Mime->Data);
 
                if (v != NULL) {
+                       WCTemplputParams *TP = NULL;
+                       WCTemplputParams SubTP;
                        addrbookent ab;
                        memset(&ab, 0, sizeof(addrbookent));
 
@@ -1098,7 +1098,12 @@ void render_MIME_VCard(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharse
                        ab.ab_msgnum = Mime->msgnum;
 
                        parse_vcard(Target, v, ab.VC, Mime);
-                       display_one_vcard (Target, &ab, HKEY("vcard_msg_display"));
+
+                       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);
 
@@ -1153,7 +1158,8 @@ InitModule_VCARD
                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);
 
@@ -1178,7 +1184,9 @@ InitModule_VCARD
        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);