Viewing file:
autoresponse.c (11.41 KB) -rw-rw-rw-Select action/file-type:

(
+) |

(
+) |

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

(
+) |
SDB (
+) |

(
+) |

(
+) |

(
+) |

(
+) |

(
+) |
/*
*/
/*
** Copyright 2001-2011 Double Precision, Inc. See COPYING for
** distribution information.
*/
#include "config.h"
#include "autoresponse.h"
#include "maildir/autoresponse.h"
#include "mailfilter.h"
#include "unicode/unicode.h"
#include "sqwebmail.h"
#include "htmllibdir.h"
#include "maildir.h"
#include "maildir/maildirmisc.h"
#include "maildir/maildirfilter.h"
#include "rfc2045/rfc2045.h"
#include "newmsg.h"
#include "cgi/cgi.h"
#include "numlib/numlib.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <errno.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
extern const char *sqwebmail_content_charset;
extern void output_attrencoded(const char *);
extern const char *calc_mime_type(const char *filename);
extern void charset_warning(const char *);
static void save_autoresponse(const char *p, size_t l, void *vp)
{
FILE *fp=*(FILE **)vp;
if (fp)
if (fwrite(p, l, 1, fp) != 1)
; /* ignore */
}
static int read_headers(FILE *);
static int show_autoresponse_trampoline(const char *ptr, size_t cnt, void *arg)
{
show_textarea((struct show_textarea_info *)arg, ptr, cnt);
return 0;
}
void autoresponse()
{
const char *autoresp_title1=getarg("TITLE1");
const char *autoresp_title2=getarg("TITLE2");
const char *autoresp_text1=getarg("TEXT1");
const char *autoresp_text2=getarg("TEXT2");
if ( *cgi("do.newautoresp"))
{
const char *name=cgi("newname");
char *p;
FILE *fp;
p=folder_toutf7(name);
if (!p || maildir_autoresponse_validate(NULL, p))
{
free(p);
printf("%s", getarg("BADNAME"));
return;
}
if ((fp=maildir_autoresponse_open(NULL, p)) != NULL)
{
free(p);
fclose(fp);
printf("%s", getarg("EEXIST"));
return;
}
printf("%s%s%s\n", autoresp_title1, name, autoresp_title2);
printf("<input type=\"hidden\" name=\"autoresponse\" value=\"");
output_attrencoded(p);
printf("\" />\n");
free(p);
printf("%s%s\n", autoresp_text1, autoresp_text2);
printf("%s<input type=\"file\" size=\"20\" name=\"uploadfile\" /><br />",
getarg("UPLOAD"));
printf("<input type=\"submit\" name=\"do.autorespcreate\""
" value=\"%s\" />", getarg("SAVE"));
return;
}
if ( *cgi("do.autorespedit"))
{
const char *autorespname=cgi("autoresponse_choose");
FILE *fp;
char *s=folder_fromutf7(autorespname);
const char *pp;
if (!s)
{
printf(getarg("ERROR"), strerror(errno));
return;
}
pp=cgi("replytext");
if ((fp=maildir_autoresponse_open(NULL, autorespname)) == NULL
&& !*pp)
{
free(s);
return;
}
printf("%s%s%s\n", autoresp_title1, s, autoresp_title2);
if (fp && read_headers(fp))
{
fclose(fp);
free(s);
return;
}
printf("<input type=\"hidden\" name=\"autoresponse\" value=\"");
output_attrencoded(autorespname);
printf("\" />\n");
free(s);
printf("%s", autoresp_text1);
if (pp && *pp)
output_attrencoded(pp);
else
{
struct show_textarea_info info;
libmail_u_convert_handle_t h;
show_textarea_init(&info, 0);
h=libmail_u_convert_init("utf-8",
sqwebmail_content_charset,
show_autoresponse_trampoline,
&info);
if (h)
{
size_t i;
char buf[BUFSIZ];
while ((i=fread(buf, 1, sizeof(buf), fp)) > 0)
{
libmail_u_convert(h, buf, i);
}
libmail_u_convert_deinit(h, NULL);
}
}
if (fp)
fclose(fp);
printf("%s\n", autoresp_text2);
printf("%s<input type=\"file\" size=\"20\" name=\"uploadfile\" /><br />",
getarg("UPLOAD"));
printf("<input type=\"submit\" name=\"do.autorespcreate\""
" value=\"%s\" />", getarg("SAVE"));
return;
}
}
/*
** Read the MIME headers in the autoresponse file, to make sure that we
** can show it.
*/
static int read_headers(FILE *fp)
{
struct rfc2045 *rfc2045p=rfc2045_alloc();
static const char mv[]="Mime-Version: 1.0\n";
char buf[BUFSIZ];
char *s;
const char *content_type, *content_transfer_encoding, *charset;
rfc2045_parse(rfc2045p, mv, sizeof(mv)-1);
while ((s=fgets(buf, sizeof(buf), fp)) != NULL)
{
rfc2045_parse(rfc2045p, s, strlen(s));
if (strcmp(s, "\n") == 0 || strcmp(s, "\r\n") == 0)
break;
}
rfc2045_parse_partial(rfc2045p);
rfc2045_mimeinfo(rfc2045p, &content_type,
&content_transfer_encoding,
&charset);
if (strcmp(content_type, "text/plain") ||
!rfc2045_isflowed(rfc2045p))
{
printf(getarg("ATT"), content_type);
rfc2045_free(rfc2045p);
return (-1);
}
rfc2045_free(rfc2045p);
return (0);
}
static FILE *upload_attachment(const char *);
void autoresponsedelete()
{
if ( *cgi("do.autorespcreate"))
{
const char *autorespname=cgi("autoresponse");
const char *autoresptxt=cgi("text");
FILE *fp;
size_t l;
if ((fp=upload_attachment(autorespname)) == NULL)
{
struct wrap_info uw;
if ((fp=maildir_autoresponse_create(NULL,
autorespname))
== NULL)
{
printf(getarg("SAVEFAILED"), strerror(errno));
return;
}
l=strlen(autoresptxt);
while (l && (autoresptxt[l-1] == '\r' ||
autoresptxt[l-1] == '\n'))
--l;
fprintf(fp, "Content-Type: text/plain");
fprintf(fp, "; format=flowed; delsp=yes"
"; charset=\"utf-8\"\n");
fprintf(fp, "Content-Transfer-Encoding: 8bit\n\n");
wrap_text_init(&uw, "utf-8", save_autoresponse, &fp);
wrap_text(&uw, autoresptxt, l);
}
if (fflush(fp) || ferror(fp))
{
fclose(fp);
printf(getarg("SAVEFAILED"), strerror(errno));
return;
}
if (maildir_autoresponse_create_finish(NULL, autorespname, fp))
{
if (errno == ENOSPC)
{
cgi_put("do.autorespedit", "1");
cgi_put("autoresponse_choose", autorespname);
cgi_put("replytext", cgi("text"));
printf(getarg("QUOTA"), strerror(errno));
}
else
printf(getarg("SAVEFAILED"), strerror(errno));
}
return;
}
if ( *cgi("do.autorespdelete"))
{
const char *autorespname=cgi("autoresponse_choose");
if (mailfilter_autoreplyused(autorespname))
{
char *s=folder_fromutf7(autorespname);
printf(getarg("INUSE"), s ? s:"");
if (s)
free(s);
}
else
maildir_autoresponse_delete(NULL, autorespname);
return;
}
}
struct upload_attach_info {
FILE *fp;
const char *filename;
const char *name;
const char *autorespname;
} ;
static int start_upload(const char *, const char *, void *);
static int upload(const char *, size_t, void *);
static void end_upload(void *);
static FILE *upload_attachment(const char *autorespname)
{
struct upload_attach_info uai;
uai.fp=NULL;
uai.autorespname=autorespname;
if (cgi_getfiles( &start_upload, &upload, &end_upload, 1, &uai ))
{
if (uai.fp)
fclose(uai.fp);
return (NULL);
}
return (uai.fp);
}
static int start_upload(const char *name, const char *filename, void *vp)
{
struct upload_attach_info *uai=(struct upload_attach_info *)vp;
const char *p;
p=strrchr(filename, '/');
if (p) filename=p+1;
p=strrchr(filename, '\\');
if (p) filename=p+1;
if (*filename)
{
uai->filename=filename;
}
else
{
p=strrchr(name, '/');
if (p) name=p+1;
p=strrchr(name, '\\');
if (p) name=p+1;
uai->filename=p;
}
uai->fp=tmpfile();
if (!uai->fp)
enomem();
return (0);
}
static int upload(const char *c, size_t n, void *vp)
{
struct upload_attach_info *uai=(struct upload_attach_info *)vp;
if (fwrite(c, n, 1, uai->fp) != 1)
{
fclose(uai->fp);
enomem();
}
return (0);
}
static int upload_messagerfc822(FILE *, FILE *);
static void end_upload(void *vp)
{
struct upload_attach_info *uai=(struct upload_attach_info *)vp;
const char *mimetype;
char *argvec[10];
int n;
pid_t pid1, pid2;
int waitstat;
FILE *afp;
if (fflush(uai->fp) || ferror(uai->fp)
|| fseek(uai->fp, 0L, SEEK_SET) < 0)
{
fclose(uai->fp);
enomem();
}
mimetype=calc_mime_type(uai->filename);
if (strcasecmp(mimetype, "message/rfc822") == 0)
{
/* Magic */
afp=maildir_autoresponse_create(NULL, uai->autorespname);
if (!afp)
{
fclose(uai->fp);
enomem();
}
if (upload_messagerfc822(uai->fp, afp) ||
fflush(afp) || ferror(afp))
{
fclose(uai->fp);
fclose(afp);
enomem();
}
fclose(uai->fp);
uai->fp=afp;
return;
}
argvec[0]="makemime";
argvec[1]="-c";
argvec[2]=(char *)mimetype;
n=3;
if (strncasecmp(argvec[2], "text/", 5) == 0 ||
strcasecmp(argvec[2], "auto") == 0)
{
argvec[3]="-C";
argvec[4]=(char *)sqwebmail_content_charset;
n=5;
}
argvec[n++]="-";
argvec[n]=0;
afp=maildir_autoresponse_create(NULL, uai->autorespname);
if (!afp)
{
fclose(uai->fp);
enomem();
}
signal(SIGCHLD, SIG_DFL);
pid1=fork();
if (pid1 < 0)
{
fclose(afp);
fclose(uai->fp);
enomem();
}
if (pid1 == 0)
{
dup2(fileno(uai->fp), 0);
dup2(fileno(afp), 1);
fclose(uai->fp);
fclose(afp);
execv(MAKEMIME, argvec);
fprintf(stderr,
"CRIT: exec %s: %s\n", MAKEMIME, strerror(errno));
exit(1);
}
for (;;)
{
pid2=wait(&waitstat);
if (pid2 == pid1)
{
waitstat= WIFEXITED(waitstat) ? WEXITSTATUS(waitstat)
: 1;
break;
}
if (pid2 == -1)
{
waitstat=1;
break;
}
}
if (waitstat)
{
fclose(afp);
fclose(uai->fp);
enomem();
}
fclose(uai->fp);
uai->fp=afp;
}
/*
** If we get something that's MIMEed as message/rfc822, read it, strip its
** headers except for the MIME content- headers, then save what's left as
** our autoreply. This allows for a convenient way to upload
** multipart/alternative content.
*/
static int upload_messagerfc822(FILE *i, FILE *o)
{
char buf[BUFSIZ];
int skip_hdr;
int c;
const char *pp;
skip_hdr=0;
for (;;)
{
if (fgets(buf, sizeof(buf), i) == NULL)
{
fprintf(o, "\n");
return (0);
}
if (strcmp(buf, "\n") == 0 || strcmp(buf, "\r\n") == 0)
{
fprintf(o, "\n");
break;
}
if (!isspace((int)(unsigned char)*buf))
skip_hdr=strncasecmp(buf, "content-", 8) != 0;
if (skip_hdr)
continue;
for (pp=buf; *pp; pp++)
if (*pp != '\r')
if (putc((int)(unsigned char)*pp, o)
== EOF)
return (-1);
}
while ((c=getc(i)) != EOF)
if (c != '\r')
if (putc(c, o) == EOF)
return (-1);
return (0);
}
static int comp_autorespname(const void *a, const void *b)
{
const char *ca=*(const char **)a;
const char *cb=*(const char **)b;
char *sa=folder_fromutf7(ca);
char *sb=folder_fromutf7(cb);
int i=sa && sb ? strcoll(sa, sb):0;
free(sa);
free(sb);
return (i);
}
void autoresponselist()
{
char **list=maildir_autoresponse_list(NULL); /* I'm sorry... */
size_t i;
if (!list)
{
printf(getarg("ERROR"), strerror(errno));
return;
}
for (i=0; list[i]; i++)
;
qsort(list, i, sizeof(list[0]), &comp_autorespname);
for (i=0; list[i]; i++)
{
char *s;
printf("<option value=\"");
output_attrencoded(list[i]);
printf("\">");
s=folder_fromutf7(list[i]);
output_attrencoded(s);
printf("</option>");
free(s);
}
maildir_autoresponse_list_free(list);
}
void autoresponsepick()
{
char **list=maildir_autoresponse_list(NULL);
size_t i;
const char *choice=cgi("autoresponse_choose");
if (!list)
{
printf(getarg("ERROR"), strerror(errno));
return;
}
for (i=0; list[i]; i++)
;
qsort(list, i, sizeof(list[0]), &comp_autorespname);
for (i=0; list[i]; i++)
{
char *s;
printf("<option%s value=\"",
strcmp(choice, list[i]) ? "":" selected='selected'");
output_attrencoded(list[i]);
printf("\">");
s=folder_fromutf7(list[i]);
output_attrencoded(s);
printf("</option>");
free(s);
}
maildir_autoresponse_list_free(list);
}