newmsg.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:17k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
- ** distribution information.
- */
- /*
- ** $Id: newmsg.c,v 1.32 2000/06/23 12:23:56 mrsam Exp $
- */
- #include "config.h"
- #include "sqwebmail.h"
- #include "newmsg.h"
- #include "cgi/cgi.h"
- #include "sqconfig.h"
- #include "auth.h"
- #include "maildir.h"
- #include "token.h"
- #include "pref.h"
- #include "folder.h"
- #include "filter.h"
- #include "addressbook.h"
- #include "maildir/maildirmisc.h"
- #include "maildir/maildirquota.h"
- #include "maildir/maildirgetquota.h"
- #include "rfc822/rfc822.h"
- #include "rfc822/rfc2047.h"
- #include "rfc2045/rfc2045.h"
- #include <string.h>
- #include <stdio.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <ctype.h>
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <sys/types.h>
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
- #include <errno.h>
- #include "htmllibdir.h"
- extern const char *sqwebmail_content_charset;
- extern int spell_start(const char *);
- extern char form_args[];
- extern const char *sqwebmail_mailboxid;
- extern const char *sqwebmail_folder;
- extern void print_safe_len(const char *, size_t, void (*)(const char *, size_t));
- extern void call_print_safe_to_stdout(const char *, size_t);
- extern void print_attrencodedlen(const char *, size_t, int, FILE *);
- extern void output_attrencoded_nltobr(const char *);
- extern void output_attrencoded_oknl(const char *);
- extern void output_attrencoded(const char *);
- extern void output_scriptptrget();
- extern void output_form(const char *);
- extern void output_urlencoded(const char *);
- extern char *newmsg_newdraft(const char *, const char *, const char *,
- const char *);
- extern char *newmsg_createdraft(const char *);
- extern char *newmsg_createsentmsg(const char *);
- extern void newmsg_handletextplain(FILE *, struct rfc2045 *,
- int (*)(const char *, size_t, void *));
- static void newmsg_header(const char *label, const char *field, const char *val)
- {
- printf("<TR><TH ALIGN=RIGHT><P>%s</TD><TD WIDTH=6> </TH>",
- label);
- printf("<TD><INPUT NAME=%s SIZE=50 MAXLENGTH=512 VALUE="",
- field);
- if (val)
- {
- char *s;
- s=rfc2047_decode_simple(val);
- if (!s) enomem();
- output_attrencoded(s);
- free(s);
- }
- printf(""></TD></TR>n");
- }
- static const char *ispreviewmsg()
- {
- const char *p=cgi("previewmsg");
- if (*p == 0)
- p=cgi("addressbook_to");
- if (*p == 0)
- p=cgi("addressbook_cc");
- if (*p == 0)
- p=cgi("addressbook_bcc");
- return (p);
- }
- void newmsg_hiddenheader(const char *label, const char *value)
- {
- printf("<INPUT TYPE=HIDDEN NAME="%s" VALUE="", label);
- output_attrencoded(value);
- printf("">");
- }
- /* ---------------------------------------------------- */
- /* Display message preview */
- static int filter_stub(const char *ptr, size_t cnt, void *voidptr)
- {
- filter(ptr, cnt);
- return (0);
- }
- static void preview_show_func_s(const char *p, size_t n)
- {
- fwrite(p, 1, n, stdout);
- }
- static void show_preview(const char *filename)
- {
- char *header, *value;
- struct rfc2045 *rfcp;
- FILE *fp;
- int fd;
- fp=0;
- fd=maildir_safeopen(filename, O_RDONLY, 0);
- if (fd >= 0)
- if ((fp=fdopen(fd, "r")) == 0)
- close(fd);
- if (!fp) return;
- while ((header=maildir_readheader(fp, &value, 1)) != 0)
- {
- /* Don't show X-, From, and Content- headers in preview */
- if (strncmp(header, "x-", 2) == 0) continue;
- if (strcmp(header, "mime-version") == 0) continue;
- if (strncmp(header, "content-", 8) == 0) continue;
- printf("%c", toupper(*header));
- output_attrencoded_oknl(header+1);
- printf(": ");
- output_attrencoded_oknl(value);
- printf("n");
- }
- printf("n");
- rfcp=rfc2045_fromfp(fp);
- if (!rfcp) return;
- filter_start(FILTER_FOR_PREVIEW, &preview_show_func_s);
- newmsg_handletextplain(fp, rfcp, &filter_stub);
- rfc2045_free(rfcp);
- filter_end();
- }
- static int show_textarea(const char *p, size_t l, void *voidptr)
- {
- print_attrencodedlen(p, l, 1, stdout);
- return (0);
- }
- /* ---------------------------------------------------- */
- void newmsg_init(const char *folder, const char *pos)
- {
- char *tolab=strtok(form_args, "|");
- char *cclab=strtok(0, "|");
- char *bcclab=strtok(0, "|");
- char *subjectlab=strtok(0, "|");
- char *messagelab=strtok(0, "|");
- char *sendlab=strtok(0, "|");
- char *previewlab=strtok(0, "|");
- char *forwardsep=strtok(0, "|");
- char *savedraft=strtok(0, "|");
- char *uploadlab=strtok(0, "|");
- char *replysalutation=strtok(0, "|");
- char *checkspellingdone=strtok(0, "|");
- char *checkspelling=strtok(0, "|");
- char *quotaerr=strtok(0, "|");
- char *fromlab=strtok(0, "|");
- char *replytolab=strtok(0, "|");
- char *addressbooklab=strtok(0, "|");
- char *draftmessage;
- char *draftmessagefilename;
- const char *p;
- FILE *fp;
- int attachcnt=0;
- char *cursubj, *curto, *curcc, *curbcc, *curfrom, *curreplyto;
- if (!fromlab) fromlab="";
- if (!replytolab) replytolab="";
- if (!tolab) tolab="";
- if (!cclab) cclab="";
- if (!bcclab) bcclab="";
- if (!subjectlab) subjectlab="";
- if (!messagelab) messagelab="";
- if (!sendlab) sendlab="";
- if (!previewlab) previewlab="";
- if (!savedraft) savedraft="";
- if (!uploadlab) uploadlab="";
- if (!replysalutation) replysalutation="";
- if (!checkspellingdone) checkspellingdone="";
- if (!checkspelling) checkspelling="";
- if (!quotaerr) quotaerr="";
- if (!addressbooklab) addressbooklab="";
- /* Picking up an existing draft? */
- p=cgi("draft");
- if (*p)
- {
- CHECKFILENAME(p);
- }
- if (*p)
- {
- draftmessage=strdup(p);
- if (!draftmessage) enomem();
- p="";
- }
- else
- {
- draftmessage=newmsg_newdraft(folder, pos,
- forwardsep, replysalutation);
- if (!draftmessage)
- {
- if (*ispreviewmsg())
- {
- p=cgi("draftmessage");
- if (*p)
- {
- CHECKFILENAME(p);
- }
- draftmessage=newmsg_createdraft(p);
- }
- }
- }
- draftmessagefilename= draftmessage ?
- maildir_find(DRAFTS, draftmessage):0;
- if (*(p=cgi("previewmsg")))
- {
- #ifdef ISPELL
- if (strcmp(p, "SPELLCHK") == 0)
- printf("%s<BR><BR>n", checkspellingdone);
- #endif
- printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=1 BGCOLOR="#000000"><TR><TD>n");
- printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=4 BGCOLOR="#FFFFFF"><TR><TD><TT><PRE>n");
- if (draftmessagefilename)
- show_preview(draftmessagefilename);
- printf("</PRE></TT></TR></TD></TABLE>n");
- printf("</TR></TD></TABLE>n");
- printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=6><TR><TD><HR WIDTH="80%%"></TD></TR></TABLE>n");
- }
- printf("<INPUT TYPE=HIDDEN NAME=form VALUE="donewmsg">n");
- newmsg_hiddenheader("pos", pos);
- newmsg_hiddenheader("focusto",
- *cgi("newmsg") ? "headers":"text");
- /* Generate unique message token, to detect duplicate SUBMITs */
- tokennew();
- /* Display any error message */
- if (*cgi("foldermsg"))
- {
- printf("<P><FONT COLOR="#FF0000">");
- output_attrencoded_nltobr(cgi("foldermsg"));
- printf("</FONT><BR>");
- }
- if (strcmp(cgi("error"), "quota") == 0)
- printf("%s", quotaerr);
- /* Read message from the draft file */
- cursubj=0;
- curto=0;
- curfrom=0;
- curreplyto=0;
- curcc=0;
- curbcc=0;
- fp=0;
- if (draftmessagefilename)
- {
- int x=maildir_safeopen(draftmessagefilename, O_RDONLY, 0);
- if (x >= 0)
- if ((fp=fdopen(x, "r")) == 0)
- close(x);
- }
- if (fp != 0)
- {
- char *header, *value;
- while ((header=maildir_readheader(fp, &value, 0)) != 0)
- {
- char **rfchp=0;
- if (strcmp(header, "subject") == 0)
- {
- if (!cursubj && !(cursubj=strdup(value)))
- enomem();
- continue;
- }
- if (strcmp(header, "from") == 0)
- rfchp= &curfrom;
- if (strcmp(header, "reply-to") == 0)
- rfchp= &curreplyto;
- if (strcmp(header, "to") == 0)
- rfchp= &curto;
- if (strcmp(header, "cc") == 0)
- rfchp= &curcc;
- if (strcmp(header, "bcc") == 0)
- rfchp= &curbcc;
- if (rfchp)
- {
- char *newh=malloc ( (*rfchp ? strlen(*rfchp)+2:1)
- +strlen(value));
- if (!newh) enomem();
- strcpy(newh, value);
- if (*rfchp)
- strcat(strcat(newh, ","), *rfchp);
- if (*rfchp) free( *rfchp );
- *rfchp=newh;
- }
- }
- }
- printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=1 BGCOLOR="#000000"><TR><TD>n");
- printf("<TABLE WIDTH="100%%" BORDER=0 CELLSPACING=0 CELLPADDING=4 BGCOLOR="#DDDDDD"><TR><TD>n");
- printf("<TABLE BORDER=0 WIDTH="100%%">n");
- if (access(NOCHANGINGFROM, 0))
- newmsg_header(fromlab, "headerfrom", curfrom ? curfrom:
- *cgi("from") ? cgi("from"):
- pref_from && *pref_from ? pref_from:
- login_fromhdr());
- printf("<TR VALIGN=MIDDLE><TH ALIGN=RIGHT><P>%s</TD><TD WIDTH=6> </TH>",
- addressbooklab);
- printf("<TD VALIGN=MIDDLE>");
- printf("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=4>");
- printf("<TR VALIGN=MIDDLE><TD><SELECT NAME="nick" SIZE=4 MULTIPLE>n");
- ab_listselect();
- printf("</select></TD><TD>");
- printf("<input type=submit name="addressbook_to" value="%s">",
- tolab);
- printf("<input type=submit name="addressbook_cc" value="%s">",
- cclab);
- printf("<input type=submit name="addressbook_bcc" value="%s">",
- bcclab);
- printf("</TD></TR></TABLE>");
- printf("</TD></TR>n");
- newmsg_header(tolab, "headerto", curto ? curto:cgi("to"));
- newmsg_header(cclab, "headercc", curcc ? curcc:cgi("cc"));
- newmsg_header(bcclab, "headerbcc", curbcc ? curbcc:cgi("bcc"));
- newmsg_header(replytolab, "headerreply-to", curreplyto ? curreplyto:cgi("replyto"));
- newmsg_header(subjectlab, "headersubject", cursubj ? cursubj:cgi("subject"));
- if (curto) free(curto);
- if (curfrom) free(curfrom);
- if (curreplyto) free(curreplyto);
- if (curcc) free(curcc);
- if (curbcc) free(curbcc);
- if (cursubj) free(cursubj);
- printf("<TR><TD COLSPAN=3><HR WIDTH="100%%"></TD></TR>");
- printf("<TR><TD> </TD><TD WIDTH=6> </TD>");
- printf("<TD><TEXTAREA NAME=message COLS=%d ROWS=15 WRAP=soft>",
- MYLINESIZE);
- if (fp)
- {
- struct rfc2045 *p=rfc2045_fromfp(fp), *q;
- /* Here's a nice opportunity to count all attachments */
- for (q=p->firstpart; q; q=q->next)
- if (!q->isdummy) ++attachcnt;
- if (attachcnt) --attachcnt;
- /* Not counting the 1st MIME part */
- if (!p) enomem();
- newmsg_handletextplain(fp, p, &show_textarea);
- rfc2045_free(p);
- fclose(fp);
- }
- else
- {
- printf("%s", cgi("body"));
- if ((fp=fopen(SIGNATURE, "r")) != NULL)
- {
- char buf[256];
- int n;
- printf("nn");
- while ((n=fread(buf, 1, sizeof(buf)-1, fp)) > 0)
- {
- buf[n]=0;
- output_attrencoded_oknl(buf);
- }
- fclose(fp);
- }
- }
- printf("</TEXTAREA><BR>n");
- if (draftmessage && *draftmessage)
- {
- printf("<INPUT TYPE=HIDDEN NAME=draftmessage VALUE="");
- output_attrencoded(draftmessage);
- printf("">");
- }
- if (draftmessage) free(draftmessage);
- printf("</TD></TR>n");
- printf("<TR><TD><P> </TD><TD> </TD><TD><INPUT TYPE=SUBMIT NAME=doattachments VALUE="");
- printf(uploadlab, attachcnt);
- printf(""></TD></TR>");
- printf("<TR><TD COLSPAN=2> </TD><TD>");
- printf("<INPUT TYPE=SUBMIT NAME=previewmsg VALUE="%s">",
- previewlab);
- printf("<INPUT TYPE=SUBMIT NAME=sendmsg VALUE="%s">",
- sendlab);
- printf("<INPUT TYPE=SUBMIT NAME=savedraft VALUE="%s">",
- savedraft);
- #ifdef ISPELL
- printf("<INPUT TYPE=SUBMIT NAME=startspellchk VALUE="%s">",
- checkspelling);
- #endif
- printf("</TD></TR>n");
- printf("</TD></TABLE>n");
- printf("</TR></TD></TABLE>n");
- printf("</TR></TD></TABLE>n");
- }
- static const char *geterrbuf(int fd)
- {
- static char errbuf[512];
- char *errbufptr=errbuf;
- size_t errbufleft=sizeof(errbuf)-1;
- while (errbufleft)
- {
- int l=read(fd, errbufptr, errbufleft);
- if (l <= 0) break;
- errbufptr += l;
- errbufleft -= l;
- }
- *errbufptr=0;
- return (errbuf);
- }
- static int waitfor(pid_t pid)
- {
- pid_t childpid;
- int wait_stat;
- while ((childpid=wait(&wait_stat)) != pid)
- if (childpid == -1) return (-1);
- return (wait_stat);
- }
- void sendmsg_done()
- {
- if ( *cgi("pos"))
- http_redirect_argss("&form=readmsg&pos=%s", cgi("pos"), "");
- else
- http_redirect_argss("&form=folders", "", "");
- }
- static int dosendmsg(const char *origdraft)
- {
- pid_t pid;
- const char *returnaddr;
- int pipefd1[2];
- char *filename;
- const char *line;
- char *draftmessage;
- if (tokencheck()) /* Duplicate submission - message was already sent */
- {
- sendmsg_done();
- return (1);
- }
- if (strcmp(cgi("form"), "doattach") == 0)
- {
- /* When called from the attachment window, we do NOT create
- ** a new draft message */
- draftmessage=strdup(origdraft);
- }
- else
- draftmessage=newmsg_createdraft(origdraft);
- if (!draftmessage)
- enomem();
- filename=newmsg_createsentmsg(draftmessage);
- if (!filename)
- {
- char *draftbase=maildir_basename(draftmessage);
- http_redirect_argss("&form=newmsg&pos=%s&draft=%s&error=quota",
- cgi("pos"), draftbase);
- free(draftmessage);
- free(draftbase);
- return (1);
- }
- if (pipe(pipefd1) != 0)
- {
- cgi_put("foldermsg", "ERROR: pipe() failed.");
- maildir_msgpurgefile(SENT, filename);
- free(filename);
- free(draftmessage);
- return (0);
- }
- returnaddr=login_returnaddr();
- pid=fork();
- if (pid < 0)
- {
- cgi_put("foldermsg", "ERROR: fork() failed.");
- close(pipefd1[0]);
- close(pipefd1[1]);
- maildir_msgpurgefile(SENT, filename);
- free(filename);
- free(draftmessage);
- return (0);
- }
- if (pid == 0)
- {
- static const char noexec[]="ERROR: Unable to execute sendit.sh.n";
- static const char nofile[]="ERROR: Temp file not available - probably exceeded quota.n";
- char *tmpfile=maildir_find(SENT, filename);
- int fd;
- if (!tmpfile)
- {
- fwrite((char*)nofile, 1, sizeof(nofile)-1, stderr);
- _exit(1);
- }
- close(0);
- fd=maildir_safeopen(tmpfile, O_RDONLY, 0);
- close(1);
- close(2);
- dup(pipefd1[1]);
- dup(pipefd1[1]);
- close(pipefd1[0]);
- close(pipefd1[1]);
- if (fd == 0)
- execl(SENDITSH, "sendit.sh", returnaddr,
- sqwebmail_mailboxid, NULL);
- fwrite(noexec, 1, sizeof(noexec)-1, stderr);
- _exit(1);
- }
- close(pipefd1[1]);
- line=geterrbuf(pipefd1[0]);
- close(pipefd1[0]);
- if (waitfor(pid))
- {
- if (!*line)
- line="Unable to send message.n";
- }
- else
- line="";
- if (*line == 0) /* Succesfully sent message */
- {
- if (*draftmessage)
- {
- char *base=maildir_basename(draftmessage);
- char *draftfile=maildir_find(DRAFTS, base);
- free(base);
- /* Remove draft file */
- if (draftfile)
- {
- char *replytofolder=0, *replytomsg=0;
- char *header, *value;
- FILE *fp;
- int x;
- unsigned long filesize;
- int rc;
- int quotafd;
- char quotabuf[QUOTABUFSIZE];
- fp=0;
- x=maildir_safeopen(draftfile, O_RDONLY, 0);
- if ( maildir_parsequota(draftfile, &filesize))
- {
- struct stat stat_buf;
- if (x < 0 || fstat(x, &stat_buf))
- stat_buf.st_size=0;
- filesize=stat_buf.st_size;
- }
- if (x >= 0)
- if ((fp=fdopen(x, "r")) == 0)
- close(x);
- /* First, look for a message that we should
- ** mark as replied */
- while (fp && (header=maildir_readheader(fp,
- &value, 0)) != 0)
- {
- if (strcmp(header,"x-reply-to-folder")
- == 0 && !replytofolder)
- {
- replytofolder=strdup(value);
- if (!replytofolder)
- enomem();
- }
- if (strcmp(header,"x-reply-to-msg")
- == 0 && !replytomsg)
- {
- replytomsg=strdup(value);
- if (!replytomsg)
- enomem();
- }
- if (replytofolder && replytomsg)
- break;
- }
- if (fp) fclose(fp);
- if (replytofolder && replytomsg)
- maildir_markreplied(replytofolder,
- replytomsg);
- if (replytofolder) free(replytofolder);
- if (replytomsg) free(replytomsg);
-
- if (maildir_getquota(".", quotabuf))
- {
- if (errno != ENOENT) enomem();
- quotabuf[0]=0;
- }
- do
- {
- if (quotabuf[0] == 0) break;
- rc=maildir_checkquota(".", "afd,
- quotabuf, -filesize, -1);
- if (rc && errno != EAGAIN)
- {
- if (quotafd >= 0)
- close(quotafd);
- enomem();
- }
- } while (rc);
- if (quotabuf[0])
- {
- maildir_addquota(".", quotafd, quotabuf,
- -filesize, -1);
- if (quotafd >= 0) close(quotafd);
- }
- unlink(draftfile);
- free(draftfile);
- }
- }
- tokensave();
- free(filename);
- free(draftmessage);
- sendmsg_done();
- return (1);
- }
- maildir_msgpurgefile(SENT, filename);
- free(filename);
- {
- char *draftbase=maildir_basename(draftmessage);
- http_redirect_argsss("&form=newmsg&pos=%s&draft=%s&foldermsg=%s",
- cgi("pos"), draftbase, line);
- free(draftmessage);
- free(draftbase);
- }
- return (1);
- }
- void newmsg_do(const char *folder)
- {
- const char *draftmessage=cgi("draftmessage");
- if (*draftmessage) /* It's ok if it's blank */
- {
- CHECKFILENAME(draftmessage);
- }
- if (*cgi("savedraft"))
- {
- char *newdraft=newmsg_createdraft(draftmessage);
- if (!newdraft) enomem();
- free(newdraft);
- sendmsg_done();
- return;
- }
- if (*cgi("sendmsg") && dosendmsg(draftmessage))
- return;
- if (*cgi("doattachments"))
- {
- char *newdraft=newmsg_createdraft(draftmessage);
- char *base;
- if (!newdraft) enomem();
- if (*cgi("error"))
- {
- cgi_put("previewmsg", "1");
- output_form("newmsg.html");
- return;
- }
- base=maildir_basename(newdraft);
- http_redirect_argss("&form=attachments&pos=%s&draft=%s",
- cgi("pos"), base);
- free(base);
- free(newdraft);
- return;
- }
- #ifdef ISPELL
- if (*cgi("startspellchk"))
- {
- char *newdraft=newmsg_createdraft(draftmessage);
- char *base;
- if (!newdraft) enomem();
- base=maildir_basename(newdraft);
- free(newdraft);
- if (spell_start(base) == 0)
- {
- cgi_put("draftmessage", base);
- output_form("spellchk.html");
- }
- else
- {
- http_redirect_argss("&form=newmsg&pos=%s&draft=%s&previewmsg=SPELLCHK",
- cgi("pos"), base);
- }
- free(base);
- return;
- }
- #endif
- if (*ispreviewmsg())
- {
- output_form("newmsg.html");
- return;
- }
- http_redirect_argsss("&form=newmsg&pos=%s&draftmessage=%s&error=%s",
- cgi("pos"), draftmessage,
- cgi("error"));
- }