diff options
Diffstat (limited to 'ext/mailparse/rfc2045.c')
-rwxr-xr-x | ext/mailparse/rfc2045.c | 1174 |
1 files changed, 0 insertions, 1174 deletions
diff --git a/ext/mailparse/rfc2045.c b/ext/mailparse/rfc2045.c deleted file mode 100755 index 0cd002f2ac..0000000000 --- a/ext/mailparse/rfc2045.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* $Id$ */ -/* - ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for - ** distribution information. - */ - -#include "php.h" -#include "php_mailparse.h" - -#define MAXLEVELS 20 -#define MAXPARTS 300 - -/* - New RFC2045 structure. - */ - -struct rfc2045 *rfc2045_alloc() -{ - struct rfc2045 *p=(struct rfc2045 *)emalloc(sizeof(struct rfc2045)); - - /* Initialize everything to nulls, except for one thing */ - - memset(p, 0, sizeof(*p)); - - p->pindex=1; /* Start with part #1 */ - - /* Most of the time, we're about to read a header */ - p->workinheader=1; - - MAKE_STD_ZVAL(p->headerhash); - array_init(p->headerhash); - - return (p); -} - -const char *rfc2045_getattr(const struct rfc2045attr *p, const char *name) -{ - while (p) - { - if (p->name && strcmp(p->name, name) == 0) - return (p->value); - p=p->next; - } - return (0); -} - -void rfc2045_setattr(struct rfc2045attr **p, const char *name, const char *val) -{ - 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) efree(q->name); - if (q->value) efree(q->value); - efree(q); - } - return; - } - - v = estrdup(val); - - if (!*p) - { - *p = (struct rfc2045attr *)emalloc(sizeof(**p)); - memset( (*p), 0, sizeof(**p)); - (*p)->name = estrdup(name); - } - if ( (*p)->value ) - efree ( (*p)->value ); - (*p)->value=v; -} - -/* static const char cb_name[]="boundary"; */ - -/* #define ContentBoundary(p) (rfc2045_getattr( (p)->content_type_attr, cb_name)) */ - -#define ContentBoundary(p) ( (p)->boundary ) - -/* - Unallocate the RFC2045 structure. Recursively unallocate - all sub-structures. Unallocate all associated buffers. - */ - -static void rfc2045_freeattr(struct rfc2045attr *p) -{ - while (p) - { - struct rfc2045attr *q=p->next; - - if (p->name) efree(p->name); - if (p->value) efree(p->value); - efree(p); - p=q; - } -} - -void rfc2045_free(struct rfc2045 *p) -{ - 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->content_md5) efree(p->content_md5); - if (p->content_base) efree(p->content_base); - if (p->content_location) efree(p->content_location); - if (p->content_language) efree(p->content_language); - if (p->content_id) efree(p->content_id); - if (p->content_description) efree(p->content_description); - if (p->content_transfer_encoding) efree(p->content_transfer_encoding); - if (p->boundary) efree(p->boundary); - if (p->content_type) efree(p->content_type); - if (p->mime_version) efree(p->mime_version); - if (p->workbuf) efree(p->workbuf); - if (p->header) efree(p->header); - if (p->content_disposition) efree(p->content_disposition); - if (p->rw_transfer_encoding) efree(p->rw_transfer_encoding); - if (p->rfc2045acptr) - efree(p->rfc2045acptr); - zval_dtor(p->headerhash); - efree(p->headerhash); - efree(p); -} - -/* - Generic dynamic buffer append. - */ - -void rfc2045_add_buf( - char **bufptr, /* Buffer */ - size_t *bufsize, /* Buffer's maximum size */ - size_t *buflen, /* Buffer's current size */ - - const char *p, size_t len) /* Append this data */ -{ - if (len + *buflen > *bufsize) - { - size_t newsize=len+*buflen+256; - char *p= *bufptr ? (char *)erealloc(*bufptr, newsize): - (char *)emalloc(newsize); - - *bufptr=p; - *bufsize=newsize; - } - - memcpy(*bufptr + *buflen, p, len); - *buflen += len; -} - -/* Append to the work buffer */ - -void rfc2045_add_workbuf(struct rfc2045 *h, const char *p, size_t len) -{ - rfc2045_add_buf( &h->workbuf, &h->workbufsize, &h->workbuflen, p, len); -} - -/* Append one character to the work buffer */ - -void rfc2045_add_workbufch(struct rfc2045 *h, int c) -{ - char cc= (char)c; - - rfc2045_add_workbuf(h, &cc, 1); -} - -/* - Generic function to duplicate contents of a string. - The destination string may already be previously allocated, - so unallocate it. - */ - -static void set_string(char **p, - const char *q) -{ - if (*p) { - efree(*p); - *p=0; - } - if (!q) return; - - *p = estrdup(q); -} - -/* Update byte counts for this structure, and all the superstructures */ - -static void update_counts(struct rfc2045 *p, size_t newcnt, size_t newendcnt, - unsigned nlines) -{ - while (p) - { - p->endpos = newcnt; - p->endbody = newendcnt; - p->nlines += nlines; - if (!p->workinheader) - p->nbodylines += nlines; - p=p->parent; - } -} - -/* - Main entry point for RFC2045 parsing. External data is fed - by repetitively calling rfc2045_parse(). - - rfc2045_parse() breaks up input into lines, and calls doline() - to process each line. - */ - -static void doline(struct rfc2045 *); - -void rfc2045_parse(struct rfc2045 *h, const char *buf, size_t s) -{ - 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; - } - - /* - ** Our buffer's getting pretty big. Let's see if we can - ** partially handle it. - */ - - if (h->workbuflen > 512) - { - 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->rfc2045acptr, 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; - } -} - -/* - Append a new RFC2045 subpart. Adds new RFC2045 structure to the - end of the list of existing RFC2045 substructures. - */ - -static struct rfc2045 *append_part_noinherit(struct rfc2045 *p, size_t startpos) -{ - 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); -} - -static struct rfc2045 *append_part(struct rfc2045 *p, size_t startpos) -{ - 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); - rfc2045_setattr(&newp->content_type_attr, "charset", - rfc2045_getattr(p->content_type_attr, "charset")); - return (newp); -} - -/* - doline() processes next line in the RFC2045 message. - - Drills down the list of all the multipart messages currently open, - and checks if the line is a boundary line for the given multipart. - In theory the boundary line, if there is one, should be the boundary - line only for the inner multipart only, but, this takes into account - broken MIME messages. - */ - -static void do_header(struct rfc2045 *); - -static void doline(struct rfc2045 *p) -{ - 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] & 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+cnt, 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)(rwp); - - /* 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 */ - - newp->mime_version = estrdup(p->mime_version); - return; - } - p=p->lastpart; - ++num_levels; - } - - /* Ok, we've found the RFC2045 section that we're working with. - ** Now 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)(rwp, 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. - * Allow broken messages that omit the Mime-Version header to still be - * parsed. - */ - - if (p->mime_version == NULL && p->content_type != NULL) { - /* technically in violation of the spec, but there are some broken - * mailers out there that send this. Sadly, they are so broken - * they don't set X-Mailer so we can't tell what they are... - * Lets be useful and allow it, but flag it as a boo-boo */ - p->mime_version = estrdup("1.0"); - p->rfcviolation |= RFC2045_ERRNOMIMEVERSION; - } - - 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) - { - efree(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)) - rfc2045_setattr(&p->content_type_attr, "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)(rwp, 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); -} - -/***********************************************************************/ - -/* - ** paste_tokens() - recombine an array of RFC822 tokens back as a string. - ** (Comments) are ignored. - */ - -static char *paste_tokens(struct rfc822t *h, int start, int cnt) -{ - 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 (mailparse_rfc822_is_atom(h->tokens[start+i].token)) - l += h->tokens[start+i].len; - else - l++; - } - - /* Do it */ - - p=( char *)emalloc(l); - l=0; - - for (i=0; i<cnt; i++) - { - if (h->tokens[start+i].token == '(') - continue; - - if (mailparse_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); -} - -/* Various permutations of the above, including forcing the string to - ** lowercase - */ - -static char *lower_paste_tokens(struct rfc822t *h, int start, int cnt) -{ - char *p=paste_tokens(h, start, cnt); - char *q; - - for (q=p; q && *q; q++) - *q=tolower(*q); - return (p); -} - -static char *paste_token(struct rfc822t *h, int i) -{ - if (i >= h->ntokens) return (0); - return (paste_tokens(h, i, 1)); -} - -static char *lower_paste_token(struct rfc822t *h, int i) -{ - char *p=paste_token(h, i); - char *q; - - for (q=p; q && *q; q++) - *q=tolower(*q); - return (p); -} - -/* - do_header() - process completed RFC822 header. - */ - -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 do_header(struct rfc2045 *p) -{ - struct rfc822t *header; - char *t; - char * val; - - 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=mailparse_rfc822t_alloc(p->header, NULL); - - if (!header) return; /* Broken header */ - - if (header->ntokens < 2 || - header->tokens[0].token || - header->tokens[1].token != ':') - { - mailparse_rfc822t_free(header); - return; /* Broken header */ - } - - t=lower_paste_token(header, 0); - - - if (t != 0) { - - /* add the header to the hash */ - val = strchr(p->header, ':'); - if (val) { - val++; - while(isspace(*val)) - val++; - add_assoc_string(p->headerhash, t, val, 1); - } - if (strcmp(t, "mime-version") == 0) - { - efree(t); - mime_version(p, header); - } - else if (strcmp(t, "content-type") == 0) - { - efree(t); - content_type(p, header); - } else if (strcmp(t, "content-transfer-encoding") == 0) - { - efree(t); - content_transfer_encoding(p, header); - } else if (strcmp(t, "content-disposition") == 0) - { - efree(t); - content_disposition(p, header); - } else if (strcmp(t, "content-id") == 0) - { - efree(t); - content_id(p, header); - } else if (strcmp(t, "content-description") == 0) - { - efree(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) - { - efree(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) - { - efree(t); - content_base(p, header); - } else if (strcmp(t, "content-location") == 0) - { - efree(t); - content_location(p, header); - } else if (strcmp(t, "content-md5") == 0) - { - efree(t); - t=strchr(p->header, ':'); - if (t) ++t; - while (t && isspace((int)(unsigned char)*t)) - ++t; - content_md5(p, t); - } - else efree(t); - } - mailparse_rfc822t_free(header); -} - -/* Mime-Version: and Content-Transfer-Encoding: headers are easy */ - -static void mime_version(struct rfc2045 *p, struct rfc822t *header) -{ - char *vers=paste_tokens(header, 2, header->ntokens-2); - - if (!vers) return; - - if (p->mime_version) efree(p->mime_version); - p->mime_version=vers; -} - -static void content_transfer_encoding(struct rfc2045 *r, - struct rfc822t *header) -{ - char *p; - - p=lower_paste_tokens(header, 2, header->ntokens-2); - if (!p) return; - - if (r->content_transfer_encoding) - efree(r->content_transfer_encoding); - r->content_transfer_encoding=p; - - if (strcmp(p, "8bit") == 0) - r->content_8bit=1; -} - -/* Dig into the content_type header */ - -static void parse_content_header(struct rfc2045 *r, struct rfc822t *header, - void (*init_token)(struct rfc2045 *, char *), - void (*init_parameter)(struct rfc2045 *, const char *, - struct rfc822t *, int, int)) -{ - int start; - int i, j; - char *p; - - /* Look for the 1st ; */ - - for (start=2; start < header->ntokens; start++) - if (header->tokens[start].token == ';') - break; - - /* Everything up to the 1st ; is the content type */ - - p=lower_paste_tokens(header, 2, start-2); - if (!p) return; - - (*init_token)(r, p); - 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; - p=lower_paste_token(header, start); - if (!p) return; - (*init_parameter)(r, p, header, j, i-j); - efree(p); - } - } - if ( i<header->ntokens ) ++i; /* Skip over ; */ - start=i; - } -} - -/* Dig into the content_type header */ - -static void save_content_type(struct rfc2045 *, char *); -static void save_content_type_parameter( struct rfc2045 *, const char *, - struct rfc822t *, int, int); - -static void content_type(struct rfc2045 *r, struct rfc822t *header) -{ - parse_content_header(r, header, &save_content_type, - &save_content_type_parameter); -} - -static void save_content_type(struct rfc2045 *r, char *content_type) -{ - if (r->content_type) efree(r->content_type); - r->content_type=content_type; -} - -static void save_content_type_parameter( - struct rfc2045 *r, const char *name, - struct rfc822t *header, int start, int len) -{ - char *p; - - p=strcmp(name, "charset") == 0 ? - lower_paste_tokens(header, start, len): - paste_tokens(header, start, len); - if (!p) return; - - rfc2045_setattr(&r->content_type_attr, name, p); - efree(p); - - if (strcmp(name, "boundary") == 0) - { - if (r->boundary) - efree(r->boundary); - p=lower_paste_tokens(header, start, len); - r->boundary=p; - } -} - -/* Dig into content-disposition */ - -static void save_content_disposition(struct rfc2045 *, char *); -static void save_content_disposition_parameter( struct rfc2045 *, const char *, - struct rfc822t *, int, int); - -static void content_disposition(struct rfc2045 *r, struct rfc822t *header) -{ - parse_content_header(r, header, &save_content_disposition, - &save_content_disposition_parameter); -} - -static void save_content_disposition(struct rfc2045 *r, - char *content_disposition) -{ - if (r->content_disposition) efree(r->content_disposition); - r->content_disposition=content_disposition; -} - -static void save_content_disposition_parameter( - struct rfc2045 *r, const char *name, - struct rfc822t *header, int start, int len) -{ - char *p; - - p=paste_tokens(header, start, len); - if (!p) return; - - rfc2045_setattr(&r->content_disposition_attr, name, p); - efree(p); -} - -char *rfc2045_related_start(const struct rfc2045 *p) -{ - const char *cb=rfc2045_getattr( p->content_type_attr, "start"); - struct rfc822t *t; - struct rfc822a *a; - int i; - - if (!cb || !*cb) return (0); - - t=mailparse_rfc822t_alloc(cb, 0); - a=mailparse_rfc822a_alloc(t); - for (i=0; i<a->naddrs; i++) - if (a->addrs[i].tokens) - { - char *s=mailparse_rfc822_getaddr(a, i); - - mailparse_rfc822a_free(a); - mailparse_rfc822t_free(t); - return (s); - } - - mailparse_rfc822a_free(a); - mailparse_rfc822t_free(t); - return (0); -} - -static void content_id(struct rfc2045 *p, struct rfc822t *t) -{ - struct rfc822a *a=mailparse_rfc822a_alloc(t); - int i; - - - for (i=0; i<a->naddrs; i++) - if (a->addrs[i].tokens) - { - char *s=mailparse_rfc822_getaddr(a, i); - if (p->content_id) - efree(p->content_id); - p->content_id=s; - break; - } - - mailparse_rfc822a_free(a); -} - -static void content_description(struct rfc2045 *p, const char *s) -{ - if (s && *s) - set_string(&p->content_description, s); -} - -static void content_language(struct rfc2045 *p, const char *s) -{ - if (s && *s) - set_string(&p->content_language, s); -} - -static void content_md5(struct rfc2045 *p, const char *s) -{ - if (s && *s) - set_string(&p->content_md5, s); -} - -static void content_base(struct rfc2045 *p, struct rfc822t *t) -{ - 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); -} - -static void content_location(struct rfc2045 *p, struct rfc822t *t) -{ - 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); -} - -/* -------------------- */ - -#define GETINFO(s, def) ( (s) && (*s) ? (s):def) - -void rfc2045_mimeinfo(const struct rfc2045 *p, - const char **content_type_s, - const char **content_transfer_encoding_s, - const char **charset_s) -{ - const char *c; - TSRMLS_FETCH(); - - *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 = MAILPARSEG(def_charset); - - *charset_s=c; -} - -const char *rfc2045_boundary(const struct rfc2045 *p) -{ - const char *cb=rfc2045_getattr( p->content_type_attr, "boundary"); - - if (!cb) cb=""; - return (cb); -} - -void rfc2045_dispositioninfo(const struct rfc2045 *p, - const char **disposition_s, - const char **disposition_name_s, - const char **disposition_filename_s) -{ - *disposition_s=p->content_disposition; - *disposition_name_s=rfc2045_getattr(p->content_disposition_attr, - "name"); - *disposition_filename_s=rfc2045_getattr(p->content_disposition_attr, - "filename"); -} - -const char *rfc2045_contentname(const struct rfc2045 *p) -{ - const char *q=rfc2045_getattr(p->content_type_attr, "name"); - - if (!q) q=""; - return (q); -} - -const char *rfc2045_content_id(const struct rfc2045 *p) -{ - return (p->content_id ? p->content_id:""); -} - -const char *rfc2045_content_description(const struct rfc2045 *p) -{ - return (p->content_description ? p->content_description:""); -} - -const char *rfc2045_content_language(const struct rfc2045 *p) -{ - return (p->content_language ? p->content_language:""); -} - -const char *rfc2045_content_md5(const struct rfc2045 *p) -{ - return (p->content_md5 ? p->content_md5:""); -} - -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) -{ - *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; -} - -unsigned rfc2045_mimepartcount(const struct rfc2045 *p) -{ - const struct rfc2045 *q; - unsigned n=0; - - for (q=p->firstpart; q; q=q->next) ++n; - return (n); -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ |