Back to index

courier  0.68.2
newmsg.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 
00007 /*
00008 */
00009 #include      "config.h"
00010 #include      "sqwebmail.h"
00011 #include      "newmsg.h"
00012 #include      "cgi/cgi.h"
00013 #include      "sqconfig.h"
00014 #include      "auth.h"
00015 #include      "maildir.h"
00016 #include      "token.h"
00017 #include      "pref.h"
00018 #include      "folder.h"
00019 #include      "filter.h"
00020 #include      "gpg.h"
00021 #include      "addressbook.h"
00022 #include      "maildir/maildirmisc.h"
00023 #include      "maildir/maildirquota.h"
00024 #include      "maildir/maildirgetquota.h"
00025 #include      "rfc822/rfc822.h"
00026 #include      "rfc822/rfc2047.h"
00027 #include      "rfc2045/rfc2045.h"
00028 #include      "gpglib/gpglib.h"
00029 #include      "courierauth.h"
00030 #include      <string.h>
00031 #include      <stdio.h>
00032 #include      <signal.h>
00033 #include      <stdlib.h>
00034 #include      <fcntl.h>
00035 #include      <ctype.h>
00036 #if    HAVE_UNISTD_H
00037 #include      <unistd.h>
00038 #endif
00039 #include      <sys/types.h>
00040 #if    HAVE_SYS_WAIT_H
00041 #include      <sys/wait.h>
00042 #endif
00043 #include      <errno.h>
00044 #include      "htmllibdir.h"
00045 #include      "unicode/unicode.h"
00046 
00047 extern const char *sqwebmail_content_charset;
00048 extern int spell_start(const char *);
00049 extern const char *sqwebmail_mailboxid;
00050 extern const char *sqwebmail_folder;
00051 extern void print_safe_len(const char *, size_t, void (*)(const char *, size_t));
00052 extern void call_print_safe_to_stdout(const char *, size_t);
00053 extern void print_attrencodedlen(const char *, size_t, int, FILE *);
00054 extern void output_attrencoded_nltobr(const char *);
00055 extern void output_attrencoded_oknl(const char *);
00056 extern void output_attrencoded(const char *);
00057 extern void output_scriptptrget();
00058 extern void output_form(const char *);
00059 extern void output_urlencoded(const char *);
00060 
00061 extern char *newmsg_newdraft(const char *, const char *, const char *,
00062                             const char *);
00063 extern char *newmsg_createdraft(const char *);
00064 extern char *newmsg_createsentmsg(const char *, int *);
00065 extern int ishttps();
00066 
00067 static void newmsg_header(const char *label, const char *field,
00068                        const char *encoded, const char *val)
00069 {
00070 int           hdrmaxlen=512;
00071 const char    *p=getarg("HDRMAXLEN");
00072 
00073        if (p && (atoi(p) > hdrmaxlen))
00074               hdrmaxlen=atoi(p);
00075 
00076        printf("<tr><th align=\"right\"><p class=\"new-message-header\">"
00077               "<span class=\"new-message-header-%s\">%s</span></p></th>"
00078               "<td width=\"6\">&nbsp;</td>",
00079               field, label);
00080 
00081        printf("<td><input type=\"text\" name=\"%s\" size=\"50\" maxlength=\"%d\""
00082               " class=\"new-message-header-text\" value=\"",
00083               field, hdrmaxlen);
00084        if (encoded)
00085        {
00086               char   *s;
00087 
00088               s=rfc822_display_hdrvalue_tobuf("subject",
00089                                           encoded,
00090                                           sqwebmail_content_charset,
00091                                           NULL,
00092                                           NULL);
00093 
00094               if (!s)
00095                      s=strdup(encoded);
00096 
00097               if (!s)       enomem();
00098               output_attrencoded(s);
00099               free(s);
00100        }
00101        else if (val)
00102               output_attrencoded(val);
00103        printf("\" /></td></tr>\n");
00104 }
00105 
00106 static void printc(char c, void *dummy)
00107 {
00108        char b[2];
00109 
00110        b[0]=c;
00111        b[1]=0;
00112        output_attrencoded(b);
00113 }
00114 
00115 static void printsep(const char *c, void *dummy)
00116 {
00117        output_attrencoded(c);
00118 }
00119 
00120 static void newmsg_header_rfc822(const char *label, const char *field,
00121                              const char *encoded, const char *val,
00122                              int is_readonly)
00123 {
00124 int           hdrmaxlen=512;
00125 const char    *p=getarg("HDRMAXLEN");
00126 
00127        if (p && (atoi(p) > hdrmaxlen))
00128               hdrmaxlen=atoi(p);
00129 
00130        printf("<tr><th align=\"right\"><p class=\"new-message-header\">"
00131               "<span class=\"new-message-header-%s\">%s</span></p></th>"
00132               "<td width=\"6\">&nbsp;</td>",
00133               field, label);
00134 
00135        printf("<td><input type=\"text\" name=\"%s\" size=\"50\" maxlength=\"%d\""
00136               " class=\"new-message-header-text\" value=\"",
00137               field, hdrmaxlen);
00138        if (encoded)
00139        {
00140               struct rfc822t *t=rfc822t_alloc_new(encoded, NULL, NULL);
00141               struct rfc822a *a=t ? rfc822a_alloc(t):NULL;
00142 
00143               if (a)
00144               {
00145                      rfc2047_print_unicodeaddr(a, sqwebmail_content_charset,
00146                                             printc,
00147                                             printsep, NULL);
00148                      rfc822a_free(a);
00149               }
00150 
00151               if (t)
00152                      rfc822t_free(t);
00153        }
00154        else if (val)
00155               output_attrencoded(val);
00156        printf("\"%s /></td></tr>\n",
00157               is_readonly ? " readonly=\"readonly\"":"");
00158 }
00159 
00160 static const char *ispreviewmsg()
00161 {
00162 const char *p=cgi("previewmsg");
00163 
00164        if (*p == 0)
00165               p=cgi("addressbook_to");
00166 
00167        if (*p == 0)
00168               p=cgi("addressbook_cc");
00169 
00170        if (*p == 0)
00171               p=cgi("addressbook_bcc");
00172 
00173        return (p);
00174 }
00175 
00176 void newmsg_hiddenheader(const char *label, const char *value)
00177 {
00178        printf("<input type=\"hidden\" name=\"%s\" value=\"", label);
00179        output_attrencoded(value);
00180        printf("\" />");
00181 }
00182 
00183 /* ---------------------------------------------------- */
00184 
00185 static size_t show_textarea_start_of_line(struct show_textarea_info *,
00186                                      const char *, size_t);
00187 
00188 static size_t show_textarea_quoted_text(struct show_textarea_info *,
00189                                    const char *, size_t);
00190 
00191 static size_t show_textarea_notseen_sp(struct show_textarea_info *,
00192                                    const char *, size_t);
00193 
00194 static size_t show_textarea_seen_sp(struct show_textarea_info *,
00195                                 const char *, size_t);
00196 
00197 static size_t show_textarea_seen_spnl(struct show_textarea_info *,
00198                                   const char *, size_t);
00199 
00200 static size_t show_textarea_check_sig(struct show_textarea_info *,
00201                                   const char *, size_t);
00202 
00203 static size_t show_textarea_ignore_sig(struct show_textarea_info *,
00204                                    const char *, size_t);
00205 
00206 void show_textarea_init(struct show_textarea_info *info,
00207                      int stop_at_sig)
00208 {
00209        info->handler=show_textarea_start_of_line;
00210        info->stop_at_sig=stop_at_sig;
00211 }
00212 
00213 void show_textarea(struct show_textarea_info *info,
00214                  const char *ptr, size_t cnt)
00215 {
00216        while (cnt)
00217        {
00218               size_t n= (*info->handler)(info, ptr, cnt);
00219 
00220               cnt -= n;
00221               ptr += n;
00222        }
00223 }
00224 
00225 static size_t show_textarea_start_of_line(struct show_textarea_info *info,
00226                                      const char *ptr, size_t cnt)
00227 {
00228        if (*ptr == '>')
00229        {
00230               info->handler=show_textarea_quoted_text;
00231               return show_textarea_quoted_text(info, ptr, cnt);
00232        }
00233 
00234        info->handler=show_textarea_notseen_sp;
00235 
00236        if (*ptr == ' ')
00237               return 1; /* Consume space-stuffed space */
00238 
00239        if (info->stop_at_sig)
00240        {
00241               info->handler=show_textarea_check_sig;
00242               info->sig_index=0;
00243               return show_textarea_check_sig(info, ptr, cnt);
00244        }
00245        return show_textarea_notseen_sp(info, ptr, cnt);
00246 }
00247 
00248 static size_t show_textarea_quoted_text(struct show_textarea_info *info,
00249                                    const char *ptr, size_t cnt)
00250 {
00251        size_t i;
00252 
00253        for (i=0; i<cnt; i++)
00254        {
00255               if (ptr[i] == '\n')
00256               {
00257                      ++i;
00258                      info->handler=show_textarea_start_of_line;
00259                      break;
00260               }
00261        }
00262 
00263        if (i)
00264               print_attrencodedlen(ptr, i, 1, stdout);
00265        return i;
00266 }
00267 
00268 static size_t show_textarea_notseen_sp(struct show_textarea_info *info,
00269                                    const char *ptr, size_t cnt)
00270 {
00271        size_t i;
00272 
00273        for (i=0; i<cnt; i++)
00274        {
00275               if (ptr[i] == '\n')
00276               {
00277                      ++i;
00278                      info->handler=show_textarea_start_of_line;
00279                      break;
00280               }
00281 
00282               if (ptr[i] == ' ')
00283               {
00284                      if (i)
00285                             print_attrencodedlen(ptr, i, 1, stdout);
00286                      info->handler=show_textarea_seen_sp;
00287                      return i+1;
00288               }
00289        }
00290 
00291        if (i)
00292               print_attrencodedlen(ptr, i, 1, stdout);
00293        return i;
00294 }
00295 
00296 static size_t show_textarea_seen_sp(struct show_textarea_info *info,
00297                                 const char *ptr, size_t cnt)
00298 {
00299        if (*ptr != '\n')
00300        {
00301               info->handler=show_textarea_notseen_sp;
00302               print_attrencodedlen(" ", 1, 1, stdout);
00303               return show_textarea_notseen_sp(info, ptr, cnt);
00304        }
00305 
00306        info->handler=show_textarea_seen_spnl;
00307        return 1;
00308 }
00309 
00310 static size_t show_textarea_seen_spnl(struct show_textarea_info *info,
00311                                   const char *ptr, size_t cnt)
00312 {
00313        if (*ptr == '>' || *ptr == '\n') /* Fix this */
00314        {
00315               print_attrencodedlen("\n", 1, 1, stdout);
00316               return show_textarea_start_of_line(info, ptr, cnt);
00317        }
00318 
00319        info->handler=show_textarea_notseen_sp;
00320        return show_textarea_notseen_sp(info, ptr, cnt);
00321 }
00322 
00323 static size_t show_textarea_check_sig(struct show_textarea_info *info,
00324                                   const char *ptr, size_t cnt)
00325 {
00326        static const char sig[]={'-', '-', ' ', '\n'};
00327        size_t i;
00328 
00329        for (i=0; i<cnt; ++i)
00330        {
00331               if (i + info->sig_index >= sizeof(sig))
00332               {
00333                      info->handler=show_textarea_ignore_sig;
00334                      return cnt;
00335               }
00336 
00337               if (ptr[i] != sig[i+info->sig_index])
00338               {
00339                      info->handler=show_textarea_notseen_sp;
00340 
00341                      show_textarea(info, sig, info->sig_index);
00342                      show_textarea(info, ptr, cnt);
00343                      return cnt;
00344               }
00345        }
00346 
00347        info->sig_index += cnt;
00348        return cnt;
00349 }
00350 
00351 static size_t show_textarea_ignore_sig(struct show_textarea_info *info,
00352                                    const char *ptr, size_t cnt)
00353 {
00354        return cnt;
00355 }
00356 
00357 /*
00358 ** Return all from/to/cc/bcc addresses in the message.
00359 */
00360 
00361 char *newmsg_alladdrs(FILE *fp)
00362 {
00363        char   *headers=NULL;
00364        struct rfc822t *t;
00365        struct rfc822a *a;
00366        char *p, *q;
00367        int l, i;
00368 
00369        if (fp)
00370        {
00371               char *header, *value;
00372 
00373               rewind(fp);
00374 
00375               /* First, combine all the headers into one header. */
00376 
00377               while ((header=maildir_readheader(fp, &value, 1)) != 0)
00378               {
00379                      char *newh;
00380 
00381                      if (strcmp(header, "from") &&
00382                          strcmp(header, "to") &&
00383                          strcmp(header, "cc") &&
00384                          strcmp(header, "bcc"))
00385                             continue;
00386 
00387                      if (headers)
00388                      {
00389                             newh=realloc(headers, strlen(headers)
00390                                         +strlen(value)+2);
00391                             if (!newh)
00392                                    continue;
00393                             strcat(newh, ",");
00394                             headers=newh;
00395                      }
00396                      else
00397                      {
00398                             newh=malloc(strlen(value)+1);
00399                             if (!newh)
00400                                    continue;
00401                             *newh=0;
00402                             headers=newh;
00403                      }
00404                      strcat(headers, value);
00405               }
00406 
00407        }
00408 
00409        /* Now, parse the header, and extract the addresses */
00410 
00411        t=rfc822t_alloc_new(headers ? headers:"", NULL, NULL);
00412        a= t ? rfc822a_alloc(t):NULL;
00413 
00414        l=1;
00415        for (i=0; i < (a ? a->naddrs:0); i++)
00416        {
00417               p=rfc822_getaddr(a, i);
00418               if (p)
00419               {
00420                      ++l;
00421                      l +=strlen(p);
00422                      free(p);
00423               }
00424        }
00425        p=malloc(l);
00426        if (p)
00427               *p=0;
00428 
00429        for (i=0; i < (a ? a->naddrs:0); i++)
00430        {
00431               q=rfc822_getaddr(a, i);
00432               if (q)
00433               {
00434                      if (p)
00435                      {
00436                             strcat(strcat(p, q), "\n");
00437                      }
00438                      free(q);
00439               }
00440        }
00441 
00442        rfc822a_free(a);
00443        rfc822t_free(t);
00444        free(headers);
00445        return (p);
00446 }
00447 
00448 static int show_textarea_trampoline(const char *ptr, size_t cnt, void *arg)
00449 {
00450        show_textarea( (struct show_textarea_info *)arg, ptr, cnt);
00451        return 0;
00452 }
00453 
00454 void newmsg_showfp(FILE *fp, int *attachcnt)
00455 {
00456        struct rfc2045 *p=rfc2045_fromfp(fp), *q;
00457 
00458        if (!p)       enomem();
00459 
00460        /* Here's a nice opportunity to count all attachments */
00461 
00462        *attachcnt=0;
00463 
00464        for (q=p->firstpart; q; q=q->next)
00465               if (!q->isdummy)     ++*attachcnt;
00466        if (*attachcnt)      --*attachcnt;
00467        /* Not counting the 1st MIME part */
00468 
00469        {
00470               const char *content_type;
00471               const char *content_transfer_encoding;
00472               const char *charset;
00473 
00474               rfc2045_mimeinfo(p, &content_type,
00475                              &content_transfer_encoding, &charset);
00476 
00477               if (content_type &&
00478                   strcmp(content_type, "multipart/alternative") == 0)
00479                      *attachcnt=0;
00480        }
00481 
00482        q=rfc2045_searchcontenttype(p, "text/plain");
00483 
00484        if (q)
00485        {
00486               struct rfc2045src *src=rfc2045src_init_fd(fileno(fp));
00487 
00488               if (src)
00489               {
00490                      struct show_textarea_info info;
00491 
00492                      show_textarea_init(&info, 1);
00493 
00494                      rfc2045_decodetextmimesection(src, q,
00495                                                 sqwebmail_content_charset,
00496                                                 NULL,
00497                                                 &show_textarea_trampoline,
00498                                                 &info);
00499                      rfc2045src_deinit(src);
00500                      show_textarea(&info, "\n", 1);
00501               }
00502        }
00503        rfc2045_free(p);
00504 }
00505 
00506 void newmsg_preview(const char *p)
00507 {
00508        size_t pos;
00509 
00510        maildir_remcache(INBOX "." DRAFTS);
00511        if (maildir_name2pos(INBOX "." DRAFTS, p, &pos) == 0)
00512        {
00513               const char *save_folder=sqwebmail_folder;
00514               cgi_put("showdraft", "1");
00515               sqwebmail_folder=INBOX "." DRAFTS;
00516               folder_showmsg(INBOX "." DRAFTS, pos);
00517               sqwebmail_folder=save_folder;
00518                             /* show_preview(draftmessagefilename); */
00519        }
00520 }
00521 
00522 /* ---------------------------------------------------- */
00523 
00524 void newmsg_init(const char *folder, const char *pos)
00525 {
00526        const char    *tolab=getarg("TOLAB");
00527        const char    *cclab=getarg("CCLAB");
00528        const char    *bcclab=getarg("BCCLAB");
00529        const char    *subjectlab=getarg("SUBJECTLAB");
00530        const char    *messagelab=getarg("MESSAGELAB");
00531        const char    *sendlab=getarg("SENDLAB");
00532        const char    *previewlab=getarg("PREVIEWLAB");
00533        const char    *forwardsep=getarg("FORWARDLAB");
00534        const char    *savedraft=getarg("SAVEDRAFT");
00535        const char    *attachmentslab=getarg("ATTACHMENTS");
00536        const char      *uploadlab=getarg("UPLOAD");
00537        const char    *replysalutation=getarg("SALUTATION");
00538        const char    *checkspellingdone=getarg("SPELLCHECKDONE");
00539        const char    *checkspelling=getarg("CHECKSPELLING");
00540        const char    *quotaerr=getarg("QUOTAERR");
00541        const char    *fromlab=getarg("FROMLAB");
00542        const char    *replytolab=getarg("REPLYTOLAB");
00543        const char    *addressbooklab=getarg("ADDRESSBOOK");
00544        const char    *select1=getarg("SELECT1");
00545        const char    *select2=getarg("SELECT2");
00546        const char    *text1=getarg("TEXT1");
00547        const char    *text2=getarg("TEXT2");
00548        char   *draftmessage;
00549        char   *draftmessagefilename;
00550        const  char *p;
00551        FILE   *fp;
00552        int    attachcnt=0;
00553        char   *cursubj, *curto, *curcc, *curbcc, *curfrom, *curreplyto;
00554        int wbnochangingfrom;
00555 
00556        /* Picking up an existing draft? */
00557 
00558        p=cgi("draft");
00559        if (*p)
00560        {
00561               CHECKFILENAME(p);
00562        }
00563 
00564        if (*p)
00565        {
00566               draftmessage=strdup(p);
00567               if (!draftmessage)   enomem();
00568               p="";
00569        }
00570        else
00571        {
00572               draftmessage=newmsg_newdraft(folder, pos,
00573                      forwardsep, replysalutation);
00574 
00575               if (!draftmessage)
00576               {
00577                      if (*ispreviewmsg())
00578                      {
00579                             p=cgi("draftmessage");
00580                             if (*p)
00581                             {
00582                                    CHECKFILENAME(p);
00583                             }
00584                             draftmessage=newmsg_createdraft(p);
00585                      }
00586               }
00587        }
00588 
00589        draftmessagefilename= draftmessage ?
00590                              maildir_find(INBOX "." DRAFTS, draftmessage):0;
00591 
00592        if (*(p=cgi("previewmsg")))
00593        {
00594 #ifdef ISPELL
00595               if (strcmp(p, "SPELLCHK") == 0)
00596                      printf("%s<br /><br />\n", checkspellingdone);
00597 #endif
00598               printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\" class=\"box-small-outer\"><tr><td>\n");
00599               printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\" class=\"preview\"><tr><td>\n");
00600 
00601               if (draftmessagefilename)
00602               {
00603                      const char *p=strrchr(draftmessagefilename, '/');
00604 
00605                      if (p)
00606                             ++p;
00607                      else
00608                             p=draftmessagefilename;
00609 
00610                      newmsg_preview(p);
00611               }
00612               printf("</td></tr></table>\n");
00613               printf("</td></tr></table>\n");
00614 
00615               printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"6\"><tr><td><hr width=\"80%%\" /></td></tr></table>\n");
00616        }
00617 
00618        printf("<input type=\"hidden\" name=\"form\" value=\"donewmsg\" />\n");
00619        newmsg_hiddenheader("pos", pos);
00620        newmsg_hiddenheader("focusto",
00621                          *cgi("newmsg") ? "headers":"text");
00622 
00623        /* Generate unique message token, to detect duplicate SUBMITs */
00624 
00625        tokennew();
00626 
00627        /* Display any error message */
00628 
00629        if (*cgi("foldermsg"))
00630        {
00631               printf("<p><span class=\"error\" style=\"color: #ff0000\">");
00632               output_attrencoded_nltobr(cgi("foldermsg"));
00633               printf("</span></p>");
00634        }
00635 
00636        if (strcmp(cgi("error"), "quota") == 0)
00637               printf("%s", quotaerr);
00638 
00639        /* Read message from the draft file */
00640 
00641        cursubj=0;
00642        curto=0;
00643        curfrom=0;
00644        curreplyto=0;
00645        curcc=0;
00646        curbcc=0;
00647        fp=0;
00648 
00649        if (draftmessagefilename)
00650        {
00651        int    x=maildir_safeopen(draftmessagefilename, O_RDONLY, 0);
00652 
00653               if (x >= 0)
00654                      if ((fp=fdopen(x, "r")) == 0)
00655                             close(x);
00656        }
00657 
00658        if (fp != 0)
00659        {
00660        char *header, *value;
00661 
00662               while ((header=maildir_readheader(fp, &value, 0)) != 0)
00663               {
00664               char   **rfchp=0;
00665 
00666                      if (strcmp(header, "subject") == 0)
00667                      {
00668                             if (!cursubj && !(cursubj=strdup(value)))
00669                                    enomem();
00670                             continue;
00671                      }
00672 
00673                      while (*value && isspace(*value))
00674                             ++value;
00675 
00676                      if (strcmp(header, "from") == 0)
00677                             rfchp= &curfrom;
00678                      if (strcmp(header, "reply-to") == 0)
00679                             rfchp= &curreplyto;
00680                      if (strcmp(header, "to") == 0)
00681                             rfchp= &curto;
00682                      if (strcmp(header, "cc") == 0)
00683                             rfchp= &curcc;
00684                      if (strcmp(header, "bcc") == 0)
00685                             rfchp= &curbcc;
00686                      if (rfchp)
00687                      {
00688                      char   *newh=malloc ( (*rfchp ? strlen(*rfchp)+2:1)
00689                                    +strlen(value));
00690 
00691                             if (!newh)    enomem();
00692                             strcpy(newh, value);
00693                             if (*rfchp)
00694                                    strcat(strcat(newh, ","), *rfchp);
00695                             if (*rfchp)   free( *rfchp );
00696                             *rfchp=newh;
00697                      }
00698               }
00699        }
00700 
00701        printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\" class=\"box-small-outer\"><tr><td>\n");
00702        printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\" class=\"new-message-box\"><tr><td>\n");
00703 
00704        printf("<table border=\"0\" width=\"100%%\">\n");
00705        wbnochangingfrom=auth_getoptionenvint("wbnochangingfrom");
00706        if (wbnochangingfrom < 2)
00707               newmsg_header_rfc822(fromlab, "headerfrom", curfrom,
00708                      *cgi("from") ? cgi("from"):
00709                      pref_from && *pref_from ? pref_from:
00710                      login_fromhdr(), wbnochangingfrom ? 1:0);
00711 
00712        printf("<tr valign=\"middle\"><th align=\"right\">"
00713               "<p class=\"new-message-header\">"
00714               "<span class=\"new-message-header-addressbook\">"
00715               "%s</span></p></th><td width=\"6\">&nbsp;</td>",
00716               addressbooklab);
00717 
00718        printf("<td valign=\"middle\">");
00719        printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"4\">");
00720        printf("<tr valign=\"middle\"><td>%s\n", select1);
00721        ab_listselect();
00722        printf("%s</td><td width=\"100%%\">", select2);
00723        printf("<input type=\"submit\" name=\"addressbook_to\" value=\"%s\" />",
00724                      tolab);
00725        printf("<input type=\"submit\" name=\"addressbook_cc\" value=\"%s\" />",
00726                      cclab);
00727        printf("<input type=\"submit\" name=\"addressbook_bcc\" value=\"%s\" />",
00728                      bcclab);
00729        printf("</td></tr></table>");
00730 
00731        printf("</td></tr>\n");
00732 
00733 #if 0
00734                      {
00735                             FILE *fp;
00736                             fp=fopen("/tmp/pid", "w");
00737                             fprintf(fp, "%d", getpid());
00738                             fclose(fp);
00739                             sleep(10);
00740                      }
00741 #endif
00742 
00743        newmsg_header_rfc822(tolab, "headerto", curto, cgi("to"), 0);
00744        newmsg_header_rfc822(cclab, "headercc", curcc, cgi("cc"), 0);
00745        newmsg_header_rfc822(bcclab, "headerbcc", curbcc, cgi("bcc"), 0);
00746        newmsg_header_rfc822(replytolab, "headerreply-to",
00747                           curreplyto, cgi("replyto"), 0);
00748        newmsg_header(subjectlab, "headersubject",
00749                     cursubj, cgi("subject"));
00750 
00751        if (curto)    free(curto);
00752        if (curfrom)  free(curfrom);
00753        if (curreplyto)      free(curreplyto);
00754        if (curcc)    free(curcc);
00755        if (curbcc)   free(curbcc);
00756        if (cursubj)  free(cursubj);
00757 
00758        printf("<tr><td colspan=\"3\"><hr width=\"100%%\" /></td></tr>");
00759        printf("<tr>"
00760 
00761               "<th valign=\"top\" align=\"right\">"
00762               "<p class=\"new-message-header\">"
00763               "<span class=\"new-message-header-message\">"
00764               "%s</span></p></th><td width=\"6\">&nbsp;</td>"
00765               "<td><select name=\"textformat\">"
00766               "<option value=\"plain\" %s>%s</option>"
00767               "<option value=\"wiki\" %s>%s</option></select>"
00768 
00769               "<small>(<a href='%s/wikifmt.html' target='_blank'>%s</a>)</small>"
00770               "</td></tr>"
00771               "<tr><th valign=\"top\" align=\"right\">"
00772               "<p class=\"new-message-header\">"
00773               "<span class=\"new-message-header-message\">"
00774               "%s</span></p></th><td width=\"6\">&nbsp;</td>",
00775 
00776               getarg("FMTNAME"),
00777               pref_wikifmt ? "":"selected='selected'", getarg("FMTTEXTPLAIN"),
00778               pref_wikifmt ? "selected='selected'":"", getarg("FMTTEXTWIKI"),
00779 
00780               get_imageurl(), getarg("FMTHELP"),
00781               messagelab);
00782 
00783        printf("<td>%s\n", text1);
00784 
00785        if (fp)
00786        {
00787               newmsg_showfp(fp, &attachcnt);
00788        }
00789        else
00790        {
00791               printf("%s", cgi("body"));
00792        }
00793        printf("%s\n", text2);
00794 
00795        if (draftmessage && *draftmessage)
00796        {
00797               printf("<input type=\"hidden\" name=\"draftmessage\" value=\"");
00798               output_attrencoded(draftmessage);
00799 
00800               printf("\" />");
00801        }
00802        if (draftmessage)    free(draftmessage);
00803        printf("</td></tr>\n");
00804 
00805        printf("<tr><th valign=\"top\" align=\"right\">"
00806               "<p class=\"new-message-header\">"
00807               "<span class=\"new-message-header-message\">"
00808               "%s</span></p></th><td>&nbsp;</td>"
00809               "<td>%d&nbsp;&nbsp;<input type=\"submit\" name=\"doattachments\" value=\"%s\" /></td></tr>",
00810               attachmentslab, attachcnt, uploadlab);
00811 
00812        printf("<tr><td colspan=\"2\" align=\"right\"><input type=\"checkbox\" "
00813               "name=\"fcc\" id=\"fcc\"%s /></td><td><label for=\"fcc\">%s</label></td></tr>\n",
00814               pref_noarchive ? "":" checked=\"checked\"",
00815               getarg("PRESERVELAB"));
00816 
00817        if (auth_getoptionenvint("wbnodsn") == 0)
00818               printf("<tr><td colspan=\"2\" align=\"right\"><input type=\"checkbox\" "
00819                      "name=\"dsn\" id=\"dsn\" /></td><td><label for=\"dsn\">%s</label></td></tr>\n",
00820                      getarg("DSN"));
00821 
00822        if (libmail_gpg_has_gpg(GPGDIR) == 0)
00823        {
00824               char *all_addr;
00825 
00826               printf("<tr><td colspan=\"2\" align=\"right\"><input type=\"checkbox\" "
00827                      "name=\"sign\" id=\"sign\" /></td><td><label for=\"sign\">%s</label><select name=\"signkey\">",
00828                      getarg("SIGNLAB"));
00829               gpgselectkey();
00830               printf("</select></td></tr>\n");
00831 
00832               all_addr=newmsg_alladdrs(fp);
00833 
00834               printf("<tr valign=\"middle\"><td colspan=\"2\" align=\"right\">"
00835                      "<input type=\"checkbox\" name=\"encrypt\" id=\"encrypt\" /></td>"
00836                      "<td><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr valign=\"middle\"><td><label for=\"encrypt\">%s</label></td><td><select size=\"4\" multiple=\"multiple\" name=\"encryptkey\">",
00837                      getarg("ENCRYPTLAB"));
00838               gpgencryptkeys(all_addr);
00839               printf("</select></td></tr>\n");
00840               printf("</table></td></tr>\n");
00841 
00842               if (ishttps())
00843                      printf("<tr><td colspan=\"2\" align=\"left\">&nbsp;</td><td>%s<input type=\"password\" name=\"passphrase\" /></td></tr>\n",
00844                             getarg("PASSPHRASE"));
00845 
00846               if (all_addr)
00847                      free(all_addr);
00848        }
00849 
00850        if (fp)
00851               fclose(fp);
00852        if (draftmessagefilename)
00853               free(draftmessagefilename);
00854 
00855        printf("<tr><td colspan=\"2\">&nbsp;</td><td>");
00856        printf("<input type=\"submit\" name=\"previewmsg\" value=\"%s\" />",
00857               previewlab);
00858        printf("<input type=\"submit\" name=\"sendmsg\" value=\"%s\" />",
00859               sendlab);
00860        printf("<input type=\"submit\" name=\"savedraft\" value=\"%s\" />",
00861               savedraft);
00862 #ifdef ISPELL
00863        printf("<input type=\"submit\" name=\"startspellchk\" value=\"%s\" />",
00864               checkspelling);
00865 #endif
00866        printf("</td></tr>\n");
00867        printf("</table>\n");
00868 
00869        printf("</td></tr></table>\n");
00870        printf("</td></tr></table>\n");
00871 }
00872 
00873 static const char *geterrbuf(int fd)
00874 {
00875 static char errbuf[512];
00876 char   *errbufptr=errbuf;
00877 size_t errbufleft=sizeof(errbuf)-1;
00878 
00879        while (errbufleft)
00880        {
00881        int    l=read(fd, errbufptr, errbufleft);
00882 
00883               if (l <= 0)   break;
00884               errbufptr += l;
00885               errbufleft -= l;
00886        }
00887        *errbufptr=0;
00888        return (errbuf);
00889 }
00890 
00891 static int waitfor(pid_t pid)
00892 {
00893 pid_t  childpid;
00894 int    wait_stat;
00895 
00896        while ((childpid=wait(&wait_stat)) != pid)
00897               if (childpid == -1)  return (-1);
00898 
00899        return (wait_stat);
00900 }
00901 
00902 void sendmsg_done()
00903 {
00904        if ( *cgi("pos"))
00905               http_redirect_argss("&form=readmsg&pos=%s", cgi("pos"), "");
00906        else if (*cgi("sendmsg"))
00907               http_redirect_argss("&form=folders&foldermsg=sent", "", "");
00908        else
00909               http_redirect_argss("&form=folders", "", "");
00910 }
00911 
00912 static int dosendmsg(const char *origdraft)
00913 {
00914 pid_t  pid;
00915 const  char *returnaddr;
00916 int    pipefd1[2];
00917 char   *filename;
00918 const char *line;
00919 char   *draftmessage;
00920 int    isgpgerr;
00921 unsigned long filesize;
00922 struct stat stat_buf;
00923 int dsn;
00924 
00925        if (tokencheck()) /* Duplicate submission - message was already sent */
00926        {
00927               sendmsg_done();
00928               return (1);
00929        }
00930 
00931        if (strcmp(cgi("form"), "doattach") == 0)
00932        {
00933               /* When called from the attachment window, we do NOT create
00934               ** a new draft message */
00935 
00936               draftmessage=strdup(origdraft);
00937        }
00938        else
00939               draftmessage=newmsg_createdraft(origdraft);
00940        if (!draftmessage)
00941               enomem();
00942 
00943        filename=newmsg_createsentmsg(draftmessage, &isgpgerr);
00944 
00945        if (!filename)
00946        {
00947               char *draftbase=maildir_basename(draftmessage);
00948 
00949               if (isgpgerr)
00950               {
00951                      cgi_put("draftmessage", draftbase);
00952                      output_form("gpgerr.html");
00953               }
00954               else
00955               {
00956                      http_redirect_argss("&form=newmsg&pos=%s"
00957                                        "&draft=%s&error=quota",
00958                                        cgi("pos"), draftbase);
00959               }
00960               free(draftmessage);
00961               free(draftbase);
00962               return (1);
00963        }
00964 
00965        if (pipe(pipefd1) != 0)
00966        {
00967               cgi_put("foldermsg", "ERROR: pipe() failed.");
00968               maildir_msgpurgefile(INBOX "." SENT, filename);
00969               free(filename);
00970               free(draftmessage);
00971               return (0);
00972        }
00973 
00974        dsn= *cgi("dsn") != 0;
00975 
00976        pid=fork();
00977        if (pid < 0)
00978        {
00979               cgi_put("foldermsg", "ERROR: fork() failed.");
00980               close(pipefd1[0]);
00981               close(pipefd1[1]);
00982               maildir_msgpurgefile(INBOX "." SENT, filename);
00983               free(filename);
00984               free(draftmessage);
00985               return (0);
00986        }
00987 
00988        if (pid == 0)
00989        {
00990        static const char noexec[]="ERROR: Unable to execute sendit.sh.\n";
00991        static const char nofile[]="ERROR: Temp file not available - probably exceeded quota.\n";
00992        char   *tmpfile=maildir_find(INBOX "." SENT, filename);
00993        int    fd;
00994 
00995               if (!tmpfile)
00996               {
00997                      if (fwrite((char*)nofile, 1, sizeof(nofile)-1, stderr))
00998                             ; /* ignore */
00999                      _exit(1);
01000               }
01001 
01002               close(0);
01003 
01004               fd=maildir_safeopen(tmpfile, O_RDONLY, 0);
01005               dup2(pipefd1[1], 1);
01006               dup2(pipefd1[1], 2);
01007               close(pipefd1[0]);
01008               close(pipefd1[1]);
01009 
01010               if (dsn)
01011                      putenv("DSN=-Nsuccess,delay,failure");
01012               else
01013                      putenv("DSN=");
01014 
01015               if (fd == 0)
01016               {
01017                      returnaddr=login_returnaddr();
01018                      execl(SENDITSH, "sendit.sh", returnaddr,
01019                             sqwebmail_mailboxid, NULL);
01020               }
01021                      
01022               if (fwrite(noexec, 1, sizeof(noexec)-1, stderr))
01023                      ; /* ignore */
01024               _exit(1);
01025        }
01026        close(pipefd1[1]);
01027 
01028        line=geterrbuf(pipefd1[0]);
01029        close(pipefd1[0]);
01030 
01031        if (waitfor(pid))
01032        {
01033               if (!*line)
01034                      line="Unable to send message.\n";
01035        }
01036        else
01037               line="";
01038 
01039        if (*line == 0)      /* Succesfully sent message */
01040        {
01041               if (*draftmessage)
01042               {
01043               char   *base=maildir_basename(draftmessage);
01044               char   *draftfile=maildir_find(INBOX "." DRAFTS, base);
01045 
01046                      free(base);
01047 
01048                      /* Remove draft file */
01049 
01050                      if (draftfile)
01051                      {
01052                      char   *replytofolder=0, *replytomsg=0;
01053                      char   *header, *value;
01054                      FILE   *fp;
01055                      int    x;
01056 
01057                             fp=0;
01058                             x=maildir_safeopen(draftfile, O_RDONLY, 0);
01059                             if ( maildir_parsequota(draftfile, &filesize))
01060                             {
01061                                    if (x < 0 || fstat(x, &stat_buf))
01062                                           stat_buf.st_size=0;
01063                                    filesize=stat_buf.st_size;
01064                             }
01065 
01066                             if (x >= 0)
01067                                    if ((fp=fdopen(x, "r")) == 0)
01068                                           close(x);
01069 
01070                             /* First, look for a message that we should
01071                             ** mark as replied */
01072 
01073                             while (fp && (header=maildir_readheader(fp,
01074                                           &value, 0)) != 0)
01075                             {
01076                                    if (strcmp(header,"x-reply-to-folder")
01077                                           == 0 && !replytofolder)
01078                                    {
01079                                           replytofolder=strdup(value);
01080                                           if (!replytofolder)
01081                                                  enomem();
01082                                    }
01083                                    if (strcmp(header,"x-reply-to-msg")
01084                                           == 0 && !replytomsg)
01085                                    {
01086                                           replytomsg=strdup(value);
01087                                           if (!replytomsg)
01088                                                  enomem();
01089                                    }
01090                                    if (replytofolder && replytomsg)
01091                                           break;
01092                             }
01093                             if (fp)       fclose(fp);
01094 
01095                             if (replytofolder && replytomsg)
01096                                    maildir_markreplied(replytofolder,
01097                                                  replytomsg);
01098                             if (replytofolder)   free(replytofolder);
01099                             if (replytomsg)      free(replytomsg);
01100                             
01101                             maildir_quota_deleted(".",
01102                                                 -(long)filesize, -1);
01103 
01104                             unlink(draftfile);
01105                             free(draftfile);
01106                      }
01107               }
01108 
01109               tokensave();
01110 
01111               if (*cgi("fcc") == 0)
01112               {
01113                      unsigned long filesize=0;
01114                      char   *tmpfile=maildir_find(INBOX "." SENT, filename);
01115 
01116                      if (tmpfile)
01117                      {
01118                             maildir_parsequota(tmpfile, &filesize);
01119                             unlink(tmpfile);
01120                             maildir_quota_deleted(".", -(long)filesize,-1);
01121                             free(tmpfile);
01122                      }
01123               }
01124 
01125               free(filename);
01126               free(draftmessage);
01127               sendmsg_done();
01128               return (1);
01129        }
01130 
01131        if (stat(filename, &stat_buf) == 0)
01132               maildir_quota_deleted(".", -(long)stat_buf.st_size, -1);
01133        maildir_msgpurgefile(INBOX "." SENT, filename);
01134        free(filename);
01135 
01136        {
01137        char *draftbase=maildir_basename(draftmessage);
01138 
01139               http_redirect_argsss("&form=newmsg&pos=%s&draft=%s&foldermsg=%s",
01140                      cgi("pos"), draftbase, line);
01141               free(draftmessage);
01142               free(draftbase);
01143        }
01144        return (1);
01145 }
01146 
01147 void newmsg_do(const char *folder)
01148 {
01149 const  char *draftmessage=cgi("draftmessage");
01150 
01151        if (*draftmessage)   /* It's ok if it's blank */
01152        {
01153               CHECKFILENAME(draftmessage);
01154        }
01155 
01156        if (*cgi("savedraft"))
01157        {
01158        char   *newdraft=newmsg_createdraft(draftmessage);
01159 
01160               if (!newdraft)       enomem();
01161               free(newdraft);
01162               sendmsg_done();
01163               return;
01164        }
01165 
01166        if (*cgi("sendmsg") && dosendmsg(draftmessage))
01167               return;
01168 
01169        if (*cgi("doattachments"))
01170        {
01171        char   *newdraft=newmsg_createdraft(draftmessage);
01172        char   *base;
01173 
01174               if (!newdraft)       enomem();
01175               if (*cgi("error"))
01176               {
01177                      cgi_put("previewmsg", "1");
01178                      output_form("newmsg.html");
01179                      return;
01180               }
01181 
01182               base=maildir_basename(newdraft);
01183               http_redirect_argss("&form=attachments&pos=%s&draft=%s",
01184                      cgi("pos"), base);
01185               free(base);
01186               free(newdraft);
01187               return;
01188        }
01189 #ifdef ISPELL
01190        if (*cgi("startspellchk"))
01191        {
01192        char   *newdraft=newmsg_createdraft(draftmessage);
01193        char   *base;
01194 
01195               if (!newdraft)       enomem();
01196               base=maildir_basename(newdraft);
01197               free(newdraft);
01198               if (spell_start(base) == 0)
01199               {
01200                      cgi_put("draftmessage", base);
01201                      output_form("spellchk.html");
01202               }
01203               else
01204               {
01205                      http_redirect_argss("&form=newmsg&pos=%s&draft=%s&previewmsg=SPELLCHK",
01206                             cgi("pos"), base);
01207               }
01208               free(base);
01209               return;
01210        }
01211 #endif
01212        if (*ispreviewmsg())
01213        {
01214               output_form("newmsg.html");
01215               return;
01216        }
01217        http_redirect_argsss("&form=newmsg&pos=%s&draftmessage=%s&error=%s",
01218               cgi("pos"), draftmessage,
01219               cgi("error"));
01220 }