Exemple #1
0
static void content_id(struct rfc2045 *p, struct rfc822t *t)
{
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);
}
Exemple #2
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)	free(q->name);
			if (q->value)	free(q->value);
			free(q);
		}
		return;
	}

	v=strdup(val);
	if (!v)
	{
		rfc2045_enomem();
		return;
	}

	if (!*p)
	{
		if (((*p)=(struct rfc2045attr *)malloc(sizeof(**p))) == 0)
		{
			free(v);
			rfc2045_enomem();
			return;
		}
		memset( (*p), 0, sizeof(**p));
		if ( ((*p)->name=strdup(name)) == 0)
		{
			free( *p );
			*p=0;
			free(v);
			rfc2045_enomem();
			return;
		}
	}
	if ( (*p)->value )	free ( (*p)->value );
	(*p)->value=v;
}
Exemple #3
0
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 *)realloc(*bufptr, newsize):
				(char *)malloc(newsize);

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

	memcpy(*bufptr + *buflen, p, len);
	*buflen += len;
}
Exemple #4
0
void rfc2045_setdefaultcharset(const char *charset)
{
char	*p=strdup(charset);

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

	if (rfc2045_defcharset)	free(rfc2045_defcharset);
	rfc2045_defcharset=p;
}
Exemple #5
0
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=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);
}
char *rfc2045_mk_boundary(struct rfc2045 *s, int fd)
{
char	pidbuf[NUMBUFSIZE];
char	timebuf[NUMBUFSIZE];
char	cntbuf[60];
int	cnt=0;
time_t	mytime;
#ifndef __WINDOWS__
char	hostnamebuf[256];
pid_t	mypid;
#endif
char	*p;
int	rc;

	time(&mytime);

#ifdef __WINDOWS__
	sprintf(pidbuf, "%ld", GetCurrentThreadId());
	sprintf(timebuf, "%ld", (long)mytime);
#else
	hostnamebuf[sizeof(hostnamebuf)-1]=0;
	if (gethostname(hostnamebuf, sizeof(hostnamebuf)-1))
		hostnamebuf[0]=0;
	mypid=getpid();
	sprintf(pidbuf, "%d", (int)mypid);
	sprintf(timebuf, "%ld", mytime);
#endif

	for (;;)
	{
		sprintf(cntbuf, "%d", ++cnt);
		p=malloc(strlen(pidbuf)+strlen(timebuf)+
			strlen(cntbuf)+10);
		if (!p)
		{
			rfc2045_enomem();
			return (NULL);
		}

		sprintf(p, "=_%s-%s-%s", pidbuf, timebuf, cntbuf);
		if ((rc=rfc2045_try_boundary(s, fd, p)) == 0)
			break;
		free(p);
		if (rc < 0)
			return (NULL);
	}
	return (p);
}
Exemple #7
0
static void set_string(char **p,
	const char *q)
{
	if (*p)	free(*p);

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

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

	strcpy(*p, q);
}
Exemple #8
0
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 (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);
}
Exemple #9
0
char *rfc2045_mk_boundary(struct rfc2045 *s, int fd)
{
char	hostnamebuf[256];
pid_t	mypid;
char	pidbuf[NUMBUFSIZE];
time_t	mytime;
char	timebuf[NUMBUFSIZE];
static size_t	cnt=0;
char	cntbuf[NUMBUFSIZE];
char	*p;
int	rc;

	hostnamebuf[sizeof(hostnamebuf)-1]=0;
	if (gethostname(hostnamebuf, sizeof(hostnamebuf)-1))
		hostnamebuf[0]=0;
	mypid=getpid();
	time(&mytime);
	libmail_str_pid_t(mypid, pidbuf);
	libmail_str_time_t(mytime, timebuf);
	for (;;)
	{
		char tempbuf[NUMBUFSIZE];

		libmail_str_size_t(++cnt, tempbuf);
		sprintf(cntbuf, "%4s", tempbuf);
		for (p=cntbuf; *p == ' '; *p++ = '0')
			;
		p=malloc(strlen(hostnamebuf)+strlen(pidbuf)
			 +strlen(timebuf)+strlen(cntbuf)+11);
		if (!p)
		{
			rfc2045_enomem();
			return (NULL);
		}

		sprintf(p, "=_%s-%s-%s-%s", hostnamebuf,
			pidbuf, timebuf, cntbuf);
		if ((rc=rfc2045_try_boundary(s, fd, p)) == 0)
			break;
		free(p);
		if (rc < 0)
			return (NULL);
	}
	return (p);
}
Exemple #10
0
struct rfc2045 *rfc2045_alloc()
{
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);
}
Exemple #11
0
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] == 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);
}
Exemple #12
0
int rfc2045_ac_check(struct rfc2045 *p, int rwmode)
{
int	flag=0;		/* Flag - rewriting suggested */
struct	rfc2045 *c;
int	hasnon7bit=p->has8bitchars;
		/* hasnon7bit: 8bit chars in this section or subsections */
const char *te;
int	is8bitte;

	for (c=p->firstpart; c; c=c->next)
		if (!c->isdummy)
		{
			if (rfc2045_ac_check(c, rwmode))	flag=1;
			if (strcmp(c->content_transfer_encoding, "7bit") &&
				strcmp(c->content_transfer_encoding, "quoted-printable"))
				hasnon7bit=1;
			if (c->has8bitchars)
				p->has8bitchars=1;
		}

	if (RFC2045_ISMIME1DEF(p->mime_version) && !p->content_type)
	{
		if ((p->content_type=strdup("text/plain")) == 0)
			rfc2045_enomem();
		if (p->mime_version)
		{
			flag=1;
		}
	}

	if (RFC2045_ISMIME1DEF(p->mime_version)
		&& !rfc2045_getattr(p->content_type_attr, "charset")
		&& strncasecmp(p->content_type, "text/", 5) == 0)
	{
		rfc2045_setattr(&p->content_type_attr, "charset",
			rfc2045_getdefaultcharset());

		if (p->mime_version

			&& p->firstpart == 0 /* sam - don't trigger rewrites on changes to multipart headers */

			)
		{
			flag=1;
		}
	}

	if (RFC2045_ISMIME1DEF(p->mime_version)
		&& !p->content_transfer_encoding)
	{
		if ((p->content_transfer_encoding=strdup(
			hasnon7bit ? "8bit":"7bit")) == 0)
			rfc2045_enomem();
		if (p->mime_version

			&& p->firstpart == 0 /* sam - don't trigger rewrites on changes to multipart headers */
			)
		{
			flag=1;
		}
	}

#if 0
	if (RFC2045_ISMIME1DEF(p->mime_version)
		&& strncmp(p->content_type, "text/", 5) == 0 && !hasnon7bit
		&& strcmp(p->content_transfer_encoding, "7bit"))
	{
		if (p->mime_version)
		{
			flag=1;
		}
	}
#endif

	if (RFC2045_ISMIME1DEF(p->mime_version))
	{
		/* Check for conversions */

		te=p->content_transfer_encoding;
		is8bitte=strcasecmp(te, "base64") &&
			strcasecmp(te, "quoted-printable") &&
			strcasecmp(te, "7bit");	/* 8 bit contents */

		if (is8bitte && !p->has8bitchars && !p->haslongline)
		{
			if (p->rw_transfer_encoding)
				free(p->rw_transfer_encoding);
			if ((p->rw_transfer_encoding=strdup("7bit")) == 0)
				rfc2045_enomem();
			flag=1;
			is8bitte=0;
		}

		if (rwmode == RFC2045_RW_7BIT && (is8bitte || p->haslongline))
		{
			if (p->rw_transfer_encoding)
				free(p->rw_transfer_encoding);
			if ((p->rw_transfer_encoding=strdup("quoted-printable"))
				== 0)
				rfc2045_enomem();
			flag=1;
		}
		else if (rwmode == RFC2045_RW_8BIT &&
			strcasecmp(te, "quoted-printable") == 0 &&
			!p->haslongline)
		{
			if (p->rw_transfer_encoding)
				free(p->rw_transfer_encoding);
			if ((p->rw_transfer_encoding=strdup(hasnon7bit
					? "8bit":"7bit")) == 0)
				rfc2045_enomem();
			flag=1;
		}
	}

	if (!p->mime_version)
	{
		if ((p->mime_version=strdup("1.0")) == 0)
			rfc2045_enomem();
	}
	return (flag);
}