Back to index

courier  0.68.2
rfc2045header.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000-2011 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 #include "rfc2045_config.h"
00007 #include      "rfc2045.h"
00008 #include      "rfc2045src.h"
00009 #include      <stdio.h>
00010 #include      <unistd.h>
00011 #include      <stdlib.h>
00012 #include      <string.h>
00013 #include      <ctype.h>
00014 #include      <sys/types.h>
00015 #include      <sys/stat.h>
00016 
00017 
00018 struct rfc2045src_fd {
00019        struct rfc2045src src;
00020        int fd;
00021 };
00022 
00023 static void deinit_func_fd(void *);
00024 
00025 static int seek_func_fd(int64_t pos, void *);
00026 
00027 static ssize_t read_func_fd(char *buf, size_t cnt, void *);
00028 
00029 struct rfc2045src *rfc2045src_init_fd(int fd)
00030 {
00031        struct rfc2045src_fd *ptr=malloc(sizeof(struct rfc2045src_fd));
00032 
00033        if (!ptr)
00034               return NULL;
00035 
00036        memset(ptr, 0, sizeof(*ptr));
00037 
00038        ptr->src.arg=ptr;
00039        ptr->src.deinit_func=deinit_func_fd;
00040        ptr->src.seek_func=seek_func_fd;
00041        ptr->src.read_func=read_func_fd;
00042        ptr->fd=fd;
00043        return &ptr->src;
00044 }
00045 
00046 void rfc2045src_deinit(struct rfc2045src *ptr)
00047 {
00048        (*ptr->deinit_func)(ptr->arg);
00049 }
00050 
00051 static void deinit_func_fd(void *ptr)
00052 {
00053        struct rfc2045src_fd *s=(struct rfc2045src_fd *)ptr;
00054 
00055        free(s);
00056 }
00057 
00058 static int seek_func_fd(off_t pos, void *ptr)
00059 {
00060        struct rfc2045src_fd *s=(struct rfc2045src_fd *)ptr;
00061 
00062        if (lseek(s->fd, pos, SEEK_SET) < 0)
00063               return -1;
00064 
00065        return 0;
00066 }
00067 
00068 static ssize_t read_func_fd(char *buf, size_t cnt, void *ptr)
00069 {
00070        struct rfc2045src_fd *s=(struct rfc2045src_fd *)ptr;
00071 
00072        return read(s->fd, buf, cnt);
00073 }
00074 
00075 
00076 struct rfc2045headerinfo {
00077 
00078        struct rfc2045src *src;
00079 
00080        char *headerbuf;
00081        size_t headerbufsize;
00082 
00083        char readbuf[1024];
00084 
00085        char *readptr;
00086        size_t readleft;
00087 
00088        size_t headerleft;
00089        int firstheader;
00090 } ;
00091 
00092 struct rfc2045headerinfo *rfc2045header_start(struct rfc2045src *src,
00093                                          struct rfc2045 *rfcp)
00094 {
00095        off_t start_pos, dummy, start_body;
00096        int firstheader;
00097        struct rfc2045headerinfo *p;
00098 
00099        if (rfcp)
00100        {
00101               rfc2045_mimepos(rfcp, &start_pos, &dummy, &start_body, &dummy,
00102                             &dummy);
00103               firstheader=0;
00104        }
00105        else
00106        {
00107               start_pos=0;
00108               start_body=0;
00109               firstheader=1;
00110        }
00111 
00112        if (SRC_SEEK(src, start_pos) < 0)
00113               return NULL;
00114 
00115        p=(struct rfc2045headerinfo *)calloc(sizeof(struct rfc2045headerinfo),
00116                                         1);
00117 
00118        if (!p)
00119               return (NULL);
00120        p->src=src;
00121 
00122        p->headerleft=start_body - start_pos;
00123        p->firstheader=firstheader;
00124        return (p);
00125 }
00126 
00127 void rfc2045header_end(struct rfc2045headerinfo *p)
00128 {
00129        if (p->headerbuf)
00130               free(p->headerbuf);
00131        free(p);
00132 }
00133 
00134 static int fill(struct rfc2045headerinfo *p)
00135 {
00136        ssize_t n;
00137 
00138        n=sizeof(p->readbuf);
00139 
00140        if (p->firstheader == 0)
00141        {
00142               if (p->headerleft == 0)
00143                      return (-1);
00144 
00145 
00146               if (n > p->headerleft)
00147                      n=p->headerleft;
00148        }
00149 
00150        n=SRC_READ(p->src, p->readbuf, n);
00151 
00152        if (n <= 0)
00153        {
00154               p->headerleft=0;
00155               p->readleft=0;
00156               return (-1);
00157        }
00158        p->readptr=p->readbuf;
00159        p->readleft = n;
00160 
00161        if (p->firstheader == 0)
00162               p->headerleft -= n;
00163 
00164        return ((int)(unsigned char)p->readbuf[0]);
00165 }
00166 
00167 #define PEEK(p) ((p)->readleft ? (int)(unsigned char)*p->readptr:fill(p))
00168 
00169 
00170 int rfc2045header_get(struct rfc2045headerinfo *p, char **header,
00171                     char **value,
00172                     int flags)
00173 {
00174        int c=PEEK(p);
00175        int isnl=0;
00176        size_t n=0;
00177        char *s, *t;
00178        int eatspace=0;
00179 
00180        if (c == -1 || c == '\r' || c == '\n')
00181        {
00182               *header=*value=NULL;
00183               return (0);
00184        }
00185 
00186        for (;;)
00187        {
00188               if (n >= p->headerbufsize)
00189               {
00190                      size_t n=p->headerbufsize += 256;
00191                      char *s= p->headerbuf ?
00192                             realloc(p->headerbuf, n):
00193                             malloc(n);
00194 
00195                      if (!s)
00196                             return (-1);
00197                      p->headerbuf=s;
00198                      p->headerbufsize=n;
00199               }
00200 
00201               c=PEEK(p);
00202               if (c < 0)
00203                      break;
00204 
00205               if (c == '\r')
00206               {
00207                      --p->readleft;
00208                      ++p->readptr;
00209                      continue;
00210               }
00211 
00212               if (isnl) /* Last char was newline */
00213               {
00214                      if (!isspace((int)(unsigned char)c) || c == '\n')
00215                             break;
00216 
00217                      isnl=0;
00218 
00219                      if ((flags & RFC2045H_KEEPNL) == 0)
00220                             eatspace=1; /* Fold headers */
00221               }
00222 
00223               if (c == '\n')
00224                      isnl=1;
00225 
00226               if (eatspace)
00227               {
00228                      if (c != '\n' && isspace((int)(unsigned char)c))
00229                      {
00230                             --p->readleft;
00231                             ++p->readptr;
00232                             continue;
00233                      }
00234                      eatspace=0;
00235               }
00236 
00237               if (c == '\n' && (flags & RFC2045H_KEEPNL) == 0)
00238                      c=' ';
00239 
00240               p->headerbuf[n++]=c;
00241               --p->readleft;
00242               ++p->readptr;
00243        }
00244 
00245        while (n > 0 && p->headerbuf[n-1] == ' ')
00246               --n;
00247 
00248        p->headerbuf[n]=0;
00249 
00250        *header= *value= p->headerbuf;
00251 
00252        while (**value)
00253        {
00254               if (**value == ':')
00255               {
00256                      **value=0;
00257                      ++*value;
00258 
00259                      while (**value && isspace((int)(unsigned char)**value))
00260                             ++*value;
00261                      break;
00262               }
00263 
00264               if (!(flags & RFC2045H_NOLC))
00265               {
00266                      if (**value >= 'A' && **value <= 'Z')
00267                             **value += 'a' - 'A';
00268               }
00269               ++*value;
00270        }
00271 
00272        s=strrchr( *value, '\n');
00273 
00274        if (s && *s && s[1] == 0)
00275               *s=0;
00276 
00277        s=strrchr( *value, '\r');
00278 
00279        if (s && *s && s[1] == 0)
00280               *s=0;
00281 
00282        for (s=t=*value; *s; )
00283               if (!isspace((int)(unsigned char)*s++))
00284                      t=s;
00285        *t=0;
00286        return (0);
00287 }