summaryrefslogtreecommitdiffstats
path: root/rfc2045/rfc2045header.c
diff options
context:
space:
mode:
authorSam Varshavchik2013-08-19 16:39:41 -0400
committerSam Varshavchik2013-08-25 14:43:51 -0400
commit9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch)
tree7a81a04cb51efb078ee350859a64be2ebc6b8813 /rfc2045/rfc2045header.c
parenta9520698b770168d1f33d6301463bb70a19655ec (diff)
downloadcourier-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.c287
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);
+}