Advertisement
Guest User

Untitled

a guest
Aug 10th, 2017
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 51.33 KB | None | 0 0
  1. /*
  2. ** Copyright 1998 - 2002 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5.  
  6.  
  7. /*
  8. ** $Id: sqwebmail.c,v 1.96 2003/01/05 04:01:19 mrsam Exp $
  9. */
  10. #include    "sqwebmail.h"
  11. #include    "sqconfig.h"
  12. #include    "auth.h"
  13. #include    "folder.h"
  14. #include    "pref.h"
  15. #include    "maildir.h"
  16. #include    "cgi/cgi.h"
  17. #include    "pref.h"
  18. #include    "mailinglist.h"
  19. #include    "newmsg.h"
  20. #include    "pcp.h"
  21. #include    "addressbook.h"
  22. #include    "autoresponse.h"
  23. #include    "http11/http11.h"
  24. #include    "random128/random128.h"
  25. #include    "maildir/maildirmisc.h"
  26. #include    "rfc822/rfc822hdr.h"
  27. #include    <stdio.h>
  28. #include    <errno.h>
  29. #include    <stdlib.h>
  30. #if HAVE_UNISTD_H
  31. #include    <unistd.h>
  32. #endif
  33. #include    <string.h>
  34. #include    <signal.h>
  35. #include    <sys/types.h>
  36. #include    <sys/stat.h>
  37. #if HAVE_FCNTL_H
  38. #include    <fcntl.h>
  39. #endif
  40. #if HAVE_LOCALE_H
  41. #if HAVE_SETLOCALE
  42. #include    <locale.h>
  43. #endif
  44. #endif
  45. #include    <ctype.h>
  46. #if HAVE_SYS_WAIT_H
  47. #include    <sys/wait.h>
  48. #endif
  49. #define MD5_INTERNAL
  50. #include    "md5/md5.h"
  51.  
  52. #include    "maildir/maildircache.h"
  53. #include    "mailfilter.h"
  54. #include    "numlib/numlib.h"
  55. #include    "gpglib/gpglib.h"
  56. #include    "authlib/authstaticlist.h"
  57. #include    "gpg.h"
  58. #if HAVE_CRYPT_H
  59. #include    <crypt.h>
  60. #endif
  61. #if     NEED_CRYPT_PROTOTYPE
  62. extern char *crypt(const char *, const char *);
  63. #endif
  64. #include    "htmllibdir.h"
  65.  
  66. #if 0
  67. #ifdef  WEBPASS_CHANGE_VCHKPW
  68. #include "vpopmail.h"
  69. #include "vauth.h"
  70. #endif
  71. #endif
  72.  
  73. #if HAVE_SYSLOG_H
  74. #include    <syslog.h>
  75. #else
  76. #define syslog(a,b)
  77. #endif
  78.  
  79. #include "token.h"
  80. #include "attachments.h"
  81. #include "nl-tags.h"
  82. #include "nl-auth.h"
  83.  
  84. extern void spell_show();
  85. extern void spell_check_continue();
  86. extern void print_safe(const char *);
  87. extern void ldaplist();
  88. extern int ldapsearch();
  89. extern void doldapsearch();
  90.  
  91. extern void sent_gpgerrtxt();
  92. extern void sent_gpgerrresume();
  93. extern const char *redirect_hash(const char *);
  94.  
  95. const char *sqwebmail_mailboxid=0;
  96. const char *sqwebmail_folder=0;
  97. const char *sqwebmail_sessiontoken=0;
  98.  
  99. const char *sqwebmail_content_language=0;
  100. const char *sqwebmail_content_locale;
  101. const char *sqwebmail_content_ispelldict;
  102. const char *sqwebmail_content_charset;
  103.  
  104. static int noimages=0;
  105.  
  106. time_t  login_time;
  107.  
  108. /* Need to cache the following environment variables */
  109. static const char * const authvars[] = { "AUTHADDR", "AUTHFULLNAME", 0 };
  110.  
  111. #ifdef  GZIP
  112. static int gzip_save_fd;
  113. #endif
  114.  
  115. static const char *sqwebmail_formname;
  116.  
  117. extern void attachments_head(const char *, const char *, const char *);
  118. extern void attachments_opts(const char *);
  119. extern void doattach(const char *, const char *);
  120.  
  121. static void timezonelist();
  122.  
  123. struct template_stack {
  124.     struct template_stack *next;
  125.     FILE *fp;
  126. } ;
  127.  
  128. static struct template_stack *template_stack=NULL;
  129.  
  130. #if HAVE_LIBFCGI
  131. #include <signal.h>
  132. #include <setjmp.h>
  133.  
  134. static jmp_buf stackenv;
  135.  
  136. void fake_exit(int n)
  137. {
  138.     struct template_stack *s;
  139.  
  140.     maildir_cache_cancel();
  141.     FCGI_SetExitStatus(n);
  142.  
  143.     while ((s=template_stack) != NULL)
  144.     {
  145.         template_stack=s->next;
  146.         fclose(s->fp);
  147.         free(s);
  148.     }
  149.  
  150.     longjmp(stackenv,1);
  151. }
  152.  
  153. #ifdef  BANNERPROG
  154. #error "Bannerprog not supported with FCGI"
  155. #endif
  156.  
  157. #else
  158.  
  159. void fake_exit(int n)
  160. {
  161.     maildir_cache_cancel();
  162.     exit(n);
  163. }
  164.  
  165. #endif
  166.  
  167. /* Stub to catch aborts from authlib */
  168.  
  169. void authexit(int n)
  170. {
  171.     fake_exit(n);
  172. }
  173.  
  174. /* enomem() used to be just an out-of-memory handler.  Now, I use it as a
  175. ** generic failure type of a deal.
  176. */
  177.  
  178. void rfc2045_error(const char *p)
  179. {
  180.     error(p);
  181. }
  182.  
  183. void print_attrencodedlen(const char *p, size_t len, int oknl, FILE *fp)
  184. {
  185.     for (; len; p++, --len)
  186.     {
  187.         switch (*p) {
  188.         case '<':
  189.             fprintf(fp, "<");
  190.             continue;
  191.         case '>':
  192.             fprintf(fp, ">");
  193.             continue;
  194.         case '&':
  195.             fprintf(fp, "&");
  196.             continue;
  197.         case '"':
  198.             fprintf(fp, """);
  199.             continue;
  200.         case '\n':
  201.             if (oknl)
  202.             {
  203.                 if (oknl == 2)
  204.                 {
  205.                     fprintf(fp, "<BR>");
  206.                     continue;
  207.                 }
  208.                 putc('\n', fp);
  209.                 continue;
  210.             }
  211.         default:
  212.             if (!ISCTRL(*p))
  213.             {
  214.                 putc(*p, fp);
  215.                 continue;
  216.             }
  217.         }
  218.         fprintf(fp, "&#%d;", (int)(unsigned char)*p);
  219.     }
  220. }
  221.  
  222. void output_attrencoded_fp(const char *p, FILE *fp)
  223. {
  224.     print_attrencodedlen(p, strlen(p), 0, fp);
  225. }
  226.  
  227. void output_attrencoded(const char *p)
  228. {
  229.     output_attrencoded_fp(p, stdout);
  230. }
  231.  
  232. void output_attrencoded_oknl_fp(const char *p, FILE *fp)
  233. {
  234.     print_attrencodedlen(p, strlen(p), 1, fp);
  235. }
  236.  
  237. void output_attrencoded_oknl(const char *p)
  238. {
  239.     output_attrencoded_oknl_fp(p, stdout);
  240. }
  241.  
  242. void output_attrencoded_nltobr(const char *p)
  243. {
  244.     print_attrencodedlen(p, strlen(p), 2, stdout);
  245. }
  246.  
  247. void output_urlencoded(const char *p)
  248. {
  249. char    *q=cgiurlencode(p);
  250.  
  251.     printf("%s", q);
  252.     free(q);
  253. }
  254.  
  255. void output_loginscriptptr()
  256. {
  257. #if USE_HTTPS_LOGIN
  258. const   char *p=cgihttpsscriptptr();
  259. #elif   USE_RELATIVE_URL
  260. const   char *p=cgirelscriptptr();
  261. #else
  262. const   char *p=cgihttpscriptptr();
  263. #endif
  264.  
  265.     printf("%s", p);
  266. }
  267.  
  268. const char *nonloginscriptptr()
  269. {
  270. #if USE_HTTPS
  271.     return (cgihttpsscriptptr());
  272. #elif   USE_RELATIVE_URL
  273.     return (cgirelscriptptr());
  274. #else
  275.     return (cgihttpscriptptr());
  276. #endif
  277. }
  278.  
  279.  
  280. void output_scriptptr()
  281. {
  282. const   char *p=nonloginscriptptr();
  283.  
  284.     printf("%s", p);
  285.     if (sqwebmail_mailboxid)
  286.     {
  287.     char    *q=cgiurlencode(sqwebmail_mailboxid);
  288.     char    buf[NUMBUFSIZE];
  289.  
  290.         printf("/login/%s/%s/%s", q,
  291.             sqwebmail_sessiontoken ?  sqwebmail_sessiontoken:" ",
  292.             libmail_str_time_t(login_time, buf));
  293.         free(q);
  294.     }
  295. }
  296.  
  297. void output_loginscriptptr_get()
  298. {
  299.     output_loginscriptptr();
  300.     if (sqwebmail_mailboxid)
  301.     {
  302.     char    *q=cgiurlencode(sqwebmail_mailboxid);
  303.     char    buf[NUMBUFSIZE];
  304.  
  305.         printf("/login/%s/%s/%s", q,
  306.             sqwebmail_sessiontoken ?  sqwebmail_sessiontoken:" ",
  307.             libmail_str_time_t(login_time, buf));
  308.         free(q);
  309.     }
  310. }
  311.  
  312. char *scriptptrget()
  313. {
  314. char    *q=0;
  315. size_t  l=0;
  316. int i;
  317. char    buf[NUMBUFSIZE];
  318.  
  319. #define ADD(s) {const char *zz=(s); if (i) strcat(q, zz); l += strlen(zz);}
  320. #define ADDE(ue) { char *yy=cgiurlencode(ue); ADD(yy); free(yy); }
  321.  
  322.     for (i=0; i<2; i++)
  323.     {
  324.         if (i && (q=malloc(l+1)) == 0)  enomem();
  325.         if (i)  *q=0;
  326.         ADD( nonloginscriptptr() );
  327.         if (!sqwebmail_mailboxid)
  328.         {
  329.             ADD("?");
  330.             continue;
  331.         }
  332.  
  333.         ADD("/login/");
  334.         ADDE(sqwebmail_mailboxid);
  335.         ADD("/");
  336.         ADD(sqwebmail_sessiontoken ? sqwebmail_sessiontoken:" ");
  337.         ADD("/");
  338.         ADD(libmail_str_time_t(login_time, buf));
  339.  
  340.         ADD( "?" );
  341.         if (sqwebmail_folder)
  342.         {
  343.             ADD("folder=");
  344.             ADDE(sqwebmail_folder);
  345.         }
  346.     }
  347. #undef  ADD
  348. #undef  ADDE
  349.     return (q);
  350. }
  351.  
  352. void output_scriptptrget()
  353. {
  354. char    *p=scriptptrget();
  355.  
  356.     printf("%s", p);
  357.     free(p);
  358.     return;
  359. }
  360.  
  361. void output_scriptptrpostinfo()
  362. {
  363. #if 0
  364.     if (sqwebmail_mailboxid)
  365.     {
  366.         printf("<INPUT TYPE=HIDDEN NAME=\"mailbox\" VALUE=\"");
  367.         output_attrencoded(sqwebmail_mailboxid);
  368.         printf("\">");
  369.     }
  370.     if (sqwebmail_sessiontoken)
  371.         printf("<INPUT TYPE=HIDDEN NAME=\"session\" VALUE=\"%s\">",
  372.             sqwebmail_sessiontoken);
  373. #endif
  374.     if (sqwebmail_folder)
  375.     {
  376.         printf("<INPUT TYPE=HIDDEN NAME=\"folder\" VALUE=\"");
  377.         output_attrencoded(sqwebmail_folder);
  378.         printf("\">");
  379.     }
  380.  
  381.     if (*cgi("folderdir"))  /* In folders.html */
  382.     {
  383.         printf("<INPUT TYPE=HIDDEN NAME=\"folderdir\" VALUE=\"");
  384.         output_attrencoded(cgi("folderdir"));
  385.         printf("\">");
  386.     }
  387. }
  388.  
  389. void error(const char *errmsg)
  390. {
  391.     cginocache();
  392.     printf("Content-Type: text/html; charset=\"us-ascii\"\n\n<H1>%s</H1>\n",
  393.         errmsg);
  394.     cleanup();
  395.     fake_exit(1);
  396. }
  397.  
  398. void error2(const char *file, int line)
  399. {
  400.     cginocache();
  401.     printf("Content-Type: text/html; charset=\"us-ascii\"\n\n<H1>Internal error (module %s, line %d) - contact system administrator</H1>\n",
  402.         file, line);
  403.     cleanup();
  404.     fake_exit(1);
  405. }
  406.  
  407. FILE *open_langform(const char *lang, const char *formname,
  408.             int print_header)
  409. {
  410. char    *formpath;
  411. FILE    *f;
  412. char    *templatedir=getenv("SQWEBMAIL_TEMPLATEDIR");
  413.    
  414.     if (!templatedir || !*templatedir)  templatedir=HTMLLIBDIR;
  415.  
  416.     /* templatedir/lang/formname */
  417.  
  418.     if (!(formpath=malloc(strlen(templatedir)+3+
  419.         strlen(lang)+strlen(formname))))
  420.         error("Out of memory.");
  421.  
  422.     strcat(strcat(strcat(strcat(strcpy(formpath, templatedir), "/"),
  423.         lang), "/"), formname);
  424.  
  425.     f=fopen(formpath, "r");
  426.     free(formpath);
  427.     if (f && print_header)
  428.         printf("Content-Language: %s\n", lang);
  429.     if (f)
  430.         fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
  431.     return (f);
  432. }
  433.  
  434. int ishttps()
  435. {
  436.     const char *p=getenv("HTTPS");
  437.  
  438.     return (p && strcasecmp(p, "on") == 0);
  439. }
  440.  
  441. struct var_put_buf {
  442.     char argbuf[3072];
  443.     char *argp;
  444.     size_t argn;
  445. } ;
  446.  
  447. static void var_put_buf_func(int c, void *p)
  448. {
  449.     struct var_put_buf *pp=(struct var_put_buf *)p;
  450.  
  451.     if (pp->argn)
  452.     {
  453.         *pp->argp++=c;
  454.         --pp->argn;
  455.     }
  456. }
  457.  
  458. static void pass_image_through(int c, void *p)
  459. {
  460.     putchar(c);
  461. }
  462.  
  463. static void output_image( FILE *f,
  464.               void (*output_func)(int, void *), void *void_arg)
  465. {
  466.     int c;
  467.  
  468.     /*
  469.       Conditional image.  It's formatted as follows:
  470.  
  471.       @@filename,width=x height=y@text@
  472.             ^
  473.             |
  474.         ----- we're at this point now.
  475.  
  476.       If images are enabled, we replace that with an IMG tag we build from
  477.       filename,width=x, height=y.
  478.       If images are disabled, we replace all of this with text.
  479.  
  480.     */
  481.  
  482. #define MKIMG(c)    (*output_func)((c), void_arg)
  483.  
  484.     if (noimages)
  485.     {
  486.         while ((c=getc(f)) >= 0
  487.                && c != '@')
  488.             ;
  489.         while ((c=getc(f)) >= 0
  490.                && c != '@')
  491.             MKIMG(c);
  492.     }
  493.     else
  494.     {
  495.         char    *p;
  496.  
  497.         MKIMG('<');
  498.         MKIMG('I');
  499.         MKIMG('M');
  500.         MKIMG('G');
  501.         MKIMG(' ');
  502.         MKIMG('S');
  503.         MKIMG('R');
  504.         MKIMG('C');
  505.         MKIMG('=');
  506.         MKIMG('"');
  507.         for (p=IMGPATH; *p; p++)
  508.             MKIMG(*p);
  509.         MKIMG('/');
  510.         while ((c=getc(f)) >= 0
  511.                && c != '@' && c != ',')
  512.             MKIMG(c);
  513.         MKIMG('"');
  514.         MKIMG(' ');
  515.         if (c == ',')
  516.             c=getc(f);
  517.         while (c >= 0 && c != '@')
  518.         {
  519.             MKIMG(c);
  520.             c=getc(f);
  521.         }
  522.         while ((c=getc(f)) >= 0 && c != '@')
  523.             ;
  524.         MKIMG('>');
  525.     }
  526. }
  527.  
  528. /* ---- time zone list ---- */
  529.  
  530. static int timezonefile( int (*callback_func)(const char *, const char *,
  531.                           void *), void *callback_arg)
  532. {
  533.     FILE *f=NULL;
  534.     char buffer[BUFSIZ];
  535.  
  536.     if (sqwebmail_content_language)
  537.         f=open_langform(sqwebmail_content_language, "TIMEZONELIST", 0);
  538.  
  539.     if (!f) f=open_langform(HTTP11_DEFAULTLANG, "TIMEZONELIST", 0);
  540.  
  541.     if (!f)
  542.         return (0);
  543.  
  544.     while (fgets(buffer, sizeof(buffer), f) != NULL)
  545.     {
  546.         char *p=strchr(buffer, '\n');
  547.         char *tz;
  548.         int rc;
  549.  
  550.         if (p) *p=0;
  551.  
  552.         p=strchr(buffer, '#');
  553.         if (p) *p=0;
  554.  
  555.         for (p=buffer; *p; p++)
  556.             if (!isspace((int)(unsigned char)*p))
  557.                 break;
  558.  
  559.         if (!*p)
  560.             continue;
  561.  
  562.         tz=p;
  563.         while (*p)
  564.         {
  565.             if (isspace((int)(unsigned char)*p))
  566.                 break;
  567.             ++p;
  568.         }
  569.         if (*p) *p++=0;
  570.         while (*p && isspace((int)(unsigned char)*p))
  571.             ++p;
  572.  
  573.         if (strcmp(p, "*") == 0)
  574.             p="";
  575.         if (strcmp(tz, "*") == 0)
  576.             tz="";
  577.  
  578.         rc= (*callback_func)(tz, p, callback_arg);
  579.  
  580.         if (rc)
  581.         {
  582.             fclose(f);
  583.             return (rc);
  584.         }
  585.     }
  586.     fclose(f);
  587.     return (0);
  588. }
  589.  
  590. static int callback_timezonelist(const char *, const char *, void *);
  591.  
  592. static void timezonelist()
  593. {
  594.     printf("<select name=\"timezonelist\">");
  595.     timezonefile(callback_timezonelist, NULL);
  596.     printf("</select>\n");
  597. }
  598.  
  599. static int callback_timezonelist(const char *tz, const char *n, void *dummy)
  600. {
  601.     printf("<option value=\"%s\">", tz);
  602.     output_attrencoded(n);
  603.     printf("\n");
  604.     return (0);
  605. }
  606.  
  607. static int set_timezone(const char *p)
  608. {
  609.     static char *s_buffer=0;
  610.     char *buffer;
  611.  
  612.     if (!p || !*p || strcmp(p, "*") == 0)
  613.         return (0);
  614.  
  615.     buffer=malloc(strlen(p)+10);
  616.     if (!buffer)
  617.         return (0);
  618.     strcat(strcpy(buffer, "TZ="), p);
  619.  
  620.     putenv(buffer);
  621.  
  622.     if (s_buffer)
  623.         free(buffer);
  624.     s_buffer=buffer;
  625.  
  626.     return (0);
  627. }
  628.  
  629. static int callback_get_timezone(const char *, const char *, void *);
  630.  
  631. /* Return TZ selected from login dropdown */
  632.  
  633. static char *get_timezone()
  634. {
  635.     char *langptr=0;
  636.  
  637.     timezonefile(callback_get_timezone, &langptr);
  638.  
  639.     if (!langptr)
  640.     {
  641.         langptr=strdup("");
  642.         if (!langptr)
  643.             enomem();
  644.     }
  645.  
  646.     if (*langptr == 0)
  647.     {
  648.         free(langptr);
  649.         langptr=strdup("*");
  650.         if (!langptr)
  651.             enomem();
  652.     }
  653.  
  654.     return(langptr);
  655. }
  656.  
  657. static int callback_get_timezone(const char *tz, const char *n, void *dummy)
  658. {
  659.     if (strcmp(tz, cgi("timezonelist")) == 0)
  660.     {
  661.         char **p=(char **)dummy;
  662.  
  663.         if (*p)
  664.             free(*p);
  665.  
  666.         *p=strdup(tz);
  667.     }
  668.     return (0);
  669. }
  670.  
  671. /* ------------------------ */
  672.  
  673. static FILE *do_open_form(const char *formname, int flag)
  674. {
  675.     struct template_stack *ts;
  676.     FILE    *f=NULL;
  677.  
  678.     if ((ts=(struct template_stack *)malloc(sizeof(struct template_stack)))
  679.         == NULL)
  680.         return (NULL);
  681.  
  682.     if (sqwebmail_content_language)
  683.         f=open_langform(sqwebmail_content_language, formname, flag);
  684.     if (!f) f=open_langform(HTTP11_DEFAULTLANG, formname, flag);
  685.  
  686.     if (!f)
  687.     {
  688.         free(ts);
  689.         return (NULL);
  690.     }
  691.  
  692.     ts->next=template_stack;
  693.     template_stack=ts;
  694.     ts->fp=f;
  695.     return (f);
  696. }
  697.  
  698. static void do_close_form()
  699. {
  700.     struct template_stack *ts=template_stack;
  701.  
  702.     if (!ts)
  703.         enomem();
  704.  
  705.     fclose(ts->fp);
  706.     template_stack=ts->next;
  707.     free(ts);
  708. }
  709.  
  710. static void do_output_form_loop(FILE *, const char *formname);
  711.  
  712. void output_form(const char *formname)
  713. {
  714.     FILE    *f;
  715.  
  716. #ifdef  GZIP
  717.     int dogzip;
  718.     int pipefd[2];
  719.     pid_t   pid= -1;
  720. #endif
  721.  
  722.     noimages= access(NOIMAGES, 0) == 0;
  723.  
  724.     f=do_open_form(formname, 1);
  725.  
  726.     sqwebmail_formname=formname;
  727.  
  728.     if (!f) error("Can't open form template.");
  729.  
  730.     /*
  731.     ** Except for the dummy frame window (and the tiny empty frame),
  732.     ** and the window containing the print preview of the message,
  733.     ** expire everything.
  734.     */
  735.  
  736.     if (strcmp(formname, "index.html") && strcmp(formname, "empty.html") &&
  737.         strcmp(formname, "print.html"))
  738.         cginocache();
  739.  
  740. #ifdef  GZIP
  741.  
  742.     dogzip=0;
  743.     if (strcmp(formname, "readmsg.html") == 0 ||
  744.         strcmp(formname, "folder.html") == 0 ||
  745.         strcmp(formname, "folders.html") == 0 ||
  746.         strcmp(formname, "gpg.html") == 0)
  747.     {
  748.     const char *p=getenv("HTTP_ACCEPT_ENCODING");
  749.  
  750.         if (p)
  751.         {
  752.         char    *q=strdup(p), *r;
  753.  
  754.             if (!q) enomem();
  755.             for (r=q; *r; r++)
  756.                 *r= tolower((int)(unsigned char)*r);
  757.             for (r=q; (r=strtok(r, ", ")) != 0; r=0)
  758.                 if (strcmp(r, "gzip") == 0)
  759.                 {
  760.                     dogzip=1;
  761.                     if (pipe(pipefd))
  762.                         enomem();
  763.                 }
  764.             free(q);
  765.         }
  766.     }
  767. #endif
  768.  
  769.     /* Do not send a Vary header for attachment downloads */
  770.  
  771.     if (*cgi("download") == 0)
  772.         printf("Vary: Accept-Language\n");
  773.  
  774. #ifdef  GZIP
  775.     if (dogzip)
  776.         printf("Content-Encoding: gzip\n");
  777. #endif
  778.  
  779.     printf("Content-Type: text/html");
  780.  
  781.     if (sqwebmail_content_charset)
  782.         printf("; charset=\"%s\"", sqwebmail_content_charset);
  783.  
  784.     printf("\n\n");
  785.  
  786. #ifdef  GZIP
  787.     if (dogzip)
  788.     {
  789.         fflush(stdout);
  790.         while ((pid=fork()) == -1)
  791.             sleep(5);
  792.         if (pid == 0)
  793.         {
  794.             close(0);
  795.             dup(pipefd[0]);
  796.             close(pipefd[0]);
  797.             close(pipefd[1]);
  798.             execl(GZIP, "gzip", "-c", (char *)0);
  799.             syslog(LOG_DAEMON | LOG_CRIT,
  800.                    "sqwebmail: Cannot execute " GZIP);
  801.             exit(1);
  802.         }
  803.  
  804.         gzip_save_fd=dup(1);
  805.         close(1);
  806.         dup(pipefd[1]);
  807.         close(pipefd[1]);
  808.         close(pipefd[0]);
  809.     }
  810. #endif
  811.  
  812.     do_output_form_loop(f, formname);
  813.     do_close_form();
  814.  
  815. #ifdef  GZIP
  816.     if (pid > 0)
  817.     {
  818.     int waitstat;
  819.     pid_t   p2;
  820.  
  821.         /* Restore original stdout */
  822.  
  823.         fflush(stdout);
  824.         close(1);
  825.         dup(gzip_save_fd);
  826.         close(gzip_save_fd);
  827.         gzip_save_fd= -1;
  828.         while ((p2=wait(&waitstat)) >= 0 && p2 != pid)
  829.             ;
  830.     }
  831. #endif
  832. }
  833.  
  834. static FILE *openinclude(const char *);
  835.  
  836.  
  837. void insert_include(const char *inc_name)
  838. {
  839.     FILE *ff=openinclude(inc_name);
  840.     do_output_form_loop(ff, inc_name);
  841.     do_close_form();
  842. }
  843.  
  844. static void do_output_form_loop(FILE *f, const char *formname)
  845. {
  846.     int c, c2, c3;
  847.  
  848.     while ((c=getc(f)) >= 0)
  849.     {
  850.     char    kw[64];
  851.  
  852.         if (c != '[')
  853.         {
  854.             putchar(c);
  855.             continue;
  856.         }
  857.         c=getc(f);
  858.         if (c != '#')
  859.         {
  860.             putchar('[');
  861.             ungetc(c,f);
  862.             continue;
  863.         }
  864.         c=getc(f);
  865.         if (c == '?')
  866.         {
  867.             c=getc(f);
  868.             if (c < '0' || c > '9')
  869.             {
  870.                 putchar('[');
  871.                 putchar('#');
  872.                 putchar('?');
  873.                 putchar(c);
  874.                 continue;
  875.             }
  876.             if (
  877.                 ( c == '0' && auth_changepass == 0) ||
  878.                 (c == '1' && *cgi("folderdir") == ':') ||
  879.                 (c == '2' && *cgi("folderdir") != ':') ||
  880.                 (c == '4' && maildir_filter_hasmaildirfilter(".")) ||
  881.                 (c == '5' && has_gpg(GPGDIR)) ||
  882.                 (c == '6' && !ishttps()) ||
  883.                 (c == '7' && !sqpcp_has_calendar()) ||
  884.                 (c == '8' && !sqpcp_has_groupware())
  885.                 )
  886.             {
  887.                 while ((c=getc(f)) != EOF)
  888.                 {
  889.                     if (c != '[')   continue;
  890.                     if ( getc(f) != '#')    continue;
  891.                     if ( getc(f) != '?')    continue;
  892.                     if ( getc(f) != '#')    continue;
  893.                     if ( getc(f) == ']')    break;
  894.                 }
  895.             }
  896.             continue;
  897.         }
  898.  
  899.         if (c == '$')
  900.         {
  901.             struct var_put_buf buf;
  902.  
  903.             buf.argp=buf.argbuf;
  904.             buf.argn=sizeof(buf.argbuf)-1;
  905.  
  906.             while ((c=getc(f)) >= 0 && c != '\n')
  907.             {
  908.                 if (c == '#')
  909.                 {
  910.                     c=getc(f);
  911.                     if (c == ']')   break;
  912.                     ungetc(c, f);
  913.                     c='#';
  914.                 }
  915.  
  916.                 if (c == '@')
  917.                 {
  918.                     c=getc(f);
  919.                     if (c == '@')
  920.                     {
  921.                         output_image(f,
  922.                                  var_put_buf_func,
  923.                                  &buf);
  924.                         continue;
  925.                     }
  926.                     ungetc(c, f);
  927.                     c='@';
  928.                 }
  929.                 var_put_buf_func(c, &buf);
  930.             }
  931.             *buf.argp=0;
  932.             addarg(buf.argbuf);
  933.  
  934.             continue;
  935.         }
  936.  
  937.         if (c == '@')
  938.         {
  939.             output_image(f, pass_image_through, NULL);
  940.             c=getc(f);
  941.             if (c == '#')
  942.             {
  943.                 c=getc(f);
  944.                 if (c == ']')
  945.                     continue;
  946.             }
  947.             if (c != EOF)
  948.                 ungetc(c, f);
  949.             continue;
  950.         }
  951.  
  952.         if (!isalnum(c) && c != ':')
  953.         {
  954.             putchar('[');
  955.             putchar('#');
  956.             ungetc(c, f);
  957.             continue;
  958.         }
  959.         c2=0;
  960.         while (c != EOF && (isalnum(c) || c == ':' || c == '_'))
  961.         {
  962.             if (c2 < sizeof(kw)-1)
  963.                 kw[c2++]=c;
  964.             c=getc(f);
  965.         }
  966.         kw[c2]=0;
  967.         c2=c;
  968.  
  969.         if (c2 != '#')
  970.         {
  971.             putchar('[');
  972.             putchar('#');
  973.             printf("%s", kw);
  974.             ungetc(c2, f);
  975.             continue;
  976.         }
  977.  
  978.         if ((c3=getc(f)) != ']')
  979.         {
  980.             putchar('[');
  981.             putchar('#');
  982.             printf("%s", kw);
  983.             putchar(c2);
  984.             ungetc(c3, f);
  985.             continue;
  986.         }
  987.  
  988.         if (strcmp(kw, "a") == 0)
  989.         {
  990.             addressbook();
  991.         }
  992.         else if (strcmp(kw, "d") == 0)
  993.         {
  994.             if (*cgi("folderdir"))
  995.             {
  996.             const char *c=cgi("folderdir");
  997.  
  998.                 if (*c == ':')
  999.                     ++c;    /* Sharable hierarchy */
  1000.  
  1001.                 printf(" - ");
  1002.                 print_safe(c);
  1003.             }
  1004.         }
  1005.         else if (strcmp(kw, "D") == 0)
  1006.         {
  1007.             const char *p=cgi("folder");
  1008.             const char *q=strrchr(p, '.');
  1009.  
  1010.                 if (q)
  1011.                 {
  1012.                 char    *r=malloc(q-p+1);
  1013.  
  1014.                     if (!r) enomem();
  1015.                     memcpy(r, p, q-p);
  1016.                     r[q-p]=0;
  1017.                     output_urlencoded(r);
  1018.                     free(r);
  1019.                 }
  1020.         }
  1021.         else if (strcmp(kw, "G") == 0)
  1022.         {
  1023.             output_attrencoded(login_returnaddr());
  1024.         }
  1025.         else if (strcmp(kw, "r") == 0)
  1026.         {
  1027.             output_attrencoded(cgi("redirect"));
  1028.         }
  1029.         else if (strcmp(kw, "s") == 0)
  1030.         {
  1031.             output_scriptptrget();
  1032.         }
  1033.         else if (strcmp(kw, "S") == 0)
  1034.         {
  1035.             output_loginscriptptr();
  1036.         }
  1037.         else if (strcmp(kw, "R") == 0)
  1038.         {
  1039.             output_loginscriptptr_get();
  1040.         }
  1041.         else if (strcmp(kw, "p") == 0)
  1042.         {
  1043.             output_scriptptr();
  1044.         }
  1045.         else if (strcmp(kw, "P") == 0)
  1046.         {
  1047.             output_scriptptrpostinfo();
  1048.         }
  1049.         else if (strcmp(kw, "f") == 0)
  1050.         {
  1051.             folder_contents_title();
  1052.         }
  1053.         else if (strcmp(kw, "F") == 0)
  1054.         {
  1055.             folder_contents(sqwebmail_folder, atol(cgi("pos")));
  1056.         }
  1057.         else if (strcmp(kw, "n") == 0)
  1058.         {
  1059.             folder_initnextprev(sqwebmail_folder, atol(cgi("pos")));
  1060.         }
  1061.         else if (strcmp(kw, "N") == 0)
  1062.         {
  1063.             folder_nextprev();
  1064.         }
  1065.         else if (strcmp(kw, "m") == 0)
  1066.         {
  1067.             folder_msgmove();
  1068.         }
  1069.         else if (strcmp(kw, "M") == 0)
  1070.         {
  1071.             folder_showmsg(sqwebmail_folder, atol(cgi("pos")));
  1072.         }
  1073.         else if (strcmp(kw, "T") == 0)
  1074.         {
  1075.             folder_showtransfer();
  1076.         }
  1077.         else if (strcmp(kw, "L") == 0)
  1078.         {
  1079.             folder_list();
  1080.         }
  1081.         else if (strcmp(kw, "l") == 0)
  1082.         {
  1083.             folder_list2();
  1084.         }
  1085.         else if (strcmp(kw, "E") == 0)
  1086.         {
  1087.             folder_rename_list();
  1088.         }
  1089.         else if (strcmp(kw, "W") == 0)
  1090.         {
  1091.             newmsg_init(sqwebmail_folder, cgi("pos"));
  1092.         }
  1093.         else if (strcmp(kw, "z") == 0)
  1094.         {
  1095.             pref_isdisplayfullmsg();
  1096.         }
  1097.         else if (strcmp(kw, "y") == 0)
  1098.         {
  1099.             pref_isoldest1st();
  1100.         }
  1101.         else if (strcmp(kw, "H") == 0)
  1102.         {
  1103.             pref_displayhtml();
  1104.         }
  1105.         else if (strcmp(kw, "FLOWEDTEXT") == 0)
  1106.         {
  1107.             pref_displayflowedtext();
  1108.         }
  1109.         else if (strcmp(kw, "NOARCHIVE") == 0)
  1110.         {
  1111.             pref_displaynoarchive();
  1112.         }
  1113.         else if (strcmp(kw, "x") == 0)
  1114.         {
  1115.             pref_setprefs();
  1116.         }
  1117.         else if (strcmp(kw, "w") == 0)
  1118.         {
  1119.             pref_sortorder();
  1120.         }
  1121.         else if (strcmp(kw, "t") == 0)
  1122.         {
  1123.             pref_signature();
  1124.         }
  1125.         else if (strcmp(kw, "u") == 0)
  1126.         {
  1127.             pref_pagesize();
  1128.         }
  1129.         else if (strcmp(kw, "v") == 0)
  1130.         {
  1131.             pref_displayautopurge();
  1132.         }
  1133.         else if (strcmp(kw, "A") == 0)
  1134.         {
  1135.             attachments_head(sqwebmail_folder, cgi("pos"),
  1136.                 cgi("draft"));
  1137.         }
  1138.         else if (strcmp(kw, "ATTACHOPTS") == 0)
  1139.         {
  1140.             attachments_opts(cgi("draft"));
  1141.         }
  1142.         else if (strcmp(kw, "GPGERR") == 0)
  1143.         {
  1144.             sent_gpgerrtxt();
  1145.         }
  1146.         else if (strcmp(kw, "GPGERRRESUME") == 0)
  1147.         {
  1148.             sent_gpgerrresume();
  1149.         }
  1150. #ifdef  ISPELL
  1151.         else if (strcmp(kw, "K") == 0)
  1152.         {
  1153.             spell_show();
  1154.         }
  1155. #endif
  1156. #ifdef  BANNERPROG
  1157.         else if (strcmp(kw, "B") == 0)
  1158.         {
  1159.             char banargbuf[31];
  1160.             int i=0;
  1161.             int wait_stat;
  1162.             pid_t   p, p2;
  1163.                 if ((c=getc(f)) != '{')
  1164.                     ungetc(c, f);
  1165.                 else    while ((c=getc(f)), isalnum(c))
  1166.                         if (i < sizeof(banargbuf)-1)
  1167.                             banargbuf[i++]=c;
  1168.                 banargbuf[i]=0;
  1169.                 fflush(stdout);
  1170.                 if ( (p=fork()) == 0 )
  1171.                 {
  1172.                     execl(BANNERPROG, BANNERPROG,
  1173.                         sqwebmail_formname,
  1174.                         banargbuf, (char *)0);
  1175.                     _exit(0);
  1176.                 }
  1177.                 if (p > 0)
  1178.                     while ((p2=wait(&wait_stat)) > 0 &&
  1179.                         p2 != p)
  1180.                         ;
  1181.         }
  1182. #endif
  1183.         else if (strcmp(kw, "h") == 0)
  1184.         {
  1185.             FILE *fp=fopen(LOGINDOMAINLIST, "r");
  1186.             char    buf[256];
  1187.  
  1188.                 if (!fp)    continue;
  1189.                 printf("<select name=logindomain><option value=\"\">&nbsp;");
  1190.                 while (fgets(buf, sizeof(buf), fp))
  1191.                 {
  1192.                 char    *p=strchr(buf, '\n');
  1193.  
  1194.                     if (*p) *p=0;
  1195.                     printf("<option value=\"%s\">@%s",
  1196.                         buf, buf);
  1197.                 }
  1198.                 fclose(fp);
  1199.                 printf("</select>");
  1200.         }
  1201.         else if (strcmp(kw, "o") == 0)
  1202.         {
  1203.             ldaplist();
  1204.         }
  1205.         else if (strcmp(kw, "O") == 0)
  1206.         {
  1207.             doldapsearch();
  1208.         }
  1209.         else if (strcmp(kw, "LOADMAILFILTER") == 0)
  1210.         {
  1211.             mailfilter_init();
  1212.         }
  1213.         else if (strcmp(kw, "MAILFILTERLIST") == 0)
  1214.         {
  1215.             mailfilter_list();
  1216.         }
  1217.         else if (strcmp(kw, "MAILFILTERLISTFOLDERS") == 0)
  1218.         {
  1219.             mailfilter_listfolders();
  1220.         }
  1221.         else if (strcmp(kw, "QUOTA") == 0)
  1222.         {
  1223.             folder_showquota();
  1224.         }
  1225.         else if (strcmp(kw, "NICKLIST") == 0)
  1226.         {
  1227.                 ab_listselect();
  1228.         }
  1229.         else if (strcmp(kw, "LISTPUB") == 0)
  1230.         {
  1231.             gpglistpub();
  1232.         }
  1233.         else if (strcmp(kw, "LISTSEC") == 0)
  1234.         {
  1235.             gpglistsec();
  1236.         }
  1237.         else if (strcmp(kw, "KEYIMPORT") == 0)
  1238.         {
  1239.             folder_keyimport(sqwebmail_folder, atol(cgi("pos")));
  1240.         }
  1241.         else if (strcmp(kw, "GPGCREATE") == 0)
  1242.         {
  1243.             gpgcreate();
  1244.         }
  1245.         else if (strcmp(kw, "DOGPG") == 0)
  1246.         {
  1247.             gpgdo();
  1248.         }
  1249.         else if (strcmp(kw, "ATTACHPUB") == 0)
  1250.         {
  1251.             gpgselectpubkey();
  1252.         }
  1253.         else if (strcmp(kw, "ATTACHSEC") == 0)
  1254.         {
  1255.             gpgselectprivkey();
  1256.         }
  1257.         else if (strcmp(kw, "MAILINGLISTS") == 0)
  1258.         {
  1259.             char *p=getmailinglists();
  1260.  
  1261.             /* <sigh> amaya inserts a bunch of spaces that mess
  1262.             ** things up in Netscape.
  1263.             */
  1264.  
  1265.             printf("<textarea class=\"form-text\" "
  1266.                    "cols=\"40\" rows=\"4\" "
  1267.                    "name=\"mailinglists\" wrap=soft>");
  1268.             output_attrencoded(p ? p:"");
  1269.             if (p)
  1270.                 free(p);
  1271.             printf("</textarea>");
  1272.         }
  1273.         else if (strcmp(kw, "AUTORESPONSE") == 0)
  1274.         {
  1275.             autoresponse();
  1276.         }
  1277.         else if (strcmp(kw, "AUTORESPONSE_LIST") == 0)
  1278.         {
  1279.             autoresponselist();
  1280.         }
  1281.         else if (strcmp(kw, "AUTORESPONSE_PICK") == 0)
  1282.         {
  1283.             autoresponsepick();
  1284.         }
  1285.         else if (strcmp(kw, "AUTORESPONSE_DELETE") == 0)
  1286.         {
  1287.             autoresponsedelete();
  1288.         }
  1289.         else if (strcmp(kw, "SQWEBMAILCSS") == 0)
  1290.         {
  1291.             printf(IMGPATH "/sqwebmail.css");
  1292.         }
  1293.         else if (strcmp(kw, "timezonelist") == 0)
  1294.         {
  1295.             timezonelist();
  1296.         }
  1297.         else if (strcmp(kw, "PREFWEEK") == 0)
  1298.         {
  1299.             pref_displayweekstart();
  1300.         }
  1301.         else if (strcmp(kw, "NEWEVENT") == 0)
  1302.         {
  1303.             sqpcp_newevent();
  1304.         }
  1305.         else if (strcmp(kw, "RECURRING") == 0)
  1306.         {
  1307.             printf("%s", getarg("RECURRING"));
  1308.         }
  1309.         else if (strcmp(kw, "EVENTSTART") == 0)
  1310.         {
  1311.             sqpcp_eventstart();
  1312.         }
  1313.         else if (strcmp(kw, "EVENTEND") == 0)
  1314.         {
  1315.             sqpcp_eventend();
  1316.         }
  1317.         else if (strcmp(kw, "EVENTFROM") == 0)
  1318.         {
  1319.             sqpcp_eventfrom();
  1320.         }
  1321.         else if (strcmp(kw, "EVENTTIMES") == 0)
  1322.         {
  1323.             sqpcp_eventtimes();
  1324.         }
  1325.         else if (strcmp(kw, "EVENTPARTICIPANTS") == 0)
  1326.         {
  1327.             sqpcp_eventparticipants();
  1328.         }
  1329.         else if (strcmp(kw, "EVENTTEXT") == 0)
  1330.         {
  1331.             sqpcp_eventtext();
  1332.         }
  1333.         else if (strcmp(kw, "EVENTATTACH") == 0)
  1334.         {
  1335.             sqpcp_eventattach();
  1336.         }
  1337.         else if (strcmp(kw, "EVENTSUMMARY") == 0)
  1338.         {
  1339.             sqpcp_summary();
  1340.         }
  1341.         else if (strcmp(kw, "CALENDARTODAY") == 0)
  1342.         {
  1343.             sqpcp_todays_date();
  1344.         }
  1345.         else if (strcmp(kw, "CALENDARWEEKLYLINK") == 0)
  1346.         {
  1347.             sqpcp_weeklylink();
  1348.         }
  1349.         else if (strcmp(kw, "CALENDARMONTHLYLINK") == 0)
  1350.         {
  1351.             sqpcp_monthlylink();
  1352.         }
  1353.         else if (strcmp(kw, "CALENDARTODAYV") == 0)
  1354.         {
  1355.             sqpcp_todays_date_verbose();
  1356.         }
  1357.         else if (strcmp(kw, "CALENDARDAYVIEW") == 0)
  1358.         {
  1359.             sqpcp_daily_view();
  1360.         }
  1361.         else if (strcmp(kw, "CALENDARPREVDAY") == 0)
  1362.         {
  1363.             sqpcp_prevday();
  1364.         }
  1365.         else if (strcmp(kw, "CALENDARNEXTDAY") == 0)
  1366.         {
  1367.             sqpcp_nextday();
  1368.         }
  1369.         else if (strcmp(kw, "CALENDARWEEK") == 0)
  1370.         {
  1371.             sqpcp_show_cal_week();
  1372.         }
  1373.         else if (strcmp(kw, "CALENDARNEXTWEEK") == 0)
  1374.         {
  1375.             sqpcp_show_cal_nextweek();
  1376.         }
  1377.         else if (strcmp(kw, "CALENDARPREVWEEK") == 0)
  1378.         {
  1379.             sqpcp_show_cal_prevweek();
  1380.         }
  1381.         else if (strcmp(kw, "CALENDARWEEKVIEW") == 0)
  1382.         {
  1383.             sqpcp_displayweek();
  1384.         }
  1385.         else if (strcmp(kw, "CALENDARMONTH") == 0)
  1386.         {
  1387.             sqpcp_show_cal_month();
  1388.         }
  1389.         else if (strcmp(kw, "CALENDARNEXTMONTH") == 0)
  1390.         {
  1391.             sqpcp_show_cal_nextmonth();
  1392.         }
  1393.         else if (strcmp(kw, "CALENDARPREVMONTH") == 0)
  1394.         {
  1395.             sqpcp_show_cal_prevmonth();
  1396.         }
  1397.         else if (strcmp(kw, "CALENDARMONTHVIEW") == 0)
  1398.         {
  1399.             sqpcp_displaymonth();
  1400.         }
  1401.         else if (strcmp(kw, "EVENTDISPLAYINIT") == 0)
  1402.         {
  1403.             sqpcp_displayeventinit();
  1404.         }
  1405.         else if (strcmp(kw, "EVENTDELETEINIT") == 0)
  1406.         {
  1407.             sqpcp_deleteeventinit();
  1408.         }
  1409.         else if (strcmp(kw, "EVENTDISPLAY") == 0)
  1410.         {
  1411.             sqpcp_displayevent();
  1412.         }
  1413.         else if (strcmp(kw, "EVENTBACKLINK") == 0)
  1414.         {
  1415.             sqpcp_eventbacklink();
  1416.         }
  1417.         else if (strcmp(kw, "EVENTEDITLINK") == 0)
  1418.         {
  1419.             sqpcp_eventeditlink();
  1420.         }
  1421.         else if (strcmp(kw, "EVENTCANCELUNCANCELLINK") == 0)
  1422.         {
  1423.             sqpcp_eventcanceluncancellink();
  1424.         }
  1425.         else if (strcmp(kw, "EVENTCANCELUNCANCELLINK") == 0)
  1426.         {
  1427.             sqpcp_eventcanceluncancellink();
  1428.         }
  1429.         else if (strcmp(kw, "EVENTCANCELUNCANCELIMAGE") == 0)
  1430.         {
  1431.             sqpcp_eventcanceluncancelimage();
  1432.         }
  1433.         else if (strcmp(kw, "EVENTCANCELUNCANCELTEXT") == 0)
  1434.         {
  1435.             sqpcp_eventcanceluncanceltext();
  1436.         }
  1437.         else if (strcmp(kw, "EVENTDELETELINK") == 0)
  1438.         {
  1439.             sqpcp_eventdeletelink();
  1440.         }
  1441.         else if (strcmp(kw, "EVENTACL") == 0)
  1442.         {
  1443.             sqpcp_eventacl();
  1444.         }
  1445.         else if (strcmp(kw, "ABOOKNAMELIST") == 0)
  1446.         {
  1447.             ab_addrselect();
  1448.         }
  1449.         else if (strncmp(kw, "radio:", 6) == 0)
  1450.         {
  1451.         const char *name=strtok(kw+6, ":");
  1452.         const char *value=strtok(0, ":");
  1453.  
  1454.             if (name && value)
  1455.             {
  1456.                 printf("<input class=\"form-radio\" "
  1457.                        "type=\"radio\" name=\"%s\""
  1458.                     " value=\"%s\"",
  1459.                     name, value);
  1460.                 if ( strcmp(cgi(name), value) == 0)
  1461.                     printf(" checked");
  1462.                 printf(">");
  1463.             }
  1464.         }
  1465.         else if (strncmp(kw, "checkbox:", 9) == 0)
  1466.         {
  1467.         const char *name=strtok(kw+9, ":");
  1468.         const char *cgivar=strtok(0, ":");
  1469.  
  1470.             if (name && cgivar)
  1471.             {
  1472.                 printf("<input class=\"form-checkbox\" "
  1473.                        "type=\"checkbox\" name=\"%s\""
  1474.                     "%s>",
  1475.                     name,
  1476.                     *cgi(cgivar) ? " checked":"");
  1477.             }
  1478.         }
  1479.         else if (strncmp(kw, "input:", 6) == 0)
  1480.         {
  1481.             output_attrencoded(cgi(kw+6));
  1482.         }
  1483.         else if (strncmp(kw, "select:", 7) == 0)
  1484.         {
  1485.         const char *name=strtok(kw+7, ":");
  1486.         const char *size=strtok(0, ":");
  1487.  
  1488.             printf("<select name=\"%s\"", name ? name:"");
  1489.             if (size)   printf(" size=%s", size);
  1490.             printf(">");
  1491.         }
  1492.         else if (strncmp(kw, "option:", 7) == 0)
  1493.         {
  1494.         const char *name=strtok(kw+7, ":");
  1495.         const char *cgivar=strtok(0, ":");
  1496.         const char *cgival=strtok(0, ":");
  1497.  
  1498.             printf("<option value=\"%s\"", name ? name:"");
  1499.             if (cgivar && cgival &&
  1500.                 strcmp(cgi(cgivar), cgival) == 0)
  1501.                 printf(" selected");
  1502.             printf(">");
  1503.         }
  1504.         else if (strcmp(kw, "endselect") == 0)
  1505.             printf("</select>");
  1506.         else if (strncmp(kw, "env:", 4) == 0) {
  1507.             const char *val = getenv(kw+4);
  1508.             if (val) output_attrencoded(val);
  1509.         }
  1510.         else if (strncmp(kw, "include:", 8) == 0)
  1511.         {
  1512.             insert_include(kw+8);
  1513.         }
  1514.         else if (strcmp(kw, "endinclude") == 0)
  1515.         {
  1516.             break;
  1517.         }
  1518.         else if (nl_is_tag(kw))
  1519.         {      
  1520.             nl_process_tag (kw, formname, sqwebmail_folder, cgi ("pos"), cgi ("draft"));
  1521.         }
  1522.     }
  1523. }
  1524.  
  1525. /* Include another template file */
  1526.  
  1527. static FILE *openinclude(const char *p)
  1528. {
  1529.     char buffer[BUFSIZ];
  1530.     FILE *f;
  1531.  
  1532.     buffer[0]=0;
  1533.     strncat(buffer, p, 100);
  1534.     strcat(buffer, ".inc.html");
  1535.  
  1536.     f=do_open_form(buffer, 0);
  1537.  
  1538.     if (!f)
  1539.         error("Can't open form template");
  1540.  
  1541.     while (fgets(buffer, sizeof(buffer), f))
  1542.     {
  1543.         const char *p=strchr(buffer, '[');
  1544.  
  1545.         if (!p)
  1546.             continue;
  1547.  
  1548.         if (strncmp(p, "[#begininclude#]", 16) == 0)
  1549.         {
  1550.             break;
  1551.         }
  1552.     }
  1553.     return (f);
  1554. }
  1555.  
  1556.  
  1557. /* Top level HTTP redirect without referencing a particular mailbox */
  1558.  
  1559. static void http_redirect_top(const char *app)
  1560. {
  1561. const   char *p=nonloginscriptptr();
  1562. char    *buf=malloc(strlen(p)+strlen(app)+2);
  1563.  
  1564.     if (!buf)   enomem();
  1565.     strcat(strcpy(buf, p), app);
  1566.     cgiredirect(buf);
  1567.     free(buf);
  1568. }
  1569.  
  1570. /* HTTP redirects within a given mailbox, various formats */
  1571.  
  1572. void http_redirect_argu(const char *fmt, unsigned long un)
  1573. {
  1574. char    buf[MAXLONGSIZE];
  1575.  
  1576.     sprintf(buf, "%lu", un);
  1577.     http_redirect_argss(fmt, buf, "");
  1578. }
  1579.  
  1580. void http_redirect_argss(const char *fmt, const char *arg1, const char *arg2)
  1581. {
  1582.     http_redirect_argsss(fmt, arg1, arg2, "");
  1583. }
  1584.  
  1585. void http_redirect_argsss(const char *fmt, const char *arg1, const char *arg2,
  1586.     const char *arg3)
  1587. {
  1588. char *base=scriptptrget();
  1589. char *arg1s=cgiurlencode(arg1);
  1590. char *arg2s=cgiurlencode(arg2);
  1591. char *arg3s=cgiurlencode(arg3);
  1592. char *q;
  1593.  
  1594.     /* We generate a Location: redirected_url header.  The actual
  1595.     ** header is generated in cgiredirect, we just build it here */
  1596.  
  1597.     q=malloc(strlen(base)+strlen(fmt)+strlen(arg1s)+strlen(arg2s)+
  1598.             strlen(arg3s)+1);
  1599.     if (!q) enomem();
  1600.     strcpy(q, base);
  1601.     sprintf(q+strlen(q), fmt, arg1s, arg2s, arg3s);
  1602.     cgiredirect(q);
  1603.     free(q);
  1604.     free(arg1s);
  1605.     free(arg2s);
  1606.     free(arg3s);
  1607.     free(base);
  1608. }
  1609.  
  1610. void output_user_form(const char *formname)
  1611. {
  1612. char    *p;
  1613.  
  1614.     if (!*formname || strchr(formname, '.') || strchr(formname, '/'))
  1615.         error("Invalid request.");
  1616.    
  1617.     if ((strcmp(formname, "filter") == 0
  1618.          || strcmp(formname, "autoresponse") == 0)
  1619.         && maildir_filter_hasmaildirfilter("."))
  1620.         /* Script kiddies... */
  1621.         formname="nofilter";
  1622.  
  1623.     if (strcmp(formname, "filter") == 0 && *cgi("do.submitfilter"))
  1624.         mailfilter_submit();
  1625.  
  1626.     if (strcmp(formname, "gpg") == 0 && has_gpg(GPGDIR))
  1627.         error("Invalid request.");
  1628.  
  1629.     if (strcmp(formname, "gpgcreate") == 0 && has_gpg(GPGDIR))
  1630.         error("Invalid request.");
  1631.  
  1632.     if (*cgi("ldapsearch")) /* Special voodoo for LDAP address book stuff */
  1633.     {
  1634.         if (ldapsearch() == 0)
  1635.         {
  1636.             output_form("ldapsearch.html");
  1637.             return;
  1638.         }
  1639.     }
  1640.  
  1641.     if (nl_is_form(formname)) {
  1642.         nl_process_form (formname, sqwebmail_folder, cgi ("pos"));
  1643.         return;
  1644.     }
  1645.  
  1646.     /*
  1647.     ** In order to hide the session ID in the URL of the message what
  1648.     ** we do is that the initial URL, that contains setcookie=1, results
  1649.     ** in us setting a temporary cookie that contains the session ID,
  1650.     ** then we return a redirect to a url which has /printmsg/ in the
  1651.     ** PATH_INFO, instead of the session ID.  The code in main()
  1652.     ** traps /printmsg/ PATH_INFO, fetches the path info from the
  1653.     ** cookie, and punts after resetting setcookie to 0.
  1654.     */
  1655.  
  1656.     if (strcmp(formname, "print") == 0 && *cgi("setcookie") == '1')
  1657.     {
  1658.     const char *qs=getenv("QUERY_STRING");
  1659.     const char *pi=getenv("PATH_INFO");
  1660.     const char *nl;
  1661.     char    *buf;
  1662.  
  1663.         if (!pi)    pi="";
  1664.         if (!pi)    pi="";
  1665.  
  1666.         nl=nonloginscriptptr();
  1667.  
  1668.         buf=malloc(strlen(nl) + sizeof("/printmsg/print?")+strlen(qs));
  1669.         if (!buf)   enomem();
  1670.         strcat(strcat(strcpy(buf, nl), "/printmsg/print?"), qs);
  1671.         cginocache();
  1672.         cgi_setcookie("sqwebmail-pi", pi);
  1673.         printf("Refresh: 0; URL=\"%s\"\n", buf);
  1674.         free(buf);
  1675.         output_form("printredirect.html");
  1676.         return;
  1677.     }
  1678.  
  1679.     if (strcmp(cgi("fromscreen"), "mailfilter") == 0)
  1680.         maildir_filter_endmaildirfilter(".");   /* Remove the temp file */
  1681.  
  1682.     if (strcmp(formname, "logout") == 0)
  1683.     {
  1684.         unlink(IPFILE);
  1685.         http_redirect_top("");
  1686.         return;
  1687.     }
  1688.  
  1689.     if (strcmp(formname, "fetch") == 0)
  1690.     {
  1691.         folder_download( sqwebmail_folder, atol(cgi("pos")),
  1692.             cgi("mimeid") );
  1693.         return;
  1694.     }
  1695.  
  1696.     if (strcmp(formname, "delmsg") == 0)
  1697.     {
  1698.         folder_delmsg( atol(cgi("pos")));
  1699.         return;
  1700.     }
  1701.  
  1702.     if (strcmp(formname, "donewmsg") == 0)
  1703.     {
  1704.         if (*cgi("dodelete"))
  1705.         {
  1706.             if (!tokencheck())
  1707.             {
  1708.                 attach_delete(cgi("draft"));
  1709.                 tokensave();
  1710.                 maildir_reload(DRAFTS);
  1711.             }
  1712.         }
  1713.  
  1714.         newmsg_do(sqwebmail_folder);
  1715.         return;
  1716.     }
  1717.  
  1718.     if (strcmp(formname, "doattach") == 0)
  1719.     {
  1720.         doattach(sqwebmail_folder, cgi("draft"));
  1721.         return;
  1722.     }
  1723.     if (strcmp(formname, "folderdel") == 0)
  1724.     {
  1725.         folder_delmsgs(sqwebmail_folder, atol(cgi("pos")));
  1726.         return;
  1727.     }
  1728.     if (strcmp(formname, "spellchk") == 0)
  1729.     {
  1730. #ifdef  ISPELL
  1731.         spell_check_continue();
  1732. #else
  1733.         printf("Status: 404");
  1734. #endif
  1735.         return;
  1736.     }
  1737.  
  1738.     if (sqpcp_loggedin())
  1739.     {
  1740.         if (*cgi("do.neweventpreview"))
  1741.         {
  1742.             sqpcp_preview();
  1743.             return;
  1744.         }
  1745.  
  1746.         if (*cgi("do.neweventsave"))
  1747.         {
  1748.             sqpcp_save();
  1749.             return;
  1750.         }
  1751.  
  1752.         if (*cgi("do.neweventpostpone"))
  1753.         {
  1754.             sqpcp_postpone();
  1755.             return;
  1756.         }
  1757.  
  1758.         if (*cgi("do.neweventdeleteattach"))
  1759.         {
  1760.             sqpcp_deleteattach();
  1761.             return;
  1762.         }
  1763.  
  1764.         if (*cgi("do.neweventupload"))
  1765.         {
  1766.             sqpcp_uploadattach();
  1767.             return;
  1768.         }
  1769.  
  1770.         if (*cgi("do.neweventuppubkey"))
  1771.         {
  1772.             sqpcp_attachpubkey();
  1773.             return;
  1774.         }
  1775.  
  1776.         if (*cgi("do.neweventupprivkey"))
  1777.         {
  1778.             sqpcp_attachprivkey();
  1779.             return;
  1780.         }
  1781.         if (*cgi("do.eventdelete"))
  1782.         {
  1783.             sqpcp_dodelete();
  1784.             return;
  1785.         }
  1786.     }
  1787.  
  1788.     if (strcmp(formname, "event-edit") == 0)
  1789.     {
  1790.         formname="folders";
  1791.         if (sqpcp_loggedin())
  1792.         {
  1793.             formname="eventshow";   /* default */
  1794.             if (sqpcp_eventedit() == 0)
  1795.                 formname="newevent";
  1796.         }
  1797.     }
  1798.  
  1799.  
  1800.     if (strcmp(formname, "open-draft") == 0)
  1801.     {
  1802.         formname="newmsg";
  1803.         if (sqpcp_has_calendar())
  1804.             /* DRAFTS may contain event files */
  1805.         {
  1806.             const char *n=cgi("draft");
  1807.             char *filename;
  1808.             FILE *fp;
  1809.  
  1810.             CHECKFILENAME(n);
  1811.  
  1812.             filename=maildir_find(DRAFTS, n);
  1813.  
  1814.             if (filename)
  1815.             {
  1816.                 if ((fp=fopen(filename, "r")) != NULL)
  1817.                 {
  1818.                     struct rfc822hdr h;
  1819.  
  1820.                     rfc822hdr_init(&h, 8192);
  1821.  
  1822.                     while (rfc822hdr_read(&h, fp, NULL, 0)
  1823.                            == 0)
  1824.                     {
  1825.                         if (strcasecmp(h.header,
  1826.                                    "X-Event") == 0)
  1827.                         {
  1828.                             formname="newevent";
  1829.                             cgi_put("draftmessage",
  1830.                                 cgi("draft"));
  1831.                             break;
  1832.                         }
  1833.                     }
  1834.                     rfc822hdr_free(&h);
  1835.                     fclose(fp);
  1836.                 }
  1837.                 free(filename);
  1838.             }
  1839.         }
  1840.     }
  1841.  
  1842.     if (strcmp(formname, "newevent") == 0 ||
  1843.         strcmp(formname, "eventdaily") == 0 ||
  1844.         strcmp(formname, "eventweekly") == 0 ||
  1845.         strcmp(formname, "eventmonthly") == 0 ||
  1846.         strcmp(formname, "eventshow") == 0 ||
  1847.         strcmp(formname, "eventacl") == 0)
  1848.     {
  1849.         if (!sqpcp_has_calendar() ||
  1850.             !sqpcp_loggedin())
  1851.             formname="folders"; /* Naughty boy */
  1852.     }
  1853.    
  1854.     p=malloc(strlen(formname)+6);
  1855.     if (!p) enomem();
  1856.  
  1857.     strcat(strcpy(p, formname),".html");
  1858.     output_form(p);
  1859.     free(p);
  1860. }
  1861.  
  1862. #if 0
  1863. #if ENABLE_WEBPASS
  1864.  
  1865. /* System-compatible crypt function */
  1866.  
  1867. static const char *auth_crypt(const char *password, const char *salt)
  1868. {
  1869. #if     HAVE_CRYPT
  1870.     if (strncmp(salt, "$1$", 3))
  1871.         return (crypt(password, salt));
  1872. #endif
  1873.     return (md5_crypt(password, salt));
  1874. }
  1875.  
  1876. /*
  1877. ** Support for sqwebmail-only password.  Versions prior to 0.12 stored
  1878. ** it in clear test.  0.12 and later use crypt(), but still are able to
  1879. ** handle cleartext.
  1880. **
  1881. ** flag is non-zero if the authentication module does not support password
  1882. ** changes, therefore we need to create sqwebmail-webpass.
  1883. */
  1884.  
  1885. int check_sqwebpass(const char *pass)
  1886. {
  1887. const char *p=read_sqconfig(".", PASSFILE, 0);
  1888.  
  1889.     if (p && *p == '\t')
  1890.                     /* Starts with \t - crypt */
  1891.     {
  1892.         ++p;
  1893.         if (strcmp(p, auth_crypt(pass, p)) == 0)    return (0);
  1894.         return (-1);
  1895.     }
  1896.  
  1897.     if (p && strcmp(p, pass) == 0)  return (0);
  1898.     return (-1);
  1899. }
  1900.  
  1901. int has_sqwebpass()
  1902. {
  1903.     return (read_sqconfig(".", PASSFILE, 0) ? 1:0);
  1904. }
  1905. #endif
  1906.  
  1907. #if 0
  1908. static const char salt[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
  1909.  
  1910. void set_sqwebpass(const char *pw)
  1911. {
  1912. char    buf[100];
  1913. char    buf2[100];
  1914. const char *r=random128();
  1915. unsigned i;
  1916. #ifdef WEBPASS_CHANGE_VCHKPW
  1917. const char *p;
  1918. #endif
  1919.     /* r is 16 bytes.  We need 12 bits to initialize the salt */
  1920.  
  1921.     buf2[4]=0;
  1922.  
  1923.     i=0;
  1924.     while (*r)
  1925.     {
  1926.         i <<= 1;
  1927.         i |= (*r & 1);
  1928.         ++r;
  1929.     }
  1930.  
  1931.     buf[0]= salt[ i & 63];
  1932.     i /= 64;
  1933.     buf[1]= salt[ i & 63 ];
  1934.     buf[2]= 0;
  1935.  
  1936.     strcpy(buf, auth_crypt(pw, buf));
  1937.  
  1938.     buf2[0]='\t';
  1939.     strcpy(buf2+1, buf);
  1940.  
  1941. #ifdef WEBPASS_CHANGE_VCHKPW
  1942.     if(( p=login_returnaddr() ))
  1943.     {
  1944.         char *user;
  1945.         char *domain;
  1946.         char *p2;
  1947.         char *pw2;
  1948.  
  1949.         p2=strdup(p);
  1950.         pw2=strdup(pw);
  1951.         user=strtok(p2, "@");
  1952.         domain=strtok(0, "@");
  1953.         if(vpasswd(user,domain,pw2,0) == 0)
  1954.             write_sqconfig(".", PASSFILE, buf2);
  1955.         free(p2);
  1956.         free(pw2);
  1957.         return;
  1958.     }
  1959. #endif
  1960.     write_sqconfig(".", PASSFILE, buf2);
  1961. }
  1962. #endif
  1963. #endif
  1964.  
  1965. extern void folder_cleanup();
  1966. extern void maildir_cleanup();
  1967. extern void mailfilter_cleanup();
  1968.  
  1969. #ifdef  ISPELL
  1970. extern void ispell_cleanup();
  1971. #endif
  1972.  
  1973. void cleanup()
  1974. {
  1975.     sqwebmail_formname = NULL;
  1976.     sqwebmail_mailboxid=0;
  1977.     sqwebmail_folder=0;
  1978.     sqwebmail_sessiontoken=0;
  1979.     sqwebmail_content_language=0;
  1980.     sqwebmail_content_locale=0;
  1981.     sqwebmail_content_ispelldict=0;
  1982.     folder_cleanup();
  1983.     maildir_cleanup();
  1984.     mailfilter_cleanup();
  1985. #ifdef ISPELL
  1986.     ispell_cleanup();
  1987. #endif
  1988.  
  1989. #ifdef GZIP
  1990.     if (gzip_save_fd >= 0)  /* Restore original stdout */
  1991.     {
  1992.         close(1);
  1993.         dup(gzip_save_fd);
  1994.         close(gzip_save_fd);
  1995.         gzip_save_fd= -1;
  1996.     }
  1997. #endif
  1998.  
  1999. #if HAVE_SQWEBMAIL_UNICODE
  2000.     gpg_cleanup();
  2001. #endif
  2002.     freeargs();
  2003.     sqpcp_close();
  2004. }
  2005.  
  2006. #if HAVE_SQWEBMAIL_UNICODE
  2007.  
  2008. #else
  2009.  
  2010. /* Head it off at the pass */
  2011.  
  2012. int has_gpg(const char *dummy)
  2013. {
  2014.     return (-1);
  2015. }
  2016. #endif
  2017.  
  2018. static RETSIGTYPE catch_sig(int n)
  2019. {
  2020.     n=n;
  2021.     cleanup();
  2022.     fake_exit(0);
  2023. #if RETSIGTYPE != void
  2024.     return (0);
  2025. #endif
  2026. }
  2027.  
  2028. static void setlang()
  2029. {
  2030.     static char *lang_buf=0;
  2031.     char *p;
  2032.  
  2033.     if (sqwebmail_content_locale && *sqwebmail_content_locale
  2034.         && (p=malloc(sizeof("LANG=")+strlen(sqwebmail_content_locale)))!=0)
  2035.     {
  2036.         strcat(strcpy(p, "LANG="), sqwebmail_content_locale);
  2037.         putenv(p);
  2038.         if (lang_buf)
  2039.             free(lang_buf);
  2040.         lang_buf=p;
  2041.     }
  2042. }
  2043.  
  2044. static void init_default_locale()
  2045. {
  2046. char    *cl=http11_best_content_language(HTMLLIBDIR,
  2047.             getenv("HTTP_ACCEPT_LANGUAGE"));
  2048.  
  2049.     sqwebmail_content_language=
  2050.                 http11_content_language(HTMLLIBDIR, cl);
  2051.     sqwebmail_content_locale=
  2052.             http11_content_locale(HTMLLIBDIR, cl);
  2053.     sqwebmail_content_ispelldict=
  2054.             http11_content_ispelldict(HTMLLIBDIR, cl);
  2055.     sqwebmail_content_charset=
  2056.             http11_content_charset(HTMLLIBDIR, cl);
  2057.  
  2058.     free(cl);
  2059. #if HAVE_LOCALE_H
  2060. #if HAVE_SETLOCALE
  2061.     setlocale(LC_ALL, sqwebmail_content_locale);
  2062.     setlocale(LC_CTYPE, "C");
  2063.     setlang();
  2064. #endif
  2065. #endif
  2066. }
  2067.  
  2068. static void rename_sent_folder()
  2069. {
  2070.     char buf[128], buf2[200];
  2071.     time_t t;
  2072.     struct tm *tm;
  2073.     struct stat stat_buf;
  2074.     char *pp;
  2075.  
  2076.     time(&t);
  2077.     tm=localtime(&t);
  2078.     if (!tm)
  2079.         return;
  2080.  
  2081.     if (tm->tm_mon == 0)
  2082.     {
  2083.         tm->tm_mon=11;
  2084.         --tm->tm_year;
  2085.     }
  2086.     else
  2087.         --tm->tm_mon;
  2088.  
  2089.     if (strftime (buf, sizeof(buf), "." SENT ".%Y.%m-%b", tm) == 0)
  2090.         return;
  2091.  
  2092.     strcat(strcpy(buf2, "." SENT "/sqwebmail"), buf);
  2093.  
  2094.     if (stat(buf2, &stat_buf) == 0)
  2095.         return; /* Already renamed */
  2096.  
  2097.     pp=folder_toutf7(buf);
  2098.  
  2099.     rename("." SENT, pp);
  2100.     free(pp);
  2101.     (void)maildir_create(SENT);
  2102.     close(open(buf2, O_RDWR|O_CREAT, 0600));
  2103. }
  2104.  
  2105. static int valid_redirect();
  2106.  
  2107. static void redirect(const char *url)
  2108. {
  2109.     if (valid_redirect())
  2110.     {
  2111.         printf("Refresh: 0; URL=\"%s\"\n", url);
  2112.         output_form("redirect.html");
  2113.         return;
  2114.     }
  2115.  
  2116.     printf("Content-Type: text/plain\n\n"
  2117.            "The URL you clicked on is no longer valid.\n");
  2118.     return;
  2119. }
  2120.  
  2121. static int valid_redirect()
  2122. {
  2123.     const char *timestamp=cgi("timestamp"), *p;
  2124.     unsigned long timestamp_n;
  2125.     time_t timestamp_t;
  2126.     time_t now;
  2127.  
  2128.     if (sscanf(timestamp, "%lu", &timestamp_n) != 1)
  2129.         return 0;
  2130.  
  2131.     timestamp_t=(time_t)timestamp_n;
  2132.     time(&now);
  2133.  
  2134.     if (now < timestamp_t || now > timestamp_t + TIMEOUTHARD)
  2135.         return 0;
  2136.  
  2137.     p=redirect_hash(timestamp);
  2138.  
  2139.     if (*p == 0 || strcmp(cgi("md5"), p))
  2140.         return 0;
  2141.     return 1;
  2142. }
  2143.  
  2144. static int main2();
  2145.  
  2146. int main()
  2147. {
  2148. int rc;
  2149.  
  2150. #if HAVE_LIBFCGI
  2151.  
  2152.     while ( FCGI_Accept() >= 0)
  2153.     {
  2154.         if (setjmp(stackenv) == 0)
  2155.         {
  2156.             rc=main2();
  2157.             cleanup(); /* make sure we hit it */
  2158.             FCGI_SetExitStatus(rc);
  2159.             continue;
  2160.         }
  2161.         cleanup(); /* make sure we hit it */
  2162.  
  2163.         signal(SIGHUP, catch_sig);
  2164.         signal(SIGINT, catch_sig);
  2165.         signal(SIGPIPE, catch_sig);
  2166.         signal(SIGTERM, catch_sig);
  2167.     }
  2168.     return (0);
  2169. #else
  2170.     rc=main2();
  2171.     cleanup();
  2172.     exit(rc);
  2173.     return (rc);
  2174. #endif
  2175. }
  2176.  
  2177. static int setuidgid(uid_t u, gid_t g, const char *dir, void *dummy)
  2178. {
  2179.     if (setgid(g) || setuid(u))
  2180.     {
  2181.         syslog(LOG_DAEMON | LOG_CRIT,
  2182.             "sqwebmail: Cache - can't setuid/setgid to %u/%u",
  2183.                (unsigned)u, (unsigned)g);
  2184.         return (-1);
  2185.     }
  2186.  
  2187.     if (chdir(dir))
  2188.     {
  2189.         syslog(LOG_DAEMON | LOG_CRIT,
  2190.             "sqwebmail: Cache - can't chdir to %s", dir);
  2191.         return (-1);
  2192.     }
  2193.     return (0);
  2194. }
  2195.  
  2196. static int main2()
  2197. {
  2198. const char  *u;
  2199. const char  *ip_addr;
  2200. char    *pi;
  2201. char    *pi_malloced;
  2202. int reset_cookie=0;
  2203. time_t  timeouthard=TIMEOUTHARD;
  2204.  
  2205.  
  2206. #ifdef  GZIP
  2207.     gzip_save_fd= -1;
  2208. #endif
  2209.     u=ip_addr=pi=NULL;
  2210.  
  2211.     ip_addr=getenv("REMOTE_ADDR");
  2212.  
  2213.     signal(SIGHUP, catch_sig);
  2214.     signal(SIGINT, catch_sig);
  2215.     signal(SIGPIPE, catch_sig);
  2216.     signal(SIGTERM, catch_sig);
  2217.  
  2218.     if (!ip_addr)   ip_addr="127.0.0.1";
  2219.  
  2220.     umask(0077);
  2221.  
  2222.     {
  2223.         const char *p=getenv("SQWEBMAIL_TIMEOUTHARD");
  2224.  
  2225.         if (p && *p)
  2226.             timeouthard=atoi(p);
  2227.     }
  2228.  
  2229.     if (maildir_cache_init(timeouthard, CACHEDIR, CACHEOWNER, authvars))
  2230.     {
  2231.         printf("Content-Type: text/plain\n\nmaildir_cache_init() failed\n");
  2232.         fake_exit(0);
  2233.     }
  2234.  
  2235.     pi=getenv("PATH_INFO");
  2236.  
  2237.     pi_malloced=0;
  2238.     sqpcp_init();
  2239.  
  2240.     if (pi && strncmp(pi, "/printmsg/", 10) == 0)
  2241.     {
  2242.         /* See comment in output_user_form */
  2243.  
  2244.         pi_malloced=pi=cgi_cookie("sqwebmail-pi");
  2245.         if (*pi_malloced == 0)
  2246.         {
  2247.             free(pi_malloced);
  2248.             setgid(getgid());
  2249.             setuid(getuid());
  2250.             output_form("printnocookie.html");
  2251.             return (0);
  2252.         }
  2253.         reset_cookie=1;
  2254.         cgi_setcookie("sqwebmail-pi", "DELETED");
  2255.     }
  2256.  
  2257.     if (pi && strncmp(pi, "/login/", 7) == 0)
  2258.     {
  2259.     const char  *p;
  2260.     time_t  last_time, current_time;
  2261.     char    *q;
  2262.     time_t  timeoutsoft=TIMEOUTSOFT;
  2263.  
  2264.         p=getenv("SQWEBMAIL_TIMEOUTSOFT");
  2265.  
  2266.         if (p && *p)
  2267.             timeoutsoft=atoi(p);
  2268.  
  2269.         /* Logging into the mailbox */
  2270.  
  2271.         pi=strdup(pi);
  2272.         if (pi_malloced)    free(pi_malloced);
  2273.  
  2274.         if (!pi)    enomem();
  2275.  
  2276.         (void)strtok(pi, "/");  /* Skip login */
  2277.         u=strtok(NULL, "/");    /* mailboxid */
  2278.         sqwebmail_sessiontoken=strtok(NULL, "/"); /* sessiontoken */
  2279.         q=strtok(NULL, "/");    /* login time */
  2280.         login_time=0;
  2281.         while (q && *q >= '0' && *q <= '9')
  2282.             login_time=login_time * 10 + (*q++ - '0');
  2283.  
  2284.         if (maildir_cache_search(u, login_time, setuidgid, NULL)
  2285.             && prelogin(u))
  2286.         {
  2287.             free(pi);
  2288.             error("Unable to access your mailbox, sqwebmail permissions may be wrong.");
  2289.         }
  2290.  
  2291.         time(&current_time);
  2292.  
  2293.         /* Ok, boys and girls, time to validate the connection as
  2294.         ** follows */
  2295.  
  2296.         if (    !sqwebmail_sessiontoken
  2297.  
  2298.         /* 1. Read IPFILE.  Check that it's timestamp is current enough,
  2299.         ** and the session hasn't timed out.
  2300.         */
  2301.  
  2302.             || !(p=read_sqconfig(".", IPFILE, &last_time))
  2303.  
  2304. /*          || last_time > current_time */
  2305.  
  2306.             || last_time + timeouthard < current_time
  2307.  
  2308.         /* 2. IPFILE will contain seven words - IP address, session
  2309.         ** token, language, locale, ispell dictionary,
  2310.         ** timezone, charset.  Validate both.
  2311.         */
  2312.             || !(q=strdup(p))
  2313.             || !(p=strtok(q, " "))
  2314.             || (strcmp(p, ip_addr) && strcmp(p, "none"))
  2315.             || !(p=strtok(NULL, " "))
  2316.             || strcmp(p, sqwebmail_sessiontoken)
  2317.             || !(p=strtok(NULL, " "))
  2318.             || !(sqwebmail_content_language=strdup(p))
  2319.             || !(p=strtok(NULL, " "))
  2320.             || !(sqwebmail_content_locale=strdup(p))
  2321.             || !(p=strtok(NULL, " "))
  2322.             || !(sqwebmail_content_ispelldict=strdup(p))
  2323.             || !(p=strtok(NULL, " "))
  2324.             || set_timezone(p)
  2325.             || !(p=strtok(NULL, " "))
  2326.             || !(sqwebmail_content_charset=strdup(p))
  2327.  
  2328.         /* 3. Check the timestamp on the TIMESTAMP file.  See if the
  2329.         ** session has reached its soft timeout.
  2330.         */
  2331.  
  2332.             || !read_sqconfig(".", TIMESTAMP, &last_time)
  2333.  
  2334. /*          || last_time > current_time */
  2335.  
  2336.             || last_time + timeoutsoft < current_time)
  2337.         {
  2338.             setgid(getgid());
  2339.             setuid(getuid());   /* Drop root prevs */
  2340.             chdir("/");
  2341.             cgi_setup();
  2342.             init_default_locale();
  2343.             free(pi);
  2344.  
  2345.             if (strcmp(cgi("form"), "logout") == 0)
  2346.                 /* Already logged out, and the link
  2347.                 ** had target=_parent tag.
  2348.                 */
  2349.             {
  2350.                 http_redirect_top("");
  2351.                 return (0);
  2352.             }
  2353.             output_form("expired.html");
  2354.             return (0);
  2355.         }
  2356.         free(q);
  2357.         cgiformdatatempdir("tmp");
  2358.         cgi_setup();    /* Read CGI environment */
  2359.         if (reset_cookie)
  2360.             cgi_put("setcookie", "0");
  2361.  
  2362.         /* Update soft timeout stamp */
  2363.  
  2364.         write_sqconfig(".", TIMESTAMP, "");
  2365.  
  2366.         /* We must always have the folder CGI arg */
  2367.  
  2368.         if (!*(sqwebmail_folder=cgi("folder")))
  2369.         {
  2370.             init_default_locale();
  2371.             output_form("expired.html");
  2372.             free(pi);
  2373.             return (0);
  2374.         }
  2375.  
  2376.         CHECKFILENAME(sqwebmail_folder);
  2377.  
  2378.         sqwebmail_mailboxid=u;
  2379. #if HAVE_LOCALE_H
  2380. #if HAVE_SETLOCALE
  2381.         setlocale(LC_ALL, sqwebmail_content_locale);
  2382.         setlocale(LC_CTYPE, "C");
  2383.         setlang();
  2384. #endif
  2385. #endif
  2386.         pref_init();
  2387.         (void)sqpcp_loggedin();
  2388.         output_user_form(cgi("form"));
  2389.         free(pi);
  2390.     }
  2391.     else
  2392.         /* Must be one of those special forms */
  2393.     {
  2394.     char    *rm;
  2395.     long    n;
  2396.  
  2397.         if (pi_malloced)    free(pi_malloced);
  2398.  
  2399.         if ((rm=getenv("REQUEST_METHOD")) == 0 ||
  2400.             (strcmp(rm, "POST") == 0 &&
  2401.                 ((rm=getenv("CONTENT_TYPE")) != 0 &&
  2402.                 strncasecmp(rm,"multipart/form-data;", 20)
  2403.                     == 0)))
  2404.             enomem();   /* multipart/formdata posts not allowed
  2405.                     */
  2406.  
  2407.         /* Some additional safety checks */
  2408.  
  2409.         rm=getenv("CONTENT_LENGTH");
  2410.         n= rm ? atol(rm):0;
  2411.         if (n < 0 || n > 256)   enomem();
  2412.  
  2413.         cgi_setup();
  2414.         init_default_locale();
  2415.  
  2416.         if (*(u=cgi("username")))
  2417.             /* Request to log in */
  2418.         {
  2419.         const char *p=cgi("password");
  2420.         const char *mailboxid;             
  2421.         char *ubuf;
  2422.         int can_changepwd;
  2423.  
  2424.             if (nl_must_redirect(u))
  2425.             {
  2426.                 nl_redirect(u, p);
  2427.                 return (0);
  2428.             }
  2429.            
  2430.             if (nl_must_append_domain(u)) {
  2431.                 ubuf = nl_append_domain(u);
  2432.             } else {
  2433.                 ubuf = malloc ((strlen (u) + 1) * sizeof(char));
  2434.                 if (ubuf == NULL) {
  2435.                     enomem();
  2436.                 }
  2437.                 strcpy (ubuf, u);
  2438.             }
  2439.  
  2440.             if (nl_must_remove_domain(ubuf)) {
  2441.                 char* utemp = nl_remove_domain (ubuf);
  2442.                 free (ubuf);
  2443.                 ubuf = utemp;
  2444.             }
  2445.  
  2446.             maildir_cache_start();
  2447.             if (*p && (mailboxid=login(ubuf, p, &can_changepwd))
  2448.                 != 0)
  2449.             {
  2450.                 char    *q;
  2451.                 const   char *saveip=ip_addr;
  2452.                 char    *tz;
  2453.  
  2454. #if 0
  2455. #if ENABLE_WEBPASS
  2456.                 if (!can_changepwd && !has_sqwebpass())
  2457.                     set_sqwebpass(p);
  2458. #endif
  2459. #endif
  2460.                 sqwebmail_mailboxid=mailboxid;
  2461.                 sqwebmail_folder="INBOX";
  2462.                 sqwebmail_sessiontoken=random128();
  2463.  
  2464.                 tz=get_timezone();
  2465.                 if (*cgi("sameip") == 0)
  2466.                     saveip="none";
  2467.  
  2468.                 q=malloc(strlen(saveip)
  2469.                      +strlen(sqwebmail_sessiontoken)
  2470.                      +strlen(sqwebmail_content_language)
  2471.                      +strlen(sqwebmail_content_ispelldict)
  2472.                      +strlen(sqwebmail_content_charset)
  2473.                      +strlen(tz)
  2474.                      +strlen(sqwebmail_content_locale)+7);
  2475.                 if (!q) enomem();
  2476.                 sprintf(q, "%s %s %s %s %s %s %s", saveip,
  2477.                     sqwebmail_sessiontoken,
  2478.                     sqwebmail_content_language,
  2479.                     sqwebmail_content_locale,
  2480.                     sqwebmail_content_ispelldict,
  2481.                     tz,
  2482.                     sqwebmail_content_charset);
  2483.                 write_sqconfig(".", IPFILE, q);
  2484.                 free(q);
  2485.                 free(tz);
  2486.                 time(&login_time);
  2487.                 {
  2488.                     char buf[1024];
  2489.  
  2490.                     buf[sizeof(buf)-1]=0;
  2491.                     if (getcwd(buf, sizeof(buf)-1) == 0)
  2492.                     {
  2493.                         syslog(LOG_DAEMON,
  2494.                                "sqwebmail: "
  2495.                                "getcwd() failed");
  2496.                         fake_exit(1);
  2497.                     } /* oops */
  2498.  
  2499.                     maildir_cache_save(mailboxid,
  2500.                                login_time,
  2501.                                buf,
  2502.                                geteuid(), getegid()
  2503.                                );
  2504.  
  2505.                 }
  2506.                 write_sqconfig(".", TIMESTAMP, "");
  2507. #if HAVE_LOCALE_H
  2508. #if HAVE_SETLOCALE
  2509.                 setlocale(LC_ALL, sqwebmail_content_locale);
  2510.                 setlocale(LC_CTYPE, "C");
  2511.                 setlang();
  2512. #endif
  2513. #endif
  2514.                 (void)maildir_create(DRAFTS);
  2515.                 {
  2516.                     const char *autorenamesent=AUTORENAMESENT;
  2517.                     const char *p=getenv("SQWEBMAIL_AUTORENAMESENT");
  2518.                     if (p && *p)
  2519.                         autorenamesent = p;
  2520.                     if ( strncmp(autorenamesent, "no", 2) != 0 )
  2521.                         (void)rename_sent_folder();
  2522.                 }
  2523.                 (void)maildir_create(SENT);
  2524.                 (void)maildir_create(TRASH);
  2525.                 pref_init();
  2526.                 if (pref_autopurge > 0) maildir_autopurge();
  2527.  
  2528.                 sqpcp_login(ubuf, p);
  2529.  
  2530.                 http_redirect_argss("&form=folder&folder=INBOX", "", "");
  2531.                 /* output_form("folders.html"); */
  2532.                 free(ubuf);
  2533.                 return(0);
  2534.             }
  2535.             maildir_cache_cancel();
  2536.  
  2537.             free(ubuf);
  2538.             setgid(getgid());
  2539.             setuid(getuid());
  2540.             output_form("invalid.html");    /* Invalid login */
  2541.             return (0);
  2542.         }
  2543.  
  2544.         setgid(getgid());
  2545.         setuid(getuid());
  2546.         if ( *(u=cgi("redirect")))
  2547.             /* Redirection request to hide the referral tag */
  2548.         {
  2549.             redirect(u);
  2550.         }
  2551.         else if ( *cgi("noframes") == '1')
  2552.             output_form("login.html");  /* Main frame */
  2553.         else
  2554.         if ( *cgi("empty") == '1')
  2555.             output_form("empty.html");  /* Minor frameset */
  2556.  
  2557. /*
  2558. ** Apparently we can't show just SCRIPT NAME as our frameset due to some
  2559. ** weird bug in Communicator which, under certain conditions, will get
  2560. ** confused figuring out which page views have expired.  POSTs with URLs
  2561. ** referring to SCRIPT_NAME will be replied with an expiration header, and
  2562. ** Communicator will assume that index.html also has expired, forcing a
  2563. ** frameset reload the next time the Communicator window is resized,
  2564. ** essentially logging the user off.
  2565. */
  2566.  
  2567.         else if (*cgi("index") == '1')
  2568.             output_form("index.html");  /* Frameset Window */
  2569.         else
  2570.         {
  2571.             http_redirect_top("?index=1");
  2572.         }
  2573.                
  2574.         return (0);
  2575.     }
  2576.     return (0);
  2577. }
  2578.  
  2579. #ifdef  malloc
  2580.  
  2581. #undef  malloc
  2582. #undef  realloc
  2583. #undef  free
  2584. #undef  strdup
  2585. #undef  calloc
  2586.  
  2587. static void *allocp[1000];
  2588.  
  2589. extern void *malloc(size_t), *realloc(void *, size_t), free(void *),
  2590.     *calloc(size_t, size_t);
  2591. extern char *strdup(const char *);
  2592.  
  2593. char *my_strdup(const char *c)
  2594. {
  2595. size_t  i;
  2596.  
  2597.     for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
  2598.         if (!allocp[i])
  2599.             return (allocp[i]=strdup(c));
  2600.     abort();
  2601.     return (0);
  2602. }
  2603.  
  2604. void *my_malloc(size_t n)
  2605. {
  2606. size_t  i;
  2607.  
  2608.     for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
  2609.         if (!allocp[i])
  2610.             return (allocp[i]=malloc(n));
  2611.     abort();
  2612.     return (0);
  2613. }
  2614.  
  2615. void *my_calloc(size_t a, size_t b)
  2616. {
  2617. size_t  i;
  2618.  
  2619.     for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
  2620.         if (!allocp[i])
  2621.             return (allocp[i]=calloc(a,b));
  2622.     abort();
  2623.     return (0);
  2624. }
  2625.  
  2626. void *my_realloc(void *p, size_t s)
  2627. {
  2628. size_t  i;
  2629.  
  2630.     for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
  2631.         if (p && allocp[i] == p)
  2632.         {
  2633.         void    *q=realloc(p, s);
  2634.  
  2635.             if (q)  allocp[i]=q;
  2636.             return (q);
  2637.         }
  2638.     abort();
  2639. }
  2640.  
  2641. void my_free(void *p)
  2642. {
  2643. size_t i;
  2644.  
  2645.     for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
  2646.         if (p && allocp[i] == p)
  2647.         {
  2648.             free(p);
  2649.             allocp[i]=0;
  2650.             return;
  2651.         }
  2652.     abort();
  2653. }
  2654. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement