Back to index

courier  0.68.2
Classes | Defines | Functions | Variables
newmsg_create.c File Reference
#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 <stdlib.h>
#include <ctype.h>
#include <fcntl.h>

Go to the source code of this file.

Classes

struct  lookup_buffers

Defines

#define HASTEXTPLAIN(q)   (rfc2045_searchcontenttype((q), "text/plain") != NULL)
#define ISLWS(c)   ((c)=='\t' || (c)=='\r' || (c)=='\n' || (c)==' ')

Functions

const char * rfc822_mkdt (time_t)
char * newmsg_createdraft_do (const char *, const char *, int)
char * newmsg_createdraft (const char *curdraft)
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)
static void header_wrap (const char *name, const char *hdr, char *outbuf, size_t *outcnt)
void newmsg_create_multipart (int newdraftfd, const char *charset, const char *multipart_boundary)
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)
void newmsg_copy_content_headers (FILE *fp)
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)
static void do_save_u_line (struct wrap_info *uw, const unicode_char *uc, size_t ucsize, int flowed)
static void flush_line (struct wrap_info *uw, int flowed)
static void add_word (struct wrap_info *uw)
static int do_save_u_process_lb (int type, void *arg)
static void do_wrap_u_line (struct wrap_info *uw, const unicode_char *uc, size_t ucsize)
static void save_textplain (const char *p, size_t l, void *dummy)
void wrap_text (struct wrap_info *uw, const char *newmsg, size_t newmsg_size)
static void convert_text2html (const char *p, size_t l, void *arg)
static char * mkurl (const char *url, void *dummy)
static void sentmsg_copy (FILE *f, struct rfc2045 *p)
static void header_uc (char *h)
static int lookup_addressbook_do (const char *header, const char *value, struct lookup_buffers **lookup_buffer_list)
static void lookup_addressbook (const char *header, const char *value)
char * newmsg_createsentmsg (const char *draftname, int *isgpgerr)
char * multipart_boundary_create ()
int multipart_boundary_checks (const char *boundary, const char *msg)
int multipart_boundary_checkf (const char *boundary, FILE *f)

Variables

const char * sqwebmail_content_charset
const char * sqwebmail_content_language
int newdraftfd
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"

Class Documentation

struct lookup_buffers

Definition at line 947 of file newmsg_create.c.

Collaboration diagram for lookup_buffers:
Class Members
char * buf
char * buf2
struct lookup_buffers * next

Define Documentation

#define HASTEXTPLAIN (   q)    (rfc2045_searchcontenttype((q), "text/plain") != NULL)

Definition at line 41 of file newmsg_create.c.

#define ISLWS (   c)    ((c)=='\t' || (c)=='\r' || (c)=='\n' || (c)==' ')

Definition at line 110 of file newmsg_create.c.


Function Documentation

static void add_word ( struct wrap_info uw) [static]

Definition at line 358 of file newmsg_create.c.

{
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void convert_text2html ( const char *  p,
size_t  l,
void *  arg 
) [static]

Definition at line 490 of file newmsg_create.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void create_draftheader ( const char *  hdrname,
const char *  p,
const char *  q,
int  isrfc822addr 
) [static]

Definition at line 81 of file newmsg_create.c.

{
       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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void create_draftheader_do ( const char *  hdrname,
const char *  p,
int  isrfc822addr 
) [static]

Definition at line 176 of file newmsg_create.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_save_u_line ( struct wrap_info uw,
const unicode_char uc,
size_t  ucsize,
int  flowed 
) [static]

Definition at line 301 of file newmsg_create.c.

{
       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);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_save_u_process_lb ( int  type,
void *  arg 
) [static]

Definition at line 370 of file newmsg_create.c.

{
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_wrap_u_line ( struct wrap_info uw,
const unicode_char uc,
size_t  ucsize 
) [static]

Definition at line 396 of file newmsg_create.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void flush_line ( struct wrap_info uw,
int  flowed 
) [static]

Definition at line 349 of file newmsg_create.c.

{
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void header_uc ( char *  h) [static]

Definition at line 935 of file newmsg_create.c.

{
       while (*h)
       {
              *h=toupper( (int)(unsigned char) *h);
              while (*h)
              {
                     if (*h++ == '-')     break;
              }
       }
}

Here is the caller graph for this function:

static void header_wrap ( const char *  name,
const char *  hdr,
char *  outbuf,
size_t *  outcnt 
) [static]

Definition at line 112 of file newmsg_create.c.

{
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;
}

Here is the caller graph for this function:

static void lookup_addressbook ( const char *  header,
const char *  value 
) [static]

Definition at line 1060 of file newmsg_create.c.

{
       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();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int lookup_addressbook_do ( const char *  header,
const char *  value,
struct lookup_buffers **  lookup_buffer_list 
) [static]

Definition at line 953 of file newmsg_create.c.

{
       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; i<a->naddrs; 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; j<a->naddrs; 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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* mkurl ( const char *  url,
void *  dummy 
) [static]

Definition at line 498 of file newmsg_create.c.

{
       char *buf=malloc(strlen(url)*2+100);

       if (!buf)
              return NULL;

       /* msg2html guarantees that the characters in url are "safe" */

       sprintf(buf, "<a href=\"%s\">%s</a>", url, url);
       return buf;
}

Here is the caller graph for this function:

int multipart_boundary_checkf ( const char *  boundary,
FILE *  f 
)

Definition at line 1375 of file newmsg_create.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int multipart_boundary_checks ( const char *  boundary,
const char *  msg 
)

Definition at line 1358 of file newmsg_create.c.

{
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);
}

Here is the caller graph for this function:

Definition at line 1334 of file newmsg_create.c.

{
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);
}

Here is the caller graph for this function:

static void newmsg_copy_attachments ( struct rfc2045 rfcp,
FILE *  f,
const char *  boundary 
) [static]

Definition at line 1413 of file newmsg_create.c.

{
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 */
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void newmsg_copy_content_headers ( FILE *  fp)

Definition at line 266 of file newmsg_create.c.

{
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");
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void newmsg_copy_nonmime_headers ( FILE *  fp)

Definition at line 239 of file newmsg_create.c.

{
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");
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void newmsg_create_multipart ( int  newdraftfd,
const char *  charset,
const char *  multipart_boundary 
)

Definition at line 220 of file newmsg_create.c.

{
       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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* newmsg_createdraft ( const char *  curdraft)

Definition at line 58 of file newmsg_create.c.

{
       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));
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* newmsg_createdraft_do ( const char *  curdraft,
const char *  newmsg,
int  keepheader 
)

Definition at line 511 of file newmsg_create.c.

{
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("<hr />\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("<br />\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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* newmsg_createsentmsg ( const char *  draftname,
int *  isgpgerr 
)

Definition at line 1098 of file newmsg_create.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char * newmsg_multipart_boundary ( FILE *  f,
const char *  msg 
) [static]

Definition at line 1400 of file newmsg_create.c.

{
       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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* rfc822_mkdt ( time_t  )

Definition at line 238 of file rfc822_parsedt.c.

{
static char buf[80];
struct tm *tmptr=gmtime(&t);

       buf[0]=0;
       if (tmptr)
       {
              sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
                     weekdays[tmptr->tm_wday],
                     tmptr->tm_mday,
                     mnames[tmptr->tm_mon],
                     tmptr->tm_year + 1900,
                     tmptr->tm_hour,
                     tmptr->tm_min,
                     tmptr->tm_sec);
       }
       return (buf);
}
static void save_textplain ( const char *  p,
size_t  l,
void *  dummy 
) [static]

Definition at line 425 of file newmsg_create.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void sentmsg_copy ( FILE *  f,
struct rfc2045 p 
) [static]

Definition at line 898 of file newmsg_create.c.

{
       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;
        }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void wrap_text ( struct wrap_info uw,
const char *  newmsg,
size_t  newmsg_size 
)

Definition at line 430 of file newmsg_create.c.

{
       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<newmsg_size && newmsg[i] != '\n')
                     ++i;

              h=libmail_u_convert_tou_init(sqwebmail_content_charset,
                                        &uc, &ucsize, 0);

              if (h)
              {
                     libmail_u_convert(h, newmsg+j, i-j);

                     if (libmail_u_convert_deinit(h, NULL))
                            uc=NULL;
              }
              else
              {
                     uc=NULL;
              }

              if (uc)
              {
                     size_t i, j;

                     /* Get rid of any CRs that sneak in */

                     for (i=j=0; i<ucsize; ++i)
                     {
                            if (uc[i] == '\r')
                                   continue;

                            uc[j]=uc[i];
                            ++j;
                     }

                     if (j && *uc == '>')
                            do_save_u_line(uw, uc, j, 0);
                     else
                            do_wrap_u_line(uw, uc, j);

                     free(uc);
              }

              if (i < newmsg_size)
                     ++i;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void wrap_text_init ( struct wrap_info uw,
const char *  output_chset,
void(*)(const char *p, size_t l, void *arg)  output_func,
void *  arg 
)

Definition at line 290 of file newmsg_create.c.

{
       memset(uw, 0, sizeof(*uw));
       uw->output_func=output_func;
       uw->output_chset=output_chset;
       uw->arg=arg;
}

Here is the caller graph for this function:


Variable Documentation

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"

Definition at line 52 of file newmsg_create.c.

Definition at line 49 of file newmsg_create.c.

Definition at line 39 of file gpg.c.

Definition at line 123 of file sqwebmail.c.

const char* sqwebmail_mailboxid

Definition at line 105 of file sqwebmail.c.