sqwebmail.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:28k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
- ** distribution information.
- */
- /*
- ** $Id: sqwebmail.c,v 1.43 2000/07/01 23:09:28 mrsam Exp $
- */
- #include "sqwebmail.h"
- #include "sqconfig.h"
- #include "auth.h"
- #include "folder.h"
- #include "pref.h"
- #include "maildir.h"
- #include "cgi/cgi.h"
- #include "pref.h"
- #include "newmsg.h"
- #include "addressbook.h"
- #include "http11/http11.h"
- #include "random128/random128.h"
- #include "maildir/maildirmisc.h"
- #include <stdio.h>
- #include <errno.h>
- #include <stdlib.h>
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <string.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #if HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #if HAVE_LOCALE_H
- #if HAVE_SETLOCALE
- #include <locale.h>
- #endif
- #endif
- #include <ctype.h>
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
- #define MD5_INTERNAL
- #include "md5/md5.h"
- #include "logincache.h"
- #include "numlib/numlib.h"
- #if HAVE_CRYPT_H
- #include <crypt.h>
- #endif
- #if NEED_CRYPT_PROTOTYPE
- extern char *crypt(const char *, const char *);
- #endif
- #include "htmllibdir.h"
- #ifdef WEBPASS_CHANGE_VCHKPW
- #include "vpopmail.h"
- #include "vauth.h"
- #endif
- extern void spell_show();
- extern void spell_check_continue();
- extern void print_safe(const char *);
- extern void ldaplist();
- extern int ldapsearch();
- extern void doldapsearch();
- const char *sqwebmail_mailboxid=0;
- const char *sqwebmail_folder=0;
- const char *sqwebmail_sessiontoken=0;
- const char *sqwebmail_content_language=0;
- const char *sqwebmail_content_locale;
- const char *sqwebmail_content_ispelldict;
- const char *sqwebmail_content_charset;
- static int noimages=0;
- time_t login_time;
- #ifdef GZIP
- static int gzip_save_fd;
- #endif
- static const char *sqwebmail_formname;
- extern void attachments_head(const char *, const char *, const char *);
- extern void doattach(const char *, const char *);
- char form_args[2048];
- #if HAVE_LIBFCGI
- #include <signal.h>
- #include <setjmp.h>
- static jmp_buf stackenv;
- void fake_exit(int n)
- {
- cancel_login_cache();
- FCGI_SetExitStatus(n);
- longjmp(stackenv,1);
- }
- #ifdef BANNERPROG
- #error "Bannerprog not supported with FCGI"
- #endif
- #else
- void fake_exit(int n)
- {
- cancel_login_cache();
- exit(n);
- }
- #endif
- /* Stub to catch aborts from authlib */
- void authexit(int n)
- {
- fake_exit(n);
- }
- /* enomem() used to be just an out-of-memory handler. Now, I use it as a
- ** generic failure type of a deal.
- */
- void rfc2045_error(const char *p)
- {
- error(p);
- }
- void print_attrencodedlen(const char *p, size_t len, int oknl, FILE *fp)
- {
- for (; len; p++, --len)
- {
- switch (*p) {
- case '<':
- fprintf(fp, "<");
- continue;
- case '>':
- fprintf(fp, ">");
- continue;
- case '&':
- fprintf(fp, "&");
- continue;
- case '"':
- fprintf(fp, """);
- continue;
- case 'n':
- if (oknl)
- {
- if (oknl == 2)
- {
- fprintf(fp, "<BR>");
- continue;
- }
- putc('n', fp);
- continue;
- }
- default:
- if (!ISCTRL(*p))
- {
- putc(*p, fp);
- continue;
- }
- }
- fprintf(fp, "&#%d;", (int)(unsigned char)*p);
- }
- }
- void output_attrencoded_fp(const char *p, FILE *fp)
- {
- print_attrencodedlen(p, strlen(p), 0, fp);
- }
- void output_attrencoded(const char *p)
- {
- output_attrencoded_fp(p, stdout);
- }
- void output_attrencoded_oknl_fp(const char *p, FILE *fp)
- {
- print_attrencodedlen(p, strlen(p), 1, fp);
- }
- void output_attrencoded_oknl(const char *p)
- {
- output_attrencoded_oknl_fp(p, stdout);
- }
- void output_attrencoded_nltobr(const char *p)
- {
- print_attrencodedlen(p, strlen(p), 2, stdout);
- }
- void output_urlencoded(const char *p)
- {
- char *q=cgiurlencode(p);
- printf("%s", q);
- free(q);
- }
- void output_loginscriptptr()
- {
- #if USE_HTTPS_LOGIN
- const char *p=cgihttpsscriptptr();
- #else
- const char *p=cgihttpscriptptr();
- #endif
- printf("%s", p);
- }
- const char *nonloginscriptptr()
- {
- #if USE_HTTPS
- return (cgihttpsscriptptr());
- #else
- return (cgihttpscriptptr());
- #endif
- }
- void output_scriptptr()
- {
- const char *p=nonloginscriptptr();
- printf("%s", p);
- if (sqwebmail_mailboxid)
- {
- char *q=cgiurlencode(sqwebmail_mailboxid);
- char buf[NUMBUFSIZE];
- printf("/login/%s/%s/%s", q,
- sqwebmail_sessiontoken ? sqwebmail_sessiontoken:" ",
- str_time_t(login_time, buf));
- free(q);
- }
- }
- void output_loginscriptptr_get()
- {
- output_loginscriptptr();
- if (sqwebmail_mailboxid)
- {
- char *q=cgiurlencode(sqwebmail_mailboxid);
- char buf[NUMBUFSIZE];
- printf("/login/%s/%s/%s", q,
- sqwebmail_sessiontoken ? sqwebmail_sessiontoken:" ",
- str_time_t(login_time, buf));
- free(q);
- }
- }
- char *scriptptrget()
- {
- char *q=0;
- size_t l=0;
- int i;
- char buf[NUMBUFSIZE];
- #define ADD(s) {const char *zz=(s); if (i) strcat(q, zz); l += strlen(zz);}
- #define ADDE(ue) { char *yy=cgiurlencode(ue); ADD(yy); free(yy); }
- for (i=0; i<2; i++)
- {
- if (i && (q=malloc(l+1)) == 0) enomem();
- if (i) *q=0;
- ADD( nonloginscriptptr() );
- if (!sqwebmail_mailboxid)
- {
- ADD("?");
- continue;
- }
- ADD("/login/");
- ADD(sqwebmail_mailboxid);
- ADD("/");
- ADD(sqwebmail_sessiontoken ? sqwebmail_sessiontoken:" ");
- ADD("/");
- ADD(str_time_t(login_time, buf));
- ADD( "?" );
- if (sqwebmail_folder)
- {
- ADD("folder=");
- ADDE(sqwebmail_folder);
- }
- }
- #undef ADD
- #undef ADDE
- return (q);
- }
- void output_scriptptrget()
- {
- char *p=scriptptrget();
- printf("%s", p);
- free(p);
- return;
- }
- void output_scriptptrpostinfo()
- {
- #if 0
- if (sqwebmail_mailboxid)
- {
- printf("<INPUT TYPE=HIDDEN NAME="mailbox" VALUE="");
- output_attrencoded(sqwebmail_mailboxid);
- printf("">");
- }
- if (sqwebmail_sessiontoken)
- printf("<INPUT TYPE=HIDDEN NAME="session" VALUE="%s">",
- sqwebmail_sessiontoken);
- #endif
- if (sqwebmail_folder)
- {
- printf("<INPUT TYPE=HIDDEN NAME="folder" VALUE="");
- output_attrencoded(sqwebmail_folder);
- printf("">");
- }
- if (*cgi("folderdir")) /* In folders.html */
- {
- printf("<INPUT TYPE=HIDDEN NAME="folderdir" VALUE="");
- output_attrencoded(cgi("folderdir"));
- printf("">");
- }
- }
- void error(const char *errmsg)
- {
- cginocache();
- printf("Content-Type: text/html; charset="us-ascii"nn<H1>%s</H1>n",
- errmsg);
- cleanup();
- fake_exit(1);
- }
- void error2(const char *file, int line)
- {
- cginocache();
- printf("Content-Type: text/html; charset="us-ascii"nn<H1>Internal error (module %s, line %d) - contact system administrator</H1>n",
- file, line);
- cleanup();
- fake_exit(1);
- }
- static FILE *open_langform(const char *lang, const char *formname)
- {
- char *formpath;
- FILE *f;
- char *templatedir=getenv("SQWEBMAIL_TEMPLATEDIR");
-
- if (!templatedir || !*templatedir) templatedir=HTMLLIBDIR;
- /* templatedir/lang/formname */
- if (!(formpath=malloc(strlen(templatedir)+3+
- strlen(lang)+strlen(formname))))
- error("Out of memory.");
- strcat(strcat(strcat(strcat(strcpy(formpath, templatedir), "/"),
- lang), "/"), formname);
- f=fopen(formpath, "r");
- free(formpath);
- if (f)
- printf("Content-Language: %sn", lang);
- return (f);
- }
- void output_form(const char *formname)
- {
- int c, c2, c3;
- char *argp;
- size_t argn;
- FILE *f=0;
- #ifdef GZIP
- int dogzip;
- int pipefd[2];
- pid_t pid= -1;
- #endif
- noimages= access(NOIMAGES, 0) == 0;
- if (sqwebmail_content_language)
- f=open_langform(sqwebmail_content_language, formname);
- if (!f) f=open_langform(HTTP11_DEFAULTLANG, formname);
- sqwebmail_formname=formname;
- if (!f) error("Can't open form template.");
- /*
- ** Except for the dummy frame window (and the tiny empty frame),
- ** and the window containing the print preview of the message,
- ** expire everything.
- */
- if (strcmp(formname, "index.html") && strcmp(formname, "empty.html") &&
- strcmp(formname, "print.html"))
- cginocache();
- #ifdef GZIP
- dogzip=0;
- if (strcmp(formname, "readmsg.html") == 0)
- {
- const char *p=getenv("HTTP_ACCEPT_ENCODING");
- if (p)
- {
- char *q=strdup(p), *r;
- if (!q) enomem();
- for (r=q; *r; r++)
- *r= tolower((int)(unsigned char)*r);
- for (r=q; (r=strtok(r, ", ")) != 0; r=0)
- if (strcmp(r, "gzip") == 0)
- {
- dogzip=1;
- if (pipe(pipefd))
- enomem();
- }
- free(q);
- }
- }
- #endif
- printf("Vary: Accept-Languagen");
- #ifdef GZIP
- if (dogzip)
- printf("Content-Encoding: gzipn");
- #endif
- printf("Content-Type: text/htmlnn");
- form_args[0]=' ';
- #ifdef GZIP
- if (dogzip)
- {
- fflush(stdout);
- while ((pid=fork()) == -1)
- sleep(5);
- if (pid == 0)
- {
- close(0);
- dup(pipefd[0]);
- close(pipefd[0]);
- close(pipefd[1]);
- execl(GZIP, "gzip", "-c", (char *)0);
- exit(1);
- }
- gzip_save_fd=dup(1);
- close(1);
- dup(pipefd[1]);
- close(pipefd[1]);
- close(pipefd[0]);
- }
- #endif
- while ((c=getc(f)) >= 0)
- {
- if (c != '[')
- {
- putchar(c);
- continue;
- }
- c=getc(f);
- if (c != '#')
- {
- putchar('[');
- ungetc(c,f);
- continue;
- }
- c=getc(f);
- if (c == '?')
- {
- c=getc(f);
- if (c < '0' || c > '9')
- {
- putchar('[');
- putchar('#');
- putchar('?');
- putchar(c);
- continue;
- }
- if (
- #if ENABLE_WEBPASS
- #else
- c == '0' ||
- #endif
- (c == '1' && *cgi("folderdir") == ':') ||
- (c == '2' && *cgi("folderdir") != ':')
- )
- {
- while ((c=getc(f)) != EOF)
- {
- if (c != '[') continue;
- if ( getc(f) != '#') continue;
- if ( getc(f) != '?') continue;
- if ( getc(f) != '#') continue;
- if ( getc(f) == ']') break;
- }
- }
- continue;
- }
- if (c == '@')
- {
- argp=form_args;
- argn=sizeof(form_args)-1;
- while ((c=getc(f)) >= 0 && c != 'n' && argn)
- {
- if (c == '#')
- {
- c=getc(f);
- if (c == ']') break;
- ungetc(c, f);
- c='#';
- }
- if (c == '@')
- {
- c=getc(f);
- if (c == '@')
- {
- /*
- Conditional image. It's formatted as follows:
- @@filename,width=x height=y@text@
- If images are enabled, we replace that with an IMG tag we build from
- filename,width=x, height=y.
- If images are disabled, we replace all of this with text.
- */
- #define MKIMG(c) (argn ? *argp++=(c):0)
- if (noimages)
- {
- while ((c=getc(f)) >= 0
- && c != '@')
- if (c == '@')
- c=getc(f);
- while ((c=getc(f)) >= 0
- && c != '@')
- MKIMG(c);
- }
- else
- {
- char *p;
- MKIMG('<');
- MKIMG('I');
- MKIMG('M');
- MKIMG('G');
- MKIMG(' ');
- MKIMG('S');
- MKIMG('R');
- MKIMG('C');
- MKIMG('=');
- MKIMG('"');
- for (p=IMGPATH; *p; p++)
- MKIMG(*p);
- while ((c=getc(f)) >= 0
- && c != '@'
- && c != ',')
- MKIMG(c);
- MKIMG('"');
- MKIMG(' ');
- if (c == ',')
- c=getc(f);
- while (c >= 0 &&
- c != '@')
- {
- MKIMG(c);
- c=getc(f);
- }
- while ((c=getc(f)) >= 0
- && c != '@')
- ;
- MKIMG('>');
- }
- continue;
- }
- ungetc(c, f);
- c='@';
- }
- *argp++=c;
- --argn;
- }
- *argp=0;
- continue;
- }
- if (!isalnum(c))
- {
- putchar('[');
- putchar('#');
- ungetc(c, f);
- continue;
- }
- if ((c2=getc(f)) != '#')
- {
- putchar('[');
- putchar('#');
- putchar(c);
- ungetc(c2, f);
- continue;
- }
- if ((c3=getc(f)) != ']')
- {
- putchar('[');
- putchar('#');
- putchar(c);
- putchar(c2);
- ungetc(c3, f);
- continue;
- }
- switch (c) {
- case 'a':
- addressbook();
- break;
- case 'd':
- if (*cgi("folderdir"))
- {
- const char *c=cgi("folderdir");
- if (*c == ':')
- ++c; /* Sharable hierarchy */
- printf(" - ");
- print_safe(c);
- }
- break;
- case 'D':
- {
- const char *p=cgi("folder");
- const char *q=strrchr(p, '.');
- if (q)
- {
- char *r=malloc(q-p+1);
- if (!r) enomem();
- memcpy(r, p, q-p);
- r[q-p]=0;
- output_urlencoded(r);
- free(r);
- }
- }
- break;
- case 'G':
- output_attrencoded(login_returnaddr());
- break;
- case 'r':
- output_attrencoded(cgi("redirect"));
- break;
- case 's':
- output_scriptptrget();
- break;
- case 'S':
- output_loginscriptptr();
- break;
- case 'R':
- output_loginscriptptr_get();
- break;
- case 'p':
- output_scriptptr();
- break;
- case 'P':
- output_scriptptrpostinfo();
- break;
- case 'f':
- folder_contents_title();
- break;
- case 'F':
- folder_contents(sqwebmail_folder, atol(cgi("pos")));
- break;
- case 'n':
- folder_initnextprev(sqwebmail_folder, atol(cgi("pos")));
- break;
- case 'N':
- folder_nextprev();
- break;
- case 'm':
- folder_msgmove();
- break;
- case 'M':
- folder_showmsg(sqwebmail_folder, atol(cgi("pos")));
- break;
- case 'T':
- folder_showtransfer();
- break;
- case 'L':
- folder_list();
- break;
- case 'l':
- folder_list2();
- break;
- case 'E':
- folder_rename_list();
- break;
- case 'W':
- newmsg_init(sqwebmail_folder, cgi("pos"));
- break;
- case 'z':
- pref_isdisplayfullmsg();
- break;
- case 'y':
- pref_isoldest1st();
- break;
- case 'H':
- pref_displayhtml();
- break;
- case 'x':
- pref_setprefs();
- break;
- case 'w':
- pref_sortorder();
- break;
- case 't':
- pref_signature();
- break;
- case 'u':
- pref_pagesize();
- break;
- case 'v':
- pref_displayautopurge();
- break;
- case 'A':
- attachments_head(sqwebmail_folder, cgi("pos"),
- cgi("draft"));
- break;
- #ifdef ISPELL
- case 'K':
- spell_show();
- break;
- #endif
- #ifdef BANNERPROG
- case 'B':
- {
- char banargbuf[31];
- int i=0;
- int wait_stat;
- pid_t p, p2;
- if ((c=getc(f)) != '{')
- ungetc(c, f);
- else while ((c=getc(f)), isalnum(c))
- if (i < sizeof(banargbuf)-1)
- banargbuf[i++]=c;
- banargbuf[i]=0;
- fflush(stdout);
- if ( (p=fork()) == 0 )
- {
- execl(BANNERPROG, BANNERPROG,
- sqwebmail_formname,
- banargbuf, (char *)0);
- _exit(0);
- }
- if (p > 0)
- while ((p2=wait(&wait_stat)) > 0 &&
- p2 != p)
- ;
- }
- break;
- #endif
- case 'h':
- {
- FILE *fp=fopen(LOGINDOMAINLIST, "r");
- char buf[256];
- if (!fp) break;
- printf("<select name=logindomain><option value=""> ");
- while (fgets(buf, sizeof(buf), fp))
- {
- char *p=strchr(buf, 'n');
- if (*p) *p=0;
- printf("<option value="%s">@%s",
- buf, buf);
- }
- fclose(fp);
- printf("</select>");
- }
- break;
- case 'o':
- ldaplist();
- break;
- case 'O':
- doldapsearch();
- break;
- }
- }
- fclose(f);
- #ifdef GZIP
- if (pid > 0)
- {
- int waitstat;
- pid_t p2;
- /* Restore original stdout */
- fflush(stdout);
- close(1);
- dup(gzip_save_fd);
- close(gzip_save_fd);
- gzip_save_fd= -1;
- while ((p2=wait(&waitstat)) >= 0 && p2 != pid)
- ;
- }
- #endif
- }
- /* Top level HTTP redirect without referencing a particular mailbox */
- static void http_redirect_top(const char *app)
- {
- const char *p=nonloginscriptptr();
- char *buf=malloc(strlen(p)+strlen(app)+2);
- if (!buf) enomem();
- strcat(strcpy(buf, p), app);
- cgiredirect(buf);
- free(buf);
- }
- /* HTTP redirects within a given mailbox, various formats */
- void http_redirect_argu(const char *fmt, unsigned long un)
- {
- char buf[MAXLONGSIZE];
- sprintf(buf, "%lu", un);
- http_redirect_argss(fmt, buf, "");
- }
- void http_redirect_argss(const char *fmt, const char *arg1, const char *arg2)
- {
- http_redirect_argsss(fmt, arg1, arg2, "");
- }
- void http_redirect_argsss(const char *fmt, const char *arg1, const char *arg2,
- const char *arg3)
- {
- char *base=scriptptrget();
- char *arg1s=cgiurlencode(arg1);
- char *arg2s=cgiurlencode(arg2);
- char *arg3s=cgiurlencode(arg3);
- char *q;
- /* We generate a Location: redirected_url header. The actual
- ** header is generated in cgiredirect, we just build it here */
- q=malloc(strlen(base)+strlen(fmt)+strlen(arg1s)+strlen(arg2s)+
- strlen(arg3s)+1);
- if (!q) enomem();
- strcpy(q, base);
- sprintf(q+strlen(q), fmt, arg1s, arg2s, arg3s);
- cgiredirect(q);
- free(q);
- free(arg1s);
- free(arg2s);
- free(arg3s);
- free(base);
- }
- void output_user_form(const char *formname)
- {
- char *p;
- if (!*formname || strchr(formname, '.') || strchr(formname, '/'))
- error("Invalid request.");
- if (*cgi("ldapsearch")) /* Special voodoo for LDAP address book stuff */
- {
- if (ldapsearch() == 0)
- {
- output_form("ldapsearch.html");
- return;
- }
- }
- /*
- ** In order to hide the session ID in the URL of the message what
- ** we do is that the initial URL, that contains setcookie=1, results
- ** in us setting a temporary cookie that contains the session ID,
- ** then we return a redirect to a url which has /printmsg/ in the
- ** PATH_INFO, instead of the session ID. The code in main()
- ** traps /printmsg/ PATH_INFO, fetches the path info from the
- ** cookie, and punts after resetting setcookie to 0.
- */
- if (strcmp(formname, "print") == 0 && *cgi("setcookie") == '1')
- {
- const char *qs=getenv("QUERY_STRING");
- const char *pi=getenv("PATH_INFO");
- const char *nl;
- char *buf;
- if (!pi) pi="";
- if (!pi) pi="";
- nl=nonloginscriptptr();
- buf=malloc(strlen(nl) + sizeof("/printmsg/print?")+strlen(qs));
- if (!buf) enomem();
- strcat(strcat(strcpy(buf, nl), "/printmsg/print?"), qs);
- cginocache();
- cgi_setcookie("sqwebmail-pi", pi);
- printf("Refresh: 0; URL="%s"n", buf);
- free(buf);
- output_form("printredirect.html");
- return;
- }
- if (strcmp(formname, "logout") == 0)
- {
- unlink(IPFILE);
- http_redirect_top("");
- return;
- }
- if (strcmp(formname, "fetch") == 0)
- {
- folder_download( sqwebmail_folder, atol(cgi("pos")),
- cgi("mimeid") );
- return;
- }
- if (strcmp(formname, "delmsg") == 0)
- {
- folder_delmsg( atol(cgi("pos")));
- return;
- }
- if (strcmp(formname, "donewmsg") == 0)
- {
- newmsg_do(sqwebmail_folder);
- return;
- }
- if (strcmp(formname, "doattach") == 0)
- {
- doattach(sqwebmail_folder, cgi("draft"));
- return;
- }
- if (strcmp(formname, "folderdel") == 0)
- {
- folder_delmsgs(sqwebmail_folder, atol(cgi("pos")));
- return;
- }
- if (strcmp(formname, "spellchk") == 0)
- {
- #ifdef ISPELL
- spell_check_continue();
- #else
- printf("Status: 404");
- #endif
- return;
- }
- p=malloc(strlen(formname)+6);
- if (!p) enomem();
- strcat(strcpy(p, formname),".html");
- output_form(p);
- free(p);
- }
- #if ENABLE_WEBPASS
- /* System-compatible crypt function */
- static const char *auth_crypt(const char *password, const char *salt)
- {
- #if HAVE_CRYPT
- if (strncmp(salt, "$1$", 3))
- return (crypt(password, salt));
- #endif
- return (md5_crypt(password, salt));
- }
- /*
- ** Support for sqwebmail-only password. Versions prior to 0.12 stored
- ** it in clear test. 0.12 and later use crypt(), but still are able to
- ** handle cleartex
- */
- int check_sqwebpass(const char *pass)
- {
- const char *p=read_sqconfig(".", PASSFILE, 0);
- if (p && *p == 't')
- /* Starts with t - crypt */
- {
- ++p;
- if (strcmp(p, auth_crypt(pass, p)) == 0) return (0);
- return (-1);
- }
- if (p && strcmp(p, pass) == 0) return (0);
- return (-1);
- }
- int has_sqwebpass()
- {
- return (read_sqconfig(".", PASSFILE, 0) ? 1:0);
- }
- static const char salt[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
- void set_sqwebpass(const char *pw)
- {
- char buf[100];
- char buf2[100];
- const char *r=random128();
- unsigned i;
- #ifdef WEBPASS_CHANGE_VCHKPW
- const char *p;
- #endif
- /* r is 16 bytes. We need 12 bits to initialize the salt */
- buf2[4]=0;
- i=0;
- while (*r)
- {
- i <<= 1;
- i |= (*r & 1);
- ++r;
- }
- buf[0]= salt[ i & 63];
- i /= 64;
- buf[1]= salt[ i & 63 ];
- buf[2]= 0;
- strcpy(buf, auth_crypt(pw, buf));
- buf2[0]='t';
- strcpy(buf2+1, buf);
- #ifdef WEBPASS_CHANGE_VCHKPW
- if(( p=login_returnaddr() ))
- {
- char *user;
- char *domain;
- char *p2;
- char *pw2;
- p2=strdup(p);
- pw2=strdup(pw);
- user=strtok(p2, "@");
- domain=strtok(0, "@");
- if(vpasswd(user,domain,pw2,0) == 0)
- write_sqconfig(".", PASSFILE, buf2);
- free(p2);
- free(pw2);
- return;
- }
- #endif
- write_sqconfig(".", PASSFILE, buf2);
- }
- #endif
- extern void folder_cleanup();
- extern void maildir_cleanup();
- #ifdef ISPELL
- extern void ispell_cleanup();
- #endif
- void cleanup()
- {
- int i;
- for(i=0; i<sizeof(form_args); ++i)
- form_args[i] = ' ';
- sqwebmail_formname = NULL;
- sqwebmail_mailboxid=0;
- sqwebmail_folder=0;
- sqwebmail_sessiontoken=0;
- sqwebmail_content_language=0;
- sqwebmail_content_locale=0;
- sqwebmail_content_ispelldict=0;
- folder_cleanup();
- maildir_cleanup();
- #ifdef ISPELL
- ispell_cleanup();
- #endif
- #ifdef GZIP
- if (gzip_save_fd >= 0) /* Restore original stdout */
- {
- close(1);
- dup(gzip_save_fd);
- close(gzip_save_fd);
- gzip_save_fd= -1;
- }
- #endif
- }
- static RETSIGTYPE catch_sig(int n)
- {
- n=n;
- cleanup();
- fake_exit(0);
- #if RETSIGTYPE != void
- return (0);
- #endif
- }
- static void init_default_locale()
- {
- char *cl=http11_best_content_language(HTMLLIBDIR,
- getenv("HTTP_ACCEPT_LANGUAGE"));
- sqwebmail_content_language=
- http11_content_language(HTMLLIBDIR, cl);
- sqwebmail_content_locale=
- http11_content_locale(HTMLLIBDIR, cl);
- sqwebmail_content_ispelldict=
- http11_content_ispelldict(HTMLLIBDIR, cl);
- sqwebmail_content_charset=
- http11_content_charset(HTMLLIBDIR, cl);
- free(cl);
- #if HAVE_LOCALE_H
- #if HAVE_SETLOCALE
- setlocale(LC_ALL, sqwebmail_content_locale);
- #endif
- #endif
- }
- static int main2();
- int main()
- {
- int rc;
- #if HAVE_LIBFCGI
- while ( FCGI_Accept() >= 0)
- {
- if (setjmp(stackenv) == 0)
- {
- rc=main2();
- cleanup(); /* make sure we hit it */
- FCGI_SetExitStatus(rc);
- continue;
- }
- cleanup(); /* make sure we hit it */
- signal(SIGHUP, catch_sig);
- signal(SIGINT, catch_sig);
- signal(SIGPIPE, catch_sig);
- signal(SIGTERM, catch_sig);
- }
- return (0);
- #else
- rc=main2();
- exit(rc);
- return (rc);
- #endif
- }
- static int main2()
- {
- const char *u;
- const char *ip_addr;
- char *pi;
- char *pi_malloced;
- int reset_cookie=0;
- #ifdef GZIP
- gzip_save_fd= -1;
- #endif
- u=ip_addr=pi=NULL;
- ip_addr=getenv("REMOTE_ADDR");
- signal(SIGHUP, catch_sig);
- signal(SIGINT, catch_sig);
- signal(SIGPIPE, catch_sig);
- signal(SIGTERM, catch_sig);
- if (!ip_addr) ip_addr="127.0.0.1";
- umask(0077);
- init_login_cache(TIMEOUTHARD);
- pi=getenv("PATH_INFO");
- pi_malloced=0;
- if (pi && strncmp(pi, "/printmsg/", 10) == 0)
- {
- /* See comment in output_user_form */
- pi_malloced=pi=cgi_cookie("sqwebmail-pi");
- if (*pi_malloced == 0)
- {
- free(pi_malloced);
- output_form("printnocookie.html");
- return (0);
- }
- reset_cookie=1;
- cgi_setcookie("sqwebmail-pi", "DELETED");
- }
- if (pi && strncmp(pi, "/login/", 7) == 0)
- {
- const char *p;
- time_t last_time, current_time;
- char *q;
- /* Logging into the mailbox */
- pi=strdup(pi);
- if (pi_malloced) free(pi_malloced);
- if (!pi) enomem();
- (void)strtok(pi, "/"); /* Skip login */
- u=strtok(NULL, "/"); /* mailboxid */
- sqwebmail_sessiontoken=strtok(NULL, "/"); /* sessiontoken */
- q=strtok(NULL, "/"); /* login time */
- login_time=0;
- while (q && *q >= '0' && *q <= '9')
- login_time=login_time * 10 + (*q++ - '0');
- if (check_login_cache(u, login_time) && prelogin(u))
- {
- free(pi);
- error("Unable to access your mailbox, sqwebmail permissions may be wrong.");
- }
- time(¤t_time);
- /* Ok, boys and girls, time to validate the connection as
- ** follows */
- if ( !sqwebmail_sessiontoken
- /* 1. Read IPFILE. Check that it's timestamp is current enough,
- ** and the session hasn't timed out.
- */
- || !(p=read_sqconfig(".", IPFILE, &last_time))
- /* || last_time > current_time */
- || last_time + TIMEOUTHARD < current_time
- /* 2. IPFILE will contain four words - IP address, session
- ** token, language, locale, ispell dictionary. Validate both.
- */
- || !(q=strdup(p))
- || !(p=strtok(q, " "))
- || (strcmp(p, ip_addr) && strcmp(p, "none"))
- || !(p=strtok(NULL, " "))
- || strcmp(p, sqwebmail_sessiontoken)
- || !(p=strtok(NULL, " "))
- || !(sqwebmail_content_language=strdup(p))
- || !(p=strtok(NULL, " "))
- || !(sqwebmail_content_locale=strdup(p))
- || !(p=strtok(NULL, " "))
- || !(sqwebmail_content_ispelldict=strdup(p))
- || !(p=strtok(NULL, " "))
- || !(sqwebmail_content_charset=strdup(p))
- /* 3. Check the timestamp on the TIMESTAMP file. See if the
- ** session has reached its soft timeout.
- */
- || !read_sqconfig(".", TIMESTAMP, &last_time)
- /* || last_time > current_time */
- || last_time + TIMEOUTSOFT < current_time)
- {
- setgid(getgid());
- setuid(getuid()); /* Drop root prevs */
- chdir("/");
- cgi_setup();
- init_default_locale();
- free(pi);
- if (strcmp(cgi("form"), "logout") == 0)
- /* Already logged out, and the link
- ** had target=_parent tag.
- */
- {
- http_redirect_top("");
- return (0);
- }
- output_form("expired.html");
- return (0);
- }
- free(q);
- cgiformdatatempdir("tmp");
- cgi_setup(); /* Read CGI environment */
- if (reset_cookie)
- cgi_put("setcookie", "0");
- /* Update soft timeout stamp */
- write_sqconfig(".", TIMESTAMP, "");
- /* We must always have the folder CGI arg */
- if (!*(sqwebmail_folder=cgi("folder")))
- {
- init_default_locale();
- output_form("expired.html");
- free(pi);
- return (0);
- }
- sqwebmail_mailboxid=u;
- #if HAVE_LOCALE_H
- #if HAVE_SETLOCALE
- setlocale(LC_ALL, sqwebmail_content_locale);
- #endif
- #endif
- pref_init();
- output_user_form(cgi("form"));
- free(pi);
- }
- else
- /* Must be one of those special forms */
- {
- char *rm;
- long n;
- if (pi_malloced) free(pi_malloced);
- if ((rm=getenv("REQUEST_METHOD")) == 0 ||
- (strcmp(rm, "POST") == 0 &&
- ((rm=getenv("CONTENT_TYPE")) != 0 &&
- strncasecmp(rm,"multipart/form-data;", 20)
- == 0)))
- enomem(); /* multipart/formdata posts not allowed
- */
- /* Some additional safety checks */
- rm=getenv("CONTENT_LENGTH");
- n= rm ? atol(rm):0;
- if (n < 0 || n > 256) enomem();
- cgi_setup();
- init_default_locale();
- if (*(u=cgi("username")))
- /* Request to log in */
- {
- const char *p=cgi("password");
- const char *mailboxid;
- const char *u2=cgi("logindomain");
- char *ubuf=malloc(strlen(u)+strlen(u2)+2);
- strcpy(ubuf, u);
- if (*u2)
- strcat(strcat(ubuf, "@"), u2);
- prepare_login_cache();
- if (*p && (mailboxid=login(ubuf, p)) != 0)
- {
- char *q;
- const char *saveip=ip_addr;
- #if ENABLE_WEBPASS
- if (!has_sqwebpass())
- set_sqwebpass(p);
- #endif
- sqwebmail_mailboxid=mailboxid;
- sqwebmail_folder="INBOX";
- sqwebmail_sessiontoken=random128();
- if (*cgi("sameip") == 0)
- saveip="none";
- q=malloc(strlen(saveip)
- +strlen(sqwebmail_sessiontoken)
- +strlen(sqwebmail_content_language)
- +strlen(sqwebmail_content_ispelldict)
- +strlen(sqwebmail_content_charset)
- +strlen(sqwebmail_content_locale)+6);
- if (!q) enomem();
- sprintf(q, "%s %s %s %s %s %s", saveip,
- sqwebmail_sessiontoken,
- sqwebmail_content_language,
- sqwebmail_content_locale,
- sqwebmail_content_ispelldict,
- sqwebmail_content_charset);
- write_sqconfig(".", IPFILE, q);
- free(q);
- time(&login_time);
- save_login_cache(mailboxid, login_time);
- write_sqconfig(".", TIMESTAMP, "");
- (void)maildir_create(DRAFTS);
- (void)maildir_create(SENT);
- (void)maildir_create(TRASH);
- pref_init();
- maildir_autopurge();
- http_redirect_argss("&form=folders", "", "");
- /* output_form("folders.html"); */
- free(ubuf);
- return(0);
- }
- cancel_login_cache();
- free(ubuf);
- output_form("invalid.html"); /* Invalid login */
- return (0);
- }
- setgid(getgid());
- setuid(getuid());
- if ( *(u=cgi("redirect")))
- /* Redirection request to hide the referral tag */
- {
- printf("Refresh: 0; URL="%s"n", u);
- output_form("redirect.html");
- }
- else if ( *cgi("noframes") == '1')
- output_form("login.html"); /* Main frame */
- else
- if ( *cgi("empty") == '1')
- output_form("empty.html"); /* Minor frameset */
- /*
- ** Apparently we can't show just SCRIPT NAME as our frameset due to some
- ** weird bug in Communicator which, under certain conditions, will get
- ** confused figuring out which page views have expired. POSTs with URLs
- ** referring to SCRIPT_NAME will be replied with an expiration header, and
- ** Communicator will assume that index.html also has expired, forcing a
- ** frameset reload the next time the Communicator window is resized,
- ** essentially logging the user off.
- */
- else if (*cgi("index") == '1')
- output_form("index.html"); /* Frameset Window */
- else
- {
- http_redirect_top("?index=1");
- }
-
- return (0);
- }
- return (0);
- }
- #ifdef malloc
- #undef malloc
- #undef realloc
- #undef free
- #undef strdup
- #undef calloc
- static void *allocp[1000];
- extern void *malloc(size_t), *realloc(void *, size_t), free(void *),
- *calloc(size_t, size_t);
- extern char *strdup(const char *);
- char *my_strdup(const char *c)
- {
- size_t i;
- for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
- if (!allocp[i])
- return (allocp[i]=strdup(c));
- abort();
- return (0);
- }
- void *my_malloc(size_t n)
- {
- size_t i;
- for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
- if (!allocp[i])
- return (allocp[i]=malloc(n));
- abort();
- return (0);
- }
- void *my_calloc(size_t a, size_t b)
- {
- size_t i;
- for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
- if (!allocp[i])
- return (allocp[i]=calloc(a,b));
- abort();
- return (0);
- }
- void *my_realloc(void *p, size_t s)
- {
- size_t i;
- for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
- if (p && allocp[i] == p)
- {
- void *q=realloc(p, s);
- if (q) allocp[i]=q;
- return (q);
- }
- abort();
- }
- void my_free(void *p)
- {
- size_t i;
- for (i=0; i<sizeof(allocp)/sizeof(allocp[0]); i++)
- if (p && allocp[i] == p)
- {
- free(p);
- allocp[i]=0;
- return;
- }
- abort();
- }
- #endif