Back to index

courier  0.68.2
Classes | Defines | Functions | Variables
rfc2045.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "rfc2045.h"
#include "rfc822/rfc822.h"
#include "rfc2045charset.h"

Go to the source code of this file.

Classes

struct  rfc2045_parse_mime_info

Defines

#define MAXLEVELS   20
#define MAXPARTS   300
#define ContentBoundary(p)   ( (p)->boundary )
#define GETINFO(s, def)   ( (s) && (*s) ? (s):def)

Functions

void rfc2045_enomem ()
struct rfc2045rfc2045_alloc ()
const char * rfc2045_getattr (const struct rfc2045attr *p, const char *name)
int rfc2045_attrset (struct rfc2045attr **p, const char *name, const char *val)
static void rfc2045_freeattr (struct rfc2045attr *p)
void rfc2045_free (struct rfc2045 *p)
void rfc2045_add_buf (char **bufptr, size_t *bufsize, size_t *buflen, const char *p, size_t len)
void rfc2045_add_workbuf (struct rfc2045 *h, const char *p, size_t len)
void rfc2045_add_workbufch (struct rfc2045 *h, int c)
static void set_string (char **p, const char *q)
static void update_counts (struct rfc2045 *p, size_t newcnt, size_t newendcnt, unsigned nlines)
static void doline (struct rfc2045 *)
void rfc2045_parse_partial (struct rfc2045 *h)
void rfc2045_parse (struct rfc2045 *h, const char *buf, size_t s)
static struct rfc2045append_part_noinherit (struct rfc2045 *p, size_t startpos)
static struct rfc2045append_part (struct rfc2045 *p, size_t startpos)
static void do_header (struct rfc2045 *)
static char * paste_tokens (struct rfc822t *h, int start, int cnt)
static char * lower_paste_tokens (struct rfc822t *h, int start, int cnt)
static char * paste_token (struct rfc822t *h, int i)
static char * lower_paste_token (struct rfc822t *h, int i)
static void mime_version (struct rfc2045 *, struct rfc822t *)
static void content_type (struct rfc2045 *, struct rfc822t *)
static void content_transfer_encoding (struct rfc2045 *, struct rfc822t *)
static void content_disposition (struct rfc2045 *, struct rfc822t *)
static void content_id (struct rfc2045 *, struct rfc822t *)
static void content_description (struct rfc2045 *, const char *)
static void content_language (struct rfc2045 *, const char *)
static void content_md5 (struct rfc2045 *, const char *)
static void content_base (struct rfc2045 *, struct rfc822t *)
static void content_location (struct rfc2045 *, struct rfc822t *)
static void parse_content_header (struct rfc822t *header, int init_start, void(*init_token)(char *, void *), void(*init_parameter)(const char *, struct rfc822t *, int, int, void *), void *void_arg)
static void save_content_type (char *, void *)
static void save_content_type_parameter (const char *, struct rfc822t *, int, int, void *)
static void save_content_disposition (char *, void *)
static void save_content_disposition_parameter (const char *, struct rfc822t *, int, int, void *)
char * rfc2045_related_start (const struct rfc2045 *p)
void rfc2045_mimeinfo (const struct rfc2045 *p, const char **content_type_s, const char **content_transfer_encoding_s, const char **charset_s)
const char * rfc2045_getdefaultcharset ()
void rfc2045_setdefaultcharset (const char *charset)
const char * rfc2045_boundary (const struct rfc2045 *p)
int rfc2045_isflowed (const struct rfc2045 *p)
int rfc2045_isdelsp (const struct rfc2045 *p)
const char * rfc2045_content_id (const struct rfc2045 *p)
const char * rfc2045_content_description (const struct rfc2045 *p)
const char * rfc2045_content_language (const struct rfc2045 *p)
const char * rfc2045_content_md5 (const struct rfc2045 *p)
void rfc2045_mimepos (const struct rfc2045 *p, off_t *start_pos, off_t *end_pos, off_t *start_body, off_t *nlines, off_t *nbodylines)
unsigned rfc2045_mimepartcount (const struct rfc2045 *p)
static void parse_mime_cb (char *, void *)
static void parse_param_cb (const char *, struct rfc822t *, int, int, void *)
int rfc2045_parse_mime_header (const char *header, void(*header_type_cb)(const char *, void *), void(*header_param_cb)(const char *, const char *, void *), void *void_arg)

Variables

static char * rfc2045_defcharset = 0
int rfc2045_in_reformime = 0

Define Documentation

#define ContentBoundary (   p)    ( (p)->boundary )

Definition at line 119 of file rfc2045.c.

#define GETINFO (   s,
  def 
)    ( (s) && (*s) ? (s):def)

Definition at line 1201 of file rfc2045.c.

#define MAXLEVELS   20

Definition at line 28 of file rfc2045.c.

#define MAXPARTS   300

Definition at line 29 of file rfc2045.c.


Function Documentation

static struct rfc2045* append_part ( struct rfc2045 p,
size_t  startpos 
) [static, read]

Definition at line 369 of file rfc2045.c.

{
struct rfc2045 *newp=append_part_noinherit(p, startpos);

       /* Substructures inherit content transfer encoding and character set */

       set_string(&newp->content_transfer_encoding,
                     p->content_transfer_encoding);

       if (rfc2045_attrset(&newp->content_type_attr, "charset",
                         rfc2045_getattr(p->content_type_attr, "charset"))
           < 0)
              rfc2045_enomem();

       return (newp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct rfc2045* append_part_noinherit ( struct rfc2045 p,
size_t  startpos 
) [static, read]

Definition at line 342 of file rfc2045.c.

                                                                                {
struct rfc2045 *newp;

       newp=rfc2045_alloc();
       if (p->lastpart)
       {
              p->lastpart->next=newp;
              newp->pindex=p->lastpart->pindex+1;
       }
       else
       {
              p->firstpart=newp;
              newp->pindex=0;
       }
       p->lastpart=newp;
       newp->parent=p;

       /* Initialize source pointers */
       newp->startpos=newp->endpos=newp->startbody=newp->endbody=startpos;

       while (p->parent)
              p=p->parent;
       ++p->numparts;

       return (newp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_base ( struct rfc2045 p,
struct rfc822t t 
) [static]

Definition at line 1172 of file rfc2045.c.

{
char   *s;
int    i;

       for (i=0; i<t->ntokens; i++)
              if (t->tokens[i].token == '"')
                     t->tokens[i].token=0;

       s=paste_tokens(t, 2, t->ntokens-2);
       set_string(&p->content_base, s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_description ( struct rfc2045 p,
const char *  s 
) [static]

Definition at line 1154 of file rfc2045.c.

{
       if (s && *s)
              set_string(&p->content_description, s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_disposition ( struct rfc2045 r,
struct rfc822t header 
) [static]

Definition at line 1050 of file rfc2045.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_id ( struct rfc2045 p,
struct rfc822t t 
) [static]

Definition at line 1123 of file rfc2045.c.

{
struct rfc822a       *a=rfc822a_alloc(t);
int    i;

       if (!a)
       {
              rfc2045_enomem();
              return;
       }

       for (i=0; i<a->naddrs; i++)
              if (a->addrs[i].tokens)
              {
              char   *s=rfc822_getaddr(a, i);

                     if (!s)
                     {
                            rfc822a_free(a);
                            rfc2045_enomem();
                            return;
                     }
                     if (p->content_id)
                            free(p->content_id);
                     p->content_id=s;
                     break;
              }

       rfc822a_free(a);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_language ( struct rfc2045 p,
const char *  s 
) [static]

Definition at line 1160 of file rfc2045.c.

{
       if (s && *s)
              set_string(&p->content_language, s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_location ( struct rfc2045 p,
struct rfc822t t 
) [static]

Definition at line 1185 of file rfc2045.c.

{
char   *s;
int    i;

       for (i=0; i<t->ntokens; i++)
              if (t->tokens[i].token == '"')
                     t->tokens[i].token=0;

       s=paste_tokens(t, 2, t->ntokens-2);
       set_string(&p->content_location, s);
       free(s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_md5 ( struct rfc2045 p,
const char *  s 
) [static]

Definition at line 1166 of file rfc2045.c.

{
       if (s && *s)
              set_string(&p->content_md5, s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_transfer_encoding ( struct rfc2045 r,
struct rfc822t header 
) [static]

Definition at line 876 of file rfc2045.c.

{
char   *p;

       p=lower_paste_tokens(header, 2, header->ntokens-2);
       if (!p)       return;

       if (r->content_transfer_encoding)
              free(r->content_transfer_encoding);
       r->content_transfer_encoding=p;

       if (strcmp(p, "8bit") == 0)
              r->content_8bit=1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void content_type ( struct rfc2045 r,
struct rfc822t header 
) [static]

Definition at line 970 of file rfc2045.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_header ( struct rfc2045 p) [static]

Definition at line 779 of file rfc2045.c.

{
struct rfc822t *header;
char   *t;

       if (p->headerlen == 0)      return;
       rfc2045_add_buf( &p->header, &p->headersize, &p->headerlen, "", 1);
                            /* 0 terminate */

       /* Parse the header line according to RFC822 */

       header=rfc822t_alloc_new(p->header, NULL, NULL);

       if (!header)  return;       /* Broken header */

       if (header->ntokens < 2 ||
              header->tokens[0].token ||
              header->tokens[1].token != ':')
       {
              rfc822t_free(header);
              return;       /* Broken header */
       }

       t=lower_paste_token(header, 0);

       if (t == 0)
              ;
       else if (strcmp(t, "mime-version") == 0)
       {
              free(t);
              mime_version(p, header);
       }
       else if (strcmp(t, "content-type") == 0)
       {
              free(t);
              content_type(p, header);
       } else if (strcmp(t, "content-transfer-encoding") == 0)
       {
              free(t);
              content_transfer_encoding(p, header);
       } else if (strcmp(t, "content-disposition") == 0)
       {
              free(t);
              content_disposition(p, header);
       } else if (strcmp(t, "content-id") == 0)
       {
              free(t);
              content_id(p, header);
       } else if (strcmp(t, "content-description") == 0)
       {
              free(t);
              t=strchr(p->header, ':');
              if (t) ++t;
              while (t && isspace((int)(unsigned char)*t))
                     ++t;
              content_description(p, t);
       } else if (strcmp(t, "content-language") == 0)
       {
              free(t);
              t=strchr(p->header, ':');
              if (t) ++t;
              while (t && isspace((int)(unsigned char)*t))
                     ++t;
              content_language(p, t);
       } else if (strcmp(t, "content-base") == 0)
       {
              free(t);
              content_base(p, header);
       } else if (strcmp(t, "content-location") == 0)
       {
              free(t);
              content_location(p, header);
       } else if (strcmp(t, "content-md5") == 0)
       {
              free(t);
              t=strchr(p->header, ':');
              if (t) ++t;
              while (t && isspace((int)(unsigned char)*t))
                     ++t;
              content_md5(p, t);
       }
       else   free(t);
       rfc822t_free(header);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void doline ( struct rfc2045 p) [static]

Definition at line 398 of file rfc2045.c.

{
size_t cnt=p->workbuflen;
char *c=p->workbuf;
size_t n=cnt-1;      /* Strip \n (we always get at least a \n here) */
struct rfc2045 *newp;
struct rfc2045ac *rwp=p->rfc2045acptr;
unsigned num_levels=0;

size_t k;
int    bit8=0;

       if (p->numparts > MAXPARTS)
       {
              p->rfcviolation |= RFC2045_ERR2COMPLEX;
              return;
       }

       for (k=0; k<cnt; k++)
       {
              if (c[k] == 0)
                     c[k]=' ';
              if (c[k] & 0x80)     bit8=1;
       }

       if (n && c[n-1] == '\r')    /* Strip trailing \r */
              --n;

       /* Before the main drill down loop before, look ahead and see if we're
       ** in a middle of a form-data section.  */

       for (newp=p; newp->lastpart &&
                     !newp->lastpart->workclosed; newp=newp->lastpart,
                     ++num_levels)
       {
              if (ContentBoundary(newp) == 0 || newp->workinheader)
                     continue;

              if (newp->lastpart->informdata)
              {
                     p=newp->lastpart;
                     p->informdata=0;
                     break;
              }
       }

       /* Drill down until we match a boundary, or until we've reached
       the last RFC2045 section that has been opened.
       */

       while (p->lastpart)
       {
       size_t l;
       const char *cb;

              if (p->lastpart->workclosed)
              {
                     update_counts(p, p->endpos+cnt, p->endpos+n, 1);
                     return;
              }
              /* Leftover trash -- workclosed is set when the final
              ** terminating boundary has been seen */

              /* content_boundary may be set before the entire header
              ** has been seen, so continue drilling down in that case
              */

              cb=ContentBoundary(p);

              if (cb == 0 || p->workinheader)
              {
                     p=p->lastpart;
                     ++num_levels;
                     continue;
              }

              l=strlen(cb);

              if (c[0] == '-' && c[1] == '-' && n >= 2+l &&
                     strncasecmp(cb, c+2, l) == 0)
              {

                     if (rwp && (!p->lastpart || !p->lastpart->isdummy))
                            (*rwp->end_section)();

              /* Ok, we've found a boundary */

                     if (n >= 4+l && strncmp(c+2+l, "--", 2) == 0)
                     {
                     /* Last boundary */

                            p->lastpart->workclosed=1;
                            update_counts(p, p->endpos+cnt, p->endpos+cnt,
                                   1);
                            return;
                     }

              /* Create new RFC2045 section */

                     newp=append_part(p, p->endpos+cnt);
                     update_counts(p, p->endpos+cnt, p->endpos+n, 1);

                     /* The new RFC2045 section is MIME compliant */

                     if ((newp->mime_version=strdup(p->mime_version)) == 0)
                            rfc2045_enomem();
                     return;
              }
              p=p->lastpart;
              ++num_levels;
       }

       /* Ok, we've found the RFC2045 section that we're working with.
       ** No what?
       */

       if (! p->workinheader)
       {
              /* Processing body, just update the counts. */

       size_t cnt_update=cnt;

              if (bit8 && !p->content_8bit &&
                     (p->rfcviolation & RFC2045_ERR8BITCONTENT) == 0)
              {
              struct rfc2045 *q;

                     for (q=p; q; q=q->parent)
                            q->rfcviolation |= RFC2045_ERR8BITCONTENT;
              }

              /*
              ** In multiparts, the final newline in a part belongs to the
              ** boundary, otherwise, include it in the text.
              */
              if (p->parent && p->parent->content_type &&
                            strncasecmp(p->parent->content_type,
                                          "multipart/", 10) == 0)
                     cnt_update=n;

              if (!p->lastpart || !p->lastpart->workclosed)
              {
                     if (rwp && !p->isdummy)
                            (*rwp->section_contents)(c, cnt);

                     update_counts(p, p->endpos+cnt, p->endpos+cnt_update,
                            1);
              }
              return;
       }

       if (bit8 && (p->rfcviolation & RFC2045_ERR8BITHEADER) == 0)
       {
       struct rfc2045 *q;

              for (q=p; q; q=q->parent)
                     q->rfcviolation |= RFC2045_ERR8BITHEADER;
       }

       /* In the header */

       if ( n == 0 ) /* End of header, body begins.  Parse header. */
       {
              do_header(p); /* Clean up any left over header line */
              p->workinheader=0;

              /* Message body starts right here */

              p->startbody=p->endpos+cnt;
              update_counts(p, p->startbody, p->startbody, 1);
              --p->nbodylines;     /* Don't count the blank line */

              /* Discard content type and boundary if I don't understand
              ** this MIME flavor.
              */

              if (!RFC2045_ISMIME1(p->mime_version))
              {
                     set_string(&p->content_type, 0);

                     rfc2045_freeattr(p->content_type_attr);
                     p->content_type_attr=0;
                     set_string(&p->content_disposition, 0);
                     rfc2045_freeattr(p->content_disposition_attr);
                     p->content_disposition_attr=0;
                     if (p->boundary)
                     {
                            free(p->boundary);
                            p->boundary=0;
                     }
              }

              /* Normally, if we don't have a content_type, default it
              ** to text/plain.  However, if the multipart type is
              ** multipart/digest, it is message/rfc822.
              */

              if (RFC2045_ISMIME1(p->mime_version) && !p->content_type)
              {
              char   *q="text/plain";

                     if (p->parent && p->parent->content_type &&
                            strcmp(p->parent->content_type,
                                   "multipart/digest") == 0)
                            q="message/rfc822";
                     set_string(&p->content_type, q);
              }

              /* If this is not a multipart section, we don't want to
              ** hear about any boundaries
              */

              if (!p->content_type ||
                     strncmp(p->content_type, "multipart/", 10))
              {
                     if (p->boundary)
                            free(p->boundary);
                     p->boundary=0;
              }

              /* If this section's a message, we will expect to see
              ** more RFC2045 stuff, so create a nested RFC2045 structure,
              ** and indicate that we expect to see headers.
              */

              if (p->content_type &&
                     strcmp(p->content_type, "message/rfc822") == 0)
              {
                     newp=append_part_noinherit(p, p->startbody);
                     newp->workinheader=1;
                     return;
              }

              /*
              ** If this is a multipart message (boundary defined),
              ** create a RFC2045 structure for the pseudo-section
              ** that precedes the first boundary line.
              */

              if (ContentBoundary(p))
              {
                     newp=append_part(p, p->startbody);
                     newp->workinheader=0;
                     newp->isdummy=1;
                            /* It's easier just to create it. */
                     return;
              }

              if (rwp)
                     (*rwp->start_section)(p);
              return;
       }

       /* RFC822 header continues */

       update_counts(p, p->endpos + cnt, p->endpos+n, 1);

       /* If this header line starts with a space, append one space
       ** to the saved contents of the previous line, and append this
       ** line to it.
       */

       if (isspace((int)(unsigned char)*c))
       {
              rfc2045_add_buf(&p->header, &p->headersize, &p->headerlen, " ", 1);
       }
       else
       {
       /* Otherwise the previous header line is complete, so process it */

              do_header(p);
              p->headerlen=0;
       }

       /* Save this line in the header buffer, because the next line
       ** could be a continuation.
       */

       rfc2045_add_buf( &p->header, &p->headersize, &p->headerlen, c, n);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* lower_paste_token ( struct rfc822t h,
int  i 
) [static]

Definition at line 754 of file rfc2045.c.

{
char *p=paste_token(h, i);
char *q;

       for (q=p; q && *q; q++)
              *q=tolower(*q);
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* lower_paste_tokens ( struct rfc822t h,
int  start,
int  cnt 
) [static]

Definition at line 738 of file rfc2045.c.

{
char   *p=paste_tokens(h, start, cnt);
char   *q;

       for (q=p; q && *q; q++)
              *q=tolower(*q);
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mime_version ( struct rfc2045 p,
struct rfc822t header 
) [static]

Definition at line 866 of file rfc2045.c.

{
char   *vers=paste_tokens(header, 2, header->ntokens-2);

       if (!vers)    return;

       if (p->mime_version) free(p->mime_version);
       p->mime_version=vers;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_content_header ( struct rfc822t header,
int  init_start,
void(*)(char *, void *)  init_token,
void(*)(const char *, struct rfc822t *, int, int, void *)  init_parameter,
void *  void_arg 
) [static]

Definition at line 894 of file rfc2045.c.

{
int    start;
int    i, j;
char   *p;

       /* Look for the 1st ; */

       for (start=init_start; start < header->ntokens; start++)
              if (header->tokens[start].token == ';')
                     break;

       /* Everything up to the 1st ; is the content type */

       p=lower_paste_tokens(header, init_start, start-init_start);
       if (!p)       return;

       (*init_token)(p, void_arg);
       if (start < header->ntokens) start++;

       /* Handle the remainder of the Content-Type: header */

       while (start < header->ntokens)
       {
              /* Look for next ; */

              for (i=start; i<header->ntokens; i++)
                     if (header->tokens[i].token == ';')
                            break;
              j=start;
              if (j < i)
              {
                     ++j;

                     /* We only understand <atom>= */

                     while (j < i && header->tokens[j].token == '(')
                            ++j;
                     if (j < i && header->tokens[j].token == '=')
                     {
                            ++j;

                            /*
                            ** reformime: loose parsing due to loose
                            ** parsing in MSOE, leading to viruses slipping
                            ** through virus scanners if we strictly
                            ** parsed the content-type header.
                            */
                            if (rfc2045_in_reformime && j < i
                                && header->tokens[j].token == '"')
                                   i=j+1;

                            p=lower_paste_token(header, start);
                            if (!p)       return;
                            (*init_parameter)(p, header, j, i-j, void_arg);
                            free(p);
                     }
              }
              if ( i<header->ntokens ) ++i;      /* Skip over ; */
              start=i;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_mime_cb ( char *  t,
void *  void_arg 
) [static]

Definition at line 1352 of file rfc2045.c.

{
       struct rfc2045_parse_mime_info *mi=
              (struct rfc2045_parse_mime_info *)void_arg;

       (*mi->header_type_cb)(t, mi->void_arg);
       free(t);
}

Here is the caller graph for this function:

static void parse_param_cb ( const char *  name,
struct rfc822t header,
int  start,
int  len,
void *  void_arg 
) [static]

Definition at line 1362 of file rfc2045.c.

{
       struct rfc2045_parse_mime_info *mi=
              (struct rfc2045_parse_mime_info *)void_arg;
       char *p=paste_tokens(header, start, len);

       if (!p)
              return;

       (*mi->header_param_cb)(name, p, mi->void_arg);
       free(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* paste_token ( struct rfc822t h,
int  i 
) [static]

Definition at line 748 of file rfc2045.c.

{
       if (i >= h->ntokens) return (0);
       return (paste_tokens(h, i, 1));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* paste_tokens ( struct rfc822t h,
int  start,
int  cnt 
) [static]

Definition at line 686 of file rfc2045.c.

{
int    l;
int    i;
char   *p;

       /* Calculate string size */

       l=1;
       for (i=0; i<cnt; i++)
       {
              if (h->tokens[start+i].token == '(')
                     continue;

              if (rfc822_is_atom(h->tokens[start+i].token))
                     l += h->tokens[start+i].len;
              else
                     l++;
       }

       /* Do it */

       p=( char *)malloc(l);
       if (!p)
       {
              rfc2045_enomem();
              return (0);
       }
       l=0;

       for (i=0; i<cnt; i++)
       {
              if (h->tokens[start+i].token == '(')
                     continue;

              if (rfc822_is_atom(h->tokens[start+i].token))
              {
              int l2=h->tokens[start+i].len;

                     memcpy(p+l, h->tokens[start+i].ptr, l2);
                     l += l2;
              }
              else   p[l++]=h->tokens[start+i].token;
       }
       p[l]=0;
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rfc2045_add_buf ( char **  bufptr,
size_t *  bufsize,
size_t *  buflen,
const char *  p,
size_t  len 
)

Definition at line 173 of file rfc2045.c.

{
       if (len + *buflen > *bufsize)
       {
       size_t newsize=len+*buflen+256;
       char   *p= *bufptr ? (char *)realloc(*bufptr, newsize):
                            (char *)malloc(newsize);

              if (!p)
              {
                     rfc2045_enomem();
                     return;
              }
              *bufptr=p;
              *bufsize=newsize;
       }

       memcpy(*bufptr + *buflen, p, len);
       *buflen += len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rfc2045_add_workbuf ( struct rfc2045 h,
const char *  p,
size_t  len 
)

Definition at line 201 of file rfc2045.c.

{
       rfc2045_add_buf( &h->workbuf, &h->workbufsize, &h->workbuflen, p, len);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rfc2045_add_workbufch ( struct rfc2045 h,
int  c 
)

Definition at line 208 of file rfc2045.c.

{
char cc= (char)c;

       rfc2045_add_workbuf(h, &cc, 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct rfc2045* rfc2045_alloc ( ) [read]

Definition at line 35 of file rfc2045.c.

{
struct rfc2045 *p=(struct rfc2045 *)malloc(sizeof(struct rfc2045));

       if (!p)
       {
              rfc2045_enomem();
              return (0);
       }

       /* Initialize everything to nulls, except for one thing */

       memset(p, '\0', sizeof(*p));

       p->pindex=1;  /* Start with part #1 */
       p->workinheader=1;
       /* Most of the time, we're about to read a header */

       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int rfc2045_attrset ( struct rfc2045attr **  p,
const char *  name,
const char *  val 
)

Definition at line 67 of file rfc2045.c.

{
char   *v;

       while (*p)
       {
              if (strcmp( (*p)->name, name) == 0)       break;
              p=&(*p)->next;
       }
       if (val == 0)
       {
       struct rfc2045attr *q= *p;

              if (q)
              {
                     *p=q->next;
                     if (q->name)  free(q->name);
                     if (q->value) free(q->value);
                     free(q);
              }
              return 0;
       }

       v=strdup(val);
       if (!v)
              return -1;

       if (!*p)
       {
              if (((*p)=(struct rfc2045attr *)malloc(sizeof(**p))) == 0)
              {
                     free(v);
                     return -1;
              }
              memset( (*p), 0, sizeof(**p));
              if ( ((*p)->name=strdup(name)) == 0)
              {
                     free( *p );
                     *p=0;
                     free(v);
                     return -1;
              }
       }
       if ( (*p)->value )   free ( (*p)->value );
       (*p)->value=v;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* rfc2045_boundary ( const struct rfc2045 p)

Definition at line 1242 of file rfc2045.c.

{
const char *cb=rfc2045_getattr( p->content_type_attr, "boundary");

       if (!cb)      cb="";
       return (cb);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* rfc2045_content_description ( const struct rfc2045 p)

Definition at line 1269 of file rfc2045.c.

{
       return (p->content_description ? p->content_description:"");
}

Here is the caller graph for this function:

const char* rfc2045_content_id ( const struct rfc2045 p)

Definition at line 1264 of file rfc2045.c.

{
       return (p->content_id ? p->content_id:"");
}

Here is the caller graph for this function:

const char* rfc2045_content_language ( const struct rfc2045 p)

Definition at line 1274 of file rfc2045.c.

{
       return (p->content_language ? p->content_language:"");
}

Here is the caller graph for this function:

const char* rfc2045_content_md5 ( const struct rfc2045 p)

Definition at line 1279 of file rfc2045.c.

{
       return (p->content_md5 ? p->content_md5:"");
}

Here is the caller graph for this function:

void rfc2045_enomem ( )

Definition at line 44 of file pcp.c.

{
       fprintf(stderr, "Out of memory.\n");
       exit(1);
}
void rfc2045_free ( struct rfc2045 p)

Definition at line 139 of file rfc2045.c.

{
struct rfc2045 *q, *r;

       for (q=p->firstpart; q; )
       {
              r=q->next;
              rfc2045_free(q);
              q=r;
       }
       rfc2045_freeattr(p->content_type_attr);
       rfc2045_freeattr(p->content_disposition_attr);

       if (p->header)              free(p->header);
       if (p->content_md5)  free(p->content_md5);
       if (p->content_base) free(p->content_base);
       if (p->content_location)    free(p->content_location);
       if (p->content_language)    free(p->content_language);
       if (p->content_id)   free(p->content_id);
       if (p->content_description) free(p->content_description);
       if (p->content_transfer_encoding) free(p->content_transfer_encoding);
       if (p->boundary) free(p->boundary);
       if (p->content_type) free(p->content_type);
       if (p->mime_version) free(p->mime_version);
       if (p->workbuf)             free(p->workbuf);
       if (p->content_disposition) free(p->content_disposition);
       if (p->rw_transfer_encoding) free(p->rw_transfer_encoding);
       free(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void rfc2045_freeattr ( struct rfc2045attr p) [static]

Definition at line 126 of file rfc2045.c.

{
       while (p)
       {
       struct rfc2045attr *q=p->next;

              if (p->name)  free(p->name);
              if (p->value) free(p->value);
              free(p);
              p=q;
       }
}

Here is the caller graph for this function:

const char* rfc2045_getattr ( const struct rfc2045attr p,
const char *  name 
)

Definition at line 56 of file rfc2045.c.

{
       while (p)
       {
              if (p->name && strcmp(p->name, name) == 0)
                     return (p->value);
              p=p->next;
       }
       return (0);
}

Here is the caller graph for this function:

const char* rfc2045_getdefaultcharset ( )

Definition at line 1220 of file rfc2045.c.

{
const char *p=rfc2045_defcharset;

       if (!p)       p=RFC2045CHARSET;
       return (p);
}

Here is the caller graph for this function:

int rfc2045_isdelsp ( const struct rfc2045 p)

Definition at line 1257 of file rfc2045.c.

{
       const char *cb=rfc2045_getattr(p->content_type_attr, "delsp");

       return (cb && strcmp(cb, "yes") == 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int rfc2045_isflowed ( const struct rfc2045 p)

Definition at line 1250 of file rfc2045.c.

{
       const char *cb=rfc2045_getattr(p->content_type_attr, "format");

       return (cb && strcmp(cb, "flowed") == 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rfc2045_mimeinfo ( const struct rfc2045 p,
const char **  content_type_s,
const char **  content_transfer_encoding_s,
const char **  charset_s 
)

Definition at line 1203 of file rfc2045.c.

{
const char *c;

       *content_type_s=GETINFO(p->content_type, "text/plain");
       *content_transfer_encoding_s=GETINFO(p->content_transfer_encoding,
                                          "8bit");

       c=rfc2045_getattr(p->content_type_attr, "charset");
       if (!c)       c=rfc2045_getdefaultcharset();

       *charset_s=c;
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned rfc2045_mimepartcount ( const struct rfc2045 p)

Definition at line 1307 of file rfc2045.c.

{
const struct rfc2045 *q;
unsigned n=0;

       for (q=p->firstpart; q; q=q->next) ++n;
       return (n);
}
void rfc2045_mimepos ( const struct rfc2045 p,
off_t *  start_pos,
off_t *  end_pos,
off_t *  start_body,
off_t *  nlines,
off_t *  nbodylines 
)

Definition at line 1284 of file rfc2045.c.

{
       *start_pos=p->startpos;
       *end_pos=p->endpos;

       *nlines=p->nlines;
       *nbodylines=p->nbodylines;
       if (p->parent)       /* MIME parts do not have the trailing CRLF */
       {
              *end_pos=p->endbody;
              if (*nlines)  --*nlines;
              if (*nbodylines) --*nbodylines;
       }
       *start_body=p->startbody;

       if (*start_body == *start_pos)     /* No header */
       {
              *start_body= *end_pos;
       }
}

Here is the caller graph for this function:

void rfc2045_parse ( struct rfc2045 h,
const char *  buf,
size_t  s 
)

Definition at line 266 of file rfc2045.c.

{
       size_t l;

       while (s)
       {
              for (l=0; l<s; l++)
                     if (buf[l] == '\n')  break;
              if (l < s && buf[l] == '\n')
              {
                     ++l;
                     rfc2045_add_workbuf(h, buf, l);
                     doline(h);
                     h->workbuflen=0;
              }
              else
                     rfc2045_add_workbuf(h, buf, l);
              buf += l;
              s -= l;
       }

       if (h->workbuflen > 1024)
              rfc2045_parse_partial(h);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int rfc2045_parse_mime_header ( const char *  header,
void(*)(const char *, void *)  header_type_cb,
void(*)(const char *, const char *, void *)  header_param_cb,
void *  void_arg 
)

Definition at line 1330 of file rfc2045.c.

{
       struct rfc2045_parse_mime_info mi;
       struct rfc822t *h=rfc822t_alloc_new(header, NULL, NULL);

       mi.header_type_cb=header_type_cb;
       mi.header_param_cb=header_param_cb;
       mi.void_arg=void_arg;

       if (!h)
              return -1;

       parse_content_header(h, 0, parse_mime_cb, parse_param_cb, &mi);
       rfc822t_free(h);
       return 0;
}

Here is the call graph for this function:

void rfc2045_parse_partial ( struct rfc2045 h)

Definition at line 291 of file rfc2045.c.

{
       /*
       ** Our buffer's getting pretty big.  Let's see if we can
       ** partially handle it.
       */

       if (h->workbuflen > 0)
       {
       struct rfc2045 *p;
       int    l, i;

              for (p=h; p->lastpart && !p->lastpart->workclosed;
                            p=p->lastpart)
                     ;

              /* If p->workinheader, we've got a mother of all headers
              ** here.  Well, that's just too bad, we'll end up garbling
              ** it.
              */

              l=h->workbuflen;

              /* We do need to make sure that the final \r\n gets
              ** stripped off, so don't gobble up everything if
              ** the last character we see is a \r
              */

              if (h->workbuf[l-1] == '\r')
                     --l;

              /* If we'll be rewriting, make sure rwprep knows about
              ** stuff that was skipped just now. */

              if (h->rfc2045acptr && !p->workinheader &&
                     (!p->lastpart || !p->lastpart->workclosed))
                     (*h->rfc2045acptr->section_contents)(h->workbuf, l);

              update_counts(p, p->endpos+l, p->endpos+l, 0);
              p->informdata=1;
              for (i=0; l<h->workbuflen; l++)
                     h->workbuf[i++]=h->workbuf[l];
              h->workbuflen=i;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* rfc2045_related_start ( const struct rfc2045 p)

Definition at line 1083 of file rfc2045.c.

{
const char *cb=rfc2045_getattr( p->content_type_attr, "start");
struct rfc822t *t;
struct rfc822a       *a;
int    i;

       if (!cb || !*cb)     return (0);

       t=rfc822t_alloc_new(cb, 0, NULL);
       if (!t)
       {
              rfc2045_enomem();
              return(0);
       }

       a=rfc822a_alloc(t);
       if (!a)
       {
              rfc822t_free(t);
              rfc2045_enomem();
              return (0);
       }
       for (i=0; i<a->naddrs; i++)
              if (a->addrs[i].tokens)
              {
              char   *s=rfc822_getaddr(a, i);

                     rfc822a_free(a);
                     rfc822t_free(t);
                     if (!s)
                            rfc2045_enomem();
                     return (s);
              }

       rfc822a_free(a);
       rfc822t_free(t);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rfc2045_setdefaultcharset ( const char *  charset)

Definition at line 1228 of file rfc2045.c.

{
char   *p=strdup(charset);

       if (!p)
       {
              rfc2045_enomem();
              return;
       }

       if (rfc2045_defcharset)     free(rfc2045_defcharset);
       rfc2045_defcharset=p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void save_content_disposition ( char *  content_disposition,
void *  void_arg 
) [static]

Definition at line 1056 of file rfc2045.c.

{
       struct rfc2045 *r=(struct rfc2045 *)void_arg;

       if (r->content_disposition) free(r->content_disposition);
       r->content_disposition=content_disposition;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void save_content_disposition_parameter ( const char *  name,
struct rfc822t header,
int  start,
int  len,
void *  void_arg 
) [static]

Definition at line 1064 of file rfc2045.c.

{
       struct rfc2045 *r=(struct rfc2045 *)void_arg;
       char   *p;

       p=paste_tokens(header, start, len);
       if (!p)       return;

       if (rfc2045_attrset(&r->content_disposition_attr, name, p) < 0)
       {
              free(p);
              rfc2045_enomem();
       }
       free(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void save_content_type ( char *  content_type,
void *  void_arg 
) [static]

Definition at line 976 of file rfc2045.c.

{
       struct rfc2045 *r=(struct rfc2045 *)void_arg;

       if (r->content_type) free(r->content_type);
       r->content_type=content_type;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void save_content_type_parameter ( const char *  name,
struct rfc822t header,
int  start,
int  len,
void *  void_arg 
) [static]

Definition at line 984 of file rfc2045.c.

{
       struct rfc2045 *r=(struct rfc2045 *)void_arg;
       char   *p;

       p=strcmp(name, "charset") == 0 ?
                     lower_paste_tokens(header, start, len):
                     paste_tokens(header, start, len);
       if (!p)       return;

       if (rfc2045_attrset(&r->content_type_attr, name, p) < 0)
       {
              free(p);
              rfc2045_enomem();
       }

       free(p);

       if (strcmp(name, "boundary") == 0)
       {
              struct rfc2045 *q;

              if (r->boundary)
                     free(r->boundary);
              p=lower_paste_tokens(header, start, len);
              r->boundary=p;

              /*
              ** Check all the outer MIME boundaries.  If this is a
              ** substring of an outer MIME boundary, or the outer
              ** boundary is a substring of the inner boundary, we
              ** have an ambiguity - see "IMPLEMENTOR'S NOTE" in
              ** section 5.1.1 of RFC 2046.
              */

              for (q=r->parent; q; q=q->parent)
              {
                     const char *a, *b;

                     if (!q->boundary)
                            continue;

                     for (a=q->boundary, b=p; *a && *b; a++, b++)
                            if (*a != *b)
                                   break;

                     if (!*a || !*b)
                     {
                            while (q->parent)
                                   q=q->parent;
                            q->rfcviolation |= RFC2045_ERRBADBOUNDARY;
                            break;
                     }
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void set_string ( char **  p,
const char *  q 
) [static]

Definition at line 221 of file rfc2045.c.

{
       if (*p)       free(*p);

       *p=0;
       if (!q)       return;

       if ((*p=(char *)malloc(strlen(q)+1)) == 0)
       {
              rfc2045_enomem();
              return;
       }

       strcpy(*p, q);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void update_counts ( struct rfc2045 p,
size_t  newcnt,
size_t  newendcnt,
unsigned  nlines 
) [static]

Definition at line 240 of file rfc2045.c.

{
       while (p)
       {
              p->endpos = newcnt;
              p->endbody = newendcnt;
              p->nlines += nlines;
              if (!p->workinheader)
                     p->nbodylines += nlines;
              p=p->parent;
       }
}

Here is the caller graph for this function:


Variable Documentation

char* rfc2045_defcharset = 0 [static]

Definition at line 22 of file rfc2045.c.

Definition at line 24 of file rfc2045.c.