From 9c45d9ad13fdf439d44d7443ae75da15ea0223ed Mon Sep 17 00:00:00 2001 From: Sam Varshavchik Date: Mon, 19 Aug 2013 16:39:41 -0400 Subject: Initial checkin Imported from subversion report, converted to git. Updated all paths in scripts and makefiles, reflecting the new directory hierarchy. --- sqwebmail/newmsg_create.c | 1433 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1433 insertions(+) create mode 100644 sqwebmail/newmsg_create.c (limited to 'sqwebmail/newmsg_create.c') diff --git a/sqwebmail/newmsg_create.c b/sqwebmail/newmsg_create.c new file mode 100644 index 0000000..5053d47 --- /dev/null +++ b/sqwebmail/newmsg_create.c @@ -0,0 +1,1433 @@ +/* +** Copyright 1998 - 2009 Double Precision, Inc. See COPYING for +** distribution information. +*/ + + +/* +*/ +#include "config.h" +#include "cgi/cgi.h" +#include "sqconfig.h" +#include "sqwebmail.h" +#include "auth.h" +#include "maildir.h" +#include "newmsg.h" +#include "folder.h" +#include "filter.h" +#include "pref.h" +#include "gpg.h" +#include "addressbook.h" +#include "maildir/maildirmisc.h" +#include "rfc822/rfc822.h" +#include "rfc2045/rfc2045.h" +#include "rfc822/rfc2047.h" +#include "rfc822/encode.h" +#include "rfc822/rfc822hdr.h" +#include "msg2html.h" +#include "gpglib/gpglib.h" +#include "http11/http11.h" +#include "htmllibdir.h" +#include "unicode/unicode.h" +#include "courierauth.h" + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#define HASTEXTPLAIN(q) (rfc2045_searchcontenttype((q), "text/plain") != NULL) +/* Also in attachments.c */ + +extern const char *rfc822_mkdt(time_t); + +extern const char *sqwebmail_content_charset; +extern const char *sqwebmail_content_language; + +int newdraftfd; +extern const char *sqwebmail_mailboxid; + +const char mimemsg[]="This is a MIME-formatted message. If you see this text it means that your\nmail software cannot handle MIME-formatted messages.\n\n"; + +char *newmsg_createdraft_do(const char *, const char *, int); + +/* Save message in a draft file */ + +char *newmsg_createdraft(const char *curdraft) +{ + if (curdraft && *curdraft) + { + char *base=maildir_basename(curdraft); + char *filename=maildir_find(INBOX "." DRAFTS, base); + + if (filename) + { + char *p=newmsg_createdraft_do(filename, cgi("message"), 0); + + free(filename); + free(base); + return (p); + } + free(base); + } + return (newmsg_createdraft_do(0, cgi("message"), 0)); +} + +static void create_draftheader_do(const char *hdrname, const char *p, + int isrfc822addr); + +static void create_draftheader(const char *hdrname, const char *p, + const char *q, int isrfc822addr) +{ + if (q && *q) /* Add from address book */ + { + char *nick=cgi_multiple("nick", ","); + char *s; + + if (nick) + { + s=malloc(strlen(p)+strlen(nick)+2); + + if (s) + { + strcpy(s, p); + if (*s && *nick) strcat(s, ","); + strcat(s, nick); + create_draftheader_do(hdrname, s, isrfc822addr); + free(s); + free(nick); + return; + } + free(nick); + } + + } + create_draftheader_do(hdrname, p, isrfc822addr); +} + +#define ISLWS(c) ((c)=='\t' || (c)=='\r' || (c)=='\n' || (c)==' ') + +static void header_wrap(const char *name, const char *hdr, + char *outbuf, size_t *outcnt) +{ +char *pfix; +size_t offset=strlen(name); + + *outcnt=0; + pfix=""; + + while (*hdr) + { + size_t i; + size_t spc; + + for (spc=0, i=0; hdr[i]; i++) + { + if (i + offset >= 75 && spc) + { + i = spc; + offset = 0; + break; + } + + if (ISLWS(hdr[i])) + { + spc = i; + while (ISLWS(hdr[i+1])) + ++i; + } + } + + if (outbuf) + { + strcpy(outbuf, pfix); + outbuf += strlen(pfix); + } + *outcnt += strlen(pfix); + + if (outbuf) + { + size_t j; + for (j=0; j < i; j++) + { + if (ISLWS(hdr[j])) + { + *(outbuf++) = ' '; + while (ISLWS(hdr[j+1])) + ++j; + } + else + *(outbuf++) = hdr[j]; + } + } + *outcnt += i; + pfix="\n "; + hdr += i; + while (ISLWS(*hdr)) + ++hdr; + } + if (outbuf) + *outbuf=0; + ++*outcnt; +} + +static void create_draftheader_do(const char *hdrname, const char *p, + int isrfc822addr) +{ +char *s, *t; +size_t l; + + if (!*p) return; + + if (!isrfc822addr) + { + s=rfc2047_encode_str(p, sqwebmail_content_charset, + rfc2047_qp_allow_any); + } + else + { + s=rfc2047_encode_header_tobuf("to", p, + sqwebmail_content_charset); + } + + header_wrap(hdrname, s, NULL, &l); + if (l) + { + if (!(t=malloc(l))) enomem(); + header_wrap(hdrname, s, t, &l); + if (*t) + { + free(s); + s = t; + } + else + free(t); + } + + if (!s) + { + close(newdraftfd); + enomem(); + } + maildir_writemsgstr(newdraftfd, hdrname); + maildir_writemsgstr(newdraftfd, s); + maildir_writemsgstr(newdraftfd, "\n"); + free(s); +} + +void newmsg_create_multipart(int newdraftfd, const char *charset, + const char *multipart_boundary) +{ + maildir_writemsgstr(newdraftfd, + "Mime-version: 1.0\n" + "Content-Type: multipart/mixed; boundary=\""); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd, "\"; charset=\""); + maildir_writemsgstr(newdraftfd, charset); + maildir_writemsgstr(newdraftfd, + "\"\n\n"); + + maildir_writemsgstr(newdraftfd, mimemsg); +} + + +static char *newmsg_multipart_boundary(FILE *, const char *); +static void newmsg_copy_attachments(struct rfc2045 *, FILE *, const char *); + +void newmsg_copy_nonmime_headers(FILE *fp) +{ +char *header, *value; +char *q; + + while ((header=maildir_readheader(fp, &value, 1)) != NULL) + { + if (strcmp(header, "mime-version") == 0 || + strncmp(header, "content-", 8) == 0) continue; + + /* Fluff - capitalize header names */ + + for (q=header; *q; q++) + { + for (*q=toupper(*q); *q; q++) + if (*q == '-') break; + if (!*q) + break; + } + + maildir_writemsgstr(newdraftfd, header); + maildir_writemsgstr(newdraftfd, ": "); + maildir_writemsgstr(newdraftfd, value); + maildir_writemsgstr(newdraftfd, "\n"); + } +} + +void newmsg_copy_content_headers(FILE *fp) +{ +char *header, *value; +char *q; + + while ((header=maildir_readheader(fp, &value, 1)) != NULL) + { + if (strncmp(header, "content-", 8)) continue; + + for (q=header; *q; q++) + { + for (*q=toupper(*q); *q; q++) + if (*q == '-') break; + if (!*q) + break; + } + + maildir_writemsgstr(newdraftfd, header); + maildir_writemsgstr(newdraftfd, ": "); + maildir_writemsgstr(newdraftfd, value); + maildir_writemsgstr(newdraftfd, "\n"); + } +} + +void wrap_text_init(struct wrap_info *uw, + const char *output_chset, + void (*output_func)(const char *p, size_t l, void *arg), + void *arg) +{ + memset(uw, 0, sizeof(*uw)); + uw->output_func=output_func; + uw->output_chset=output_chset; + uw->arg=arg; +} + +static void do_save_u_line(struct wrap_info *uw, + const unicode_char *uc, + size_t ucsize, + int flowed) +{ + char *cbuf; + size_t csize; + + libmail_u_convert_handle_t h= + libmail_u_convert_fromu_init(uw->output_chset, + &cbuf, + &csize, + 0); + + if (h) + { + if (ucsize) + { + if (uc[0] == ' ') + libmail_u_convert_uc(h, uc, 1); + /* Space stuff */ + + libmail_u_convert_uc(h, uc, ucsize); + } + if (flowed) + { + unicode_char spc=' '; + libmail_u_convert_uc(h, &spc, 1); + } + + { + unicode_char nl='\n'; + libmail_u_convert_uc(h, &nl, 1); + } + + if (libmail_u_convert_deinit(h, NULL)) + cbuf=NULL; + } + else + cbuf=NULL; + + if (cbuf) + { + (*uw->output_func)(cbuf, csize, uw->arg); + free(cbuf); + } +} + +static void flush_line(struct wrap_info *uw, int flowed) +{ + do_save_u_line(uw, uw->uc + uw->line_start, + uw->word_start - uw->line_start, flowed); + + uw->line_start=uw->word_start; + uw->line_width=0; +} + +static void add_word(struct wrap_info *uw) +{ + if (uw->line_start < uw->word_start && + uw->line_width + uw->word_width > MYLINESIZE) + flush_line(uw, 1); + + uw->line_width += uw->word_width; + + uw->word_start=uw->cur_index; + uw->word_width=0; +} + +static int do_save_u_process_lb(int type, void *arg) +{ + struct wrap_info *uw=(struct wrap_info *)arg; + + if (uw->cur_index >= uw->ucsize) + enomem(); + + if (type != UNICODE_LB_NONE) + { + add_word(uw); + if (type == UNICODE_LB_MANDATORY) + flush_line(uw, 0); + } + + + if (uw->word_width >= MYLINESIZE && + uw->cur_index > 0 && + unicode_grapheme_break(uw->uc[uw->cur_index-1], + uw->uc[uw->cur_index])) + add_word(uw); + + uw->word_width += unicode_wcwidth(uw->uc[uw->cur_index]); + ++uw->cur_index; + return 0; +} + +static void do_wrap_u_line(struct wrap_info *uw, + const unicode_char *uc, + size_t ucsize) +{ + unicode_lb_info_t lb; + + while (ucsize && uc[ucsize-1] == ' ') + --ucsize; + + uw->uc=uc; + uw->ucsize=ucsize; + uw->cur_index=0; + uw->word_start=0; + uw->word_width=0; + + uw->line_start=0; + uw->line_width=0; + if ((lb=unicode_lb_init(do_save_u_process_lb, uw)) != NULL) + { + unicode_lb_set_opts(lb, + UNICODE_LB_OPT_PRBREAK + | UNICODE_LB_OPT_SYBREAK); + unicode_lb_next_cnt(lb, uc, ucsize); + unicode_lb_end(lb); + add_word(uw); + flush_line(uw, 0); + } +} + +static void save_textplain(const char *p, size_t l, void *dummy) +{ + maildir_writemsg(newdraftfd, p, l); +} + +void wrap_text(struct wrap_info *uw, + const char *newmsg, + size_t newmsg_size) +{ + size_t i=0, j; + + while (i < newmsg_size) + { + unicode_char *uc; + size_t ucsize; + libmail_u_convert_handle_t h; + + j=i; + + while (i') + do_save_u_line(uw, uc, j, 0); + else + do_wrap_u_line(uw, uc, j); + + free(uc); + } + + if (i < newmsg_size) + ++i; + } +} + +static void convert_text2html(const char *p, size_t l, void *arg) +{ + struct msg2html_textplain_info *info= + (struct msg2html_textplain_info *)arg; + + msg2html_textplain(info, p, l); +} + +static char *mkurl(const char *url, void *dummy) +{ + char *buf=malloc(strlen(url)*2+100); + + if (!buf) + return NULL; + + /* msg2html guarantees that the characters in url are "safe" */ + + sprintf(buf, "%s", url, url); + return buf; +} + +char *newmsg_createdraft_do(const char *curdraft, const char *newmsg, + int keepheader) +{ +char *draftfilename; +FILE *fp=0; +char *multipart_boundary; +const char *content_type; +const char *content_transfer_encoding; +const char *charset; +unsigned long prev_size=0; +off_t transferencodingpos; +off_t transferencoding2pos; +int is_newevent=strcmp(cgi("form"), "newevent") == 0; +struct rfc2045 *rfcp; +int has_attachments=0; +size_t newmsg_size; +char *sig, *footer; + +/* +** Trim extra newlines. +*/ + newmsg_size=strlen(newmsg); + + while (newmsg_size && newmsg[newmsg_size-1] == '\n') + --newmsg_size; + +/* We're on the 'new event' screen */ + + if (curdraft) /* Reuse a draft filename */ + newdraftfd=maildir_recreatemsg(INBOX "." DRAFTS, curdraft, &draftfilename); + else + newdraftfd=maildir_createmsg(INBOX "." DRAFTS, 0, &draftfilename); + if (newdraftfd < 0) enomem(); + + pref_wikifmt=0; + if (strcmp(cgi("textformat"), "wiki") == 0) + pref_wikifmt=1; + pref_update(); + + fp=NULL; + if (curdraft) + { + int x=maildir_safeopen(curdraft, O_RDONLY, 0); + + if (x >= 0) + if ((fp=fdopen(x, "r")) == 0) + close(x); + } + + if (fp) + { + char *header, *value; + struct stat stat_buf; + + if (fstat(fileno(fp), &stat_buf)) + { + fclose(fp); + enomem(); + } + prev_size=stat_buf.st_size; + + while ((header=maildir_readheader(fp, &value, 1)) != NULL) + { + if (keepheader == NEWMSG_SQISPELL) + { + if (strcasecmp(header, "mime-version") == 0 || + strncasecmp(header, "content-", 8) == 0) + continue; + } + else if (keepheader == NEWMSG_PCP) + { + if (strcasecmp(header, "mime-version") == 0 || + strncasecmp(header, "content-", 8) == 0 || + strcasecmp(header, "date") == 0 || + strcasecmp(header, "from") == 0 || + strcasecmp(header, "subject") == 0) + continue; + } + else + { + if (strcmp(header, "in-reply-to") && + strcmp(header, "references") && + strncmp(header, "x-", 2)) continue; + /* Do not discard these headers */ + } + + if (strcasecmp(header, "x-sqwebmail-wikifmt") == 0) + continue; + + maildir_writemsgstr(newdraftfd, header); + maildir_writemsgstr(newdraftfd, ": "); + maildir_writemsgstr(newdraftfd, value); + maildir_writemsgstr(newdraftfd, "\n"); + } + } + else if (is_newevent) + maildir_writemsgstr(newdraftfd, "X-Event: 1\n"); + + if (!keepheader + || keepheader == NEWMSG_PCP) + /* Coming back from msg edit, set headers */ + { + const char *p=cgi("headerfrom"); + + if (!*p) p=pref_from; + if (!p || !*p || auth_getoptionenvint("wbnochangingfrom")) + p=login_fromhdr(); + + create_draftheader("From: ", p, 0, 1); + + if (!pref_from || strcmp(p, pref_from)) + pref_setfrom(p); + +/* sam ???? + create_draftheader("In-Reply-To: ", cgi("headerin-reply-to")); +*/ + if (!is_newevent) + { +#if 0 + { + FILE *fp; + fp=fopen("/tmp/pid", "w"); + fprintf(fp, "%d", getpid()); + fclose(fp); + sleep(10); + } +#endif + + create_draftheader("To: ", cgi("headerto"), + cgi("addressbook_to"), 1); + create_draftheader("Cc: ", cgi("headercc"), + cgi("addressbook_cc"), 1); + create_draftheader("Bcc: ", cgi("headerbcc"), + cgi("addressbook_bcc"), 1); + create_draftheader("Reply-To: ", cgi("headerreply-to"), 0, 1); + } + } + + if (pref_wikifmt) + create_draftheader("x-sqwebmail-wikifmt: ", "1", 0, 0); + + if (!keepheader || keepheader == NEWMSG_PCP) + { + time_t t; + + create_draftheader("Subject: ", cgi("headersubject"), 0, 0); + + time(&t); + create_draftheader("Date: ", rfc822_mkdate(t), 0, 0); + } + + /* If the message has attachments, calculate multipart boundary */ + + rfcp=NULL; + + if (fp) + { + rfcp=rfc2045_fromfp(fp); + if (!rfcp) + { + close(newdraftfd); + fclose(fp); + enomem(); + } + } + + multipart_boundary=newmsg_multipart_boundary(fp, newmsg); + + if (rfcp && rfcp->firstpart && + strcmp((rfc2045_mimeinfo(rfcp, &content_type, + &content_transfer_encoding, &charset), + content_type), "multipart/mixed") == 0) + { + has_attachments=1; + newmsg_create_multipart(newdraftfd, + sqwebmail_content_charset, multipart_boundary); + + maildir_writemsgstr(newdraftfd, "--"); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd,"\n"); + } + else + { + maildir_writemsgstr(newdraftfd, "Mime-Version: 1.0\n"); + } + + if (pref_wikifmt) + { + ++multipart_boundary[strlen(multipart_boundary)-1]; + + maildir_writemsgstr(newdraftfd, + "Content-Type: multipart/alternative;" + " boundary=\""); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd, "\"\n" + "\n" + "\n" + "--"); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd, "\n"); + } + + maildir_writemsgstr(newdraftfd, + "Content-Type: text/plain; format=flowed; delsp=yes;" + " charset=\""); + maildir_writemsgstr(newdraftfd, sqwebmail_content_charset); + maildir_writemsgstr(newdraftfd, "\"\n"); + + maildir_writemsgstr(newdraftfd, "Content-Transfer-Encoding: "); + transferencoding2pos=transferencodingpos=writebufpos; + maildir_writemsgstr(newdraftfd, "7bit\n\n"); + + /* maildir_writemsgstr(newdraftfd, "\n"); */ + + sig=pref_getsig(); + footer=pref_getfile(http11_open_langfile(get_templatedir(), + sqwebmail_content_language, + "footer")); + + while (newmsg_size && + (newmsg[newmsg_size-1] == '\r' || + newmsg[newmsg_size-1] == '\n')) + --newmsg_size; + + { + struct wrap_info uw; + + wrap_text_init(&uw, sqwebmail_content_charset, + save_textplain, NULL); + + wrap_text(&uw, newmsg, newmsg_size); + + if ((sig && *sig) || (footer && *footer)) + { + static const unicode_char sig_line[]={'-', '-', ' '}; + + do_save_u_line(&uw, sig_line, 0, 0); + do_save_u_line(&uw, sig_line, 3, 0); + } + + if (sig && *sig) + wrap_text(&uw, sig, strlen(sig)); + + if (footer && *footer) + { + do_save_u_line(&uw, NULL, 0, 0); + maildir_writemsg(newdraftfd, footer, strlen(footer)); + } + + } + + if (pref_wikifmt) + { + struct msg2html_textplain_info *info; + + maildir_writemsgstr(newdraftfd, "\n" + "--"); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd, "\n" + "Content-Type: text/html; charset=\""); + maildir_writemsgstr(newdraftfd, sqwebmail_content_charset); + maildir_writemsgstr(newdraftfd, "\"\n" + "Content-Transfer-Encoding: "); + transferencoding2pos=writebufpos; + maildir_writemsgstr(newdraftfd, "7bit\n\n"); + + info=msg2html_textplain_start(sqwebmail_content_charset, + sqwebmail_content_charset, + 1, + 1, + 0, + mkurl, NULL, + NULL, + NULL, + 1, + save_textplain, + NULL); + + if (info) + { + struct wrap_info uw; + + wrap_text_init(&uw, sqwebmail_content_charset, + convert_text2html, info); + + wrap_text(&uw, newmsg, newmsg_size); + msg2html_textplain_end(info); + } + + if ((sig && *sig) || (footer && *footer)) + save_textplain("
\n", 7, NULL); + + if (sig && *sig) + { + + info=msg2html_textplain_start(sqwebmail_content_charset, + sqwebmail_content_charset, + 1, + 1, + 0, + mkurl, NULL, + NULL, + NULL, + 1, + save_textplain, + NULL); + + if (info) + { + struct wrap_info uw; + + wrap_text_init(&uw, sqwebmail_content_charset, + convert_text2html, info); + + wrap_text(&uw, sig, strlen(sig)); + msg2html_textplain_end(info); + } + } + + if (footer && *footer) + { + save_textplain("
\n", 7, NULL); + + info=msg2html_textplain_start(sqwebmail_content_charset, + sqwebmail_content_charset, + 1, + 1, + 0, + mkurl, NULL, + NULL, + NULL, + 1, + save_textplain, + NULL); + + if (info) + { + msg2html_textplain(info, footer, + strlen(footer)); + msg2html_textplain_end(info); + } + } + + maildir_writemsgstr(newdraftfd, "\n" + "--"); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd, "--\n"); + --multipart_boundary[strlen(multipart_boundary)-1]; + + } + + if (sig) + free(sig); + + if (footer) + free(footer); + + if ( multipart_boundary && rfcp && has_attachments) + { + newmsg_copy_attachments(rfcp, fp, multipart_boundary); + maildir_writemsgstr(newdraftfd, "\n--"); + maildir_writemsgstr(newdraftfd, multipart_boundary); + maildir_writemsgstr(newdraftfd, "--\n"); + free(multipart_boundary); + } + if (fp) fclose(fp); + if (rfcp) + rfc2045_free(rfcp); + + if ( maildir_writemsg_flush(newdraftfd) == 0 && writebuf8bit) + { + if (lseek(newdraftfd, transferencodingpos, SEEK_SET) < 0 || + write(newdraftfd, "8", 1) != 1 || + lseek(newdraftfd, transferencoding2pos, SEEK_SET) < 0 || + write(newdraftfd, "8", 1) != 1) + { + close(newdraftfd); + enomem(); + } + } + + if ( maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, -1, prev_size)) + cgi_put("error", "quota"); + + return(draftfilename); +} + +static void sentmsg_copy(FILE *f, struct rfc2045 *p) +{ + off_t start_pos, end_pos, start_body; + char buf[BUFSIZ]; + int n; + off_t dummy; + + rfc2045_mimepos(p, &start_pos, &end_pos, &start_body, &dummy, &dummy); + if (fseek(f, start_pos, SEEK_SET) == -1) + { + fclose(f); + close(newdraftfd); + enomem(); + } + + while (start_pos < end_pos) + { + int cnt=sizeof(buf); + + if (cnt > end_pos - start_pos) + cnt=end_pos - start_pos; + + if ((n=fread(buf, 1, cnt, f)) <= 0) + { + fclose(f); + close(newdraftfd); + enomem(); + } + + maildir_writemsg(newdraftfd, buf, n); + start_pos += n; + } +} + + +/* Create message in the sent folder */ + +static void header_uc(char *h) +{ + while (*h) + { + *h=toupper( (int)(unsigned char) *h); + while (*h) + { + if (*h++ == '-') break; + } + } +} + +struct lookup_buffers { + struct lookup_buffers *next; + char *buf; + char *buf2; + } ; + +static int lookup_addressbook_do(const char *header, const char *value, + struct lookup_buffers **lookup_buffer_list) +{ + struct rfc822t *t; + struct rfc822a *a; + int i; + char *newbuf; + struct lookup_buffers *ptr; + int expanded=0; + + t=rfc822t_alloc_new(value, NULL, NULL); + if (!t) enomem(); + a=rfc822a_alloc(t); + if (!a) + { + rfc822t_free(t); + enomem(); + } + + for (i=0; inaddrs; i++) + { + char *p; + char *s; + const char *q; + struct lookup_buffers *r; + + if (a->addrs[i].tokens == 0) + continue; + if (a->addrs[i].name) + continue; /* Can't be a nickname */ + + p=rfc822_getaddr(a, i); + if (!p) + { + rfc822a_free(a); + rfc822t_free(t); + free(p); + return (-1); + } + + for (ptr= *lookup_buffer_list; ptr; ptr=ptr->next) + if (strcmp(ptr->buf2, p) == 0) + break; + + if (ptr) /* Address book loop */ + { + int j; + + for (j=i+1; jnaddrs; j++) + a->addrs[j-1]=a->addrs[j]; + --a->naddrs; + --i; + free(p); + continue; + } + + s=rfc822_display_addr_str_tobuf(p, "utf-8"); + + if (s == NULL || (q=ab_find(s)) == 0) + { + if (s) + free(s); + free(p); + continue; + } + free(s); + + r=malloc(sizeof(struct lookup_buffers)); + if (r) r->buf=r->buf2=0; + + if (!r || !(r->buf=strdup(q)) || !(r->buf2=strdup(p))) + { + free(p); + if (r && r->buf) free(r->buf); + if (r) free(r); + rfc822a_free(a); + rfc822t_free(t); + return (-1); + } + free(p); + r->next= *lookup_buffer_list; + *lookup_buffer_list=r; + a->addrs[i].tokens->next=0; + a->addrs[i].tokens->token=0; + a->addrs[i].tokens->ptr=r->buf; + a->addrs[i].tokens->len=strlen(r->buf); + expanded=1; + } + + newbuf=rfc822_getaddrs_wrap(a, 70); + rfc822a_free(a); + rfc822t_free(t); + if (!newbuf) return (-1); + + if (expanded) /* Look through the address book again */ + { + int rc=lookup_addressbook_do(header, newbuf, lookup_buffer_list); + + free(newbuf); + return (rc); + } + + create_draftheader_do(header, newbuf, 1); + free(newbuf); + return (0); +} + +static void lookup_addressbook(const char *header, const char *value) +{ + struct lookup_buffers *lookup_buffer_list=0; + int rc; + char *header_cpy; + char *value_cpy; + /* + ** header & value may be pointing to buffer allocated by + ** maildir_readheader. + ** lookup_addressbook_do may call it again. + */ + + header_cpy=strdup(header); + if (!header_cpy) + enomem(); + + value_cpy=strdup(value); + if (!value_cpy) + { + free(header_cpy); + enomem(); + } + + rc=lookup_addressbook_do(header_cpy, value_cpy, &lookup_buffer_list); + free(header_cpy); + + while (lookup_buffer_list) + { + struct lookup_buffers *p=lookup_buffer_list; + + lookup_buffer_list=p->next; + free(p->buf); + free(p->buf2); + free(p); + } + if (rc) enomem(); +} + +char *newmsg_createsentmsg(const char *draftname, int *isgpgerr) +{ +char *filename=maildir_find(INBOX "." DRAFTS, draftname); +FILE *fp; +char *sentname; +char *header, *value; +struct rfc2045 *rfcp; +int x; + + *isgpgerr=0; + + if (!filename) return (0); + + fp=0; + + x=maildir_safeopen(filename, O_RDONLY, 0); + if (x >= 0) + if ((fp=fdopen(x, "r")) == 0) + close(x); + + if (fp == 0) + { + free(filename); + enomem(); + } + + rfcp=rfc2045_fromfp(fp); + if (!rfcp || fseek(fp, 0L, SEEK_SET) < 0) + { + fclose(fp); + close(newdraftfd); + enomem(); + } + + newdraftfd=maildir_createmsg(INBOX "." SENT, 0, &sentname); + if (newdraftfd < 0) + { + rfc2045_free(rfcp); + free(filename); + fclose(fp); + enomem(); + } + /* First, copy all headers except X- headers */ + + while ((header=maildir_readheader(fp, &value, 1)) != 0) + { + if (strncmp(header, "x-", 2) == 0) continue; + header_uc(header); + if (rfc822hdr_namecmp(header, "To") == 0) + { + lookup_addressbook("To: ", value); + continue; + } + + if (rfc822hdr_namecmp(header, "Cc") == 0) + { + lookup_addressbook("Cc: ", value); + continue; + } + + if (rfc822hdr_namecmp(header, "Bcc") == 0) + { + lookup_addressbook("Bcc: ", value); + continue; + } + + maildir_writemsgstr(newdraftfd, header); + maildir_writemsgstr(newdraftfd, ": "); + maildir_writemsgstr(newdraftfd, value); + maildir_writemsgstr(newdraftfd, "\n"); + } + if (auth_getoptionenvint("wbusexsender")) + { + maildir_writemsgstr(newdraftfd, "X-Sender: "); + maildir_writemsgstr(newdraftfd, login_returnaddr()); + maildir_writemsgstr(newdraftfd, "\n"); + } + + maildir_writemsgstr(newdraftfd, "\n"); + + { + off_t start_pos, end_pos, start_body; + char buf[BUFSIZ]; + int n; + off_t dummy; + + rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body, + &dummy, &dummy); + + if (fseek(fp, start_body, SEEK_SET) == -1) + { + fclose(fp); + close(newdraftfd); + enomem(); + } + + while (start_body < end_pos) + { + int cnt=sizeof(buf); + + if (cnt > end_pos - start_pos) + cnt=end_pos - start_pos; + + if ((n=fread(buf, 1, cnt, fp)) <= 0) + { + fclose(fp); + close(newdraftfd); + enomem(); + } + + maildir_writemsg(newdraftfd, buf, n); + start_body += n; + } + } + + + if ( maildir_writemsg_flush(newdraftfd)) + { + free(sentname); + return (0); + } + +#if 0 + if (writebuf8bit) + { + if (lseek(newdraftfd, transferencodingpos, SEEK_SET) < 0 || + write(newdraftfd, "8", 1) != 1) + { + free(sentname); + return (0); + } + } +#endif + + if ( maildir_writemsg_flush(newdraftfd)) + { + maildir_closemsg(newdraftfd, INBOX "." SENT, sentname, 0, 0); + free(sentname); + return (0); + } + + if (libmail_gpg_has_gpg(GPGDIR) == 0) + { + char dosign= *cgi("sign"); + char doencrypt= *cgi("encrypt"); + const char *signkey= cgi("signkey"); + char *encryptkeys=cgi_multiple("encryptkey", " "); + + if (!encryptkeys) + enomem(); + + if (gpgbadarg(encryptkeys) || !*encryptkeys) + { + free(encryptkeys); + encryptkeys=0; + } + + if (gpgbadarg(signkey) || !*signkey) + { + signkey=0; + } + + if (!encryptkeys) + doencrypt=0; + + if (!signkey) + dosign=0; + + if (lseek(newdraftfd, 0L, SEEK_SET) < 0) + { + maildir_closemsg(newdraftfd, INBOX "." SENT, + sentname, 0, 0); + free(sentname); + return (0); + } + + if (!dosign) + signkey=0; + if (!doencrypt) + encryptkeys=0; + + if (dosign || doencrypt) + { + /* + ** What we do is create another draft, then substitute + ** it for newdraftfd/sentname. Sneaky. + */ + + char *newnewsentname; + int newnewdraftfd=maildir_createmsg(INBOX "." SENT, 0, + &newnewsentname); + + if (newnewdraftfd < 0) + { + maildir_closemsg(newdraftfd, INBOX "." SENT, + sentname, 0, 0); + free(sentname); + free(encryptkeys); + return (0); + } + + if (gpgdomsg(newdraftfd, newnewdraftfd, + signkey, encryptkeys)) + { + maildir_closemsg(newnewdraftfd, INBOX "." SENT, + newnewsentname, 0, 0); + free(newnewsentname); + maildir_closemsg(newdraftfd, INBOX "." SENT, + sentname, 0, 0); + free(sentname); + free(encryptkeys); + *isgpgerr=1; + return (0); + } + + maildir_closemsg(newdraftfd, INBOX "." SENT, sentname, 0, 0); + free(sentname); + sentname=newnewsentname; + newdraftfd=newnewdraftfd; + + } + free(encryptkeys); + } + + if ( maildir_closemsg(newdraftfd, INBOX "." SENT, sentname, 1, 0)) + { + free(sentname); + return (0); + } + return (sentname); +} + +/* ---------------------------------------------------------------------- */ + +/* Create a potential multipart boundary separator tag */ + +char *multipart_boundary_create() +{ +char pidbuf[MAXLONGSIZE]; +char timebuf[MAXLONGSIZE]; +time_t t; +char cntbuf[MAXLONGSIZE]; +static unsigned long cnt=0; +char *p; + + sprintf(pidbuf, "%lu", (unsigned long)getpid()); + time(&t); + sprintf(timebuf, "%lu", (unsigned long)t); + sprintf(cntbuf, "%lu", cnt++); + p=malloc(strlen(pidbuf)+strlen(timebuf) +strlen(cntbuf)+20); + sprintf(p, "=_%s_%s_%s_000", cntbuf, pidbuf, timebuf); + return (p); +} + +/* Search for the boundary tag in a string buffer - this is the new message +** we're creating. We should really look for the tag at the beginning of the +** line, however, the text is not yet linewrapped, besides, why make your +** life hard? +*/ + +int multipart_boundary_checks(const char *boundary, const char *msg) +{ +size_t boundarylen=strlen(boundary); + + while (*msg) + { + if (msg[0] == '-' && msg[1] == '-' && msg[2] != '-' && + strncasecmp(msg+2, boundary, boundarylen) == 0) + return (-1); + ++msg; + } + return (0); +} + +/* Again, just look for it at the beginning of the line -- why make your +** life hard? */ + +int multipart_boundary_checkf(const char *boundary, FILE *f) +{ +size_t boundarylen=strlen(boundary); +const char *line; + + if (fseek(f, 0L, SEEK_SET) == -1) + { + fclose(f); + close(newdraftfd); + enomem(); + } + + while ((line=maildir_readline(f)) != 0) + if (line[0] == '-' && line[1] == '-' && + strncasecmp(line+2, boundary, boundarylen) == 0) + return (-1); + return (0); +} + +/* ---------------------------------------------------------------------- */ + +/* Copy existing attachments into the new draft message */ + +/* multipart_boundary - determine if current draft has attachments */ + +static char *newmsg_multipart_boundary(FILE *f, const char *msg) +{ + char *p=0; + + do + { + if (p) free(p); + p=multipart_boundary_create(); + } while (multipart_boundary_checks(p, msg) + || (f && multipart_boundary_checkf(p, f))); + return (p); +} + +static void newmsg_copy_attachments(struct rfc2045 *rfcp, + FILE *f, const char *boundary) +{ +struct rfc2045 *p; +int foundtextplain=0; + + for (p=rfcp->firstpart; p; p=p->next) + { + if (p->isdummy) continue; + if (!foundtextplain && HASTEXTPLAIN(p)) + { /* Previous version of this message */ + + foundtextplain=1; + continue; + } + maildir_writemsgstr(newdraftfd, "\n--"); + maildir_writemsgstr(newdraftfd, boundary); + maildir_writemsgstr(newdraftfd, "\n"); + sentmsg_copy(f, p); /* Reuse some code */ + } +} -- cgit v1.2.3