Back to index

courier  0.68.2
addressbook.c
Go to the documentation of this file.
00001 #include "config.h"
00002 /*
00003 ** Copyright 2000-2011 Double Precision, Inc.  See COPYING for
00004 ** distribution information.
00005 */
00006 
00007 /*
00008 */
00009 
00010 #include      "sqwebmail.h"
00011 #include      "addressbook.h"
00012 #include      "maildir.h"
00013 #include      "cgi/cgi.h"
00014 #include      "rfc822/rfc822.h"
00015 #include      "maildir/maildirmisc.h"
00016 #include      "numlib/numlib.h"
00017 #include      <stdio.h>
00018 #include      <string.h>
00019 #include      <ctype.h>
00020 
00021 #define       ADDRESSBOOK   "sqwebmail-addressbook"
00022 
00023 #define TOUTF8(what) \
00024        libmail_u_convert_toutf8((what), sqwebmail_content_charset, NULL)
00025 
00026 extern const char *sqwebmail_content_charset;
00027 
00028 extern void output_attrencoded(const char *);
00029 extern void output_attrencoded_fp(const char *, FILE *);
00030 extern void output_urlencoded(const char *);
00031 extern void print_safe(const char *);
00032 extern void call_print_safe_to_stdout(const char *p, size_t cnt);
00033 
00034 static char *q_escape(const char *name)
00035 {
00036        char *names;
00037        const char *cp;
00038        size_t namelen;
00039        char *p;
00040 
00041        namelen=1;
00042 
00043        for (cp=name; *cp; ++cp, ++namelen)
00044               if (*cp == '"' || *cp == '\\')
00045                      ++namelen;
00046 
00047        names=malloc(namelen);
00048        if (!names)
00049        {
00050               enomem();
00051        }
00052 
00053        for (p=names, cp=name; *cp; ++cp)
00054        {
00055               if (iscntrl((int)(unsigned char)*cp))     continue;
00056 
00057               if (*cp == '"' || *cp == '\\')
00058                      *p++='\\';
00059               *p++= *cp;
00060        }
00061        *p=0;
00062 
00063        return names;
00064 }
00065 
00066 /*
00067 ** When adding a new name/address pair into the address book delete
00068 ** bad characters from both.
00069 */
00070 
00071 static void fix_nameaddr(const char *name, const char *addr,
00072        char **nameret, char **addrret)
00073 {
00074        char *names, *addresss;
00075        char   *p, *q;
00076 
00077        names=q_escape(name);
00078 
00079        if ((addresss=strdup(addr)) == 0)
00080        {
00081               free(names);
00082               enomem();
00083        }
00084 
00085        for (p=q=addresss; *p; p++)
00086        {
00087               if (isspace((int)(unsigned char)*p))      continue;
00088               if (iscntrl((int)(unsigned char)*p))      continue;
00089               if (*p == '<' || *p == '>' || *p == '(' || *p == ')' ||
00090                      *p == '\\')
00091                      continue;
00092               *q++=*p;
00093        }
00094        *q=0;
00095 
00096        *nameret=names;
00097        *addrret=addresss;
00098 }
00099 
00100 static void ab_add_int(const char *name, const char *address, const char *nick)
00101 {
00102        char   *nicks, *names, *addresss, *p, *q;
00103        FILE   *fp;
00104        char   *header, *value;
00105 
00106        int    new_fd;
00107        char   *new_name;
00108        FILE   *new_fp;
00109        int    written;
00110 
00111        /* Delete bad characters from nickname, name, address */
00112 
00113        if ((nicks=strdup(nick)) == 0)     enomem();
00114 
00115        for (p=q=nicks; *p; p++)
00116        {
00117               if (isspace((int)(unsigned char)*p))      continue;
00118               if (iscntrl((int)(unsigned char)*p))      continue;
00119               if (strchr(":;,<>@\\", *p)) continue;
00120               *q++=*p;
00121        }
00122        *q=0;
00123 
00124        if (*nicks == 0)
00125        {
00126               free(nicks);
00127               return;
00128        }
00129 
00130        /* Remove quotes from name */
00131 
00132        fix_nameaddr(name, address, &names, &addresss);
00133 
00134        if (*addresss == 0)
00135        {
00136               free(addresss);
00137               free(nicks);
00138               free(names);
00139               return;
00140        }
00141 
00142        fp=fopen(ADDRESSBOOK, "r");
00143 
00144        new_fd=maildir_createmsg(INBOX, "addressbook", &new_name);
00145        p=malloc(sizeof("tmp/")+strlen(new_name));
00146        if (!p)
00147        {
00148               close(new_fd);
00149               free(new_name);
00150               enomem();
00151        }
00152        strcat(strcpy(p, "tmp/"), new_name);
00153        free(new_name);
00154        new_name=p;
00155 
00156        if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
00157        {
00158               if (new_fd >= 0)     close(new_fd);
00159               free(addresss);
00160               free(nicks);
00161               free(names);
00162               enomem();
00163               return;
00164        }
00165 
00166        written=0;
00167        while (fp && (header=maildir_readheader_nolc(fp, &value)) != 0)
00168        {
00169               if (strcmp(header, nicks) == 0)
00170               {
00171                      fprintf(new_fp, "%s: %s,\n    ",
00172                             nicks, value);
00173                      written=1;
00174                      break;
00175               }
00176               fprintf(new_fp, "%s: %s\n", header, value);
00177        }
00178        if (!written)
00179               fprintf(new_fp, "%s: ", nicks);
00180        if (*names)
00181               fprintf(new_fp, "\"%s\" <%s>\n",
00182                      names, addresss);
00183        else
00184               fprintf(new_fp, "<%s>\n", addresss);
00185        free(names);
00186        free(addresss);
00187        free(nicks);
00188 
00189        while (fp && (header=maildir_readheader_nolc(fp, &value)) != 0)
00190               fprintf(new_fp, "%s: %s\n", header, value);
00191 
00192        if (fp) fclose(fp);
00193 
00194        if (fflush(new_fp) || ferror(new_fp))
00195        {
00196               fclose(new_fp);
00197               close(new_fd);
00198               unlink(new_name);
00199               free(new_name);
00200               error("Unable to write out new address book -- write error, or out of disk space.");
00201               return;
00202        }
00203        fclose(new_fp);
00204 
00205        rename(new_name, ADDRESSBOOK);
00206        free(new_name);
00207 }
00208 
00209 void ab_add(const char *name, const char *address, const char *nick)
00210 {
00211        char *nick_utf8, *name_utf8, *addr_utf8;
00212 
00213        if (*nick == 0 || *address == 0)
00214               return;
00215 
00216        nick_utf8=TOUTF8(nick);
00217        name_utf8=TOUTF8(name ? name:"");
00218        addr_utf8=TOUTF8(address);
00219 
00220        if (nick_utf8 && name_utf8 && addr_utf8)
00221               ab_add_int(name_utf8, addr_utf8, nick_utf8);
00222 
00223        if (nick_utf8)
00224               free(nick_utf8);
00225        if (name_utf8)
00226               free(name_utf8);
00227        if (addr_utf8)
00228               free(addr_utf8);
00229 }
00230 
00231 /* note: we're always passing utf-8 to dodel() */
00232 
00233 static void dodel(const char *nick, struct rfc822a *a, int n,
00234        const char *replace_name, const char *replace_addr)
00235 {
00236 char   *p;
00237 FILE   *fp, *new_fp;
00238 char   *new_name;
00239 int    new_fd;
00240 char   *header, *value;
00241 
00242 char   *namebuf=0, *addrbuf=0;
00243 struct rfc822token namet, addresst;
00244 
00245        if (replace_name && replace_addr && n < a->naddrs)
00246        {
00247               fix_nameaddr(replace_name, replace_addr, &namebuf, &addrbuf);
00248               namet.token='"';
00249               namet.ptr=namebuf;
00250               namet.len=strlen(namebuf);
00251               namet.next=0;
00252               a->addrs[n].name= &namet;
00253 
00254               addresst.token=0;
00255               addresst.ptr=addrbuf;
00256               addresst.len=strlen(addrbuf);
00257               addresst.next=0;
00258               a->addrs[n].tokens= &addresst;
00259        }
00260        else
00261        {
00262               while (++n < a->naddrs)
00263                      a->addrs[n-1]=a->addrs[n];
00264               --a->naddrs;         /* It's that simple... */
00265        }
00266 
00267        fp=fopen(ADDRESSBOOK, "r");
00268 
00269        new_fd=maildir_createmsg(INBOX, "addressbook", &new_name);
00270        if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
00271        {
00272               if (new_fd >= 0)     close(new_fd);
00273               fclose(fp);
00274               enomem();
00275               return;
00276        }
00277        p=malloc(sizeof("tmp/")+strlen(new_name));
00278        if (!p)
00279        {
00280               unlink(new_name);
00281               fclose(fp);
00282               fclose(new_fp);
00283               free(new_name);
00284               enomem();
00285        }
00286        strcat(strcpy(p, "tmp/"), new_name);
00287        free(new_name);
00288        new_name=p;
00289 
00290        while (fp && (header=maildir_readheader_nolc(fp, &value)) != 0)
00291        {
00292               if (strcmp(header, nick) == 0)
00293               {
00294               char   *s, *t;
00295 
00296                      if (a->naddrs == 0)
00297                             continue;
00298                      s=rfc822_getaddrs_wrap(a, 70);
00299 
00300                      if (!s)
00301                      {
00302                             fclose(new_fp);
00303                             close(new_fd);
00304                             fclose(fp);
00305                             unlink(new_name);
00306                             enomem();
00307                      }
00308                      fprintf(new_fp, "%s: ", header);
00309                             for (t=s; *t; t++)
00310                             {
00311                                    putc(*t, new_fp);
00312                                    if (*t == '\n')
00313                                           fprintf(new_fp, "    ");
00314                             }
00315                      fprintf(new_fp, "\n");
00316                      free(s);
00317                      continue;
00318               }
00319               fprintf(new_fp, "%s: %s\n", header, value);
00320        }
00321        if (fp) fclose(fp);
00322 
00323        if (namebuf)  free(namebuf);
00324        if (addrbuf)  free(addrbuf);
00325 
00326        if (fflush(new_fp) || ferror(new_fp))
00327        {
00328               fclose(new_fp);
00329               unlink(new_name);
00330               free(new_name);
00331               error("Unable to write out new address book -- write error, or out of disk space.");
00332               return;
00333        }
00334 
00335        fclose(new_fp);
00336        rename(new_name, ADDRESSBOOK);
00337        free(new_name);
00338 }
00339 
00340 static void dodelall(const char *nick)
00341 {
00342 FILE   *fp, *new_fp;
00343 int    new_fd;
00344 char   *new_name, *p;
00345 char   *header, *value;
00346 
00347        fp=fopen(ADDRESSBOOK, "r");
00348 
00349        new_fd=maildir_createmsg(INBOX, "addressbook", &new_name);
00350        if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
00351        {
00352               if (new_fd >= 0)     close(new_fd);
00353               fclose(fp);
00354               enomem();
00355               return;
00356        }
00357        p=malloc(sizeof("tmp/")+strlen(new_name));
00358        if (!p)
00359        {
00360               unlink(new_name);
00361               fclose(fp);
00362               fclose(new_fp);
00363               free(new_name);
00364               enomem();
00365        }
00366        strcat(strcpy(p, "tmp/"), new_name);
00367        free(new_name);
00368        new_name=p;
00369 
00370        while (fp && (header=maildir_readheader_nolc(fp, &value)) != 0)
00371        {
00372               if (strcmp(header, nick) == 0)     continue;
00373               fprintf(new_fp, "%s: %s\n", header, value);
00374        }
00375        if (fp) fclose(fp);
00376 
00377        if (fflush(new_fp) || ferror(new_fp))
00378        {
00379               fclose(new_fp);
00380               unlink(new_name);
00381               free(new_name);
00382               error("Unable to write out new address book -- write error, or out of disk space.");
00383               return;
00384        }
00385 
00386        fclose(new_fp);
00387        rename(new_name, ADDRESSBOOK);
00388        free(new_name);
00389 }
00390 
00391 void ab_listselect()
00392 {
00393        ab_listselect_fp(stdout);
00394 }
00395 
00396 struct abooklist {
00397        struct abooklist *next;
00398        char *name;
00399        } ;
00400 
00401 static void abl_free(struct abooklist *a)
00402 {
00403 struct abooklist *b;
00404 
00405        while (a)
00406        {
00407               b=a->next;
00408               free(a->name);
00409               free(a);
00410               a=b;
00411        }
00412 }
00413 
00414 static int sortabook(const void *a, const void *b)
00415 {
00416        return ( strcmp( (*(struct abooklist * const *)a)->name,
00417                      (*(struct abooklist * const *)b)->name));
00418 }
00419 
00420 void ab_listselect_fp(FILE *w)
00421 {
00422        FILE   *fp;
00423        char *header, *value;
00424        struct abooklist *a=0, *b, **aa;
00425        size_t acnt=0, i;
00426 
00427        if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
00428        {
00429               while ((header=maildir_readheader_nolc(fp, &value)) != NULL)
00430               {
00431                      if ((b=malloc(sizeof(struct abooklist))) == 0 ||
00432                             (b->name=strdup(header)) == 0)
00433                      {
00434                             if (b) free(b);
00435                             abl_free(a);
00436                             enomem();
00437                      }
00438                      b->next=a;
00439                      a=b;
00440                      acnt++;
00441               }
00442               fclose(fp);
00443 
00444               if ((aa=malloc(sizeof(struct abooklist *)*(acnt+1))) == 0)
00445               {
00446                      abl_free(a);
00447                      enomem();
00448               }
00449 
00450               for (acnt=0, b=a; b; b=b->next)
00451                      aa[acnt++]=b;
00452               qsort(aa, acnt, sizeof(*aa), sortabook);
00453 
00454               for (i=0; i<acnt; i++)
00455               {
00456                      char *p=libmail_u_convert_fromutf8(aa[i]->name,
00457                                                     sqwebmail_content_charset,
00458                                                     NULL);
00459 
00460                      fprintf(w, "<option value=\"");
00461                      output_attrencoded_fp(p ? p:aa[i]->name, w);
00462                      fprintf(w, "\">");
00463 
00464                      output_attrencoded_fp(p ? p:aa[i]->name, w);
00465                      if (p)
00466                             free(p);
00467                      fprintf(w, "</option>\n");
00468               }
00469               free(aa);
00470               abl_free(a);
00471        }
00472 }
00473 
00474 /*
00475 ** Extract all name/address entries from the address book, for external
00476 ** processing (mostly calendaring).
00477 */
00478 
00479 int ab_get_nameaddr( int (*callback_func)(const char *, const char *,
00480                                      void *),
00481                    void *callback_arg)
00482 {
00483        FILE   *fp;
00484        char *header, *value;
00485        int rc=0;
00486 
00487        if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
00488        {
00489               while ((header=maildir_readheader_nolc(fp, &value)) != NULL)
00490               {
00491                      struct rfc822t *t;
00492                      struct rfc822a *a;
00493 
00494                      if (!value)
00495                             continue;
00496 
00497                      t=rfc822t_alloc_new(value, NULL, NULL);
00498                      a=t ? rfc822a_alloc(t):0;
00499 
00500                      if (a)
00501                      {
00502                             int i;
00503 
00504                             for (i=0; i<a->naddrs; i++)
00505                             {
00506                                    char *addr;
00507                                    char *name;
00508 
00509                                    if (a->addrs[i].tokens == NULL)
00510                                           continue;
00511 
00512                                    addr=rfc822_display_addr_tobuf(a, i,
00513                                                                NULL);
00514                                    if (!addr)
00515                                           continue;
00516 
00517                                    name=a->addrs[i].name ?
00518                                           rfc822_display_name_tobuf(a, i,
00519                                                                  NULL):
00520                                           NULL;
00521 
00522                                    rc=(*callback_func)(addr, name,
00523                                                      callback_arg);
00524                                    if (name)
00525                                           free(name);
00526                                    free(addr);
00527                                    if (rc)
00528                                           break;
00529                             }
00530                      }
00531 
00532                      if (a) rfc822a_free(a);
00533                      if (t) rfc822t_free(t);
00534                      if (rc)
00535                             break;
00536               }
00537               fclose(fp);
00538        }
00539        return (rc);
00540 }
00541 
00542 struct ab_addrselect_s {
00543        struct ab_addrselect_s *next;
00544        char *name;
00545        char *addr;
00546 } ;
00547 
00548 static int ab_addrselect_cb(const char *a, const char *n, void *vp)
00549 {
00550        struct ab_addrselect_s **p=(struct ab_addrselect_s **)vp, *q;
00551 
00552        if (!n || !a)
00553               return (0);
00554 
00555        while ( (*p) && strcasecmp((*p)->name, n) < 0)
00556               p= &(*p)->next;
00557 
00558        if ((q=malloc(sizeof(struct ab_addrselect_s))) == NULL)
00559               return (-1);
00560 
00561        if ((q->name=strdup(n)) == NULL)
00562        {
00563               free(q);
00564               return(-1);
00565        }
00566 
00567        if ((q->addr=strdup(a)) == NULL)
00568        {
00569               free(q->name);
00570               free(q);
00571               return(-1);
00572        }
00573 
00574        q->next= *p;
00575        *p=q;
00576        return (0);
00577 }
00578 
00579 static void ab_show_utf8(const char *p)
00580 {
00581        int err;
00582        char *p_s=libmail_u_convert_fromutf8(p, sqwebmail_content_charset,
00583                                         &err);
00584 
00585        if (!p_s)
00586               return;
00587 
00588        if (err)
00589        {
00590               free(p_s);
00591               return;
00592        }
00593 
00594        p=p_s;
00595 
00596        while (*p)
00597        {
00598               size_t i;
00599 
00600               for (i=0; p[i]; ++i)
00601               {
00602                      if (*p == '"' || *p == '\\')
00603                             break;
00604               }
00605 
00606               if (i)
00607                      call_print_safe_to_stdout(p, i);
00608 
00609               p += i;
00610 
00611               if (*p)
00612               {
00613                      putchar('\\');
00614                      putchar(*p);
00615                      ++p;
00616               }
00617        }
00618        free(p_s);
00619        return;
00620 }
00621 
00622 
00623 void ab_nameaddr_show(const char *name, const char *addr)
00624 {
00625        if (name)
00626        {
00627               printf("\"");
00628               ab_show_utf8(name);
00629               printf("\"&nbsp;");
00630        }
00631        printf("&lt;");
00632 
00633        if (addr)
00634               ab_show_utf8(addr);
00635 
00636        printf("&gt;");
00637 }
00638 
00639 void ab_addrselect()
00640 {
00641        struct ab_addrselect_s *list=NULL, *p;
00642 
00643        printf("<select name=\"addressbookname\"><option value=\"\"></option>\n");
00644 
00645        if (ab_get_nameaddr(ab_addrselect_cb, &list) == 0)
00646        {
00647               for (p=list; p; p=p->next)
00648               {
00649                      printf("<option value=\"");
00650                      output_attrencoded(p->addr);
00651                      printf("\">");
00652                      ab_nameaddr_show(p->name, p->addr);
00653                      printf("</option>\n");
00654               }
00655        }
00656        printf("</select>\n");
00657 
00658        while ((p=list) != NULL)
00659        {
00660               list=p->next;
00661               free(p->name);
00662               free(p->addr);
00663               free(p);
00664        }
00665 }
00666 
00667 const char *ab_find(const char *nick)
00668 {
00669 FILE   *fp;
00670 char *header, *value;
00671 
00672        if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
00673        {
00674               while ((header=maildir_readheader_nolc(fp, &value)) != NULL)
00675               {
00676                      if (strcmp(header, nick) == 0)
00677                      {
00678                             fclose(fp);
00679                             return (value);
00680                      }
00681               }
00682               fclose(fp);
00683        }
00684        return (0);
00685 }
00686        
00687 void addressbook()
00688 {
00689 FILE   *fp;
00690 char    *header, *value;
00691 const char    *nick_prompt=getarg("PROMPT");
00692 const char    *nick_submit=getarg("SUBMIT");
00693 const char    *nick_title1=getarg("TITLE1");
00694 const char    *nick_title2=getarg("TITLE2");
00695 const char    *nick_delete=getarg("DELETE");
00696 const char    *nick_name=getarg("NAME");
00697 const char    *nick_address=getarg("ADDRESS");
00698 const char    *nick_add=getarg("ADD");
00699 const char    *nick_edit=getarg("EDIT");
00700 const char    *nick_select1=getarg("SELECT1");
00701 const char    *nick_select2=getarg("SELECT2");
00702 const char *nick1;
00703 int    do_edit;
00704 char   *s, *q, *r;
00705 
00706 char   *edit_name=0;
00707 char   *edit_addr=0;
00708 int    replace_index=0;
00709 
00710 #if 0
00711        fp=fopen("/tmp/pid", "w");
00712        fprintf(fp, "%d", getpid());
00713        fclose(fp);
00714        sleep(10);
00715 #endif
00716 
00717        nick1=cgi("nick");
00718        do_edit=0;
00719        if (*cgi("nick.edit"))
00720               do_edit=1;
00721        else if (*cgi("nick.edit2"))
00722        {
00723               do_edit=1;
00724               nick1=cgi("nick2");
00725        }
00726        else if (*cgi("editnick"))
00727        {
00728               do_edit=1;
00729               nick1=cgi("editnick");
00730        }
00731 
00732        if (*cgi("ADDYCNT")) /* Import from LDAP */
00733        {
00734        unsigned counter=atoi(cgi("ADDYCNT"));
00735        char   numbuf[NUMBUFSIZE];
00736        char   numbuf2[NUMBUFSIZE+10];
00737        unsigned      i;
00738 
00739               if (counter < 1 || counter > 1000)
00740                      counter=1000;
00741               nick1=cgi("nick2");
00742               if (!*nick1)
00743                      nick1=cgi("nick1");
00744 
00745               if (*nick1)
00746               {
00747                      do_edit=1;
00748                      for (i=0; i<counter; i++)
00749                      {
00750                      const char *addy=cgi(strcat(strcpy(numbuf2, "ADDY"),
00751                                         libmail_str_size_t(i, numbuf)));
00752                      char   *addycpy;
00753                      char   *name;
00754 
00755                             if (*addy == 0)      continue;
00756 
00757                             addycpy=strdup(addy);
00758                             if (!addycpy) enomem();
00759 
00760                             name=strchr(addycpy, '>');
00761                             if (!name)
00762                             {
00763                                    free(addycpy);
00764                                    continue;
00765                             }
00766                             *name++=0;
00767                             while (*name == ' ') ++name;
00768                             addy=addycpy;
00769                             if (*addy == '<')    ++addy;
00770                             ab_add(name, addy, nick1);
00771                      }
00772               }
00773        }
00774 
00775        if (*cgi("nick.delete"))
00776        {
00777               char *p=TOUTF8(cgi("nick"));
00778 
00779               do_edit=0;
00780 
00781               if (p)
00782               {
00783                      dodelall(p);
00784                      free(p);
00785               }
00786        }
00787        else if (*cgi("add"))
00788        {
00789        const char *newname=cgi("newname");
00790        const char *newaddr=cgi("newaddress");
00791        const char *editnick=cgi("editnick");
00792        const char *replacenum=cgi("replacenick");
00793 
00794               if (*replacenum)
00795               {
00796                      if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
00797                      {
00798                             char *editnick_utf8=TOUTF8(editnick);
00799 
00800                             while ((header=maildir_readheader_nolc(fp,
00801                                    &value)) != NULL)
00802                                    if (editnick_utf8 &&
00803                                        strcmp(header, editnick_utf8) == 0)
00804                                           break;
00805 
00806                             if (header && editnick_utf8)
00807                             {
00808                             struct rfc822t *t;
00809                             struct rfc822a *a;
00810 
00811                                    t=rfc822t_alloc_new(value, NULL, NULL);
00812                                    a=t ? rfc822a_alloc(t):0;
00813 
00814                                    if (a)
00815                                    {
00816                                           char *newname_utf8=
00817                                                  TOUTF8(newname);
00818 
00819                                           char *newaddr_utf8=
00820                                                  TOUTF8(newaddr);
00821 
00822                                           dodel(editnick_utf8, a,
00823                                                 atoi(replacenum),
00824                                                 newname_utf8 && newaddr_utf8 ?
00825                                                 newname_utf8:NULL,
00826                                                 newname_utf8 && newaddr_utf8 ?
00827                                                 newaddr_utf8:NULL);
00828                                           rfc822a_free(a);
00829                                           if (newname_utf8)
00830                                                  free(newname_utf8);
00831                                           if (newaddr_utf8)
00832                                                  free(newaddr_utf8);
00833                                    }
00834                                    if (t) rfc822t_free(t);
00835                             }
00836                             if (editnick_utf8)
00837                                    free(editnick_utf8);
00838 
00839                             fclose(fp);
00840                      }
00841               }
00842               else
00843                      ab_add(newname, newaddr, editnick);
00844               do_edit=1;
00845               nick1=editnick;
00846        }
00847 
00848        printf("%s", nick_prompt);
00849        printf("%s\n", nick_select1);
00850 
00851        ab_listselect();
00852 
00853        printf("%s\n", nick_select2);
00854        printf("%s", nick_submit);
00855 
00856        s=strdup(nick1);
00857        if (!s)       enomem();
00858        for (q=r=s; *q; q++)
00859        {
00860               if (isspace((int)(unsigned char)*q) ||
00861                      strchr(",;:()\"%@<>'!", *q))
00862                      continue;
00863               *r++=*q;
00864        }
00865        *r=0;
00866 
00867        if (do_edit && *s)
00868        {
00869               printf("<input type=\"hidden\" name=\"editnick\" value=\"");
00870               output_attrencoded(s);
00871               printf("\" />\n");
00872 
00873               printf("<table border=\"0\" class=\"nickedit-box\">\n");
00874               printf("<tr><td colspan=\"3\">\n");
00875 
00876               printf("%s%s%s", nick_title1, s, nick_title2);
00877               printf("</td></tr>\n");
00878 
00879               if ((fp=fopen(ADDRESSBOOK, "r")) != 0)
00880               {
00881                      char *s_utf8=TOUTF8(s);
00882 
00883                      while ((header=maildir_readheader_nolc(fp, &value))
00884                             != NULL)
00885                             if (s_utf8 && strcmp(header, s_utf8) == 0)
00886                                    break;
00887 
00888                      if (s_utf8)
00889                             free(s_utf8);
00890 
00891                      if (header)
00892                      {
00893                      struct rfc822t *t;
00894                      struct rfc822a *a;
00895                      char   *save_value=strdup(value);
00896 
00897                             if (!save_value)
00898                             {
00899                                    fclose(fp);
00900                                    free(s);
00901                                    enomem();
00902                             }
00903                             strcpy(save_value, value);
00904                                    /* Need copy 'cause dodel also
00905                                    ** calls maildir_readheader */
00906 
00907 
00908                             t=rfc822t_alloc_new(save_value, NULL, NULL);
00909                             a=t ? rfc822a_alloc(t):0;
00910 
00911                             if (a)
00912                             {
00913                             int    i;
00914 
00915                                    for (i=0; i<a->naddrs; i++)
00916                                    {
00917                                    char buf[100];
00918 
00919                                           sprintf(buf, "del%d", i);
00920                                           if (*cgi(buf))
00921                                           {
00922                                                  dodel(s, a, i, 0, 0);
00923                                                  break;
00924                                           }
00925                                           sprintf(buf, "startedit%d", i);
00926                                           if (*cgi(buf))
00927                                           {
00928                                                  if (edit_name)
00929                                                         free(edit_name);
00930                                                  edit_name=
00931                                                         rfc822_display_name_tobuf(a, i, NULL);
00932                                                  if (edit_addr)
00933                                                         free(edit_addr);
00934                                                  edit_addr=
00935                                                         rfc822_display_addr_tobuf(a, i, NULL);
00936                                                  replace_index=i;
00937                                                  break;
00938                                           }
00939                                    }
00940 
00941                                    for (i=0; i<a->naddrs; i++)
00942                                    {
00943                                           char *s;
00944 
00945                                           if (a->addrs[i].tokens == 0)
00946                                                  continue;
00947                                           printf("<tr><td align=\"right\""
00948                                                  " class=\"nickname\">");
00949 
00950                                           if (a->addrs[i].name)
00951                                                  /* getname defaults it
00952                                                  ** here.
00953                                                  */
00954                                           {
00955                                                  char *n=rfc822_display_name_tobuf(a, i, NULL);
00956 
00957                                                  if (n)
00958                                                  {
00959                                                         printf("\"");
00960                                                         ab_show_utf8(n);
00961                                                         printf("\"");
00962                                                         free(n);
00963                                                  }
00964 
00965                                           }
00966 
00967                                           printf("</td><td align=\"left\""
00968                                                  " class=\"nickaddr\">"
00969                                                  "&lt;");
00970                                           s=rfc822_display_addr_tobuf(a, i, NULL);
00971 
00972                                           if (s)
00973                                           {
00974                                                  ab_show_utf8(s);
00975                                                  free(s);
00976                                           }
00977                                           printf("&gt;</td><td><input type=\"submit\" name=\"startedit%d\" value=\"%s\" />&nbsp;<input type=\"submit\" name=\"del%d\" value=\"%s\" /></td></tr>\n",
00978                                                  i, nick_edit,
00979                                                  i, nick_delete);
00980                                    }
00981                                    rfc822a_free(a);
00982                             }
00983                             if (t) rfc822t_free(t);
00984                             free(save_value);
00985                      }
00986                      fclose(fp);
00987               }
00988               printf("<tr><td colspan=\"3\"><hr width=\"90%%\" /></td></tr>\n");
00989               printf("<tr><td align=\"right\">%s</td><td colspan=\"2\"><input type=\"text\" name=\"newname\" class=\"nicknewname\"", nick_name);
00990 
00991               if (edit_name)
00992               {
00993                      int err;
00994                      char *edit_name_native=
00995                             libmail_u_convert_fromutf8(edit_name,
00996                                                     sqwebmail_content_charset,
00997                                                     &err);
00998 
00999                      if (edit_name_native)
01000                      {
01001                             if (err == 0)
01002                             {
01003                                    printf(" value=\"");
01004                                    output_attrencoded(edit_name_native);
01005                                    printf("\"");
01006                             }
01007                             free(edit_name_native);
01008                      }
01009               }
01010               printf(" /></td></tr>\n");
01011 
01012               printf("<tr><td align=\"right\">%s</td><td><input type=\"text\" name=\"newaddress\" class=\"nicknewaddr\"", nick_address);
01013               if (edit_addr)
01014               {
01015                      int err;
01016                      char *edit_addr_native=
01017                             libmail_u_convert_fromutf8(edit_addr,
01018                                                     sqwebmail_content_charset,
01019                                                     &err);
01020 
01021                      if (edit_addr_native)
01022                      {
01023                             if (err == 0)
01024                             {
01025                                    printf(" value=\"");
01026                                    output_attrencoded(edit_addr_native);
01027                                    printf("\"");
01028                             }
01029                             free(edit_addr_native);
01030                      }
01031               }
01032 
01033               printf(" /></td><td>");
01034 
01035               if (edit_name || edit_addr)
01036                      printf("<input type=\"hidden\" name=\"replacenick\" value=\"%d\" />",
01037                             replace_index);
01038 
01039               printf("<input type=\"submit\" name=\"add\" value=\"%s\" /></td></tr>\n",
01040                      edit_name || edit_addr ? nick_edit:nick_add);
01041 
01042               printf("</table>\n");
01043        }
01044        free(s);
01045 
01046        if (edit_name)
01047               free(edit_name);
01048        if (edit_addr)
01049               free(edit_addr);
01050 }