diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /rfc2045/rfc2045header.c | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'rfc2045/rfc2045header.c')
| -rw-r--r-- | rfc2045/rfc2045header.c | 287 | 
1 files changed, 287 insertions, 0 deletions
| diff --git a/rfc2045/rfc2045header.c b/rfc2045/rfc2045header.c new file mode 100644 index 0000000..a4b64f9 --- /dev/null +++ b/rfc2045/rfc2045header.c @@ -0,0 +1,287 @@ +/* +** Copyright 2000-2011 Double Precision, Inc.  See COPYING for +** distribution information. +*/ + +#include "rfc2045_config.h" +#include	"rfc2045.h" +#include	"rfc2045src.h" +#include	<stdio.h> +#include	<unistd.h> +#include	<stdlib.h> +#include	<string.h> +#include	<ctype.h> +#include	<sys/types.h> +#include	<sys/stat.h> + + +struct rfc2045src_fd { +	struct rfc2045src src; +	int fd; +}; + +static void deinit_func_fd(void *); + +static int seek_func_fd(int64_t pos, void *); + +static ssize_t read_func_fd(char *buf, size_t cnt, void *); + +struct rfc2045src *rfc2045src_init_fd(int fd) +{ +	struct rfc2045src_fd *ptr=malloc(sizeof(struct rfc2045src_fd)); + +	if (!ptr) +		return NULL; + +	memset(ptr, 0, sizeof(*ptr)); + +	ptr->src.arg=ptr; +	ptr->src.deinit_func=deinit_func_fd; +	ptr->src.seek_func=seek_func_fd; +	ptr->src.read_func=read_func_fd; +	ptr->fd=fd; +	return &ptr->src; +} + +void rfc2045src_deinit(struct rfc2045src *ptr) +{ +	(*ptr->deinit_func)(ptr->arg); +} + +static void deinit_func_fd(void *ptr) +{ +	struct rfc2045src_fd *s=(struct rfc2045src_fd *)ptr; + +	free(s); +} + +static int seek_func_fd(off_t pos, void *ptr) +{ +	struct rfc2045src_fd *s=(struct rfc2045src_fd *)ptr; + +	if (lseek(s->fd, pos, SEEK_SET) < 0) +		return -1; + +	return 0; +} + +static ssize_t read_func_fd(char *buf, size_t cnt, void *ptr) +{ +	struct rfc2045src_fd *s=(struct rfc2045src_fd *)ptr; + +	return read(s->fd, buf, cnt); +} + + +struct rfc2045headerinfo { + +	struct rfc2045src *src; + +	char *headerbuf; +	size_t headerbufsize; + +	char readbuf[1024]; + +	char *readptr; +	size_t readleft; + +	size_t headerleft; +	int firstheader; +} ; + +struct rfc2045headerinfo *rfc2045header_start(struct rfc2045src *src, +					      struct rfc2045 *rfcp) +{ +	off_t start_pos, dummy, start_body; +	int firstheader; +	struct rfc2045headerinfo *p; + +	if (rfcp) +	{ +		rfc2045_mimepos(rfcp, &start_pos, &dummy, &start_body, &dummy, +				&dummy); +		firstheader=0; +	} +	else +	{ +		start_pos=0; +		start_body=0; +		firstheader=1; +	} + +	if (SRC_SEEK(src, start_pos) < 0) +		return NULL; + +	p=(struct rfc2045headerinfo *)calloc(sizeof(struct rfc2045headerinfo), +					     1); + +	if (!p) +		return (NULL); +	p->src=src; + +	p->headerleft=start_body - start_pos; +	p->firstheader=firstheader; +	return (p); +} + +void rfc2045header_end(struct rfc2045headerinfo *p) +{ +	if (p->headerbuf) +		free(p->headerbuf); +	free(p); +} + +static int fill(struct rfc2045headerinfo *p) +{ +	ssize_t n; + +	n=sizeof(p->readbuf); + +	if (p->firstheader == 0) +	{ +		if (p->headerleft == 0) +			return (-1); + + +		if (n > p->headerleft) +			n=p->headerleft; +	} + +	n=SRC_READ(p->src, p->readbuf, n); + +	if (n <= 0) +	{ +		p->headerleft=0; +		p->readleft=0; +		return (-1); +	} +	p->readptr=p->readbuf; +	p->readleft = n; + +	if (p->firstheader == 0) +		p->headerleft -= n; + +	return ((int)(unsigned char)p->readbuf[0]); +} + +#define PEEK(p) ((p)->readleft ? (int)(unsigned char)*p->readptr:fill(p)) + + +int rfc2045header_get(struct rfc2045headerinfo *p, char **header, +		      char **value, +		      int flags) +{ +	int c=PEEK(p); +	int isnl=0; +	size_t n=0; +	char *s, *t; +	int eatspace=0; + +	if (c == -1 || c == '\r' || c == '\n') +	{ +		*header=*value=NULL; +		return (0); +	} + +	for (;;) +	{ +		if (n >= p->headerbufsize) +		{ +			size_t n=p->headerbufsize += 256; +			char *s= p->headerbuf ? +				realloc(p->headerbuf, n): +				malloc(n); + +			if (!s) +				return (-1); +			p->headerbuf=s; +			p->headerbufsize=n; +		} + +		c=PEEK(p); +		if (c < 0) +			break; + +		if (c == '\r') +		{ +			--p->readleft; +			++p->readptr; +			continue; +		} + +		if (isnl) /* Last char was newline */ +		{ +			if (!isspace((int)(unsigned char)c) || c == '\n') +				break; + +			isnl=0; + +			if ((flags & RFC2045H_KEEPNL) == 0) +				eatspace=1; /* Fold headers */ +		} + +		if (c == '\n') +			isnl=1; + +		if (eatspace) +		{ +			if (c != '\n' && isspace((int)(unsigned char)c)) +			{ +				--p->readleft; +				++p->readptr; +				continue; +			} +			eatspace=0; +		} + +		if (c == '\n' && (flags & RFC2045H_KEEPNL) == 0) +			c=' '; + +		p->headerbuf[n++]=c; +		--p->readleft; +		++p->readptr; +	} + +	while (n > 0 && p->headerbuf[n-1] == ' ') +		--n; + +	p->headerbuf[n]=0; + +	*header= *value= p->headerbuf; + +	while (**value) +	{ +		if (**value == ':') +		{ +			**value=0; +			++*value; + +			while (**value && isspace((int)(unsigned char)**value)) +				++*value; +			break; +		} + +		if (!(flags & RFC2045H_NOLC)) +		{ +			if (**value >= 'A' && **value <= 'Z') +				**value += 'a' - 'A'; +		} +		++*value; +	} + +	s=strrchr( *value, '\n'); + +	if (s && *s && s[1] == 0) +		*s=0; + +	s=strrchr( *value, '\r'); + +	if (s && *s && s[1] == 0) +		*s=0; + +	for (s=t=*value; *s; ) +		if (!isspace((int)(unsigned char)*s++)) +			t=s; +	*t=0; +	return (0); +} | 
