diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /sqwebmail/newmsg.c | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'sqwebmail/newmsg.c')
| -rw-r--r-- | sqwebmail/newmsg.c | 1220 | 
1 files changed, 1220 insertions, 0 deletions
| diff --git a/sqwebmail/newmsg.c b/sqwebmail/newmsg.c new file mode 100644 index 0000000..a81477a --- /dev/null +++ b/sqwebmail/newmsg.c @@ -0,0 +1,1220 @@ +/* +** Copyright 1998 - 2011 Double Precision, Inc.  See COPYING for +** distribution information. +*/ + + +/* +*/ +#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	"gpg.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	"gpglib/gpglib.h" +#include	"courierauth.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" +#include	"unicode/unicode.h" + +extern const char *sqwebmail_content_charset; +extern int spell_start(const char *); +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 *, int *); +extern int ishttps(); + +static void newmsg_header(const char *label, const char *field, +			  const char *encoded, const char *val) +{ +int		hdrmaxlen=512; +const char	*p=getarg("HDRMAXLEN"); + +	if (p && (atoi(p) > hdrmaxlen)) +		hdrmaxlen=atoi(p); + +	printf("<tr><th align=\"right\"><p class=\"new-message-header\">" +	       "<span class=\"new-message-header-%s\">%s</span></p></th>" +	       "<td width=\"6\"> </td>", +	       field, label); + +	printf("<td><input type=\"text\" name=\"%s\" size=\"50\" maxlength=\"%d\"" +	       " class=\"new-message-header-text\" value=\"", +		field, hdrmaxlen); +	if (encoded) +	{ +		char	*s; + +		s=rfc822_display_hdrvalue_tobuf("subject", +						encoded, +						sqwebmail_content_charset, +						NULL, +						NULL); + +		if (!s) +			s=strdup(encoded); + +		if (!s)	enomem(); +		output_attrencoded(s); +		free(s); +	} +	else if (val) +		output_attrencoded(val); +	printf("\" /></td></tr>\n"); +} + +static void printc(char c, void *dummy) +{ +	char b[2]; + +	b[0]=c; +	b[1]=0; +	output_attrencoded(b); +} + +static void printsep(const char *c, void *dummy) +{ +	output_attrencoded(c); +} + +static void newmsg_header_rfc822(const char *label, const char *field, +				 const char *encoded, const char *val, +				 int is_readonly) +{ +int		hdrmaxlen=512; +const char	*p=getarg("HDRMAXLEN"); + +	if (p && (atoi(p) > hdrmaxlen)) +		hdrmaxlen=atoi(p); + +	printf("<tr><th align=\"right\"><p class=\"new-message-header\">" +	       "<span class=\"new-message-header-%s\">%s</span></p></th>" +	       "<td width=\"6\"> </td>", +	       field, label); + +	printf("<td><input type=\"text\" name=\"%s\" size=\"50\" maxlength=\"%d\"" +	       " class=\"new-message-header-text\" value=\"", +		field, hdrmaxlen); +	if (encoded) +	{ +		struct rfc822t *t=rfc822t_alloc_new(encoded, NULL, NULL); +		struct rfc822a *a=t ? rfc822a_alloc(t):NULL; + +		if (a) +		{ +			rfc2047_print_unicodeaddr(a, sqwebmail_content_charset, +						  printc, +						  printsep, NULL); +			rfc822a_free(a); +		} + +		if (t) +			rfc822t_free(t); +	} +	else if (val) +		output_attrencoded(val); +	printf("\"%s /></td></tr>\n", +		is_readonly ? " readonly=\"readonly\"":""); +} + +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("\" />"); +} + +/* ---------------------------------------------------- */ + +static size_t show_textarea_start_of_line(struct show_textarea_info *, +					  const char *, size_t); + +static size_t show_textarea_quoted_text(struct show_textarea_info *, +					const char *, size_t); + +static size_t show_textarea_notseen_sp(struct show_textarea_info *, +				       const char *, size_t); + +static size_t show_textarea_seen_sp(struct show_textarea_info *, +				    const char *, size_t); + +static size_t show_textarea_seen_spnl(struct show_textarea_info *, +				      const char *, size_t); + +static size_t show_textarea_check_sig(struct show_textarea_info *, +				      const char *, size_t); + +static size_t show_textarea_ignore_sig(struct show_textarea_info *, +				       const char *, size_t); + +void show_textarea_init(struct show_textarea_info *info, +			int stop_at_sig) +{ +	info->handler=show_textarea_start_of_line; +	info->stop_at_sig=stop_at_sig; +} + +void show_textarea(struct show_textarea_info *info, +		   const char *ptr, size_t cnt) +{ +	while (cnt) +	{ +		size_t n= (*info->handler)(info, ptr, cnt); + +		cnt -= n; +		ptr += n; +	} +} + +static size_t show_textarea_start_of_line(struct show_textarea_info *info, +					  const char *ptr, size_t cnt) +{ +	if (*ptr == '>') +	{ +		info->handler=show_textarea_quoted_text; +		return show_textarea_quoted_text(info, ptr, cnt); +	} + +	info->handler=show_textarea_notseen_sp; + +	if (*ptr == ' ') +		return 1; /* Consume space-stuffed space */ + +	if (info->stop_at_sig) +	{ +		info->handler=show_textarea_check_sig; +		info->sig_index=0; +		return show_textarea_check_sig(info, ptr, cnt); +	} +	return show_textarea_notseen_sp(info, ptr, cnt); +} + +static size_t show_textarea_quoted_text(struct show_textarea_info *info, +					const char *ptr, size_t cnt) +{ +	size_t i; + +	for (i=0; i<cnt; i++) +	{ +		if (ptr[i] == '\n') +		{ +			++i; +			info->handler=show_textarea_start_of_line; +			break; +		} +	} + +	if (i) +		print_attrencodedlen(ptr, i, 1, stdout); +	return i; +} + +static size_t show_textarea_notseen_sp(struct show_textarea_info *info, +				       const char *ptr, size_t cnt) +{ +	size_t i; + +	for (i=0; i<cnt; i++) +	{ +		if (ptr[i] == '\n') +		{ +			++i; +			info->handler=show_textarea_start_of_line; +			break; +		} + +		if (ptr[i] == ' ') +		{ +			if (i) +				print_attrencodedlen(ptr, i, 1, stdout); +			info->handler=show_textarea_seen_sp; +			return i+1; +		} +	} + +	if (i) +		print_attrencodedlen(ptr, i, 1, stdout); +	return i; +} + +static size_t show_textarea_seen_sp(struct show_textarea_info *info, +				    const char *ptr, size_t cnt) +{ +	if (*ptr != '\n') +	{ +		info->handler=show_textarea_notseen_sp; +		print_attrencodedlen(" ", 1, 1, stdout); +		return show_textarea_notseen_sp(info, ptr, cnt); +	} + +	info->handler=show_textarea_seen_spnl; +	return 1; +} + +static size_t show_textarea_seen_spnl(struct show_textarea_info *info, +				      const char *ptr, size_t cnt) +{ +	if (*ptr == '>' || *ptr == '\n') /* Fix this */ +	{ +		print_attrencodedlen("\n", 1, 1, stdout); +		return show_textarea_start_of_line(info, ptr, cnt); +	} + +	info->handler=show_textarea_notseen_sp; +	return show_textarea_notseen_sp(info, ptr, cnt); +} + +static size_t show_textarea_check_sig(struct show_textarea_info *info, +				      const char *ptr, size_t cnt) +{ +	static const char sig[]={'-', '-', ' ', '\n'}; +	size_t i; + +	for (i=0; i<cnt; ++i) +	{ +		if (i + info->sig_index >= sizeof(sig)) +		{ +			info->handler=show_textarea_ignore_sig; +			return cnt; +		} + +		if (ptr[i] != sig[i+info->sig_index]) +		{ +			info->handler=show_textarea_notseen_sp; + +			show_textarea(info, sig, info->sig_index); +			show_textarea(info, ptr, cnt); +			return cnt; +		} +	} + +	info->sig_index += cnt; +	return cnt; +} + +static size_t show_textarea_ignore_sig(struct show_textarea_info *info, +				       const char *ptr, size_t cnt) +{ +	return cnt; +} + +/* +** Return all from/to/cc/bcc addresses in the message. +*/ + +char *newmsg_alladdrs(FILE *fp) +{ +	char	*headers=NULL; +	struct rfc822t *t; +	struct rfc822a *a; +	char *p, *q; +	int l, i; + +	if (fp) +	{ +		char *header, *value; + +		rewind(fp); + +		/* First, combine all the headers into one header. */ + +		while ((header=maildir_readheader(fp, &value, 1)) != 0) +		{ +			char *newh; + +			if (strcmp(header, "from") && +			    strcmp(header, "to") && +			    strcmp(header, "cc") && +			    strcmp(header, "bcc")) +				continue; + +			if (headers) +			{ +				newh=realloc(headers, strlen(headers) +					     +strlen(value)+2); +				if (!newh) +					continue; +				strcat(newh, ","); +				headers=newh; +			} +			else +			{ +				newh=malloc(strlen(value)+1); +				if (!newh) +					continue; +				*newh=0; +				headers=newh; +			} +			strcat(headers, value); +		} + +	} + +	/* Now, parse the header, and extract the addresses */ + +	t=rfc822t_alloc_new(headers ? headers:"", NULL, NULL); +	a= t ? rfc822a_alloc(t):NULL; + +	l=1; +	for (i=0; i < (a ? a->naddrs:0); i++) +	{ +		p=rfc822_getaddr(a, i); +		if (p) +		{ +			++l; +			l +=strlen(p); +			free(p); +		} +	} +	p=malloc(l); +	if (p) +		*p=0; + +	for (i=0; i < (a ? a->naddrs:0); i++) +	{ +		q=rfc822_getaddr(a, i); +		if (q) +		{ +			if (p) +			{ +				strcat(strcat(p, q), "\n"); +			} +			free(q); +		} +	} + +	rfc822a_free(a); +	rfc822t_free(t); +	free(headers); +	return (p); +} + +static int show_textarea_trampoline(const char *ptr, size_t cnt, void *arg) +{ +	show_textarea( (struct show_textarea_info *)arg, ptr, cnt); +	return 0; +} + +void newmsg_showfp(FILE *fp, int *attachcnt) +{ +	struct	rfc2045 *p=rfc2045_fromfp(fp), *q; + +	if (!p)	enomem(); + +	/* Here's a nice opportunity to count all attachments */ + +	*attachcnt=0; + +	for (q=p->firstpart; q; q=q->next) +		if (!q->isdummy)	++*attachcnt; +	if (*attachcnt)	--*attachcnt; +	/* Not counting the 1st MIME part */ + +	{ +		const char *content_type; +		const char *content_transfer_encoding; +		const char *charset; + +		rfc2045_mimeinfo(p, &content_type, +				 &content_transfer_encoding, &charset); + +		if (content_type && +		    strcmp(content_type, "multipart/alternative") == 0) +			*attachcnt=0; +	} + +	q=rfc2045_searchcontenttype(p, "text/plain"); + +	if (q) +	{ +		struct rfc2045src *src=rfc2045src_init_fd(fileno(fp)); + +		if (src) +		{ +			struct show_textarea_info info; + +			show_textarea_init(&info, 1); + +			rfc2045_decodetextmimesection(src, q, +						      sqwebmail_content_charset, +						      NULL, +						      &show_textarea_trampoline, +						      &info); +			rfc2045src_deinit(src); +			show_textarea(&info, "\n", 1); +		} +	} +	rfc2045_free(p); +} + +void newmsg_preview(const char *p) +{ +	size_t pos; + +	maildir_remcache(INBOX "." DRAFTS); +	if (maildir_name2pos(INBOX "." DRAFTS, p, &pos) == 0) +	{ +		const char *save_folder=sqwebmail_folder; +		cgi_put("showdraft", "1"); +		sqwebmail_folder=INBOX "." DRAFTS; +		folder_showmsg(INBOX "." DRAFTS, pos); +		sqwebmail_folder=save_folder; +				/* show_preview(draftmessagefilename); */ +	} +} + +/* ---------------------------------------------------- */ + +void newmsg_init(const char *folder, const char *pos) +{ +	const char	*tolab=getarg("TOLAB"); +	const char	*cclab=getarg("CCLAB"); +	const char	*bcclab=getarg("BCCLAB"); +	const char	*subjectlab=getarg("SUBJECTLAB"); +	const char	*messagelab=getarg("MESSAGELAB"); +	const char	*sendlab=getarg("SENDLAB"); +	const char	*previewlab=getarg("PREVIEWLAB"); +	const char	*forwardsep=getarg("FORWARDLAB"); +	const char	*savedraft=getarg("SAVEDRAFT"); +	const char	*attachmentslab=getarg("ATTACHMENTS"); +	const char      *uploadlab=getarg("UPLOAD"); +	const char	*replysalutation=getarg("SALUTATION"); +	const char	*checkspellingdone=getarg("SPELLCHECKDONE"); +	const char	*checkspelling=getarg("CHECKSPELLING"); +	const char	*quotaerr=getarg("QUOTAERR"); +	const char	*fromlab=getarg("FROMLAB"); +	const char	*replytolab=getarg("REPLYTOLAB"); +	const char	*addressbooklab=getarg("ADDRESSBOOK"); +	const char	*select1=getarg("SELECT1"); +	const char	*select2=getarg("SELECT2"); +	const char	*text1=getarg("TEXT1"); +	const char	*text2=getarg("TEXT2"); +	char	*draftmessage; +	char	*draftmessagefilename; +	const	char *p; +	FILE	*fp; +	int	attachcnt=0; +	char	*cursubj, *curto, *curcc, *curbcc, *curfrom, *curreplyto; +	int wbnochangingfrom; + +	/* 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(INBOX "." 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\" class=\"box-small-outer\"><tr><td>\n"); +		printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\" class=\"preview\"><tr><td>\n"); + +		if (draftmessagefilename) +		{ +			const char *p=strrchr(draftmessagefilename, '/'); + +			if (p) +				++p; +			else +				p=draftmessagefilename; + +			newmsg_preview(p); +		} +		printf("</td></tr></table>\n"); +		printf("</td></tr></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><span class=\"error\" style=\"color: #ff0000\">"); +		output_attrencoded_nltobr(cgi("foldermsg")); +		printf("</span></p>"); +	} + +	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; +			} + +			while (*value && isspace(*value)) +				++value; + +			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\" class=\"box-small-outer\"><tr><td>\n"); +	printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\" class=\"new-message-box\"><tr><td>\n"); + +	printf("<table border=\"0\" width=\"100%%\">\n"); +	wbnochangingfrom=auth_getoptionenvint("wbnochangingfrom"); +	if (wbnochangingfrom < 2) +		newmsg_header_rfc822(fromlab, "headerfrom", curfrom, +			*cgi("from") ? cgi("from"): +			pref_from && *pref_from ? pref_from: +			login_fromhdr(), wbnochangingfrom ? 1:0); + +	printf("<tr valign=\"middle\"><th align=\"right\">" +	       "<p class=\"new-message-header\">" +	       "<span class=\"new-message-header-addressbook\">" +	       "%s</span></p></th><td width=\"6\"> </td>", +	       addressbooklab); + +	printf("<td valign=\"middle\">"); +	printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"4\">"); +	printf("<tr valign=\"middle\"><td>%s\n", select1); +	ab_listselect(); +	printf("%s</td><td width=\"100%%\">", select2); +	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"); + +#if 0 +			{ +				FILE *fp; +				fp=fopen("/tmp/pid", "w"); +				fprintf(fp, "%d", getpid()); +				fclose(fp); +				sleep(10); +			} +#endif + +	newmsg_header_rfc822(tolab, "headerto", curto, cgi("to"), 0); +	newmsg_header_rfc822(cclab, "headercc", curcc, cgi("cc"), 0); +	newmsg_header_rfc822(bcclab, "headerbcc", curbcc, cgi("bcc"), 0); +	newmsg_header_rfc822(replytolab, "headerreply-to", +			     curreplyto, cgi("replyto"), 0); +	newmsg_header(subjectlab, "headersubject", +		      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>" + +	       "<th valign=\"top\" align=\"right\">" +	       "<p class=\"new-message-header\">" +	       "<span class=\"new-message-header-message\">" +	       "%s</span></p></th><td width=\"6\"> </td>" +	       "<td><select name=\"textformat\">" +	       "<option value=\"plain\" %s>%s</option>" +	       "<option value=\"wiki\" %s>%s</option></select>" + +	       "<small>(<a href='%s/wikifmt.html' target='_blank'>%s</a>)</small>" +	       "</td></tr>" +	       "<tr><th valign=\"top\" align=\"right\">" +	       "<p class=\"new-message-header\">" +	       "<span class=\"new-message-header-message\">" +	       "%s</span></p></th><td width=\"6\"> </td>", + +	       getarg("FMTNAME"), +	       pref_wikifmt ? "":"selected='selected'", getarg("FMTTEXTPLAIN"), +	       pref_wikifmt ? "selected='selected'":"", getarg("FMTTEXTWIKI"), + +	       get_imageurl(), getarg("FMTHELP"), +	       messagelab); + +	printf("<td>%s\n", text1); + +	if (fp) +	{ +		newmsg_showfp(fp, &attachcnt); +	} +	else +	{ +		printf("%s", cgi("body")); +	} +	printf("%s\n", text2); + +	if (draftmessage && *draftmessage) +	{ +		printf("<input type=\"hidden\" name=\"draftmessage\" value=\""); +		output_attrencoded(draftmessage); + +		printf("\" />"); +	} +	if (draftmessage)	free(draftmessage); +	printf("</td></tr>\n"); + +	printf("<tr><th valign=\"top\" align=\"right\">" +	       "<p class=\"new-message-header\">" +	       "<span class=\"new-message-header-message\">" +		"%s</span></p></th><td> </td>" +		"<td>%d  <input type=\"submit\" name=\"doattachments\" value=\"%s\" /></td></tr>", +		attachmentslab, attachcnt, uploadlab); + +	printf("<tr><td colspan=\"2\" align=\"right\"><input type=\"checkbox\" " +	       "name=\"fcc\" id=\"fcc\"%s /></td><td><label for=\"fcc\">%s</label></td></tr>\n", +	       pref_noarchive ? "":" checked=\"checked\"", +	       getarg("PRESERVELAB")); + +	if (auth_getoptionenvint("wbnodsn") == 0) +		printf("<tr><td colspan=\"2\" align=\"right\"><input type=\"checkbox\" " +		       "name=\"dsn\" id=\"dsn\" /></td><td><label for=\"dsn\">%s</label></td></tr>\n", +		       getarg("DSN")); + +	if (libmail_gpg_has_gpg(GPGDIR) == 0) +	{ +		char *all_addr; + +		printf("<tr><td colspan=\"2\" align=\"right\"><input type=\"checkbox\" " +		       "name=\"sign\" id=\"sign\" /></td><td><label for=\"sign\">%s</label><select name=\"signkey\">", +		       getarg("SIGNLAB")); +		gpgselectkey(); +		printf("</select></td></tr>\n"); + +		all_addr=newmsg_alladdrs(fp); + +		printf("<tr valign=\"middle\"><td colspan=\"2\" align=\"right\">" +		       "<input type=\"checkbox\" name=\"encrypt\" id=\"encrypt\" /></td>" +		       "<td><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr valign=\"middle\"><td><label for=\"encrypt\">%s</label></td><td><select size=\"4\" multiple=\"multiple\" name=\"encryptkey\">", +		       getarg("ENCRYPTLAB")); +		gpgencryptkeys(all_addr); +		printf("</select></td></tr>\n"); +		printf("</table></td></tr>\n"); + +		if (ishttps()) +			printf("<tr><td colspan=\"2\" align=\"left\"> </td><td>%s<input type=\"password\" name=\"passphrase\" /></td></tr>\n", +			       getarg("PASSPHRASE")); + +		if (all_addr) +			free(all_addr); +	} + +	if (fp) +		fclose(fp); +	if (draftmessagefilename) +		free(draftmessagefilename); + +	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("</table>\n"); + +	printf("</td></tr></table>\n"); +	printf("</td></tr></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 if (*cgi("sendmsg")) +		http_redirect_argss("&form=folders&foldermsg=sent", "", ""); +	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; +int	isgpgerr; +unsigned long filesize; +struct stat stat_buf; +int dsn; + +	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, &isgpgerr); + +	if (!filename) +	{ +		char *draftbase=maildir_basename(draftmessage); + +		if (isgpgerr) +		{ +			cgi_put("draftmessage", draftbase); +			output_form("gpgerr.html"); +		} +		else +		{ +			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(INBOX "." SENT, filename); +		free(filename); +		free(draftmessage); +		return (0); +	} + +	dsn= *cgi("dsn") != 0; + +	pid=fork(); +	if (pid < 0) +	{ +		cgi_put("foldermsg", "ERROR: fork() failed."); +		close(pipefd1[0]); +		close(pipefd1[1]); +		maildir_msgpurgefile(INBOX "." 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(INBOX "." SENT, filename); +	int	fd; + +		if (!tmpfile) +		{ +			if (fwrite((char*)nofile, 1, sizeof(nofile)-1, stderr)) +				; /* ignore */ +			_exit(1); +		} + +		close(0); + +		fd=maildir_safeopen(tmpfile, O_RDONLY, 0); +		dup2(pipefd1[1], 1); +		dup2(pipefd1[1], 2); +		close(pipefd1[0]); +		close(pipefd1[1]); + +		if (dsn) +			putenv("DSN=-Nsuccess,delay,failure"); +		else +			putenv("DSN="); + +		if (fd == 0) +		{ +			returnaddr=login_returnaddr(); +			execl(SENDITSH, "sendit.sh", returnaddr, +				sqwebmail_mailboxid, NULL); +		} +			 +		if (fwrite(noexec, 1, sizeof(noexec)-1, stderr)) +			; /* ignore */ +		_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(INBOX "." DRAFTS, base); + +			free(base); + +			/* Remove draft file */ + +			if (draftfile) +			{ +			char	*replytofolder=0, *replytomsg=0; +			char	*header, *value; +			FILE	*fp; +			int	x; + +				fp=0; +				x=maildir_safeopen(draftfile, O_RDONLY, 0); +				if ( maildir_parsequota(draftfile, &filesize)) +				{ +					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); +				 +				maildir_quota_deleted(".", +						      -(long)filesize, -1); + +				unlink(draftfile); +				free(draftfile); +			} +		} + +		tokensave(); + +		if (*cgi("fcc") == 0) +		{ +			unsigned long filesize=0; +			char	*tmpfile=maildir_find(INBOX "." SENT, filename); + +			if (tmpfile) +			{ +				maildir_parsequota(tmpfile, &filesize); +				unlink(tmpfile); +				maildir_quota_deleted(".", -(long)filesize,-1); +				free(tmpfile); +			} +		} + +		free(filename); +		free(draftmessage); +		sendmsg_done(); +		return (1); +	} + +	if (stat(filename, &stat_buf) == 0) +		maildir_quota_deleted(".", -(long)stat_buf.st_size, -1); +	maildir_msgpurgefile(INBOX "." 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")); +} | 
