Viewing file:
attachments.c (23.79 KB) -rw-rw-rw-Select action/file-type:

(
+) |

(
+) |

(
+) |
Code (
+) |
Session (
+) |

(
+) |
SDB (
+) |

(
+) |

(
+) |

(
+) |

(
+) |

(
+) |
/*
** Copyright 1998 - 2011 Double Precision, Inc. See COPYING for
** distribution information.
*/
/*
*/
#include "config.h"
#include "sqwebmail.h"
#include "cgi/cgi.h"
#include "sqconfig.h"
#include "maildir.h"
#include "folder.h"
#include "pref.h"
#include "rfc822/rfc822.h"
#include "rfc822/rfc2047.h"
#include "rfc2045/rfc2045.h"
#include "token.h"
#include "newmsg.h"
#include "gpg.h"
#include "gpglib/gpglib.h"
#include "courierauth.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
#include "maildir/maildirmisc.h"
#include "htmllibdir.h"
#include "unicode/unicode.h"
extern char *newmsg_alladdrs(FILE *);
extern void newmsg_copy_content_headers(FILE *fp);
extern char *alloc_filename(const char *, const char *, const char *);
extern const char *showsize(unsigned long);
extern void output_attrencoded(const char *);
extern int newdraftfd;
extern void newmsg_hiddenheader(const char *, const char *);
extern void output_scriptptrget();
extern void output_urlencoded(const char *);
extern void sendmsg_done();
extern char *multipart_boundary_create();
extern int multipart_boundary_checkf(const char *, FILE *);
extern int ishttps();
extern void newmsg_create_multipart(int, const char *, const char *);
extern void newmsg_copy_nonmime_headers(FILE *);
extern const char *sqwebmail_content_charset;
extern const char *sqwebmail_content_language;
static void attachment_showname(const char *);
#define HASTEXTPLAIN(q) (rfc2045_searchcontenttype((q), "text/plain") != NULL)
/* Also in newmsg_create.c */
static off_t max_attach()
{
off_t n=0;
const char *p=getenv("SQWEBMAIL_MAXMSGSIZE");
if (p)
n=atol(p);
if (n < MAXMSGSIZE)
n=MAXMSGSIZE;
return n;
}
void attachments_head(const char *folder, const char *pos, const char *draft)
{
char *filename;
FILE *fp;
struct rfc2045 *rfcp;
int cnt=0;
struct rfc2045 *q;
int foundtextplain=0;
const char *noattach_lab=getarg("NOATTACH");
const char *quotaerr=getarg("QUOTAERR");
const char *limiterr=getarg("LIMITERR");
off_t dummy;
int fd2;
CHECKFILENAME(draft);
filename=maildir_find(INBOX "." DRAFTS, draft);
if (!filename) return;
fd2=maildir_safeopen(filename, O_RDONLY, 0);
fp=0;
if (fd2 >= 0)
{
fp=fdopen(fd2, "r");
if (fp == NULL)
close(fd2);
}
if (fp == NULL)
{
free(filename);
return;
}
rfcp=rfc2045_fromfp(fp);
fclose(fp);
free(filename);
if (strcmp(cgi("error"), "quota") == 0)
{
printf("%s", quotaerr);
}
if (strcmp(cgi("error"), "limits") == 0)
{
printf(limiterr, (unsigned long)(max_attach() / (1024 * 1024)));
}
if (strcmp(cgi("error"), "makemime") == 0)
{
printf(getarg("MAKEMIMEERR"), MAKEMIME);
}
newmsg_hiddenheader("pos", pos);
newmsg_hiddenheader("draft", draft);
tokennew();
printf("<table width=\"100%%\" border=\"0\">");
if (rfcp)
{
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
rfc2045_mimeinfo(rfcp, &content_type,
&content_transfer_encoding, &charset);
if (content_type &&
strcmp(content_type, "multipart/alternative") == 0)
rfcp=NULL;
/* No attachments here */
}
for (q=rfcp ? rfcp->firstpart:0; q; q=q->next)
{
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
const char *name;
const char *cn;
char *content_name;
off_t start_pos, end_pos, start_body;
if (q->isdummy) continue;
rfc2045_mimeinfo(q, &content_type,
&content_transfer_encoding, &charset);
if (!foundtextplain && HASTEXTPLAIN(q))
{
foundtextplain=1;
continue;
}
rfc2045_mimepos(q, &start_pos, &end_pos, &start_body,
&dummy, &dummy);
++cnt;
printf("<tr><td align=\"left\"><input type=\"checkbox\" name=\"del%d\" id=\"del%d\" /> ",
cnt, cnt);
if (rfc2231_udecodeType(q, "name", sqwebmail_content_charset,
&content_name) < 0 ||
rfc2231_udecodeDisposition(q, "filename",
sqwebmail_content_charset,
&content_name) < 0)
content_name=NULL;
if (!content_name &&
((cn=rfc2045_getattr(q->content_type_attr, "name")) ||
(cn=rfc2045_getattr(q->content_disposition_attr,
"filename"))))
{
content_name =
rfc822_display_hdrvalue_tobuf("subject",
cn,
sqwebmail_content_charset,
NULL,
NULL);
}
if ((!content_name || !*content_name) &&
strcmp(content_type, "application/pgp-keys") == 0)
name=getarg("KEYDESCR");
else
{
name=content_name;
}
attachment_showname(name);
if (content_name)
free(content_name);
printf("</td><td align=\"left\"> <label for=\"del%d\">", cnt);
output_attrencoded( content_type );
printf("</label></td><td align=\"right\">%s<br /></td></tr>",
showsize(end_pos - start_body));
}
if (cnt == 0)
printf("<tr><td align=\"center\">%s<br /></td></tr>\n",
noattach_lab);
printf("</table>\n");
}
void attachments_opts(const char *draft)
{
char *filename;
FILE *fp;
CHECKFILENAME(draft);
filename=maildir_find(INBOX "." DRAFTS, draft);
if (!filename)
return;
fp=fopen(filename, "r");
free(filename);
if (!fp)
return;
printf("<label><input type=\"checkbox\" name=\"fcc\"%s />%s</label><br />",
pref_noarchive ? "":" checked=\"checked\"",
getarg("PRESERVELAB"));
if (auth_getoptionenvint("wbnodsn") == 0)
printf("<label><input type=\"checkbox\" name=\"dsn\" />%s</label><br />",
getarg("DSN"));
if (libmail_gpg_has_gpg(GPGDIR) == 0)
{
char *all_addr;
printf("<label><input type=\"checkbox\" "
"name=\"sign\" />%s</label><select name=\"signkey\">",
getarg("SIGNLAB"));
gpgselectkey();
printf("</select><br />\n");
all_addr=newmsg_alladdrs(fp);
printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"
"<tr valign=\"middle\"><td><input type=\"checkbox\""
" name=\"encrypt\" id=\"encrypt\" /></td><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");
if (ishttps())
printf("<tr valign=\"middle\"><td> </td><td>%s</td><td><input type=\"password\" name=\"passphrase\" /></td></tr>\n",
getarg("PASSPHRASE"));
printf("</table><br />\n");
if (all_addr)
free(all_addr);
}
fclose(fp);
}
static void attachment_showname(const char *name)
{
if (!name || !*name) name="[attachment]"; /* Eh??? */
output_attrencoded(name);
}
static void attachment_open(const char *draft,
FILE **fp,
int *fd2,
struct rfc2045 **rfcp)
{
char *oldname=maildir_find(INBOX "." DRAFTS, draft);
if (!oldname) enomem();
*fd2=maildir_safeopen(oldname, O_RDONLY, 0);
*fp=0;
if (*fd2 >= 0)
{
*fp=fdopen(*fd2, "r");
if (*fp == NULL)
close(*fd2);
}
if (*fp == NULL) enomem();
*rfcp=rfc2045_fromfp( *fp );
if (!*rfcp) enomem();
}
static int messagecopy(FILE *fp, off_t start, off_t end)
{
char buf[512];
int n;
if (fseek(fp, start, SEEK_SET) == -1) return (-1);
while (start < end)
{
n=sizeof(buf);
if (n > end - start)
n=end - start;
n=fread(buf, 1, n, fp);
if (n <= 0) enomem();
maildir_writemsg(newdraftfd, buf, n);
start += n;
}
return (0);
}
/* Return non-zero if user selected all attachments for deletion */
static int deleting_all_attachments(struct rfc2045 *p)
{
struct rfc2045 *q;
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
int foundtextplain, cnt;
char buf[MAXLONGSIZE+4];
foundtextplain=0;
cnt=0;
for (q=p->firstpart; q; q=q->next)
{
rfc2045_mimeinfo(q, &content_type,
&content_transfer_encoding, &charset);
if (q->isdummy) continue;
if (!foundtextplain && HASTEXTPLAIN(q))
{
foundtextplain=1;
continue;
}
sprintf(buf, "del%d", ++cnt);
if (*cgi(buf) == '\0') return (0);
}
return (1);
}
static int del_final_attachment(FILE *fp, struct rfc2045 *rfcp)
{
struct rfc2045 *q;
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
off_t start_pos, end_pos, start_body;
off_t dummy;
for (q=rfcp->firstpart; q; q=q->next)
{
if (q->isdummy) continue;
rfc2045_mimeinfo(q, &content_type,
&content_transfer_encoding, &charset);
if (HASTEXTPLAIN(q))
break;
}
if (!q) return (-1);
if (fseek(fp, 0L, SEEK_SET) == -1) return (-1);
newmsg_copy_nonmime_headers(fp);
maildir_writemsgstr(newdraftfd, "mime-version: 1.0\n");
rfc2045_mimepos(q, &start_pos, &end_pos, &start_body, &dummy, &dummy);
return (messagecopy(fp, start_pos, end_pos));
}
static int del_some_attachments(FILE *fp, struct rfc2045 *rfcp)
{
struct rfc2045 *q;
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
int foundtextplain;
int cnt;
const char *boundary=rfc2045_boundary(rfcp);
off_t start_pos, end_pos, start_body;
off_t dummy;
rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body, &dummy,
&dummy);
if (messagecopy(fp, 0, start_body)) return (-1);
foundtextplain=0;
cnt=0;
for (q=rfcp->firstpart; q; q=q->next)
{
rfc2045_mimeinfo(q, &content_type,
&content_transfer_encoding, &charset);
if (q->isdummy)
;
else if (!foundtextplain && HASTEXTPLAIN(q))
foundtextplain=1;
else
{
char buf[MAXLONGSIZE+4];
sprintf(buf, "del%d", ++cnt);
if (*cgi(buf)) continue; /* This one's gone */
}
if (!q->isdummy)
{
maildir_writemsgstr(newdraftfd, "\n--");
maildir_writemsgstr(newdraftfd, boundary);
maildir_writemsgstr(newdraftfd, "\n");
}
rfc2045_mimepos(q, &start_pos, &end_pos, &start_body, &dummy,
&dummy);
if (messagecopy(fp, start_pos, end_pos))
return (-1);
}
maildir_writemsgstr(newdraftfd, "\n--");
maildir_writemsgstr(newdraftfd, boundary);
maildir_writemsgstr(newdraftfd, "--\n");
return (0);
}
void attach_delete(const char *draft)
{
FILE *fp;
int fd2;
struct rfc2045 *rfcp;
char *draftfilename;
int isok=1;
struct stat stat_buf;
attachment_open(draft, &fp, &fd2, &rfcp);
if (!rfcp->firstpart)
{
rfc2045_free(rfcp);
fclose(fp);
return; /* No attachments to delete */
}
if (fstat(fileno(fp), &stat_buf))
{
fclose(fp);
enomem();
}
newdraftfd=maildir_recreatemsg(INBOX "." DRAFTS, draft, &draftfilename);
if (newdraftfd < 0)
{
fclose(fp);
enomem();
}
if (deleting_all_attachments(rfcp))
{
/* Deleting all attachments */
if (del_final_attachment(fp, rfcp)) isok=0;
}
else
{
if (del_some_attachments(fp, rfcp)) isok=0;
}
fclose(fp);
rfc2045_free(rfcp);
if ( maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, isok,
stat_buf.st_size))
{
free(draftfilename);
enomem();
}
free(draftfilename);
maildir_remcache(INBOX "." DRAFTS); /* Cache file invalid now */
}
/* ---------------------------------------------------------------------- */
/* Upload an attachment */
static int isbinary;
static int attachfd;
static const char *cgi_attachname, *cgi_attachfilename;
static int upload_start(const char *name, const char *filename, void *dummy)
{
const char *p;
p=strrchr(filename, '/');
if (p) filename=p+1;
p=strrchr(filename, '\\');
if (p) filename=p+1;
cgi_attachname=name;
cgi_attachfilename=filename;
isbinary=0;
return (0);
}
static int upload_file(const char *ptr, size_t cnt, void *voidptr)
{
size_t i;
for (i=0; i<cnt; i++)
if ( (ptr[i] < ' ' || ptr[i] >= 127) && ptr[i] != '\n' &&
ptr[i] != '\r')
isbinary=1;
maildir_writemsg(attachfd, ptr, cnt);
return (0);
}
static void upload_end(void *dummy)
{
}
#if 0
static void writebase64encode(const char *p, size_t n)
{
maildir_writemsg(newdraftfd, p, n);
}
#endif
static const char *search_mime_type(const char *mimetype, const char *filename)
{
FILE *fp;
char *p, *q;
if (!filename || !(filename=strrchr(filename, '.'))) return (0);
++filename;
if ((fp=fopen(mimetype, "r")) == NULL) return(0);
while ((p=maildir_readline(fp)) != NULL)
{
if ((q=strchr(p, '#')) != NULL) *q='\0';
if ((p=strtok(p, " \t")) == NULL) continue;
while ((q=strtok(NULL, " \t")) != NULL)
if (strcasecmp(q, filename) == 0)
{
fclose(fp);
return (p);
}
}
fclose(fp);
return (NULL);
}
const char *calc_mime_type(const char *filename)
{
static const char mimetypes[]=MIMETYPES;
const char *p;
char *q;
const char *r;
char *s;
p=mimetypes;
if (!p) enomem();
while (*p)
{
if (*p == ':')
{
++p;
continue;
}
q=strdup(p);
if (!q) enomem();
if ((s=strchr(q, ':')) != NULL) *s='\0';
if ((r=search_mime_type(q, filename)) != 0)
{
free(q);
return (r);
}
free(q);
while (*p && *p != ':')
p++;
}
return ("auto");
}
static int getkey(const char *keyname, int issecret)
{
int rc;
if (!*keyname)
return (1);
upload_start("", "", NULL);
rc=gpgexportkey(keyname, issecret, &upload_file, NULL);
upload_end(NULL);
return (rc);
}
#if 0
static void write_disposition_param(const char *label, const char *value)
{
char *p, *q;
const char *r;
while (value && ((r=strchr(value, ':')) || (r=strchr(value, '/'))
|| (r=strchr(value, '\\'))))
value=r+1;
if (!value || !*value) return;
maildir_writemsgstr(newdraftfd, "; ");
maildir_writemsgstr(newdraftfd, label);
maildir_writemsgstr(newdraftfd, "=\"");
p=strdup(value);
if (!p) enomem();
while ((q=strchr(p, '\\')) || (q=strchr(p, '"')))
*q='_';
maildir_writemsgstr(newdraftfd, p);
maildir_writemsgstr(newdraftfd, "\"");
free(p);
}
#endif
static int cnt_filename(const char *param,
const char *value,
void *void_arg)
{
*(int *)void_arg += strlen(param)+strlen(value)+5;
return 0;
}
static int save_filename(const char *param,
const char *value,
void *void_arg)
{
strcat(strcat(strcat(strcat((char *)void_arg, ";\n "), param),
"="), value);
return 0;
}
int attach_upload(const char *draft,
const char *attpubkey,
const char *attprivkey)
{
char *attachfilename;
char *draftfilename;
FILE *draftfp;
char *boundary;
FILE *tempfp;
struct rfc2045 *rfcp, *q;
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
off_t start_pos, end_pos, start_body;
int n;
char buf[BUFSIZ];
int pipefd[2];
struct stat stat_buf, attach_stat_buf;
off_t dummy;
int fd2;
char *filenamemime;
char *argvec[20];
char *filenamebuf;
pid_t pid1, pid2;
int waitstat;
/* Open the file containing the draft message */
draftfilename=maildir_find(INBOX "." DRAFTS, draft);
if (!draftfilename) return (0);
fd2=maildir_safeopen(draftfilename, O_RDONLY, 0);
draftfp=0;
if (fd2 >= 0)
{
draftfp=fdopen(fd2, "r");
if (draftfp == NULL)
close(fd2);
}
if (draftfp == 0)
enomem();
free(draftfilename);
if (fstat(fileno(draftfp), &stat_buf))
{
fclose(draftfp);
enomem();
}
/* Create a temporary file in tmp where we'll temporarily store the
** attachment
*/
attachfd=maildir_createmsg(INBOX "." DRAFTS, "temp", &attachfilename);
if (attachfd < 0)
{
fclose(draftfp);
enomem();
}
if ((
attpubkey ? getkey(attpubkey, 0):
attprivkey ? getkey(attprivkey, 1):
cgi_getfiles( &upload_start, &upload_file, &upload_end, 1, NULL))
|| maildir_writemsg_flush(attachfd))
{
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
free(attachfilename);
fclose(draftfp);
close(attachfd);
return (0);
}
if (fstat(attachfd, &attach_stat_buf) ||
attach_stat_buf.st_size + stat_buf.st_size > max_attach())
{
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
maildir_deletenewmsg(attachfd, INBOX "." DRAFTS, attachfilename);
free(attachfilename);
fclose(draftfp);
close(attachfd);
return (-2);
}
/* Calculate new MIME content boundary */
boundary=0;
tempfp=0;
n=dup(attachfd);
if (n < 0)
{
fclose(draftfp);
enomem();
}
tempfp=fdopen(n, "r");
if (tempfp == 0)
{
fclose(draftfp);
enomem();
}
do
{
if (boundary) free(boundary);
boundary=multipart_boundary_create();
} while ( multipart_boundary_checkf(boundary, draftfp) ||
multipart_boundary_checkf(boundary, tempfp));
if (tempfp) fclose(tempfp);
/* Parse existing draft for its MIME structure */
rfcp=rfc2045_fromfp(draftfp);
rfc2045_mimeinfo(rfcp, &content_type,
&content_transfer_encoding, &charset);
/* Create a new version of the draft message */
newdraftfd=maildir_recreatemsg(INBOX "." DRAFTS, draft, &draftfilename);
if (newdraftfd < 0)
{
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
fclose(draftfp);
close(attachfd);
enomem();
}
if (fseek(draftfp, 0L, SEEK_SET) < 0)
{
maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 0, 0);
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
fclose(draftfp);
close(attachfd);
enomem();
}
newmsg_copy_nonmime_headers(draftfp);
/* Create a multipart message, 1st attachment is the existing
** contents.
*/
newmsg_create_multipart(newdraftfd, charset, boundary);
maildir_writemsgstr(newdraftfd, "--");
maildir_writemsgstr(newdraftfd, boundary);
maildir_writemsgstr(newdraftfd, "\n");
if (rfcp == NULL || strcmp(content_type, "multipart/mixed"))
{
int rc;
/*
** The current draft does not have attachments. Take its
** sole contents, and write it as a text/plain attachment.
*/
if (fseek(draftfp, 0L, SEEK_SET) < 0)
rc = -1;
else
{
newmsg_copy_content_headers(draftfp);
maildir_writemsgstr(newdraftfd, "\n");
rfc2045_mimepos(rfcp, &start_pos, &end_pos,
&start_body,
&dummy, &dummy);
rc=messagecopy(draftfp, start_body, end_pos);
}
if (rc)
{
maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename,
0, 0);
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename,
0, 0);
fclose(draftfp);
close(newdraftfd);
close(attachfd);
enomem();
}
maildir_writemsgstr(newdraftfd, "\n--");
maildir_writemsgstr(newdraftfd, boundary);
maildir_writemsgstr(newdraftfd, "\n");
}
else
{
/* If the current draft already has MIME attachments,
** just copy them over to the new draft message.
*/
for (q=rfcp->firstpart; q; q=q->next)
{
if (q->isdummy) continue;
rfc2045_mimepos(q, &start_pos, &end_pos, &start_body,
&dummy, &dummy);
if (messagecopy(draftfp, start_pos, end_pos))
{
maildir_closemsg(newdraftfd, INBOX "." DRAFTS,
draftfilename, 0, 0);
maildir_closemsg(attachfd, INBOX "." DRAFTS,
attachfilename, 0, 0);
fclose(draftfp);
close(newdraftfd);
close(attachfd);
enomem();
}
maildir_writemsgstr(newdraftfd, "\n--");
maildir_writemsgstr(newdraftfd, boundary);
maildir_writemsgstr(newdraftfd, "\n");
}
}
{
const char *cp=strrchr(cgi_attachfilename, '/');
int len;
static const char fnStr[]="filename";
if (cp)
++cp;
else
cp=cgi_attachfilename;
len=1;
rfc2231_attrCreate(fnStr, cp,
sqwebmail_content_charset,
sqwebmail_content_language,
&cnt_filename, &len);
filenamemime=malloc(len);
if (filenamemime)
{
*filenamemime=0;
rfc2231_attrCreate(fnStr, cp,
sqwebmail_content_charset,
sqwebmail_content_language,
save_filename, filenamemime);
}
}
argvec[0]="makemime";
argvec[1]="-c";
if (attpubkey || attprivkey)
{
argvec[2]="application/pgp-keys";
n=3;
filenamebuf=0;
}
else
{
const char *pp;
argvec[2]=(char *)calc_mime_type(cgi_attachfilename);
argvec[3]="-N";
argvec[4]=cgi_attachfilename ?
(char *)cgi_attachfilename:"filename.dat";
n=5;
pp=*cgi("attach_inline") ?
"Content-Disposition: inline":
"Content-Disposition: attachment";
filenamebuf=malloc(strlen(pp)+strlen(filenamemime ?
filenamemime:"") + 15);
if (filenamebuf)
{
strcpy(filenamebuf, pp);
strcat(filenamebuf, filenamemime ? filenamemime:"");
argvec[n++]="-a";
argvec[n++]=filenamebuf;
}
}
argvec[n++]="-C";
argvec[n++]=(char *)sqwebmail_content_charset;
signal(SIGCHLD, SIG_DFL);
argvec[n++]="-";
argvec[n++]=0;
if (pipe(pipefd) < 0)
{
if (filenamemime)
free(filenamemime);
if (filenamebuf)
free(filenamebuf);
maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 0, 0);
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
fclose(draftfp);
close(newdraftfd);
close(attachfd);
enomem();
}
if (lseek(attachfd, 0L, SEEK_SET) < 0 || (pid1=fork()) < 0)
{
close(pipefd[0]);
close(pipefd[1]);
if (filenamemime)
free(filenamemime);
if (filenamebuf)
free(filenamebuf);
maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 0, 0);
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
fclose(draftfp);
close(newdraftfd);
close(attachfd);
enomem();
return (0);
}
if (pid1 == 0)
{
dup2(attachfd, 0);
dup2(pipefd[1], 1);
close(attachfd);
close(newdraftfd);
close(pipefd[0]);
close(pipefd[1]);
execv(MAKEMIME, argvec);
fprintf(stderr,
"CRIT: exec %s: %s\n", MAKEMIME, strerror(errno));
exit(1);
}
if (filenamemime)
free(filenamemime);
if (filenamebuf)
free(filenamebuf);
close (pipefd[1]);
while ((n=read(pipefd[0], buf, sizeof(buf))) > 0)
{
maildir_writemsg(newdraftfd, buf, n);
}
close(pipefd[0]);
for (;;)
{
pid2=wait(&waitstat);
if (pid2 == pid1)
{
waitstat= WIFEXITED(waitstat) ? WEXITSTATUS(waitstat)
: 1;
break;
}
if (pid2 == -1)
{
waitstat=1;
break;
}
}
if (waitstat > 0 || n < 0)
{
maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 0, 0);
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
fclose(draftfp);
close(newdraftfd);
maildir_deletenewmsg(attachfd, INBOX "." DRAFTS, attachfilename);
close(attachfd);
return (-3);
}
maildir_writemsgstr(newdraftfd, "\n--");
maildir_writemsgstr(newdraftfd, boundary);
maildir_writemsgstr(newdraftfd, "--\n");
/* Finish new draft message, let it replace the current one */
if (maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 1,
stat_buf.st_size))
{
maildir_closemsg(attachfd, INBOX "." DRAFTS, attachfilename, 0, 0);
free(draftfilename);
maildir_deletenewmsg(attachfd, INBOX "." DRAFTS, attachfilename);
free(attachfilename);
rfc2045_free(rfcp);
fclose(draftfp);
close(attachfd);
return (-1);
}
free(draftfilename);
fclose(draftfp);
/* Remove and delete temp attachment file */
maildir_deletenewmsg(attachfd, INBOX "." DRAFTS, attachfilename);
free(attachfilename);
rfc2045_free(rfcp);
return (0);
}
void doattach(const char *folder, const char *draft)
{
int quotaflag=0;
CHECKFILENAME(draft);
if (*cgi("dodelete"))
{
if (!tokencheck())
{
attach_delete(draft);
tokensave();
}
}
else if (*cgi("upload"))
{
if (!tokencheck())
{
quotaflag=attach_upload(draft, NULL, NULL);
tokensave();
}
}
else if (*cgi("uppubkey") && libmail_gpg_has_gpg(GPGDIR) == 0)
{
if (!tokencheck())
{
quotaflag=attach_upload(draft, cgi("pubkey"), NULL);
tokensave();
}
}
else if (*cgi("upprivkey") && *cgi("really") &&
libmail_gpg_has_gpg(GPGDIR) == 0)
{
if (!tokencheck())
{
quotaflag=attach_upload(draft, NULL, cgi("privkey"));
tokensave();
}
}
else if (*cgi("previewmsg"))
{
cgi_put("draft", draft);
newmsg_do(folder);
return;
}
else if (*cgi("sendmsg"))
{
cgi_put("draftmessage", draft);
newmsg_do(folder);
return;
}
else if (*cgi("savedraft"))
{
sendmsg_done();
return;
}
if (quotaflag == -2)
{
http_redirect_argss(
"&form=attachments&pos=%s&draft=%s&error=limits",
cgi("pos"), draft);
}
else if (quotaflag == -3)
{
http_redirect_argss(
"&form=attachments&pos=%s&draft=%s&error=makemime",
cgi("pos"), draft);
}
else
{
http_redirect_argss(
(quotaflag ? "&form=attachments&pos=%s&draft=%s&error=quota":
"&form=attachments&pos=%s&draft=%s"), cgi("pos"),
draft);
}
}