Cleanup templating of vcard lists
authorWilfried Goesgens <willi@arangodb.com>
Mon, 9 Nov 2015 20:05:17 +0000 (21:05 +0100)
committerWilfried Goesgens <willi@arangodb.com>
Mon, 9 Nov 2015 20:05:17 +0000 (21:05 +0100)
webcit/vcard_edit.c

index 659b23c7e5ffd88b1118e4ccd79f26049e860c97..b3f2cba847d5cc58eb261a9ab213b91e90977af2 100644 (file)
@@ -359,26 +359,6 @@ int conditional_VC_Havetype(StrBuf *Target, WCTemplputParams *TP)
 }
 
 
-/*
- * 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()
@@ -392,29 +372,6 @@ void nametab(char *tabbuf, long len, char *name) {
        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;
@@ -495,11 +452,6 @@ void vcard_n_prettyize(char *name)
 }
 
 
-
-
-
-
-
 void PutVcardItem(HashList *thisVC, vcField *thisField, StrBuf *ThisFieldStr, int is_qp, StrBuf *Swap)
 {
        /* if we have some untagged QP, detect it here. */
@@ -557,7 +509,7 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, wc_mime_attachme
                /*len = */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];
+                       /*int evc[10];*/
                        
                        len = extract_token(buf, ChrPtr(thisname), j, ';', sizeof buf);
                        if (!strcasecmp(buf, "encoding=quoted-printable")) {
@@ -711,118 +663,43 @@ void display_one_vcard (StrBuf *Target, HashList *VC, const char *tp_name, size_
        UnStackContext(&SubTP);
 }
 
-
 /*
- * Render the address book using info we gathered during the scan
- *
- * addrbook    the addressbook to render
- * num_ab      the number of the addressbook
+ * Extract an embedded photo from a vCard for display on the client
  */
-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;
-
-       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");
-               return;
-       }
-
-       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&nbsp;-&nbsp;%s", tabfirst_label, tablast_label);
-               tablabels[i] = strdup(this_tablabel);
-       }
-
-       tabbed_dialog(num_pages, tablabels);
-       page = (-1);
-
-       for (i=0; i<num_ab; ++i) {
-
-               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;
-               }
+void display_vcard_photo_img(void)
+{
+       long msgnum = 0L;
+       StrBuf *vcard;
+       struct vCard *v;
+       char *photosrc;
+       const char *contentType;
+       wcsession *WCC = WC;
 
-               if ((displayed % 4) == 0) {
-                       if (displayed > 0) {
-                               wc_printf("</tr>\n");
-                       }
-                       bg = 1 - bg;
-                       wc_printf("<tr bgcolor=\"#%s\">",
-                               (bg ? "dddddd" : "ffffff")
-                       );
-               }
+       msgnum = StrBufExtract_long(WCC->Hdr->HR.ReqLine, 0, '/');
        
-               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;
-       }
-
-       /* Placeholders for empty columns at end */
-       if ((num_ab % 4) != 0) {
-               for (i=0; i<(4-(num_ab % 4)); ++i) {
-                       wc_printf("<td>&nbsp;</td>");
-               }
-       }
-
-       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]);
+       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;
        }
-       free(tablabels);
+       contentType = GuessMimeType(ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
+       http_transmit_thing(contentType, 0);
+       free(v);
+       free(photosrc);
 }
 
-
-
-
 /*
  * Edit the vCard component of a MIME message.  
  * Supply the message number
@@ -857,7 +734,7 @@ void do_edit_vcard(long msgnum, char *partnum,
                        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;
                        }
@@ -959,7 +836,7 @@ void submit_vcard(void) {
        if (postVcard == NULL) {
                AppendImportantMessage(_("An error has occurred."), -1);
                edit_vcard();
-               return;//// more details
+               return;/*/// more details*/
        }
        
        Buf = NewStrBuf();
@@ -1026,39 +903,6 @@ void submit_vcard(void) {
                        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);
@@ -1110,46 +954,24 @@ void submit_vcard(void) {
 
 
 /*
- * Extract an embedded photo from a vCard for display on the client
+ * 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)
  */
-void display_vcard_photo_img(void)
-{
-       long msgnum = 0L;
-       StrBuf *vcard;
-       struct vCard *v;
-       char *photosrc;
-       const char *contentType;
-       wcsession *WCC = WC;
+typedef struct _addrbookent {
+       StrBuf *name;
+       HashList *VC;
+       long ab_msgnum;         /* message number of address book entry */
+} addrbookent;
 
-       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);
+void deleteAbEnt(void *v) {
+       addrbookent *vc = (addrbookent*)v;
+       DeleteHash(&vc->VC);
+       FreeStrBuf(&vc->name);
 }
 
 typedef struct _vcardview_struct {
        long is_singlecard;
-       addrbookent *addrbook;
-       long num_ab;
+       HashList *addrbook;
 
 } vcardview_struct;
 
@@ -1169,6 +991,7 @@ int vcard_GetParamsGetServerCall(SharedMessageStatus *Stat,
 
        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"));
                }
@@ -1180,70 +1003,6 @@ int vcard_GetParamsGetServerCall(SharedMessageStatus *Stat,
        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, 
@@ -1251,19 +1010,9 @@ int vcard_LoadMsgFromServer(SharedMessageStatus *Stat,
                            int i)
 {
        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;
 
@@ -1274,53 +1023,159 @@ int vcard_LoadMsgFromServer(SharedMessageStatus *Stat,
        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);
-       }
 
-       fetchname_parsed_vcard(v, &namebuf);
-       DeleteHash(&VC);
+       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(WC->WBuf, v, abEntry->VC, VCMime);
+
+       display_one_vcard(abEntry->name, abEntry->VC, HKEY("vcard_list_name"));
+
+       if (StrLength(abEntry->name) == 0) {
+               StrBufPlain(abEntry->name, _("(no name)"), -1);
+       }
 
        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;
+/*
+ * 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(vcardview_struct* VS) {
+       long i = 0;
+       int displayed = 0;
+       int bg = 0;
+       static int NAMESPERPAGE = 60;
+       int num_pages = 0;
+       int tabfirst = 0;
+       int tablast = 0;
+       int page = 0;
+       char **tablabels;
+       int num_ab = GetCount(VS->addrbook);
+       HashList *headlines;
+       HashPos *it;
+       wcsession *WCC = WC;
+
+       WCTemplputParams *TP = NULL;
+       WCTemplputParams SubTP;
+
+        memset(&SubTP, 0, sizeof(WCTemplputParams));    
+       
+       if (num_ab == 0) {
+               do_template("vcard_list_empty");
+               return;
+       }
+
+       if (num_ab > 1) {
+               ///SortByHashKey(VS->addrbook, 0);
+       }
+
+       num_pages = (GetCount(VS->addrbook) / NAMESPERPAGE) + 1;
+
+       tablabels = malloc(num_pages * sizeof (char *));
+       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);
+
+                       if (GetHashAt(VS->addrbook, tablast, &hklen2, &c2, &v2)) {
+
+                               a2 = (addrbookent*) v2;
+                               StrBufAppendBufPlain(headline, HKEY(" - "), 0);
+                               StrBufAppendBuf(headline, a2->name, 0);
+                       }
                }
-               free (namebuf);
-               namebuf = strdup(_("(no name)"));
+               Put(headlines, LKEY(i), headline, HFreeStrBuf);
        }
-       else {
-               namebuf = strdup(_("(no name)"));
+
+       tabbed_dialog(num_pages, tablabels);
+       page = (-1);
+
+       it = GetNewHashPos(VS->addrbook, 0);
+       for (i=0; i<num_ab; ++i) {
+               void *v;
+               long hklen;
+               const char *key;
+               addrbookent *abEnt;
+               GetNextHashPos(VS->addrbook, it, &hklen, &key, &v);
+               if (v == NULL)
+                       continue;
+               abEnt = (addrbookent *) v;
+               if ((i / NAMESPERPAGE) != page) {       /* New tab */
+                       page = (i / NAMESPERPAGE);
+                       if (page > 0) {
+                               do_template("vcard_list_section_end");
+                               end_tab(page-1, num_pages);
+                       }
+                       begin_tab(page, num_pages);
+                       do_template("vcard_list_section_start");
+                       displayed = 0;
+               }
+
+               if ((displayed % 4) == 0) {
+                       if (displayed > 0) {
+                               do_template("vcard_list_row_end");
+                       }
+                       do_template("vcard_list_row_start");
+                       bg = 1 - bg;
+               }
+       
+
+               StackContext(TP, &SubTP, abEnt->VC, CTX_VCARD, 0, NULL);
+
+               DoTemplate(HKEY("vcard_list_entry"), WCC->WBuf, &SubTP);
+               UnStackContext(&SubTP);
+
+               ++displayed;
+       }
+       DeleteHashPos(&it);
+
+       /* Placeholders for empty columns at end */
+       if ((num_ab % 4) != 0) {
+               for (i=0; i<(4-(num_ab % 4)); ++i) {
+                       do_template("vcard_list_cell_end");
+               }
        }
+       
+       do_template("vcard_list_section_end");
+       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);
 
-       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;
+       DeleteHash(&headlines);
+       wDumpContent(1);
 }
 
 
+
 int vcard_RenderView_or_Tail(SharedMessageStatus *Stat, void **ViewSpecific, long oper)
 {
        const StrBuf *Mime;
@@ -1330,7 +1185,7 @@ int vcard_RenderView_or_Tail(SharedMessageStatus *Stat, void **ViewSpecific, lon
        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 */
+               do_addrbook_view(VS);   /* Render the address book */
        return 0;
 }
 
@@ -1342,9 +1197,10 @@ int vcard_Cleanup(void **ViewSpecific)
        wDumpContent(1);
        if ((VS != NULL) && 
            (VS->addrbook != NULL))
-               free(VS->addrbook);
+               DeleteHash(&VS->addrbook);
        if (VS != NULL) 
                free(VS);
+
        return 0;
 }
 
@@ -1457,4 +1313,3 @@ InitModule_VCARD
        RegisterMimeRenderer(HKEY("text/x-vcard"), render_MIME_VCard, 1, 201);
        RegisterMimeRenderer(HKEY("text/vcard"), render_MIME_VCard, 1, 200);
 }
-