Back to index

courier  0.68.2
sqwebmail.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2009 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 
00007 /*
00008 */
00009 #include      "sqwebmail.h"
00010 #include      "sqconfig.h"
00011 #include      "auth.h"
00012 #include      "folder.h"
00013 #include      "pref.h"
00014 #include      "maildir.h"
00015 #include      "cgi/cgi.h"
00016 #include      "pref.h"
00017 #include      "mailinglist.h"
00018 #include      "newmsg.h"
00019 #include      "pcp.h"
00020 #include      "acl.h"
00021 #include      "addressbook.h"
00022 #include      "autoresponse.h"
00023 #include      "http11/http11.h"
00024 #include      "random128/random128.h"
00025 #include      "maildir/maildirmisc.h"
00026 #include      "maildir/maildirinfo.h"
00027 #include      "maildir/maildiraclt.h"
00028 #include      "liblock/config.h"
00029 #include      "liblock/liblock.h"
00030 #include      "rfc822/rfc822hdr.h"
00031 #include      "courierauth.h"
00032 #include      <stdio.h>
00033 #include      <errno.h>
00034 #include      <stdlib.h>
00035 #if    HAVE_UNISTD_H
00036 #include      <unistd.h>
00037 #endif
00038 #include      <string.h>
00039 #include      <signal.h>
00040 #include      <sys/types.h>
00041 #include      <sys/stat.h>
00042 #include      <sys/types.h>
00043 #include        <sys/socket.h>
00044 #if    HAVE_FCNTL_H
00045 #include      <fcntl.h>
00046 #endif
00047 #if    HAVE_LOCALE_H
00048 #if    HAVE_SETLOCALE
00049 #include      <locale.h>
00050 #if    USE_LIBCHARSET
00051 #if    HAVE_LOCALCHARSET_H
00052 #include      <localcharset.h>
00053 #elif  HAVE_LIBCHARSET_H
00054 #include      <libcharset.h>
00055 #endif /* HAVE_LOCALCHARSET_H */
00056 #elif  HAVE_LANGINFO_CODESET
00057 #include      <langinfo.h>
00058 #endif /* USE_LIBCHARSET */
00059 #endif /* HAVE_SETLOCALE */
00060 #endif /* HAVE_LOCALE_H */
00061 #include      <ctype.h>
00062 #if HAVE_SYS_WAIT_H
00063 #include      <sys/wait.h>
00064 #endif
00065 #if    HAVE_SYS_SELECT_H
00066 #include      <sys/select.h>
00067 #endif
00068 #if    HAVE_SYS_UIO_H
00069 #include      <sys/uio.h>
00070 #endif
00071 #define       MD5_INTERNAL
00072 #include      "md5/md5.h"
00073 
00074 #include      <courierauthdebug.h>
00075 #include      "maildir/maildircache.h"
00076 #include      "maildir/maildiraclt.h"
00077 #include      "maildir/maildirnewshared.h"
00078 #include      "mailfilter.h"
00079 #include      "numlib/numlib.h"
00080 #include      "gpglib/gpglib.h"
00081 #include      "gpg.h"
00082 #if    HAVE_CRYPT_H
00083 #include      <crypt.h>
00084 #endif
00085 #if     NEED_CRYPT_PROTOTYPE
00086 extern char *crypt(const char *, const char *);
00087 #endif
00088 #include      "htmllibdir.h"
00089 
00090 #include      "logindomainlist.h"
00091 
00092 #include      "strftime.h"
00093 
00094 extern void spell_show();
00095 extern void spell_check_continue();
00096 extern void print_safe(const char *);
00097 extern void ldaplist();
00098 extern int ldapsearch();
00099 extern void doldapsearch();
00100 
00101 extern void sent_gpgerrtxt();
00102 extern void sent_gpgerrresume();
00103 extern const char *redirect_hash(const char *);
00104 
00105 const char *sqwebmail_mailboxid=0;
00106 const char *sqwebmail_folder=0;
00107 
00108 #define ALL_RIGHTS \
00109        ACL_ADMINISTER \
00110        ACL_CREATE \
00111        ACL_EXPUNGE \
00112        ACL_INSERT \
00113        ACL_LOOKUP \
00114        ACL_READ \
00115        ACL_SEEN \
00116        ACL_DELETEMSGS \
00117        ACL_WRITE \
00118        ACL_DELETEFOLDER
00119 char sqwebmail_folder_rights[sizeof(ALL_RIGHTS)];
00120 
00121 const char *sqwebmail_sessiontoken=0;
00122 
00123 const char *sqwebmail_content_language=0;
00124 const char *sqwebmail_content_locale;
00125 const char *sqwebmail_system_charset=0;
00126 static char *sys_locale_charset=0;
00127 
00128 const char *sqwebmail_content_ispelldict;
00129 const char *sqwebmail_content_charset;
00130 
00131 dev_t sqwebmail_homedir_dev;
00132 ino_t sqwebmail_homedir_ino;
00133 
00134 static int noimages=0;
00135 
00136 time_t login_time;
00137 
00138 extern int nochangepass();
00139 
00140 /* Need to cache the following environment variables */
00141 static const char * const authvars[] = { "AUTHADDR", "AUTHFULLNAME",
00142                                     "OPTIONS", "AUTHENTICATED", 0 };
00143 
00144 #ifdef GZIP
00145 static int gzip_save_fd;
00146 
00147 #endif
00148 
00149 static const char *sqwebmail_formname;
00150 
00151 extern void attachments_head(const char *, const char *, const char *);
00152 extern void attachments_opts(const char *);
00153 extern void doattach(const char *, const char *);
00154 
00155 static void timezonelist();
00156 
00157 struct template_stack {
00158        struct template_stack *next;
00159        FILE *fp;
00160 } ;
00161 
00162 static struct template_stack *template_stack=NULL;
00163 
00164 char *trim_spaces(const char *s);
00165 
00166 size_t get_timeoutsoft()
00167 {
00168        time_t n=TIMEOUTSOFT;
00169        const char *p;
00170 
00171        p=getenv("SQWEBMAIL_TIMEOUTSOFT");
00172 
00173        if (p && *p)
00174               n=atoi(p);
00175 
00176        return n;
00177 }
00178 
00179 size_t get_timeouthard()
00180 {
00181        time_t n=TIMEOUTHARD;
00182        const char *p;
00183 
00184        p=getenv("SQWEBMAIL_TIMEOUTHARD");
00185 
00186        if (p && *p)
00187               n=atoi(p);
00188 
00189        return n;
00190 }
00191 
00192 void fake_exit(int n)
00193 {
00194        maildir_cache_cancel();
00195        exit(n);
00196 }
00197 
00198 
00199 /* Stub to catch aborts from authlib */
00200 
00201 void authexit(int n)
00202 {
00203        fake_exit(n);
00204 }
00205 
00206 /* enomem() used to be just an out-of-memory handler.  Now, I use it as a
00207 ** generic failure type of a deal.
00208 */
00209 
00210 void rfc2045_error(const char *p)
00211 {
00212        error(p);
00213 }
00214 
00215 void print_attrencodedlen(const char *p, size_t len, int oknl, FILE *fp)
00216 {
00217        for (; len; p++, --len)
00218        {
00219               switch (*p)   {
00220               case '<':
00221                      fprintf(fp, "&lt;");
00222                      continue;
00223               case '>':
00224                      fprintf(fp, "&gt;");
00225                      continue;
00226               case '&':
00227                      fprintf(fp, "&amp;");
00228                      continue;
00229               case '"':
00230                      fprintf(fp, "&quot;");
00231                      continue;
00232               case '\n':
00233                      if (oknl)
00234                      {
00235                             if (oknl == 2)
00236                             {
00237                                    fprintf(fp, "<br />");
00238                                    continue;
00239                             }
00240                             putc('\n', fp);
00241                             continue;
00242                      }
00243               default:
00244                      if (!ISCTRL(*p))
00245                      {
00246                             putc(*p, fp);
00247                             continue;
00248                      }
00249               }
00250               fprintf(fp, "&#%d;", (int)(unsigned char)*p);
00251        }
00252 }
00253 
00254 void output_attrencoded_fp(const char *p, FILE *fp)
00255 {
00256        print_attrencodedlen(p, strlen(p), 0, fp);
00257 }
00258 
00259 void output_attrencoded(const char *p)
00260 {
00261        output_attrencoded_fp(p, stdout);
00262 }
00263 
00264 void output_attrencoded_oknl_fp(const char *p, FILE *fp)
00265 {
00266        print_attrencodedlen(p, strlen(p), 1, fp);
00267 }
00268 
00269 void output_attrencoded_oknl(const char *p)
00270 {
00271        output_attrencoded_oknl_fp(p, stdout);
00272 }
00273 
00274 void output_attrencoded_nltobr(const char *p)
00275 {
00276        print_attrencodedlen(p, strlen(p), 2, stdout);
00277 }
00278 
00279 void output_urlencoded(const char *p)
00280 {
00281 char   *q=cgiurlencode(p);
00282 
00283        printf("%s", q);
00284        free(q);
00285 }
00286 
00287 void output_loginscriptptr()
00288 {
00289 #if    USE_HTTPS_LOGIN
00290 const  char *p=cgihttpsscriptptr();
00291 #elif  USE_RELATIVE_URL
00292 const  char *p=cgirelscriptptr();
00293 #else
00294 const  char *p=cgihttpscriptptr();
00295 #endif
00296 
00297        printf("%s", p);
00298 }
00299 
00300 const char *nonloginscriptptr()
00301 {
00302 #if    USE_HTTPS
00303        return (cgihttpsscriptptr());
00304 #elif  USE_RELATIVE_URL
00305        return (cgirelscriptptr());
00306 #else
00307        return (cgihttpscriptptr());
00308 #endif
00309 }
00310 
00311 
00312 void output_scriptptr()
00313 {
00314 const  char *p=nonloginscriptptr();
00315 
00316        printf("%s", p);
00317        if (sqwebmail_mailboxid)
00318        {
00319        char   *q=cgiurlencode(sqwebmail_mailboxid);
00320        char   buf[NUMBUFSIZE];
00321 
00322               printf("/login/%s/%s/%s", q,
00323                      sqwebmail_sessiontoken ?  sqwebmail_sessiontoken:" ",
00324                      libmail_str_time_t(login_time, buf));
00325               free(q);
00326        }
00327 }
00328 
00329 void output_loginscriptptr_get()
00330 {
00331        output_loginscriptptr();
00332        if (sqwebmail_mailboxid)
00333        {
00334        char   *q=cgiurlencode(sqwebmail_mailboxid);
00335        char   buf[NUMBUFSIZE];
00336 
00337               printf("/login/%s/%s/%s", q,
00338                      sqwebmail_sessiontoken ?  sqwebmail_sessiontoken:" ",
00339                      libmail_str_time_t(login_time, buf));
00340               free(q);
00341        }
00342 }
00343 
00344 char *scriptptrget()
00345 {
00346 char   *q=0;
00347 size_t l=0;
00348 int    i;
00349 char   buf[NUMBUFSIZE];
00350 
00351 #define       ADD(s) {const char *zz=(s); if (i) strcat(q, zz); l += strlen(zz);}
00352 #define ADDE(ue) { char *yy=cgiurlencode(ue); ADD(yy); free(yy); }
00353 
00354        for (i=0; i<2; i++)
00355        {
00356               if (i && (q=malloc(l+1)) == 0)     enomem();
00357               if (i) *q=0;
00358               ADD( nonloginscriptptr() );
00359               if (!sqwebmail_mailboxid)
00360               {
00361                      ADD("?");
00362                      continue;
00363               }
00364 
00365               ADD("/login/");
00366               ADDE(sqwebmail_mailboxid);
00367               ADD("/");
00368               ADD(sqwebmail_sessiontoken ? sqwebmail_sessiontoken:" ");
00369               ADD("/");
00370               ADD(libmail_str_time_t(login_time, buf));
00371 
00372               ADD( "?" );
00373               if (sqwebmail_folder)
00374               {
00375                      ADD("folder=");
00376                      ADDE(sqwebmail_folder);
00377               }
00378        }
00379 #undef ADD
00380 #undef ADDE
00381        return (q);
00382 }
00383 
00384 void output_scriptptrget()
00385 {
00386 char   *p=scriptptrget();
00387 
00388        printf("%s", p);
00389        free(p);
00390        return;
00391 }
00392 
00393 void output_scriptptrpostinfo()
00394 {
00395        if (sqwebmail_folder)
00396        {
00397               printf("<input type=\"hidden\" name=\"folder\" value=\"");
00398               output_attrencoded(sqwebmail_folder);
00399               printf("\" />");
00400        }
00401 
00402        if (*cgi("folderdir"))      /* In folders.html */
00403        {
00404               printf("<input type=\"hidden\" name=\"folderdir\" value=\"");
00405               output_attrencoded(cgi("folderdir"));
00406               printf("\" />");
00407        }
00408 }
00409 
00410 void error(const char *errmsg)
00411 {
00412        cginocache();
00413        printf("Content-Type: text/html; charset=us-ascii\n\n"
00414               "<html><head><title>%s</title></head><body><h1>%s</h1></body></html>\n",
00415               errmsg, errmsg);
00416        cleanup();
00417        fake_exit(1);
00418 }
00419 
00420 void error2(const char *file, int line)
00421 {
00422        cginocache();
00423        printf("Content-Type: text/html; charset=us-ascii\n\n"
00424               "<html><head><title>Internal error</title></head><body>"
00425               "<h1>Internal error (module %s, line %d) - contact system administrator</h1>"
00426               "</body></html>\n",
00427               file, line);
00428        cleanup();
00429        fake_exit(1);
00430 }
00431 
00432 void error3(const char *file, int line, const char *msg1, const char *msg2, int err)
00433 {
00434        cginocache();
00435        if (err == -1) err = errno;
00436        printf("Content-Type: text/html; charset=us-ascii\n\n"
00437               "<html><head><title>Internal error</title></head><body>"
00438               "<h1>Internal error (module %s, line %d) - contact system administrator</h1>"
00439               "<pre>%s\n%s\n%s</pre>"
00440               "</body></html>\n",
00441               file, line, msg1?msg1:"", msg2?msg2:"", err?strerror(err):"");
00442        cleanup();
00443        fake_exit(1);
00444 }
00445 
00446 
00447 char *get_templatedir()
00448 {
00449 char   *templatedir=getenv("SQWEBMAIL_TEMPLATEDIR");
00450        
00451        if (!templatedir || !*templatedir) templatedir=HTMLLIBDIR;
00452 
00453        return templatedir;
00454 }
00455 
00456 
00457 char *get_imageurl()
00458 {
00459 char   *imageurl=getenv("SQWEBMAIL_IMAGEURL");
00460        
00461        if (!imageurl || !*imageurl)       imageurl=IMGPATH;
00462 
00463        return imageurl;
00464 }
00465 
00466 
00467 FILE *open_langform(const char *lang, const char *formname,
00468                   int print_header)
00469 {
00470 char   *formpath;
00471 FILE   *f;
00472 char   *templatedir=get_templatedir();
00473        
00474        /* templatedir/lang/formname */
00475 
00476        if (!(formpath=malloc(strlen(templatedir)+3+
00477               strlen(lang)+strlen(formname))))
00478               error("Out of memory.");
00479 
00480        strcat(strcat(strcat(strcat(strcpy(formpath, templatedir), "/"),
00481               lang), "/"), formname);
00482 
00483        f=fopen(formpath, "r");
00484 
00485        free(formpath);
00486        
00487        if (f && print_header)
00488               printf("Content-Language: %s\n", lang);
00489        if (f)
00490               fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
00491        return (f);
00492 }
00493 
00494 int ishttps()
00495 {
00496        const char *p=getenv("HTTPS");
00497 
00498        return (p && strcasecmp(p, "on") == 0);
00499 }
00500 
00501 struct var_put_buf {
00502        char argbuf[3072];
00503        char *argp;
00504        size_t argn;
00505 } ;
00506 
00507 static void var_put_buf_func(int c, void *p)
00508 {
00509        struct var_put_buf *pp=(struct var_put_buf *)p;
00510 
00511        if (pp->argn)
00512        {
00513               *pp->argp++=c;
00514               --pp->argn;
00515        }
00516 }
00517 
00518 static void pass_image_through(int c, void *p)
00519 {
00520        putchar(c);
00521 }
00522 
00523 static void output_image( FILE *f,
00524                        void (*output_func)(int, void *), void *void_arg)
00525 {
00526        int c;
00527 
00528        /*
00529          Conditional image.  It's formatted as follows:
00530 
00531          @@filename,width=x height=y@text@
00532             ^
00533             |
00534            ----- we're at this point now.
00535 
00536          If images are enabled, we replace that with an IMG tag we build from
00537          filename,width=x, height=y.
00538          If images are disabled, we replace all of this with text.
00539 
00540        */
00541 
00542 #define       MKIMG(c)      (*output_func)((c), void_arg)
00543 
00544        if (noimages)
00545        {
00546               while ((c=getc(f)) >= 0
00547                      && c != '@')
00548                      ;
00549               while ((c=getc(f)) >= 0
00550                      && c != '@')
00551                      MKIMG(c);
00552        }
00553        else
00554        {
00555               char   *p;
00556 
00557               MKIMG('<');
00558               MKIMG('i');
00559               MKIMG('m');
00560               MKIMG('g');
00561               MKIMG(' ');
00562               MKIMG('s');
00563               MKIMG('r');
00564               MKIMG('c');
00565               MKIMG('=');
00566               MKIMG('"');
00567               for (p=get_imageurl(); *p; p++)
00568                      MKIMG(*p);
00569 
00570               MKIMG('/');
00571               while ((c=getc(f)) >= 0
00572                      && c != '@' && c != ',')
00573                      MKIMG(c);
00574               MKIMG('"');
00575               MKIMG(' ');
00576               if (c == ',')
00577                      c=getc(f);
00578               while (c >= 0 && c != '@')
00579               {
00580                      MKIMG(c);
00581                      c=getc(f);
00582               }
00583               while ((c=getc(f)) >= 0 && c != '@')
00584                      ;
00585               MKIMG(' ');
00586               MKIMG('/');
00587               MKIMG('>');
00588        }
00589 }
00590 
00591 /* ---- time zone list ---- */
00592 
00593 static int timezonefile( int (*callback_func)(const char *, const char *,
00594                                          void *), void *callback_arg)
00595 {
00596        FILE *f=NULL;
00597        char buffer[BUFSIZ];
00598 
00599        if (sqwebmail_content_language)
00600               f=open_langform(sqwebmail_content_language, "TIMEZONELIST", 0);
00601 
00602        if (!f)       f=open_langform(HTTP11_DEFAULTLANG, "TIMEZONELIST", 0);
00603 
00604        if (!f)
00605               return (0);
00606 
00607        while (fgets(buffer, sizeof(buffer), f) != NULL)
00608        {
00609               char *p=strchr(buffer, '\n');
00610               char *tz;
00611               int rc;
00612 
00613               if (p) *p=0;
00614 
00615               p=strchr(buffer, '#');
00616               if (p) *p=0;
00617 
00618               for (p=buffer; *p; p++)
00619                      if (!isspace((int)(unsigned char)*p))
00620                             break;
00621 
00622               if (!*p)
00623                      continue;
00624 
00625               tz=p;
00626               while (*p)
00627               {
00628                      if (isspace((int)(unsigned char)*p))
00629                             break;
00630                      ++p;
00631               }
00632               if (*p) *p++=0;
00633               while (*p && isspace((int)(unsigned char)*p))
00634                      ++p;
00635 
00636               if (strcmp(p, "*") == 0)
00637                      p="";
00638               if (strcmp(tz, "*") == 0)
00639                      tz="";
00640 
00641               rc= (*callback_func)(tz, p, callback_arg);
00642 
00643               if (rc)
00644               {
00645                      fclose(f);
00646                      return (rc);
00647               }
00648        }
00649        fclose(f);
00650        return (0);
00651 }
00652 
00653 static int callback_timezonelist(const char *, const char *, void *);
00654 
00655 static void timezonelist()
00656 {
00657        printf("<select name=\"timezonelist\" class=\"timezonelist\">");
00658        timezonefile(callback_timezonelist, NULL);
00659        printf("</select>\n");
00660 }
00661 
00662 static int callback_timezonelist(const char *tz, const char *n, void *dummy)
00663 {
00664        printf("<option value=\"%s\">", tz);
00665        output_attrencoded(n);
00666        printf("</option>\n");
00667        return (0);
00668 }
00669 
00670 static int set_timezone(const char *p)
00671 {
00672        static char *s_buffer=0;
00673        char *buffer;
00674 
00675        if (!p || !*p || strcmp(p, "*") == 0)
00676               return (0);
00677 
00678        buffer=malloc(strlen(p)+10);
00679        if (!buffer)
00680               return (0);
00681        strcat(strcpy(buffer, "TZ="), p);
00682 
00683        putenv(buffer);
00684 
00685        if (s_buffer)
00686               free(buffer);
00687        s_buffer=buffer;
00688 
00689        return (0);
00690 }
00691 
00692 static int callback_get_timezone(const char *, const char *, void *);
00693 
00694 /* Return TZ selected from login dropdown */
00695 
00696 static char *get_timezone()
00697 {
00698        char *langptr=0;
00699 
00700        timezonefile(callback_get_timezone, &langptr);
00701 
00702        if (!langptr)
00703        {
00704               langptr=strdup("");
00705               if (!langptr)
00706                      enomem();
00707        }
00708 
00709        if (*langptr == 0)
00710        {
00711               free(langptr);
00712               langptr=strdup("*");
00713               if (!langptr)
00714                      enomem();
00715        }
00716 
00717        return(langptr);
00718 }
00719 
00720 static int callback_get_timezone(const char *tz, const char *n, void *dummy)
00721 {
00722        if (strcmp(tz, cgi("timezonelist")) == 0)
00723        {
00724               char **p=(char **)dummy;
00725 
00726               if (*p)
00727                      free(*p);
00728 
00729               *p=strdup(tz);
00730        }
00731        return (0);
00732 }
00733 
00734 /* ------------------------ */
00735 
00736 static FILE *do_open_form(const char *formname, int flag)
00737 {
00738        struct template_stack *ts;
00739        FILE   *f=NULL;
00740 
00741        if ((ts=(struct template_stack *)malloc(sizeof(struct template_stack)))
00742            == NULL)
00743               return (NULL);
00744 
00745        if (sqwebmail_content_language)
00746               f=open_langform(sqwebmail_content_language, formname, flag);
00747        if (!f)       f=open_langform(HTTP11_DEFAULTLANG, formname, flag);
00748 
00749        if (!f)
00750        {
00751               free(ts);
00752               return (NULL);
00753        }
00754 
00755        ts->next=template_stack;
00756        template_stack=ts;
00757        ts->fp=f;
00758        return (f);
00759 }
00760 
00761 static void do_close_form()
00762 {
00763        struct template_stack *ts=template_stack;
00764 
00765        if (!ts)
00766               enomem();
00767 
00768        fclose(ts->fp);
00769        template_stack=ts->next;
00770        free(ts);
00771 }
00772 
00773 static void do_output_form_loop(FILE *);
00774 
00775 static void fix_xml_header(FILE *f)
00776 {
00777        char linebuf[80];
00778 
00779        /*
00780        ** Some templates now have an <?xml > header.  Adjust the
00781        ** encoding to match the selected default.  Yes, it's a dirty hack,
00782        ** and I'm proud of it, since it allows me to continue editing the
00783        ** HTML templates in Amaya.
00784        */
00785 
00786        if (fgets(linebuf, sizeof(linebuf), f) == NULL)
00787               return;
00788 
00789        if (strncasecmp(linebuf, "<?xml version=", 14) == 0)
00790               sprintf(linebuf, "<?xml version=\"1.0\" encoding=\"%s\"?>\n",
00791                      sqwebmail_content_charset);
00792 
00793        printf("%s", linebuf);
00794 }
00795 
00796 void output_form(const char *formname)
00797 {
00798        FILE   *f;
00799 
00800 #ifdef GZIP
00801        int    dogzip;
00802        int    pipefd[2];
00803        pid_t  pid= -1;
00804 #endif
00805 
00806        noimages= auth_getoptionenvint("wbnoimages");
00807 
00808        f=do_open_form(formname, 1);
00809 
00810        sqwebmail_formname=formname;
00811 
00812        if (!f)       error("Can't open form template.");
00813 
00814        /*
00815        ** Except for the dummy frame window (and the tiny empty frame),
00816        ** and the window containing the print preview of the message,
00817        ** expire everything.
00818        */
00819 
00820        if (strcmp(formname, "index.html") && strcmp(formname, "empty.html") &&
00821               strcmp(formname, "print.html"))
00822               cginocache();
00823 
00824 #ifdef GZIP
00825 
00826        dogzip=0;
00827        if (strcmp(formname, "readmsg.html") == 0 ||
00828            strcmp(formname, "folder.html") == 0 ||
00829            strcmp(formname, "folders.html") == 0 ||
00830            strcmp(formname, "gpg.html") == 0)
00831        {
00832        const char *p=getenv("HTTP_ACCEPT_ENCODING");
00833 
00834               if (p)
00835               {
00836               char   *q=strdup(p), *r;
00837 
00838                      if (!q)       enomem();
00839                      for (r=q; *r; r++)
00840                             *r= tolower((int)(unsigned char)*r);
00841                      for (r=q; (r=strtok(r, ", ")) != 0; r=0)
00842                             if (strcmp(r, "gzip") == 0)
00843                             {
00844                                    dogzip=1;
00845                                    if (pipe(pipefd))
00846                                           enomem();
00847                             }
00848                      free(q);
00849               }
00850        }
00851 #endif
00852 
00853        /* Do not send a Vary header for attachment downloads */
00854 
00855        if (*cgi("download") == 0)
00856               printf("Vary: Accept-Language\n");
00857 
00858 #ifdef GZIP
00859        if (dogzip)
00860               printf("Content-Encoding: gzip\n");
00861 #endif
00862 
00863        printf("Content-Type: text/html");
00864 
00865        if (sqwebmail_content_charset)
00866               printf("; charset=%s", sqwebmail_content_charset);
00867 
00868        printf("\n\n");
00869 
00870 #ifdef GZIP
00871        if (dogzip)
00872        {
00873               fflush(stdout);
00874               while ((pid=fork()) == -1)
00875                      sleep(5);
00876               if (pid == 0)
00877               {
00878                      dup2(pipefd[0], 0);
00879                      close(pipefd[0]);
00880                      close(pipefd[1]);
00881                      execl(GZIP, "gzip", "-c", (char *)0);
00882                      fprintf(stderr, 
00883                             "ERR: Cannot execute " GZIP ": %s\n",
00884                             strerror(errno));
00885                      exit(1);
00886               }
00887 
00888               gzip_save_fd=dup(1);
00889               dup2(pipefd[1], 1);
00890               close(pipefd[1]);
00891               close(pipefd[0]);
00892        }
00893 #endif
00894        fix_xml_header(f);
00895        do_output_form_loop(f);
00896        do_close_form();
00897 
00898 #ifdef GZIP
00899        if (pid > 0)
00900        {
00901        int    waitstat;
00902        pid_t  p2;
00903 
00904               /* Restore original stdout */
00905 
00906               fflush(stdout);
00907               dup2(gzip_save_fd, 1);
00908               close(gzip_save_fd);
00909               gzip_save_fd= -1;
00910               while ((p2=wait(&waitstat)) >= 0 && p2 != pid)
00911                      ;
00912        }
00913 #endif
00914 }
00915 
00916 static FILE *openinclude(const char *);
00917 
00918 
00919 void insert_include(const char *inc_name)
00920 {
00921        FILE *ff=openinclude(inc_name);
00922        do_output_form_loop(ff);
00923        do_close_form();
00924 }
00925 
00926 static void do_output_form_loop(FILE *f)
00927 {
00928        int    c, c2, c3;
00929 
00930        while ((c=getc(f)) >= 0)
00931        {
00932        char   kw[64];
00933 
00934               if (c != '[')
00935               {
00936                      putchar(c);
00937                      continue;
00938               }
00939               c=getc(f);
00940               if (c != '#')
00941               {
00942                      putchar('[');
00943                      ungetc(c,f);
00944                      continue;
00945               }
00946               c=getc(f);
00947               if (c == '?')
00948               {
00949                      c=getc(f);
00950                      if (c < '0' || c > '9')
00951                      {
00952                             putchar('[');
00953                             putchar('#');
00954                             putchar('?');
00955                             putchar(c);
00956                             continue;
00957                      }
00958                      if (
00959                          ( c == '0' && nochangepass()) ||
00960                          (c == '1' && strncmp(cgi("folderdir"),
00961                                            SHARED ".",
00962                                            sizeof(SHARED)) == 0) ||
00963                          (c == '2' && strncmp(cgi("folderdir"),
00964                                            SHARED ".",
00965                                            sizeof(SHARED))) ||
00966                          (c == '4' && maildir_filter_hasmaildirfilter(".")) ||
00967                          (c == '5' && libmail_gpg_has_gpg(GPGDIR)) ||
00968                          (c == '6' && !ishttps()) ||
00969                          (c == '7' && !sqpcp_has_calendar()) ||
00970                          (c == '8' && !sqpcp_has_groupware())
00971                          )
00972                      {
00973                             while ((c=getc(f)) != EOF)
00974                             {
00975                                    if (c != '[') continue;
00976                                    if ( getc(f) != '#') continue;
00977                                    if ( getc(f) != '?') continue;
00978                                    if ( getc(f) != '#') continue;
00979                                    if ( getc(f) == ']') break;
00980                             }
00981                      }
00982                      continue;
00983               }
00984 
00985               if (c == '$')
00986               {
00987                      struct var_put_buf buf;
00988 
00989                      buf.argp=buf.argbuf;
00990                      buf.argn=sizeof(buf.argbuf)-1;
00991 
00992                      while ((c=getc(f)) >= 0 && c != '\n')
00993                      {
00994                             if (c == '#')
00995                             {
00996                                    c=getc(f);
00997                                    if (c == ']') break;
00998                                    ungetc(c, f);
00999                                    c='#';
01000                             }
01001 
01002                             if (c == '@')
01003                             {
01004                                    c=getc(f);
01005                                    if (c == '@')
01006                                    {
01007                                           output_image(f,
01008                                                       var_put_buf_func,
01009                                                       &buf);
01010                                           continue;
01011                                    }
01012                                    ungetc(c, f);
01013                                    c='@';
01014                             }
01015                             var_put_buf_func(c, &buf);
01016                      }
01017                      *buf.argp=0;
01018                      addarg(buf.argbuf);
01019                      continue;
01020               }
01021 
01022               if (c == '@')
01023               {
01024                      output_image(f, pass_image_through, NULL);
01025                      c=getc(f);
01026                      if (c == '#')
01027                      {
01028                             c=getc(f);
01029                             if (c == ']')
01030                                    continue;
01031                      }
01032                      if (c != EOF)
01033                             ungetc(c, f);
01034                      continue;
01035               }
01036 
01037               if (!isalnum(c) && c != ':')
01038               {
01039                      putchar('[');
01040                      putchar('#');
01041                      ungetc(c, f);
01042                      continue;
01043               }
01044               c2=0;
01045               while (c != EOF && (isalnum(c) || c == ':' || c == '_'))
01046               {
01047                      if (c2 < sizeof(kw)-1)
01048                             kw[c2++]=c;
01049                      c=getc(f);
01050               }
01051               kw[c2]=0;
01052               c2=c;
01053 
01054               if (c2 != '#')
01055               {
01056                      putchar('[');
01057                      putchar('#');
01058                      printf("%s", kw);
01059                      ungetc(c2, f);
01060                      continue;
01061               }
01062 
01063               if ((c3=getc(f)) != ']')
01064               {
01065                      putchar('[');
01066                      putchar('#');
01067                      printf("%s", kw);
01068                      putchar(c2);
01069                      ungetc(c3, f);
01070                      continue;
01071               }
01072 
01073               if (strcmp(kw, "a") == 0)
01074               {
01075                      addressbook();
01076               }
01077               else if (strcmp(kw, "d") == 0)
01078               {
01079                      const char *f=cgi("folderdir");
01080                      char *origc, *c;
01081                      const char *sep="";
01082 
01083                      origc=c=folder_fromutf7(f);
01084 
01085                      if (*c && strcmp(c, INBOX))
01086                      {
01087                             printf(" - ");
01088 
01089                             if (strcmp(c, NEWSHAREDSP) == 0 ||
01090                                 strncmp(c, NEWSHAREDSP ".",
01091                                        sizeof(NEWSHAREDSP)) == 0)
01092                             {
01093                                    printf("%s", getarg("PUBLICFOLDERS"));
01094                                    sep=".";
01095                             }
01096 
01097                             c=strchr(c, '.');
01098                             if (c)
01099                             {
01100                                    printf(sep);
01101                                    print_safe(c+1);
01102                             }
01103                      }
01104                      free(origc);
01105               }
01106               else if (strcmp(kw, "D") == 0)
01107               {
01108                      const char *p=cgi("folder");
01109                      const char *q=strrchr(p, '.');
01110 
01111                             if (q)
01112                             {
01113                             char   *r=malloc(q-p+1);
01114 
01115                                    if (!r)       enomem();
01116                                    memcpy(r, p, q-p);
01117                                    r[q-p]=0;
01118                                    output_urlencoded(r);
01119                                    free(r);
01120                             }
01121               }
01122               else if (strcmp(kw, "G") == 0)
01123               {
01124                      output_attrencoded(login_returnaddr());
01125               }
01126               else if (strcmp(kw, "r") == 0)
01127               {
01128                      output_attrencoded(cgi("redirect"));
01129               }
01130               else if (strcmp(kw, "s") == 0)
01131               {
01132                      output_scriptptrget();
01133               }
01134               else if (strcmp(kw, "S") == 0)
01135               {
01136                      output_loginscriptptr();
01137               }
01138               else if (strcmp(kw, "R") == 0)
01139               {
01140                      output_loginscriptptr_get();
01141               }
01142               else if (strcmp(kw, "p") == 0)
01143               {
01144                      output_scriptptr();
01145               }
01146               else if (strcmp(kw, "P") == 0)
01147               {
01148                      output_scriptptrpostinfo();
01149               }
01150               else if (strcmp(kw, "f") == 0)
01151               {
01152                      folder_contents_title();
01153               }
01154               else if (strcmp(kw, "F") == 0)
01155               {
01156                      folder_contents(sqwebmail_folder, atol(cgi("pos")));
01157               }
01158               else if (strcmp(kw, "n") == 0)
01159               {
01160                      folder_initnextprev(sqwebmail_folder, atol(cgi("pos")));
01161               }
01162               else if (strcmp(kw, "N") == 0)
01163               {
01164                      folder_nextprev();
01165               }
01166               else if (strcmp(kw, "m") == 0)
01167               {
01168                      folder_msgmove();
01169               }
01170               else if (strcmp(kw, "M") == 0)
01171               {
01172                      folder_showmsg(sqwebmail_folder, atol(cgi("pos")));
01173               }
01174               else if (strcmp(kw, "T") == 0)
01175               {
01176                      folder_showtransfer();
01177               }
01178               else if (strcmp(kw, "L") == 0)
01179               {
01180                      folder_list();
01181               }
01182               else if (strcmp(kw, "l") == 0)
01183               {
01184                      folder_list2();
01185               }
01186               else if (strcmp(kw, "E") == 0)
01187               {
01188                      folder_rename_list();
01189               }
01190               else if (strcmp(kw, "W") == 0)
01191               {
01192                      newmsg_init(sqwebmail_folder, cgi("pos"));
01193               }
01194               else if (strcmp(kw, "z") == 0)
01195               {
01196                      pref_isdisplayfullmsg();
01197               }
01198               else if (strcmp(kw, "y") == 0)
01199               {
01200                      pref_isoldest1st();
01201               }
01202               else if (strcmp(kw, "H") == 0)
01203               {
01204                      pref_displayhtml();
01205               }
01206               else if (strcmp(kw, "FLOWEDTEXT") == 0)
01207               {
01208                      pref_displayflowedtext();
01209               }
01210               else if (strcmp(kw, "NOARCHIVE") == 0)
01211               {
01212                      pref_displaynoarchive();
01213               }
01214               else if (strcmp(kw, "NOAUTORENAMESENT") == 0)
01215               {
01216                      pref_displaynoautorenamesent();
01217               }
01218               else if (strcmp(kw, "x") == 0)
01219               {
01220                      pref_setprefs();
01221               }
01222               else if (strcmp(kw, "w") == 0)
01223               {
01224                      pref_sortorder();
01225               }
01226               else if (strcmp(kw, "t") == 0)
01227               {
01228                      pref_signature();
01229               }
01230               else if (strcmp(kw, "u") == 0)
01231               {
01232                      pref_pagesize();
01233               }
01234               else if (strcmp(kw, "v") == 0)
01235               {
01236                      pref_displayautopurge();
01237               }
01238               else if (strcmp(kw, "A") == 0)
01239               {
01240                      attachments_head(sqwebmail_folder, cgi("pos"),
01241                             cgi("draft"));
01242               }
01243               else if (strcmp(kw, "ATTACHOPTS") == 0)
01244               {
01245                      attachments_opts(cgi("draft"));
01246               }
01247               else if (strcmp(kw, "GPGERR") == 0)
01248               {
01249                      sent_gpgerrtxt();
01250               }
01251               else if (strcmp(kw, "GPGERRRESUME") == 0)
01252               {
01253                      sent_gpgerrresume();
01254               }
01255 #ifdef ISPELL
01256               else if (strcmp(kw, "K") == 0)
01257               {
01258                      spell_show();
01259               }
01260 #endif
01261 #ifdef BANNERPROG
01262               else if (strcmp(kw, "B") == 0)
01263               {
01264                      char banargbuf[31];
01265                      int    i=0;
01266                      int    wait_stat;
01267                      pid_t  p, p2;
01268 
01269                             if ((c=getc(f)) != '{')
01270                                    ungetc(c, f);
01271                             else   while ((c=getc(f)), isalnum(c))
01272                                           if (i < sizeof(banargbuf)-1)
01273                                                  banargbuf[i++]=c;
01274                             banargbuf[i]=0;
01275                             fflush(stdout);
01276 
01277                             if ( (p=fork()) == 0 )
01278                             {
01279                                    execl(BANNERPROG, BANNERPROG,
01280                                           sqwebmail_formname,
01281                                           banargbuf, (char *)0);
01282                                    _exit(0);
01283                             }
01284                             if (p > 0)
01285                             {
01286                                    while ((p2=wait(&wait_stat)) > 0 &&
01287                                           p2 != p)
01288                                           ;
01289                             }
01290               }
01291 #endif
01292               else if (strcmp(kw, "h") == 0)
01293               {
01294                      FILE *fp=fopen(LOGINDOMAINLIST, "r");
01295 
01296                      if (fp) {
01297                             /* parse LOGINDOMAINLIST and print proper output */
01298                             print_logindomainlist(fp);
01299                             fclose(fp);
01300                      }
01301               }
01302               else if (strcmp(kw, "o") == 0)
01303               {
01304                      ldaplist();
01305               }
01306               else if (strcmp(kw, "O") == 0)
01307               {
01308                      doldapsearch();
01309               }
01310               else if (strcmp(kw, "IMAGEURL") == 0)
01311               {
01312                      printf("%s", get_imageurl());
01313               }                    
01314               else if (strcmp(kw, "LOADMAILFILTER") == 0)
01315               {
01316                      mailfilter_init();
01317               }
01318               else if (strcmp(kw, "MAILFILTERLIST") == 0)
01319               {
01320                      mailfilter_list();
01321               }
01322               else if (strcmp(kw, "MAILFILTERLISTFOLDERS") == 0)
01323               {
01324                      mailfilter_listfolders();
01325               }
01326               else if (strcmp(kw, "QUOTA") == 0)
01327               {
01328                      folder_showquota();
01329               }
01330               else if (strcmp(kw, "NICKLIST") == 0)
01331               {
01332                       ab_listselect();
01333               }
01334               else if (strcmp(kw, "LISTPUB") == 0)
01335               {
01336                      gpglistpub();
01337               }
01338               else if (strcmp(kw, "LISTSEC") == 0)
01339               {
01340                      gpglistsec();
01341               }
01342               else if (strcmp(kw, "KEYIMPORT") == 0)
01343               {
01344                      folder_keyimport(sqwebmail_folder, atol(cgi("pos")));
01345               }
01346               else if (strcmp(kw, "GPGCREATE") == 0)
01347               {
01348                      gpgcreate();
01349               }
01350               else if (strcmp(kw, "DOGPG") == 0)
01351               {
01352                      gpgdo();
01353               }
01354               else if (strcmp(kw, "ATTACHPUB") == 0)
01355               {
01356                      gpgselectpubkey();
01357               }
01358               else if (strcmp(kw, "ATTACHSEC") == 0)
01359               {
01360                      gpgselectprivkey();
01361               }
01362               else if (strcmp(kw, "MAILINGLISTS") == 0)
01363               {
01364                      char *p=getmailinglists();
01365 
01366                      /* <sigh> amaya inserts a bunch of spaces that mess
01367                      ** things up in Netscape.
01368                      */
01369 
01370                      output_attrencoded(p ? p:"");
01371                      if (p)
01372                             free(p);
01373               }
01374               else if (strcmp(kw, "AUTORESPONSE") == 0)
01375               {
01376                      autoresponse();
01377               }
01378               else if (strcmp(kw, "AUTORESPONSE_LIST") == 0)
01379               {
01380                      autoresponselist();
01381               }
01382               else if (strcmp(kw, "AUTORESPONSE_PICK") == 0)
01383               {
01384                      autoresponsepick();
01385               }
01386               else if (strcmp(kw, "AUTORESPONSE_DELETE") == 0)
01387               {
01388                      autoresponsedelete();
01389               }
01390               else if (strcmp(kw, "SQWEBMAILCSS") == 0)
01391               {
01392                      printf("%s/sqwebmail.css", get_imageurl());
01393               }
01394               else if (strcmp(kw, "timezonelist") == 0)
01395               {
01396                      timezonelist();
01397               }
01398               else if (strcmp(kw, "PREFWEEK") == 0)
01399               {
01400                      pref_displayweekstart();
01401               }
01402               else if (strcmp(kw, "NEWEVENT") == 0)
01403               {
01404                      sqpcp_newevent();
01405               }
01406               else if (strcmp(kw, "RECURRING") == 0)
01407               {
01408                      printf("%s", getarg("RECURRING"));
01409               }
01410               else if (strcmp(kw, "EVENTSTART") == 0)
01411               {
01412                      sqpcp_eventstart();
01413               }
01414               else if (strcmp(kw, "EVENTEND") == 0)
01415               {
01416                      sqpcp_eventend();
01417               }
01418               else if (strcmp(kw, "EVENTFROM") == 0)
01419               {
01420                      sqpcp_eventfrom();
01421               }
01422               else if (strcmp(kw, "EVENTTIMES") == 0)
01423               {
01424                      sqpcp_eventtimes();
01425               }
01426               else if (strcmp(kw, "EVENTPARTICIPANTS") == 0)
01427               {
01428                      sqpcp_eventparticipants();
01429               }
01430               else if (strcmp(kw, "EVENTTEXT") == 0)
01431               {
01432                      sqpcp_eventtext();
01433               }
01434               else if (strcmp(kw, "EVENTATTACH") == 0)
01435               {
01436                      sqpcp_eventattach();
01437               }
01438               else if (strcmp(kw, "EVENTSUMMARY") == 0)
01439               {
01440                      sqpcp_summary();
01441               }
01442               else if (strcmp(kw, "CALENDARTODAY") == 0)
01443               {
01444                      sqpcp_todays_date();
01445               }
01446               else if (strcmp(kw, "CALENDARWEEKLYLINK") == 0)
01447               {
01448                      sqpcp_weeklylink();
01449               }
01450               else if (strcmp(kw, "CALENDARMONTHLYLINK") == 0)
01451               {
01452                      sqpcp_monthlylink();
01453               }
01454               else if (strcmp(kw, "CALENDARTODAYV") == 0)
01455               {
01456                      sqpcp_todays_date_verbose();
01457               }
01458               else if (strcmp(kw, "CALENDARDAYVIEW") == 0)
01459               {
01460                      sqpcp_daily_view();
01461               }
01462               else if (strcmp(kw, "CALENDARPREVDAY") == 0)
01463               {
01464                      sqpcp_prevday();
01465               }
01466               else if (strcmp(kw, "CALENDARNEXTDAY") == 0)
01467               {
01468                      sqpcp_nextday();
01469               }
01470               else if (strcmp(kw, "CALENDARWEEK") == 0)
01471               {
01472                      sqpcp_show_cal_week();
01473               }
01474               else if (strcmp(kw, "CALENDARNEXTWEEK") == 0)
01475               {
01476                      sqpcp_show_cal_nextweek();
01477               }
01478               else if (strcmp(kw, "CALENDARPREVWEEK") == 0)
01479               {
01480                      sqpcp_show_cal_prevweek();
01481               }
01482               else if (strcmp(kw, "CALENDARWEEKVIEW") == 0)
01483               {
01484                      sqpcp_displayweek();
01485               }
01486               else if (strcmp(kw, "CALENDARMONTH") == 0)
01487               {
01488                      sqpcp_show_cal_month();
01489               }
01490               else if (strcmp(kw, "CALENDARNEXTMONTH") == 0)
01491               {
01492                      sqpcp_show_cal_nextmonth();
01493               }
01494               else if (strcmp(kw, "CALENDARPREVMONTH") == 0)
01495               {
01496                      sqpcp_show_cal_prevmonth();
01497               }
01498               else if (strcmp(kw, "CALENDARMONTHVIEW") == 0)
01499               {
01500                      sqpcp_displaymonth();
01501               }
01502               else if (strcmp(kw, "EVENTDISPLAYINIT") == 0)
01503               {
01504                      sqpcp_displayeventinit();
01505               }
01506               else if (strcmp(kw, "EVENTDELETEINIT") == 0)
01507               {
01508                      sqpcp_deleteeventinit();
01509               }
01510               else if (strcmp(kw, "EVENTDISPLAY") == 0)
01511               {
01512                      sqpcp_displayevent();
01513               }
01514               else if (strcmp(kw, "EVENTBACKLINK") == 0)
01515               {
01516                      sqpcp_eventbacklink();
01517               }
01518               else if (strcmp(kw, "EVENTEDITLINK") == 0)
01519               {
01520                      sqpcp_eventeditlink();
01521               }
01522               else if (strcmp(kw, "EVENTCANCELUNCANCELLINK") == 0)
01523               {
01524                      sqpcp_eventcanceluncancellink();
01525               }
01526               else if (strcmp(kw, "EVENTCANCELUNCANCELLINK") == 0)
01527               {
01528                      sqpcp_eventcanceluncancellink();
01529               }
01530               else if (strcmp(kw, "EVENTCANCELUNCANCELIMAGE") == 0)
01531               {
01532                      sqpcp_eventcanceluncancelimage();
01533               }
01534               else if (strcmp(kw, "EVENTCANCELUNCANCELTEXT") == 0)
01535               {
01536                      sqpcp_eventcanceluncanceltext();
01537               }
01538               else if (strcmp(kw, "EVENTDELETELINK") == 0)
01539               {
01540                      sqpcp_eventdeletelink();
01541               }
01542               else if (strcmp(kw, "EVENTACL") == 0)
01543               {
01544                      sqpcp_eventacl();
01545               }
01546               else if (strcmp(kw, "ABOOKNAMELIST") == 0)
01547               {
01548                      ab_addrselect();
01549               }
01550               else if (strcmp(kw, "LISTRIGHTS") == 0)
01551                      listrights();
01552               else if (strcmp(kw, "GETACL") == 0)
01553                      getacl();
01554               else if (strcmp(kw, "MSGPOS") == 0)
01555               {
01556                      printf("%ld", atol(cgi("pos"))+1);
01557               }
01558               else if (strncmp(kw, "radio:", 6) == 0)
01559               {
01560               const char *name=strtok(kw+6, ":");
01561               const char *value=strtok(0, ":");
01562 
01563                      if (name && value)
01564                      {
01565                             printf("<input type=\"radio\" name=\"%s\""
01566                                    " value=\"%s\"",
01567                                    name, value);
01568                             if ( strcmp(cgi(name), value) == 0)
01569                                    printf(" checked=\"checked\"");
01570                             printf(" />");
01571                      }
01572               }
01573               else if (strncmp(kw, "checkbox:", 9) == 0)
01574               {
01575               const char *name=strtok(kw+9, ":");
01576               const char *cgivar=strtok(0, ":");
01577 
01578                      if (name && cgivar)
01579                      {
01580                             printf("<input type=\"checkbox\" name=\"%s\""
01581                                    "%s />",
01582                                    name,
01583                                    *cgi(cgivar) ? " checked=\"checked\"":"");
01584                      }
01585               }
01586               else if (strncmp(kw, "input:", 6) == 0)
01587               {
01588                      output_attrencoded(cgi(kw+6));
01589               }
01590               else if (strncmp(kw, "select:", 7) == 0)
01591               {
01592               const char *name=strtok(kw+7, ":");
01593               const char *class=strtok(0, ":");
01594               const char *size=strtok(0, ":");
01595 
01596                      printf("<select name=\"%s\"", name ? name:"");
01597                      if (class)    printf(" class=\"%s\"", class);
01598                      if (size)     printf(" size=\"%s\"", size);
01599                      printf(">");
01600               }
01601               else if (strncmp(kw, "option:", 7) == 0)
01602               {
01603               const char *name=strtok(kw+7, ":");
01604               const char *cgivar=strtok(0, ":");
01605               const char *cgival=strtok(0, ":");
01606 
01607                      printf("<option value=\"%s\"", name ? name:"");
01608                      if (cgivar && cgival &&
01609                             strcmp(cgi(cgivar), cgival) == 0)
01610                             printf(" selected='selected'");
01611                      printf(">");
01612               }
01613               else if (strcmp(kw, "endoption") == 0)
01614                      printf("</option>");
01615               else if (strcmp(kw, "endselect") == 0)
01616                      printf("</select>");
01617               else if (strncmp(kw, "env:", 4) == 0) {
01618                      const char *val = getenv(kw+4);
01619                      if (val) output_attrencoded(val);
01620               }
01621               else if (strncmp(kw, "include:", 8) == 0)
01622               {
01623                      insert_include(kw+8);
01624               }
01625               else if (strcmp(kw, "endinclude") == 0)
01626               {
01627                      break;
01628               }
01629        }
01630 }
01631 
01632 /* Include another template file */
01633 
01634 static FILE *openinclude(const char *p)
01635 {
01636        char buffer[BUFSIZ];
01637        FILE *f;
01638 
01639        buffer[0]=0;
01640        strncat(buffer, p, 100);
01641        strcat(buffer, ".inc.html");
01642 
01643        f=do_open_form(buffer, 0);
01644 
01645        if (!f)
01646               error("Can't open form template.");
01647 
01648        while (fgets(buffer, sizeof(buffer), f))
01649        {
01650               const char *p=strchr(buffer, '[');
01651 
01652               if (!p)
01653                      continue;
01654 
01655               if (strncmp(p, "[#begininclude#]", 16) == 0)
01656               {
01657                      break;
01658               }
01659        }
01660        return (f);
01661 }
01662 
01663 
01664 /* Top level HTTP redirect without referencing a particular mailbox */
01665 
01666 static void http_redirect_top(const char *app)
01667 {
01668 const  char *p=nonloginscriptptr();
01669 char   *buf=malloc(strlen(p)+strlen(app)+2);
01670 
01671        if (!buf)     enomem();
01672        strcat(strcpy(buf, p), app);
01673        cgiredirect(buf);
01674        free(buf);
01675 }
01676 
01677 /* HTTP redirects within a given mailbox, various formats */
01678 
01679 void http_redirect_argu(const char *fmt, unsigned long un)
01680 {
01681 char   buf[MAXLONGSIZE];
01682 
01683        sprintf(buf, "%lu", un);
01684        http_redirect_argss(fmt, buf, "");
01685 }
01686 
01687 void http_redirect_argss(const char *fmt, const char *arg1, const char *arg2)
01688 {
01689        http_redirect_argsss(fmt, arg1, arg2, "");
01690 }
01691 
01692 void http_redirect_argsss(const char *fmt, const char *arg1, const char *arg2,
01693        const char *arg3)
01694 {
01695 char *base=scriptptrget();
01696 char *arg1s=cgiurlencode(arg1);
01697 char *arg2s=cgiurlencode(arg2);
01698 char *arg3s=cgiurlencode(arg3);
01699 char *q;
01700 
01701        /* We generate a Location: redirected_url header.  The actual
01702        ** header is generated in cgiredirect, we just build it here */
01703 
01704        q=malloc(strlen(base)+strlen(fmt)+strlen(arg1s)+strlen(arg2s)+
01705                      strlen(arg3s)+1);
01706        if (!q)       enomem();
01707        strcpy(q, base);
01708        sprintf(q+strlen(q), fmt, arg1s, arg2s, arg3s);
01709        cgiredirect(q);
01710        free(q);
01711        free(arg1s);
01712        free(arg2s);
01713        free(arg3s);
01714        free(base);
01715 }
01716 
01717 void output_user_form(const char *formname)
01718 {
01719 char   *p;
01720 
01721        if (!*formname || strchr(formname, '.') || strchr(formname, '/'))
01722               error("Invalid request.");
01723 
01724        if ((strcmp(formname, "filter") == 0
01725             || strcmp(formname, "autoresponse") == 0)
01726            && maildir_filter_hasmaildirfilter("."))
01727               /* Script kiddies... */
01728               formname="nofilter";
01729 
01730        if (strcmp(formname, "filter") == 0 && *cgi("do.submitfilter"))
01731               mailfilter_submit();
01732 
01733        if (strcmp(formname, "gpg") == 0 && libmail_gpg_has_gpg(GPGDIR))
01734               error("Invalid request.");
01735 
01736        if (strcmp(formname, "gpgcreate") == 0 && libmail_gpg_has_gpg(GPGDIR))
01737               error("Invalid request.");
01738 
01739        if (*cgi("ldapsearch"))     /* Special voodoo for LDAP address book stuff */
01740        {
01741               if (ldapsearch() == 0)
01742               {
01743                      output_form("ldapsearch.html");
01744                      return;
01745               }
01746        }
01747 
01748        /*
01749        ** In order to hide the session ID in the URL of the message what
01750        ** we do is that the initial URL, that contains setcookie=1, results
01751        ** in us setting a temporary cookie that contains the session ID,
01752        ** then we return a redirect to a url which has /printmsg/ in the
01753        ** PATH_INFO, instead of the session ID.  The code in main()
01754        ** traps /printmsg/ PATH_INFO, fetches the path info from the
01755        ** cookie, and punts after resetting setcookie to 0.
01756        */
01757 
01758        if (strcmp(formname, "print") == 0 && *cgi("setcookie") == '1')
01759        {
01760        const char *qs=getenv("QUERY_STRING");
01761        const char *pi=getenv("PATH_INFO");
01762        const char *nl;
01763        char   *buf;
01764 
01765               if (!pi)      pi="";
01766               if (!pi)      pi="";
01767 
01768               nl=nonloginscriptptr();
01769 
01770               buf=malloc(strlen(nl) + sizeof("/printmsg/print?")+strlen(qs));
01771               if (!buf)     enomem();
01772               strcat(strcat(strcpy(buf, nl), "/printmsg/print?"), qs);
01773               cginocache();
01774               cgi_setcookie("sqwebmail-pi", pi);
01775               printf("Refresh: 0; URL=%s\n", buf);
01776               free(buf);
01777               output_form("printredirect.html");
01778               return;
01779        }
01780 
01781        if (strcmp(cgi("fromscreen"), "mailfilter") == 0)
01782               maildir_filter_endmaildirfilter(".");     /* Remove the temp file */
01783 
01784        if (strcmp(formname, "logout") == 0)
01785        {
01786               unlink(IPFILE);
01787               http_redirect_top("");
01788               return;
01789        }
01790 
01791        if (strcmp(formname, "fetch") == 0)
01792        {
01793               folder_download( sqwebmail_folder, atol(cgi("pos")),
01794                      cgi("mimeid") );
01795               return;
01796        }
01797 
01798        if (strcmp(formname, "delmsg") == 0)
01799        {
01800               folder_delmsg( atol(cgi("pos")));
01801               return;
01802        }
01803 
01804        if (strcmp(formname, "donewmsg") == 0)
01805        {
01806               newmsg_do(sqwebmail_folder);
01807               return;
01808        }
01809 
01810        if (strcmp(formname, "doattach") == 0)
01811        {
01812               doattach(sqwebmail_folder, cgi("draft"));
01813               return;
01814        }
01815 
01816        if (strcmp(formname, "folderdel") == 0)
01817        {
01818               folder_delmsgs(sqwebmail_folder, atol(cgi("pos")));
01819               return;
01820        }
01821        if (strcmp(formname, "spellchk") == 0)
01822        {
01823 #ifdef ISPELL
01824               spell_check_continue();
01825 #else
01826               printf("Status: 404");
01827 #endif
01828               return;
01829        }
01830 
01831        if (sqpcp_loggedin())
01832        {
01833               if (*cgi("do.neweventpreview"))
01834               {
01835                      sqpcp_preview();
01836                      return;
01837               }
01838 
01839               if (*cgi("do.neweventsave"))
01840               {
01841                      sqpcp_save();
01842                      return;
01843               }
01844 
01845               if (*cgi("do.neweventpostpone"))
01846               {
01847                      sqpcp_postpone();
01848                      return;
01849               }
01850 
01851               if (*cgi("do.neweventdeleteattach"))
01852               {
01853                      sqpcp_deleteattach();
01854                      return;
01855               }
01856 
01857               if (*cgi("do.neweventupload"))
01858               {
01859                      sqpcp_uploadattach();
01860                      return;
01861               }
01862 
01863               if (*cgi("do.neweventuppubkey"))
01864               {
01865                      sqpcp_attachpubkey();
01866                      return;
01867               }
01868 
01869               if (*cgi("do.neweventupprivkey"))
01870               {
01871                      sqpcp_attachprivkey();
01872                      return;
01873               }
01874               if (*cgi("do.eventdelete"))
01875               {
01876                      sqpcp_dodelete();
01877                      return;
01878               }
01879        }
01880 
01881        if (strcmp(formname, "event-edit") == 0)
01882        {
01883               formname="folders";
01884               if (sqpcp_loggedin())
01885               {
01886                      formname="eventshow";       /* default */
01887                      if (sqpcp_eventedit() == 0)
01888                             formname="newevent";
01889               }
01890        }
01891 
01892 
01893        if (strcmp(formname, "open-draft") == 0)
01894        {
01895               formname="newmsg";
01896               if (sqpcp_has_calendar())
01897                      /* DRAFTS may contain event files */
01898               {
01899                      const char *n=cgi("draft");
01900                      char *filename;
01901                      FILE *fp;
01902 
01903                      CHECKFILENAME(n);
01904 
01905                      filename=maildir_find(INBOX "." DRAFTS, n);
01906 
01907                      if (filename)
01908                      {
01909                             if ((fp=fopen(filename, "r")) != NULL)
01910                             {
01911                                    struct rfc822hdr h;
01912 
01913                                    rfc822hdr_init(&h, 8192);
01914 
01915                                    while (rfc822hdr_read(&h, fp, NULL, 0)
01916                                           == 0)
01917                                    {
01918                                           if (strcasecmp(h.header,
01919                                                         "X-Event") == 0)
01920                                           {
01921                                                  formname="newevent";
01922                                                  cgi_put("draftmessage",
01923                                                         cgi("draft"));
01924                                                  break;
01925                                           }
01926                                    }
01927                                    rfc822hdr_free(&h);
01928                                    fclose(fp);
01929                             }
01930                             free(filename);
01931                      }
01932               }
01933        }
01934 
01935        if (strcmp(formname, "newevent") == 0 ||
01936            strcmp(formname, "eventdaily") == 0 ||
01937            strcmp(formname, "eventweekly") == 0 ||
01938            strcmp(formname, "eventmonthly") == 0 ||
01939            strcmp(formname, "eventshow") == 0 ||
01940            strcmp(formname, "eventacl") == 0)
01941        {
01942               if (!sqpcp_has_calendar() ||
01943                   !sqpcp_loggedin())
01944                      formname="folders";  /* Naughty boy */
01945        }
01946 
01947        if (*cgi("do.search"))
01948        {
01949               folder_search(sqwebmail_folder, atol(cgi("pos")));
01950               return;
01951        }
01952        p=malloc(strlen(formname)+6);
01953        if (!p)       enomem();
01954 
01955        strcat(strcpy(p, formname),".html");
01956        output_form(p);
01957        free(p);
01958 }
01959 
01960 
01961 extern void folder_cleanup();
01962 extern void maildir_cleanup();
01963 extern void mailfilter_cleanup();
01964 
01965 #ifdef ISPELL
01966 extern void ispell_cleanup();
01967 #endif
01968 
01969 void cleanup()
01970 {
01971        sqwebmail_formname = NULL;
01972        sqwebmail_mailboxid=0;
01973        sqwebmail_folder=0;
01974        sqwebmail_sessiontoken=0;
01975        sqwebmail_content_language=0;
01976        sqwebmail_content_locale=0;
01977        sqwebmail_system_charset=0;
01978        if (sys_locale_charset)
01979               free(sys_locale_charset);
01980        sys_locale_charset=0;
01981        sqwebmail_content_ispelldict=0;
01982        folder_cleanup();
01983        maildir_cleanup();
01984        mailfilter_cleanup();
01985 #ifdef ISPELL
01986        ispell_cleanup();
01987 #endif
01988 
01989 #ifdef GZIP
01990        if (gzip_save_fd >= 0)      /* Restore original stdout */
01991        {
01992               dup2(gzip_save_fd, 1);
01993               close(gzip_save_fd);
01994               gzip_save_fd= -1;
01995        }
01996 #endif
01997 
01998        libmail_gpg_cleanup();
01999        freeargs();
02000        sqpcp_close();
02001 }
02002 
02003 
02004 
02005 static RETSIGTYPE catch_sig(int n)
02006 {
02007        n=n;
02008        cleanup();
02009        maildir_cache_cancel();
02010        exit(0);
02011 }
02012 
02013 static void setlang()
02014 {
02015        static char *lang_buf=0;
02016        char *p;
02017 
02018        if (sqwebmail_content_locale && *sqwebmail_content_locale
02019            && (p=malloc(sizeof("LANG=")+strlen(sqwebmail_content_locale)))!=0)
02020        {
02021               strcat(strcpy(p, "LANG="), sqwebmail_content_locale);
02022               putenv(p);
02023               if (lang_buf)
02024                      free(lang_buf);
02025               lang_buf=p;
02026        }
02027 }
02028 
02029 static void init_default_locale()
02030 {
02031 char   *templatedir=get_templatedir();
02032 char   *cl=http11_best_content_language(templatedir,
02033                      getenv("HTTP_ACCEPT_LANGUAGE"));
02034 
02035        sqwebmail_content_language=
02036                             http11_content_language(templatedir, cl);
02037        sqwebmail_content_locale=
02038                      http11_content_locale(templatedir, cl);
02039        sqwebmail_content_ispelldict=
02040                      http11_content_ispelldict(templatedir, cl);
02041        sqwebmail_content_charset=
02042                      http11_content_charset(templatedir, cl);
02043 
02044        free(cl);
02045 #if    HAVE_LOCALE_H
02046 #if    HAVE_SETLOCALE
02047        setlocale(LC_ALL, sqwebmail_content_locale);
02048 #if    USE_LIBCHARSET
02049        setlocale(LC_CTYPE, sqwebmail_content_locale);
02050        sqwebmail_system_charset = locale_charset();
02051 #elif  HAVE_LANGINFO_CODESET
02052        setlocale(LC_CTYPE, sqwebmail_content_locale);
02053        sqwebmail_system_charset = sys_locale_charset=strdup(nl_langinfo(CODESET));
02054 #else
02055        sqwebmail_system_charset = NULL;
02056 #endif /* USE_LIBCHARSET */
02057        setlocale(LC_CTYPE, "C");
02058        setlang();
02059 #endif
02060 #endif
02061 }
02062 
02063 void rename_sent_folder(int really)
02064 {
02065        char buf[128];
02066        char yyyymm[128];
02067        const char *yyyymmp;
02068 
02069        time_t t;
02070        struct tm *tm;
02071        char *pp;
02072 
02073        if (really)
02074               (void)maildir_create(INBOX "." SENT); /* No matter what */
02075 
02076        time(&t);
02077        tm=localtime(&t);
02078        if (!tm)
02079               return;
02080 
02081        if (tm->tm_mon == 0)
02082        {
02083               tm->tm_mon=11;
02084               --tm->tm_year;
02085        }
02086        else
02087               --tm->tm_mon;
02088 
02089        if (strftime (yyyymm, sizeof(yyyymm), "%Y%m", tm) == 0)
02090               return;
02091 
02092        if ((yyyymmp=read_sqconfig(".", SENTSTAMP, NULL)) != NULL &&
02093            strcmp(yyyymm, yyyymmp) == 0)
02094               return;
02095 
02096        if (strftime (buf, sizeof(buf), "." SENT ".%Y.%m-%b", tm) == 0)
02097               return;
02098 
02099        pp=folder_toutf7(buf);
02100 
02101        if (really)
02102               rename("." SENT, pp);
02103        free(pp);
02104        if (really)
02105               (void)maildir_create(INBOX "." SENT);
02106 
02107        write_sqconfig(".", SENTSTAMP, yyyymm);
02108 }
02109 
02110 static int valid_redirect();
02111 
02112 static void redirect(const char *url)
02113 {
02114        if (valid_redirect())
02115        {
02116               printf("Refresh: 0; URL=%s\n", url);
02117               output_form("redirect.html");
02118               return;
02119        }
02120 
02121        printf("Content-Type: text/plain\n\n"
02122               "The URL you clicked on is no longer valid.\n");
02123        return;
02124 }
02125 
02126 static int valid_redirect()
02127 {
02128        const char *timestamp=cgi("timestamp"), *p;
02129        unsigned long timestamp_n;
02130        time_t timestamp_t;
02131        time_t now;
02132 
02133        if (sscanf(timestamp, "%lu", &timestamp_n) != 1)
02134               return 0;
02135 
02136        timestamp_t=(time_t)timestamp_n;
02137        time(&now);
02138 
02139        if (now < timestamp_t || now > timestamp_t + get_timeouthard())
02140               return 0;
02141 
02142        p=redirect_hash(timestamp);
02143 
02144        if (*p == 0 || strcmp(cgi("md5"), p))
02145               return 0;
02146        return 1;
02147 }
02148 
02149 static void main2();
02150 
02151 static void usage()
02152 {
02153        fprintf(stderr, "sqwebmaild does not accept command arguments.\n"
02154               "Use sqwebmaild.rc script to start sqwebmaild as a daemon.\n");
02155        exit(1);
02156 }
02157 
02158 static void call_main2(void *dummy)
02159 {
02160        main2();
02161        cleanup();
02162 }
02163 
02164 int main(int argc, char **argv)
02165 {
02166        const char *prefork;
02167        int n;
02168 
02169 #if 0
02170        if (getenv("SQWEBMAIL_DEBUG"))
02171        {
02172               main2();
02173               return (0);
02174        }
02175 #endif
02176 
02177        courier_authdebug_login_init();
02178 
02179        if (argc > 1)
02180               usage();
02181 
02182        prefork=getenv("SQWEBMAIL_PREFORK");
02183 
02184        n=prefork ? atoi(prefork):5;
02185 
02186        cgi_daemon(n, SOCKFILENAME, NULL, call_main2, NULL);
02187 
02188        return (0);
02189 }
02190 
02191 static int setuidgid(uid_t u, gid_t g, const char *dir, void *dummy)
02192 {
02193        if (setgid(g) || setuid(u))
02194        {
02195               fprintf(stderr,
02196                      "CRIT: Cache - can't setuid/setgid to %u/%u\n",
02197                      (unsigned)u, (unsigned)g);
02198               return (-1);
02199        }
02200 
02201        if (chdir(dir))
02202        {
02203               fprintf(stderr,
02204                      "CRIT: Cache - can't chdir to %s: %s\n", dir, strerror(errno));
02205               return (-1);
02206        }
02207        return (0);
02208 }
02209 
02210 static void main2()
02211 {
02212 const char    *u;
02213 const char    *ip_addr;
02214 char   *pi;
02215 char   *pi_malloced;
02216 int    reset_cookie=0;
02217 time_t timeouthard=get_timeouthard();
02218 
02219 
02220 #ifdef GZIP
02221        gzip_save_fd= -1;
02222 #endif
02223        u=ip_addr=pi=NULL;
02224 
02225        ip_addr=getenv("REMOTE_ADDR");
02226 
02227 #if 0
02228        {
02229               FILE *f;
02230 
02231               f=fopen("/tmp/pid", "w");
02232               fprintf(f, "%d\n", (int)getpid());
02233               fclose(f);
02234               sleep(10);
02235        }
02236 #endif
02237 
02238        /*
02239         * Note: if we get a signal during FastCGI processing, this means
02240         * means we need to terminate so that the webserver can respawn us.
02241         * Exception is SIGPIPE which we just ignore (this is what we get
02242         * if we try to write data to a client which goes away before
02243         * we finished sending them the reply)
02244         */
02245 
02246        signal(SIGHUP, catch_sig);
02247        signal(SIGINT, catch_sig);
02248        signal(SIGPIPE, catch_sig);
02249        signal(SIGTERM, catch_sig);
02250 
02251        if (!ip_addr) ip_addr="127.0.0.1";
02252 
02253        umask(0077);
02254 
02255        {
02256               timeouthard=get_timeouthard();
02257        }
02258 
02259        if (maildir_cache_init(timeouthard, CACHEDIR, CACHEOWNER, authvars))
02260        {
02261               printf("Content-Type: text/plain\n\nmaildir_cache_init() failed\n");
02262               fake_exit(0);
02263        }
02264 
02265        pi=getenv("PATH_INFO");
02266 
02267        pi_malloced=0;
02268        sqpcp_init();
02269 
02270        if (pi && strncmp(pi, "/printmsg/", 10) == 0)
02271        {
02272               /* See comment in output_user_form */
02273 
02274               pi_malloced=pi=cgi_cookie("sqwebmail-pi");
02275               if (*pi_malloced == 0)
02276               {
02277                      free(pi_malloced);
02278                      setgid(getgid());
02279                      setuid(getuid());
02280                      output_form("printnocookie.html");
02281                      return;
02282               }
02283               reset_cookie=1;
02284               cgi_setcookie("sqwebmail-pi", "DELETED");
02285        }
02286 
02287        if (pi && strncmp(pi, "/login/", 7) == 0)
02288        {
02289        const char    *p;
02290        time_t last_time, current_time;
02291        char   *q;
02292        time_t timeoutsoft=get_timeoutsoft();
02293 
02294               /* Logging into the mailbox */
02295 
02296               pi=strdup(pi);
02297               if (pi_malloced)     free(pi_malloced);
02298 
02299               if (!pi)      enomem();
02300 
02301               (void)strtok(pi, "/");      /* Skip login */
02302               u=strtok(NULL, "/"); /* mailboxid */
02303               sqwebmail_sessiontoken=strtok(NULL, "/"); /* sessiontoken */
02304               q=strtok(NULL, "/"); /* login time */
02305               login_time=0;
02306               while (q && *q >= '0' && *q <= '9')
02307                      login_time=login_time * 10 + (*q++ - '0');
02308 
02309               if (maildir_cache_search(u, login_time, setuidgid, NULL)
02310                   && prelogin(u))
02311               {
02312                      free(pi);
02313                      error("Unable to access your mailbox, sqwebmail permissions may be wrong.");
02314               }
02315 
02316               time(&current_time);
02317 
02318               /* Ok, boys and girls, time to validate the connection as
02319               ** follows */
02320 
02321               if (   !sqwebmail_sessiontoken
02322 
02323               /* 1. Read IPFILE.  Check that it's timestamp is current enough,
02324               ** and the session hasn't timed out.
02325               */
02326 
02327                      || !(p=read_sqconfig(".", IPFILE, &last_time))
02328 
02329 /*                   || last_time > current_time */
02330 
02331                      || last_time + timeouthard < current_time
02332 
02333               /* 2. IPFILE will contain seven words - IP address, session
02334               ** token, language, locale, ispell dictionary,
02335               ** timezone, charset.  Validate both.
02336               */
02337                      || !(q=strdup(p))
02338                      || !(p=strtok(q, " "))
02339                      || (strcmp(p, ip_addr) && strcmp(p, "none"))
02340                      || !(p=strtok(NULL, " "))
02341                      || strcmp(p, sqwebmail_sessiontoken)
02342                      || !(p=strtok(NULL, " "))
02343                      || !(sqwebmail_content_language=strdup(p))
02344                      || !(p=strtok(NULL, " "))
02345                      || !(sqwebmail_content_locale=strdup(p))
02346                      || !(p=strtok(NULL, " "))
02347                      || !(sqwebmail_content_ispelldict=strdup(p))
02348                      || !(p=strtok(NULL, " "))
02349                      || set_timezone(p)
02350                      || !(p=strtok(NULL, " "))
02351                      || !(sqwebmail_content_charset=strdup(p))
02352 
02353               /* 3. Check the timestamp on the TIMESTAMP file.  See if the
02354               ** session has reached its soft timeout.
02355               */
02356 
02357                      || !read_sqconfig(".", TIMESTAMP, &last_time)
02358 
02359 /*                   || last_time > current_time */
02360 
02361                      || last_time + timeoutsoft < current_time)
02362               {
02363                      setgid(getgid());
02364                      setuid(getuid());    /* Drop root prevs */
02365                      if (chdir("/") < 0)
02366                      {
02367                             output_form("expired.html");
02368                             return;
02369                      }
02370                      cgi_setup();
02371                      init_default_locale();
02372                      free(pi);
02373 
02374                      u=getenv("SQWEBMAIL_SHAREDMUNGENAMES");
02375 
02376                      maildir_info_munge_complex(u && *u);
02377 
02378                      if (strcmp(cgi("form"), "logout") == 0)
02379                             /* Already logged out, and the link
02380                             ** had target=_parent tag.
02381                             */
02382                      {
02383                             http_redirect_top("");
02384                             return;
02385                      }
02386                      output_form("expired.html");
02387                      return;
02388               }
02389               free(q);
02390               cgiformdatatempdir("tmp");
02391               cgi_setup();  /* Read CGI environment */
02392               if (reset_cookie)
02393                      cgi_put("setcookie", "0");
02394 
02395               /* Update soft timeout stamp */
02396 
02397               write_sqconfig(".", TIMESTAMP, "");
02398 
02399               /* We must always have the folder CGI arg */
02400 
02401               if (!*(sqwebmail_folder=cgi("folder")))
02402               {
02403                      init_default_locale();
02404                      output_form("expired.html");
02405                      free(pi);
02406                      return;
02407               }
02408 
02409               sqwebmail_mailboxid=u;
02410 
02411               {
02412                      struct stat stat_buf;
02413 
02414                      if (stat(".", &stat_buf) < 0)
02415                      {
02416                             output_form("expired.html");
02417                             free(pi);
02418                             return;
02419                      }
02420 
02421                      sqwebmail_homedir_dev=stat_buf.st_dev;
02422                      sqwebmail_homedir_ino=stat_buf.st_ino;
02423               }
02424 
02425 #if    HAVE_LOCALE_H
02426 #if    HAVE_SETLOCALE
02427               setlocale(LC_ALL, sqwebmail_content_locale);
02428 #if    USE_LIBCHARSET
02429               setlocale(LC_CTYPE, sqwebmail_content_locale);
02430               sqwebmail_system_charset = locale_charset();
02431 #elif  HAVE_LANGINFO_CODESET
02432               setlocale(LC_CTYPE, sqwebmail_content_locale);
02433               sqwebmail_system_charset = sys_locale_charset
02434                      = strdup(nl_langinfo(CODESET));
02435 #else
02436               sqwebmail_system_charset = NULL;
02437 #endif  /* USE_LIBCHARSET */
02438               setlocale(LC_CTYPE, "C");
02439               setlang();
02440 #endif
02441 #endif
02442               CHECKFILENAME(sqwebmail_folder);
02443 
02444               strcpy(sqwebmail_folder_rights, ALL_RIGHTS);
02445               acl_computeRightsOnFolder(sqwebmail_folder,
02446                                      sqwebmail_folder_rights);
02447 
02448               pref_init();
02449               (void)sqpcp_loggedin();
02450               if (auth_getoptionenvint("disableshared"))
02451               {
02452                      maildir_acl_disabled=1;
02453                      maildir_newshared_disabled=1;
02454               }
02455 
02456               if (strcmp(cgi("form"), "empty"))
02457               {
02458                      if (*cgi("refresh"))
02459                      {
02460                             printf("Refresh: %ld; URL=",
02461                                    (long)get_timeoutsoft()/2);
02462                             output_scriptptrget();
02463                             printf("&empty=1&refresh=1\n");
02464                      }
02465               }
02466 
02467               output_user_form(cgi("form"));
02468               free(pi);
02469        }
02470        else
02471               /* Must be one of those special forms */
02472        {
02473        char   *rm;
02474        long   n;
02475 
02476               if (pi_malloced)     free(pi_malloced);
02477 
02478               if ((rm=getenv("REQUEST_METHOD")) == 0 ||
02479                      (strcmp(rm, "POST") == 0 &&
02480                             ((rm=getenv("CONTENT_TYPE")) != 0 &&
02481                             strncasecmp(rm,"multipart/form-data;", 20)
02482                                    == 0)))
02483                      emsg("multipart/formdata posts not allowed","");
02484 
02485               /* Some additional safety checks */
02486 
02487               rm=getenv("CONTENT_LENGTH");
02488               n= rm ? atol(rm):0;
02489               if (n < 0 || n > 256)       enomem();
02490 
02491               cgi_setup();
02492               init_default_locale();
02493 
02494               if (*(u=trim_spaces(cgi("username"))))
02495                      /* Request to log in */
02496               {
02497               const char *p=cgi("password");
02498               const char *mailboxid;
02499               const char *u2=cgi("logindomain");
02500               char   *ubuf=malloc(strlen(u)+strlen(u2)+2);
02501 
02502                      if (ubuf == NULL) enomem();
02503                      strcpy(ubuf, u);
02504                      if (*u2)
02505                             strcat(strcat(ubuf, "@"), u2);
02506 
02507                      maildir_cache_start();
02508 
02509                      if (*p && (mailboxid=do_login(ubuf, p, ip_addr))
02510                          != 0)
02511                      {
02512                             char   *q;
02513                             const  char *saveip=ip_addr;
02514                             char   *tz;
02515 
02516                             sqwebmail_mailboxid=mailboxid;
02517                             sqwebmail_folder="INBOX";
02518                             sqwebmail_sessiontoken=random128();
02519 
02520                             tz=get_timezone();
02521                             if (*cgi("sameip") == 0)
02522                                    saveip="none";
02523 
02524                             q=malloc(strlen(saveip)
02525                                     +strlen(sqwebmail_sessiontoken)
02526                                     +strlen(sqwebmail_content_language)
02527                                     +strlen(sqwebmail_content_ispelldict)
02528                                     +strlen(sqwebmail_content_charset)
02529                                     +strlen(tz)
02530                                     +strlen(sqwebmail_content_locale)+7);
02531                             if (!q)       enomem();
02532                             sprintf(q, "%s %s %s %s %s %s %s", saveip,
02533                                    sqwebmail_sessiontoken,
02534                                    sqwebmail_content_language,
02535                                    sqwebmail_content_locale,
02536                                    sqwebmail_content_ispelldict,
02537                                    tz,
02538                                    sqwebmail_content_charset);
02539                             write_sqconfig(".", IPFILE, q);
02540                             free(q);
02541                             free(tz);
02542                             time(&login_time);
02543                             {
02544                                    char buf[1024];
02545 
02546                                    buf[sizeof(buf)-1]=0;
02547                                    if (getcwd(buf, sizeof(buf)-1) == 0)
02548                                    {
02549                                           fprintf(stderr,
02550                                                  "CRIT: getcwd() failed: %s\n",strerror(errno));
02551                                           fake_exit(1);
02552                                    } /* oops */
02553 
02554                                    maildir_cache_save(mailboxid,
02555                                                     login_time,
02556                                                     buf,
02557                                                     geteuid(), getegid()
02558                                                     );
02559 
02560                             }
02561                             write_sqconfig(".", TIMESTAMP, "");
02562 #if    HAVE_LOCALE_H
02563 #if    HAVE_SETLOCALE
02564                             setlocale(LC_ALL, sqwebmail_content_locale);
02565 #if    USE_LIBCHARSET
02566                             setlocale(LC_CTYPE, sqwebmail_content_locale);
02567                             sqwebmail_system_charset = locale_charset();
02568 #elif  HAVE_LANGINFO_CODESET
02569                             setlocale(LC_CTYPE, sqwebmail_content_locale);
02570 
02571                             sqwebmail_system_charset = sys_locale_charset
02572                                    = strdup(nl_langinfo(CODESET));
02573 #else
02574                             sqwebmail_system_charset = NULL;
02575 #endif /* USE_LIBCHARSET */
02576                             setlocale(LC_CTYPE, "C");
02577                             setlang();
02578 #endif
02579 #endif
02580                             pref_init();
02581                             (void)maildir_create(INBOX "." DRAFTS);
02582 
02583                             if (!pref_noautorenamesent)
02584                                    (void)rename_sent_folder(1);
02585                             (void)maildir_create(INBOX "." SENT);
02586                             (void)maildir_create(INBOX "." TRASH);
02587                             maildir_autopurge();
02588                             unlink(SHAREDPATHCACHE);
02589 
02590                             sqpcp_login(ubuf, p);
02591                             maildir_acl_reset(".");
02592 
02593                             http_redirect_argss(*cgi("inpublic") ?
02594                                               "&form=folders":
02595                                               "&form=refreshfr", "", "");
02596                             free(ubuf);
02597                             return;
02598                      }
02599                      maildir_cache_cancel();
02600 
02601                      free(ubuf);
02602                      setgid(getgid());
02603                      setuid(getuid());
02604                      output_form("invalid.html");       /* Invalid login */
02605                      return;
02606               }
02607 
02608               setgid(getgid());
02609               setuid(getuid());
02610               if ( *(u=cgi("redirect")))
02611                      /* Redirection request to hide the referral tag */
02612               {
02613                      redirect(u);
02614               }
02615               else if ( *cgi("noframes") == '1')
02616                      output_form("login.html");  /* Main frame */
02617               else
02618               if ( *cgi("empty") == '1')
02619               {
02620                      output_form("empty.html");  /* Minor frameset */
02621               }
02622 
02623 /*
02624 ** Apparently we can't show just SCRIPT NAME as our frameset due to some
02625 ** weird bug in Communicator which, under certain conditions, will get
02626 ** confused figuring out which page views have expired.  POSTs with URLs
02627 ** referring to SCRIPT_NAME will be replied with an expiration header, and
02628 ** Communicator will assume that index.html also has expired, forcing a
02629 ** frameset reload the next time the Communicator window is resized,
02630 ** essentially logging the user off.
02631 */
02632 
02633               else if (*cgi("index") == '1')
02634                      output_form("index.html");  /* Frameset Window */
02635               else
02636               {
02637                      http_redirect_top("?index=1");
02638               }
02639                             
02640               return;
02641        }
02642        return;
02643 }
02644 
02645 #ifdef malloc
02646 
02647 #undef malloc
02648 #undef realloc
02649 #undef free
02650 #undef strdup
02651 #undef calloc
02652 
02653 static void *allocp[1000];
02654 
02655 extern void *malloc(size_t), *realloc(void *, size_t), free(void *),
02656        *calloc(size_t, size_t);
02657 extern char *strdup(const char *);
02658 
02659 char *my_strdup(const char *c)
02660 {
02661 size_t i;
02662 
02663        for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
02664               if (!allocp[i])
02665                      return (allocp[i]=strdup(c));
02666        abort();
02667        return (0);
02668 }
02669 
02670 void *my_malloc(size_t n)
02671 {
02672 size_t i;
02673 
02674        for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
02675               if (!allocp[i])
02676                      return (allocp[i]=malloc(n));
02677        abort();
02678        return (0);
02679 }
02680 
02681 void *my_calloc(size_t a, size_t b)
02682 {
02683 size_t i;
02684 
02685        for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
02686               if (!allocp[i])
02687                      return (allocp[i]=calloc(a,b));
02688        abort();
02689        return (0);
02690 }
02691 
02692 void *my_realloc(void *p, size_t s)
02693 {
02694 size_t i;
02695 
02696        for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
02697               if (p && allocp[i] == p)
02698               {
02699               void   *q=realloc(p, s);
02700 
02701                      if (q) allocp[i]=q;
02702                      return (q);
02703               }
02704        abort();
02705 }
02706 
02707 void my_free(void *p)
02708 {
02709 size_t i;
02710 
02711        for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
02712               if (p && allocp[i] == p)
02713               {
02714                      free(p);
02715                      allocp[i]=0;
02716                      return;
02717               }
02718        abort();
02719 }
02720 #endif
02721 
02722 /* Trim leading and trailing white spaces from string */
02723 
02724 char *trim_spaces(const char *s)
02725 {
02726        char *p, *q;
02727 
02728        p=strdup(s);
02729        if (!p)
02730               enomem();
02731 
02732        if (*p)
02733        {
02734               for (q=p+strlen(p)-1; q >= p && isspace(*q); q--)
02735                      *q=0;
02736 
02737               for (q=p; *q && isspace(*q); q++)
02738                      ;
02739               if (p != q)
02740                      p=q;
02741        }
02742 
02743        return (p);
02744 }
02745