Finalize vcard editing:
[citadel.git] / webcit / vcard_edit.c
index 067362a5f6559d428544981cf8c0f4521d9752b1..27ba6495b61327e0f61cd5465533d9cf30bef4e2 100644 (file)
@@ -28,6 +28,7 @@ typedef enum _VCStrEnum {
        Number,
        AliasFor,
        Base64BinaryAttachment,
+       UnKnown,
        TerminateList
 }VCStrEnum;
 typedef struct vcField vcField;
@@ -36,48 +37,50 @@ struct vcField {
        VCStrEnum Type;
        vcField *Sub;
        long cval;
+       long parentCVal;
        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("")}}
+       {{HKEY("last")},   FlatString,    NULL, 0, 0, {HKEY("Last Name")}},
+       {{HKEY("first")},  FlatString,    NULL, 0, 0, {HKEY("First Name")}},
+       {{HKEY("middle")}, FlatString,    NULL, 0, 0, {HKEY("Middle Name")}},
+       {{HKEY("prefix")}, FlatString,    NULL, 0, 0, {HKEY("Prefix")}},
+       {{HKEY("suffix")}, FlatString,    NULL, 0, 0, {HKEY("Suffix")}},
+       {{HKEY("")},       TerminateList, NULL, 0, 0, {HKEY("")}}
 };
 
 vcField VCStr_Addrs [] = {
-       {{HKEY("POBox")},    Address,    NULL, 0, {HKEY("PO box")}},
-       {{HKEY("address")},  Address,    NULL, 0, {HKEY("Address")}},
-       {{HKEY("address2")}, Address,    NULL, 0, {HKEY("")}},
-       {{HKEY("city")},     Address,    NULL, 0, {HKEY("City")}},
-       {{HKEY("state")},    Address,    NULL, 0, {HKEY("State")}},
-       {{HKEY("zip")},      Address,    NULL, 0, {HKEY("ZIP code")}},
-       {{HKEY("country")},  Address,    NULL, 0, {HKEY("Country")}},
-       {{HKEY("")},         TerminateList, NULL, 0, {HKEY("")}}
+       {{HKEY("POBox")},    Address,       NULL, 0, 0, {HKEY("PO box")}},
+       {{HKEY("extadr")},   Address,       NULL, 0, 0, {HKEY("Address")}},
+       {{HKEY("street")},   Address,       NULL, 0, 0, {HKEY("")}},
+       {{HKEY("city")},     Address,       NULL, 0, 0, {HKEY("City")}},
+       {{HKEY("state")},    Address,       NULL, 0, 0, {HKEY("State")}},
+       {{HKEY("zip")},      Address,       NULL, 0, 0, {HKEY("ZIP code")}},
+       {{HKEY("country")},  Address,       NULL, 0, 0, {HKEY("Country")}},
+       {{HKEY("")},         TerminateList, NULL, 0, 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("")}}
+       {{HKEY("version")},         Number,                 NULL,        0, 0, {HKEY("")}},
+       {{HKEY("rev")},             Number,                 NULL,        0, 0, {HKEY("")}},
+       {{HKEY("label")},           FlatString,             NULL,        0, 0, {HKEY("")}},
+       {{HKEY("uid")},             FlatString,             NULL,        0, 0, {HKEY("")}},
+       {{HKEY("n")},               StringCluster,          VCStr_Ns,    0, 0, {HKEY("")}}, /* N is name, but only if there's no FN already there */
+       {{HKEY("fn")},              FlatString,             NULL,        0, 0, {HKEY("")}}, /* FN (full name) is a true 'display name' field */
+       {{HKEY("title")},           FlatString,             NULL,        0, 0, {HKEY("Title:")}},
+       {{HKEY("org")},             FlatString,             NULL,        0, 0, {HKEY("Organization:")}},/* organization */
+       {{HKEY("email")},           EmailAddr,              NULL,        0, 0, {HKEY("E-mail:")}},
+       {{HKEY("tel")},             PhoneNumber,            NULL,        0, 0, {HKEY("Telephone:")}},
+       {{HKEY("adr")},             StringCluster,          VCStr_Addrs, 0, 0, {HKEY("Address:")}},
+       {{HKEY("photo")},           Base64BinaryAttachment, NULL,        0, 0, {HKEY("Photo:")}},
+       {{HKEY("tel;home")},        PhoneNumber,            NULL,        0, 0, {HKEY(" (home)")}},
+       {{HKEY("tel;work")},        PhoneNumber,            NULL,        0, 0, {HKEY(" (work)")}},
+       {{HKEY("tel;fax")},         PhoneNumber,            NULL,        0, 0, {HKEY(" (fax)")}},
+       {{HKEY("tel;cell")},        PhoneNumber,            NULL,        0, 0, {HKEY(" (cell)")}},
+       {{HKEY("email;internet")},  EmailAddr,              NULL,        0, 0, {HKEY("E-mail:")}},
+       {{HKEY("UNKNOWN")},         UnKnown,                NULL,        0, 0, {HKEY("")}},
+       {{HKEY("")},                TerminateList,          NULL,        0, 0, {HKEY("")}}
 };
 
 ConstStr VCStr [] = {
@@ -103,10 +106,13 @@ ConstStr VCStr [] = {
 HashList *DefineToToken = NULL;
 HashList *VCTokenToDefine = NULL;
 HashList *vcNames = NULL; /* todo: fill with the name strings */
-
+vcField* vcfUnknown = NULL;
 
 void RegisterVCardToken(vcField* vf, StrBuf *name, int inTokenCount)
 {
+       if (vf->Type == UnKnown) {
+               vcfUnknown = vf;
+       }
        RegisterTokenParamDefine(SKEY(name), vf->cval);
        Put(DefineToToken, LKEY(vf->cval), vf, reference_free_handler);
        Put(vcNames, LKEY(vf->cval), NewStrBufPlain(CKEY(vf->Name)), HFreeStrBuf);
@@ -118,13 +124,14 @@ void RegisterVCardToken(vcField* vf, StrBuf *name, int inTokenCount)
 
 }
 
-void autoRegisterTokens(long *enumCounter, vcField* vf, StrBuf *BaseStr, int layer)
+void autoRegisterTokens(long *enumCounter, vcField* vf, StrBuf *BaseStr, int layer, long parentCVal)
 {
        int i = 0;
        StrBuf *subStr = NewStrBuf();
        while (vf[i].STR.len > 0) {
                FlushStrBuf(subStr);
                vf[i].cval = (*enumCounter) ++;
+               vf[i].parentCVal = parentCVal;
                StrBufAppendBuf(subStr, BaseStr, 0);
                if (StrLength(subStr) > 0) {
                        StrBufAppendBufPlain(subStr, HKEY("."), 0);
@@ -138,9 +145,7 @@ void autoRegisterTokens(long *enumCounter, vcField* vf, StrBuf *BaseStr, int lay
                        break;
                case StringCluster:
                {
-                       autoRegisterTokens(enumCounter, vf[i].Sub, subStr, 1);
-                       i++;
-                       continue;
+                       autoRegisterTokens(enumCounter, vf[i].Sub, subStr, 1, vf[i].cval);
                }
                break;
                case PhoneNumber:
@@ -159,6 +164,8 @@ void autoRegisterTokens(long *enumCounter, vcField* vf, StrBuf *BaseStr, int lay
                        break;
                case Address:
                        break;
+               case UnKnown:
+                       break;
                }
                RegisterVCardToken(&vf[i], subStr, i);
                i++;
@@ -600,22 +607,20 @@ void PutVcardItem(HashList *thisVC, vcField *thisField, StrBuf *ThisFieldStr, in
  * 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 display
- * full                display all items of the vcard?
+ * v           the vCard to parse
  * msgnum      Citadel message pointer
  */
-void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, int full, wc_mime_attachment *Mime)
+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[20]; //SIZ];
+       char buf[SIZ];
        int is_qp = 0;
        int is_b64 = 0;
        int ntokens, len;
        StrBuf *thisname = NULL;
-       char firsttoken[20]; ///SIZ];
-       //void *V;
+       char firsttoken[SIZ];
        StrBuf *thisVCToken;
        void *vField = NULL;
 
@@ -702,10 +707,31 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, int full, wc_mim
                                break;
                        case Base64BinaryAttachment:
                        case TerminateList:
+                       case UnKnown:
                                break;
                        }
 
                }
+               else if (StrLength(thisVCToken) > 0) {
+                       /* Add it to the UNKNOWN field... */
+                       void *pv = NULL;
+                       StrBuf *oldVal;
+                       GetHash(VC, IKEY(vcfUnknown->cval), &pv);
+                       oldVal = (StrBuf*) pv;
+                       if (oldVal == NULL) {
+                               oldVal = NewStrBuf();
+                               Put(VC, IKEY(vcfUnknown->cval), oldVal, HFreeStrBuf);
+                       }
+                       else {
+                               StrBufAppendBufPlain(oldVal, HKEY("\n"), 0);
+                       }
+
+                       StrBufAppendBuf(oldVal, thisVCToken, 0);
+                       StrBufAppendBufPlain(oldVal, HKEY(":"), 0);
+                       StrBufAppendBufPlain(oldVal, v->prop[i].value, -1, 0);
+                       continue;
+               }
+
                /* copy over the payload into a StrBuf */
                Val = NewStrBufPlain(v->prop[i].value, -1);
                        
@@ -720,7 +746,6 @@ void parse_vcard(StrBuf *Target, struct vCard *v, HashList *VC, int full, wc_mim
                }
                else if (is_b64) {
                        StrBufDecodeBase64(Val);
-
                }
 #if 0
                syslog(LOG_DEBUG, "-> firsttoken: %s thisname: %s Value: [%s][%s]",
@@ -768,8 +793,6 @@ TODO: check for layer II
 */
 #endif 
                FreeStrBuf(&Val);
-               ////free(thisname);
-               /// thisname = NULL;
        }
        FreeStrBuf(&thisname);
        FreeStrBuf(&Swap);
@@ -803,7 +826,7 @@ void display_one_vcard (StrBuf *Target, struct vCard *v, int full, wc_mime_attac
 
 
        VC = NewHash(0, lFlathash);
-       parse_vcard(Target, v, VC, full, Mime);
+       parse_vcard(Target, v, VC, Mime);
 
        {
                WCTemplputParams *TP = NULL;
@@ -996,59 +1019,16 @@ void do_edit_vcard(long msgnum, char *partnum,
                   wc_mime_attachment *VCAtt,
                   const char *return_to, 
                   const char *force_room) {
+       HashList *VC;   WCTemplputParams SubTP;
        wcsession *WCC = WC;
        message_summary *Msg = NULL;
        wc_mime_attachment *VCMime = NULL;
        struct vCard *v;
-       int i;
-       char *key, *value;
        char whatuser[256];
+       VC = NewHash(0, lFlathash);
 
-       char lastname[256];
-       char firstname[256];
-       char middlename[256];
-       char prefix[256];
-       char suffix[256];
-       char pobox[256];
-       char extadr[256];
-       char street[256];
-       char city[256];
-       char state[256];
-       char zipcode[256];
-       char country[256];
-       char hometel[256];
-       char worktel[256];
-       char faxtel[256];
-       char mobiletel[256];
-       char primary_inetemail[256];
-       char other_inetemail[SIZ];
-       char extrafields[SIZ];
-       char fullname[256];
-       char title[256];
-       char org[256];
-
-       lastname[0] = 0;
-       firstname[0] = 0;
-       middlename[0] = 0;
-       prefix[0] = 0;
-       suffix[0] = 0;
-       pobox[0] = 0;
-       extadr[0] = 0;
-       street[0] = 0;
-       city[0] = 0;
-       state[0] = 0;
-       zipcode[0] = 0;
-       country[0] = 0;
-       hometel[0] = 0;
-       worktel[0] = 0;
-       faxtel[0] = 0;
-       mobiletel[0] = 0;
-       primary_inetemail[0] = 0;
-       other_inetemail[0] = 0;
-       title[0] = 0;
-       org[0] = 0;
-       extrafields[0] = 0;
-       fullname[0] = 0;
+       /* Display the form */
+       output_headers(1, 1, 1, 0, 0, 0);
 
        safestrncpy(whatuser, "", sizeof whatuser);
 
@@ -1072,279 +1052,26 @@ void do_edit_vcard(long msgnum, char *partnum,
                else {
                        v = VCardLoad(VCAtt->Data);
                }
-       
-               /* Populate the variables for our form */
-               i = 0;
-               while (key = vcard_get_prop(v, "", 0, i, 1), key != NULL) {
-                       char prp[256];  /* property name */
-                       char prm[256];  /* parameters */
-
-                       value = vcard_get_prop(v, "", 0, i++, 0);
-
-
-                       extract_token(prp, key, 0, ';', sizeof prp);
-                       safestrncpy(prm, key, sizeof prm);
-                       remove_token(prm, 0, ';');
-
-                       if (!strcasecmp(prp, "n")) {
-                               extract_token(lastname, value, 0, ';', sizeof lastname);
-                               extract_token(firstname, value, 1, ';', sizeof firstname);
-                               extract_token(middlename, value, 2, ';', sizeof middlename);
-                               extract_token(prefix, value, 3, ';', sizeof prefix);
-                               extract_token(suffix, value, 4, ';', sizeof suffix);
-                       }
-
-                       else if (!strcasecmp(prp, "fn")) {
-                               safestrncpy(fullname, value, sizeof fullname);
-                       }
-
-                       else if (!strcasecmp(prp, "title")) {
-                               safestrncpy(title, value, sizeof title);
-                       }
-       
-                       else if (!strcasecmp(prp, "org")) {
-                               safestrncpy(org, value, sizeof org);
-                       }
-       
-                       else if (!strcasecmp(prp, "adr")) {
-                               extract_token(pobox, value, 0, ';', sizeof pobox);
-                               extract_token(extadr, value, 1, ';', sizeof extadr);
-                               extract_token(street, value, 2, ';', sizeof street);
-                               extract_token(city, value, 3, ';', sizeof city);
-                               extract_token(state, value, 4, ';', sizeof state);
-                               extract_token(zipcode, value, 5, ';', sizeof zipcode);
-                               extract_token(country, value, 6, ';', sizeof country);
-                       }
-
-                       else if (!strcasecmp(prp, "tel")) {
 
-                               if (bmstrcasestr(prm, "home")) {
-                                       extract_token(hometel, value, 0, ';', sizeof hometel);
-                               }
-                               else if (bmstrcasestr(prm, "work")) {
-                                       extract_token(worktel, value, 0, ';', sizeof worktel);
-                               }
-                               else if (bmstrcasestr(prm, "fax")) {
-                                       extract_token(faxtel, value, 0, ';', sizeof faxtel);
-                               }
-                               else if (bmstrcasestr(prm, "cell")) {
-                                       extract_token(mobiletel, value, 0, ';', sizeof mobiletel);
-                               }
-                               else {  /* Missing or unknown type; put it in the home phone */
-                                       extract_token(hometel, value, 0, ';', sizeof hometel);
-                               }
-                       }
+               parse_vcard(WCC->WBuf, v, VC, NULL);
        
-                       else if ( (!strcasecmp(prp, "email")) && (bmstrcasestr(prm, "internet")) ) {
-                               if (primary_inetemail[0] == 0) {
-                                       safestrncpy(primary_inetemail, value, sizeof primary_inetemail);
-                               }
-                               else {
-                                       if (other_inetemail[0] != 0) {
-                                               strcat(other_inetemail, "\n");
-                                       }
-                                       strcat(other_inetemail, value);
-                               }
-                       }
-
-                       /* Unrecognized properties are preserved here so we don't discard them
-                        * just because the vCard was edited with WebCit.
-                        */
-                       else {
-                               strcat(extrafields, key);
-                               strcat(extrafields, ":");
-                               strcat(extrafields, value);
-                               strcat(extrafields, "\n");
-                       }
-       
-               }
        
                vcard_free(v);
        }
 
-       /* Display the form */
-       output_headers(1, 1, 1, 0, 0, 0);
-
-       do_template("box_begin_1");
-       StrBufAppendBufPlain(WC->WBuf, _("Edit contact information"), -1, 0);
-       do_template("box_begin_2");
-
-       wc_printf("<form method=\"POST\" action=\"submit_vcard\">\n");
-       wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
+        memset(&SubTP, 0, sizeof(WCTemplputParams));    
 
-       if (force_room != NULL) {
-               wc_printf("<input type=\"hidden\" name=\"force_room\" value=\"");
-               escputs(force_room);
-               wc_printf("\">\n");
-       }
-       else
        {
-               wc_printf("<input type=\"hidden\" name=\"go\" value=\"");
-               StrEscAppend(WCC->WBuf, WCC->CurRoom.name, NULL, 0, 0);
-               wc_printf("\">\n");
-       }
-
-       wc_printf("<table class=\"vcard_edit_background\"><tr><td>\n");
-
-       wc_printf("<table border=\"0\"><tr>"
-               "<td>%s</td>"
-               "<td>%s</td>"
-               "<td>%s</td>"
-               "<td>%s</td>"
-               "<td>%s</td></tr>\n",
-               _("Prefix"), _("First Name"), _("Middle Name"), _("Last Name"), _("Suffix")
-       );
-       wc_printf("<tr><td><input type=\"text\" name=\"prefix\" "
-               "value=\"%s\" maxlength=\"5\" size=\"5\"></td>",
-               prefix);
-       wc_printf("<td><input type=\"text\" name=\"firstname\" "
-               "value=\"%s\" maxlength=\"29\"></td>",
-               firstname);
-       wc_printf("<td><input type=\"text\" name=\"middlename\" "
-               "value=\"%s\" maxlength=\"29\"></td>",
-               middlename);
-       wc_printf("<td><input type=\"text\" name=\"lastname\" "
-               "value=\"%s\" maxlength=\"29\"></td>",
-               lastname);
-       wc_printf("<td><input type=\"text\" name=\"suffix\" "
-               "value=\"%s\" maxlength=\"10\" size=\"10\"></td></tr></table>\n",
-               suffix);
-
-       wc_printf("<table  class=\"vcard_edit_background_alt\">");
-       wc_printf("<tr><td>");
-
-       wc_printf(_("Display name:"));
-       wc_printf("<br>"
-               "<input type=\"text\" name=\"fullname\" "
-               "value=\"%s\" maxlength=\"40\"><br><br>\n",
-               fullname
-       );
+               WCTemplputParams *TP = NULL;
+               WCTemplputParams SubTP;
+               StackContext(TP, &SubTP, VC, CTX_VCARD, 0, NULL);
 
-       wc_printf(_("Title:"));
-       wc_printf("<br>"
-               "<input type=\"text\" name=\"title\" "
-               "value=\"%s\" maxlength=\"40\"><br><br>\n",
-               title
-       );
+               DoTemplate(HKEY("vcard_edit"), WCC->WBuf, &SubTP);
+               UnStackContext(&SubTP);
+       }
+       DeleteHash(&VC);
 
-       wc_printf(_("Organization:"));
-       wc_printf("<br>"
-               "<input type=\"text\" name=\"org\" "
-               "value=\"%s\" maxlength=\"40\"><br><br>\n",
-               org
-       );
 
-       wc_printf("</td><td>");
-
-       wc_printf("<table border=\"0\">");
-       wc_printf("<tr><td>");
-       wc_printf(_("PO box:"));
-       wc_printf("</td><td>"
-               "<input type=\"text\" name=\"pobox\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr>\n",
-               pobox);
-       wc_printf("<tr><td>");
-       wc_printf(_("Address:"));
-       wc_printf("</td><td>"
-               "<input type=\"text\" name=\"extadr\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr>\n",
-               extadr);
-       wc_printf("<tr><td> </td><td>"
-               "<input type=\"text\" name=\"street\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr>\n",
-               street);
-       wc_printf("<tr><td>");
-       wc_printf(_("City:"));
-       wc_printf("</td><td>"
-               "<input type=\"text\" name=\"city\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr>\n",
-               city);
-       wc_printf("<tr><td>");
-       wc_printf(_("State:"));
-       wc_printf("</td><td>"
-               "<input type=\"text\" name=\"state\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr>\n",
-               state);
-       wc_printf("<tr><td>");
-       wc_printf(_("ZIP code:"));
-       wc_printf("</td><td>"
-               "<input type=\"text\" name=\"zipcode\" "
-               "value=\"%s\" maxlength=\"10\"></td></tr>\n",
-               zipcode);
-       wc_printf("<tr><td>");
-       wc_printf(_("Country:"));
-       wc_printf("</td><td>"
-               "<input type=\"text\" name=\"country\" "
-               "value=\"%s\" maxlength=\"29\" width=\"5\"></td></tr>\n",
-               country);
-       wc_printf("</table>\n");
-
-       wc_printf("</table>\n");
-
-       wc_printf("<table border=0><tr><td>");
-       wc_printf(_("Home telephone:"));
-       wc_printf("</td>"
-               "<td><input type=\"text\" name=\"hometel\" "
-               "value=\"%s\" maxlength=\"29\"></td>\n",
-               hometel);
-       wc_printf("<td>");
-       wc_printf(_("Work telephone:"));
-       wc_printf("</td>"
-               "<td><input type=\"text\" name=\"worktel\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr>\n",
-               worktel);
-       wc_printf("<tr><td>");
-       wc_printf(_("Mobile telephone:"));
-       wc_printf("</td>"
-               "<td><input type=\"text\" name=\"mobiletel\" "
-               "value=\"%s\" maxlength=\"29\"></td>\n",
-               mobiletel);
-       wc_printf("<td>");
-       wc_printf(_("Fax number:"));
-       wc_printf("</td>"
-               "<td><input type=\"text\" name=\"faxtel\" "
-               "value=\"%s\" maxlength=\"29\"></td></tr></table>\n",
-               faxtel);
-
-       wc_printf("<table class=\"vcard_edit_background_alt\">");
-       wc_printf("<tr><td>");
-
-       wc_printf("<table border=0><TR>"
-               "<td valign=top>");
-       wc_printf(_("Primary Internet e-mail address"));
-       wc_printf("<br>"
-               "<input type=\"text\" name=\"primary_inetemail\" "
-               "size=40 maxlength=60 value=\"");
-       escputs(primary_inetemail);
-       wc_printf("\"><br>"
-               "</td><td valign=top>");
-       wc_printf(_("Internet e-mail aliases"));
-       wc_printf("<br>"
-               "<textarea name=\"other_inetemail\" rows=5 cols=40 width=40>");
-       escputs(other_inetemail);
-       wc_printf("</textarea></td></tr></table>\n");
-
-       wc_printf("</td></tr></table>\n");
-
-       wc_printf("<input type=\"hidden\" name=\"extrafields\" value=\"");
-       escputs(extrafields);
-       wc_printf("\">\n");
-
-       wc_printf("<input type=\"hidden\" name=\"return_to\" value=\"");
-       escputs(return_to);
-       wc_printf("\">\n");
-
-       wc_printf("<div class=\"buttons\">\n"
-               "<input type=\"submit\" name=\"ok_button\" value=\"%s\">"
-               "&nbsp;"
-               "<input type=\"submit\" name=\"cancel_button\" value=\"%s\">"
-               "</div></form>\n",
-               _("Save changes"),
-               _("Cancel")
-       );
-       
-       wc_printf("</td></tr></table>\n");
-       do_template("box_end");
        wDumpContent(1);
        if (Msg != NULL) {
                DestroyMessageSummary(Msg);
@@ -1372,10 +1099,16 @@ void edit_vcard(void) {
 void submit_vcard(void) {
        struct vCard *v;
        char *serialized_vcard;
-       char buf[SIZ];
        StrBuf *Buf;
        const StrBuf *ForceRoom;
-       int i;
+       HashList* postVcard;
+       HashPos *it, *itSub;
+       const char *Key;
+       long len;
+       void *pv;
+       StrBuf *SubStr;
+       const StrBuf *s;
+       const char *Pos = NULL;
 
        if (!havebstr("ok_button")) { 
                readloop(readnew, eUseDefault);
@@ -1407,6 +1140,13 @@ void submit_vcard(void) {
                }
        }
 
+       postVcard = getSubStruct(HKEY("VC"));
+       if (postVcard == NULL) {
+               AppendImportantMessage(_("An error has occurred."), -1);
+               edit_vcard();
+               return;//// more details
+       }
+       
        Buf = NewStrBuf();
        serv_write(HKEY("ENT0 1|||4\n"));
        if (!StrBuf_ServGetln(Buf) && (GetServerStatus(Buf, NULL) != 4))
@@ -1414,7 +1154,7 @@ void submit_vcard(void) {
                edit_vcard();
                return;
        }
-
+       
        /* Make a vCard structure out of the data supplied in the form */
        StrBufPrintf(Buf, "begin:vcard\r\n%s\r\nend:vcard\r\n",
                     bstr("extrafields")
@@ -1427,40 +1167,99 @@ void submit_vcard(void) {
                return;
        }
 
-       snprintf(buf, sizeof buf, "%s;%s;%s;%s;%s",
-               bstr("lastname"),
-               bstr("firstname"),
-               bstr("middlename"),
-               bstr("prefix"),
-               bstr("suffix") );
-       vcard_add_prop(v, "n", buf);
-       
-       vcard_add_prop(v, "title", bstr("title"));
-       vcard_add_prop(v, "fn", bstr("fullname"));
-       vcard_add_prop(v, "org", bstr("org"));
-
-       snprintf(buf, sizeof buf, "%s;%s;%s;%s;%s;%s;%s",
-               bstr("pobox"),
-               bstr("extadr"),
-               bstr("street"),
-               bstr("city"),
-               bstr("state"),
-               bstr("zipcode"),
-               bstr("country") );
-       vcard_add_prop(v, "adr", buf);
-
-       vcard_add_prop(v, "tel;home", bstr("hometel"));
-       vcard_add_prop(v, "tel;work", bstr("worktel"));
-       vcard_add_prop(v, "tel;fax", bstr("faxtel"));
-       vcard_add_prop(v, "tel;cell", bstr("mobiletel"));
-       vcard_add_prop(v, "email;internet", bstr("primary_inetemail"));
-
-       for (i=0; i<num_tokens(bstr("other_inetemail"), '\n'); ++i) {
-               extract_token(buf, bstr("other_inetemail"), i, '\n', sizeof buf);
-               if (!IsEmptyStr(buf)) {
-                       vcard_add_prop(v, "email;internet", buf);
+       SubStr = NewStrBuf();
+       it = GetNewHashPos(DefineToToken, 0);
+       while (GetNextHashPos(DefineToToken, it, &len, &Key, &pv) && 
+              (pv != NULL)) 
+       {
+               char buf[32];
+               long blen;
+               vcField *t = (vcField*) pv;
+
+               if (t->Sub != NULL){
+                       vcField *Sub;
+                       FlushStrBuf(SubStr);
+                       itSub = GetNewHashPos(DefineToToken, 0);
+                       while (GetNextHashPos(DefineToToken, itSub, &len, &Key, &pv) && 
+                              (pv != NULL)) 
+                       {
+                               Sub = (vcField*) pv;
+                               if (Sub->parentCVal == t->cval) {
+                                       if (StrLength(SubStr) > 0)
+                                               StrBufAppendBufPlain(SubStr, HKEY(";"), 0);
+
+
+
+                                       blen = snprintf(buf, sizeof(buf), "%ld", Sub->cval);
+                                       s = SSubBstr(postVcard, buf, blen);
+                       
+                                       if ((s != NULL) && (StrLength(s) > 0)) {
+                                               /// todo: utf8 qp
+                                               StrBufAppendBuf(SubStr, s, 0);
+                                       }
+                               }
+                       }
+                       if (StrLength(SubStr) > 0) {
+                               vcard_add_prop(v, t->STR.Key, ChrPtr(SubStr));
+                       }
+                       DeleteHashPos(&itSub);
+               }
+               else if (t->parentCVal == 0) {
+                       blen = snprintf(buf, sizeof(buf), "%ld", t->cval);
+                       s = SSubBstr(postVcard, buf, blen);
+                       
+                       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);
+
+       s = sbstr("other_inetemail");
+       if (StrLength(s) > 0) {
+               FlushStrBuf(SubStr);
+               while (StrBufSipLine(SubStr, s, &Pos), ((Pos!=StrBufNOTNULL) && (Pos!=NULL)) ) {
+                       if (StrLength(SubStr) > 0) {
+                               vcard_add_prop(v, "email;internet", ChrPtr(SubStr));
+                       }
+               }
+       }
+
+       FreeStrBuf(&SubStr);
+
 
        serialized_vcard = vcard_serialize(v);
        vcard_free(v);
@@ -1471,6 +1270,7 @@ void submit_vcard(void) {
                return;
        }
 
+       printf("%s", serialized_vcard);
        serv_write(HKEY("Content-type: text/x-vcard; charset=UTF-8\n"));
        serv_write(HKEY("\n"));
        serv_printf("%s\r\n", serialized_vcard);
@@ -1694,7 +1494,7 @@ InitModule_VCARD
                DefineToToken   = NewHash(1, lFlathash);
                vcNames         = NewHash(1, lFlathash);
                VCTokenToDefine = NewHash(1, NULL);
-               autoRegisterTokens(&VCEnumCounter, VCStrE, Prefix, 0);
+               autoRegisterTokens(&VCEnumCounter, VCStrE, Prefix, 0, 0);
                FreeStrBuf(&Prefix);
        }
        RegisterCTX(CTX_VCARD);