rfc2045cdecode.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:4k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
- ** distribution information.
- */
- #include "rfc2045.h"
- #include <ctype.h>
- #include <string.h>
- /* $Id: rfc2045cdecode.c,v 1.3 1999/12/06 13:29:02 mrsam Exp $ */
- extern void rfc2045_add_buf( char **, size_t *, size_t *,
- const char *, size_t);
- extern void rfc2045_add_workbuf(struct rfc2045 *, const char *, size_t);
- extern void rfc2045_add_workbufch(struct rfc2045 *, int);
- static int decode_raw(struct rfc2045 *p, const char *s, size_t l)
- {
- if (s && l) return ((*p->udecode_func)(s,l,p->misc_decode_ptr));
- return (0);
- }
- static const char xdigit[]="0123456789ABCDEF";
- static int do_decode_qp(struct rfc2045 *p)
- {
- char *a, *b, *c, *end;
- int d;
- end=p->workbuf + p->workbuflen;
- for (a=b=p->workbuf; a < end; )
- {
- if (*a != '=')
- {
- *b++ = *a++;
- continue;
- }
- ++a;
- if (!*a || a >= end || isspace((int)(unsigned char)*a))
- break;
- if ((c=strchr(xdigit, *a)) == 0) continue;
- d= (c-xdigit)*16;
- ++a;
- if (!*a || a >= end)
- break;
- if ((c=strchr(xdigit, *a)) == 0) continue;
- d += c-xdigit;
- ++a;
- *b++=d;
- }
- p->workbuflen= b-p->workbuf;
- d=(*p->udecode_func)(p->workbuf, p->workbuflen, p->misc_decode_ptr);
- p->workbuflen=0;
- return (d);
- }
- static unsigned char decode64tab[256];
- static int decode64tab_init=0;
- /* When we have enough base64-encoded data in the buffer, decode it. */
- static int do_decode_base64(struct rfc2045 *p)
- {
- size_t i, j;
- char a,b,c;
- size_t k;
- int rc;
- if (!decode64tab_init)
- {
- for (i=0; i<256; i++) decode64tab[i]=100;
- for (i=0; i<64; i++)
- decode64tab[ (int)
- ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]) ]=i;
- decode64tab[ (int)'=' ] = 99;
- }
- /* Remove everything except base64encoded data */
- for (i=j=0; i<p->workbuflen; i++)
- if (decode64tab[(int)(unsigned char)p->workbuf[i]] < 100)
- p->workbuf[j++]=p->workbuf[i];
- p->workbuflen=j;
- /* Decode the data, in 4-byte pieces */
- i=j / 4;
- i=i*4;
- k=0;
- for (j=0; j<i; j += 4)
- {
- int w=decode64tab[(int)(unsigned char)p->workbuf[j]];
- int x=decode64tab[(int)(unsigned char)p->workbuf[j+1]];
- int y=decode64tab[(int)(unsigned char)p->workbuf[j+2]];
- int z=decode64tab[(int)(unsigned char)p->workbuf[j+3]];
- a= (w << 2) | (x >> 4);
- b= (x << 4) | (y >> 2);
- c= (y << 6) | z;
- p->workbuf[k++]=a;
- if ( p->workbuf[j+2] != '=')
- p->workbuf[k++]=b;
- if ( p->workbuf[j+3] != '=')
- p->workbuf[k++]=c;
- }
- rc=(*p->udecode_func)(p->workbuf, k, p->misc_decode_ptr);
- /* Anything left? Move it to the start of the buffer */
- k=0;
- while (j < p->workbuflen)
- p->workbuf[k++]=p->workbuf[j++];
- p->workbuflen=k;
- return (0);
- }
- static int decode_qp(struct rfc2045 *p, const char *s, size_t l)
- {
- size_t start,i;
- int rc;
- if (!s)
- return (do_decode_qp(p));
- for (start=0; start<l; )
- {
- for (i=start; i<l; i++)
- {
- if (s[i] != 'n') continue;
- rfc2045_add_workbuf(p, s+start, i-start);
- rfc2045_add_workbufch(p, 'n');
- if ((rc=do_decode_qp(p)) != 0) return (rc);
- start= ++i;
- break;
- }
- rfc2045_add_workbuf(p, s+start, i-start);
- if (p->workbuflen > 1024)
- {
- char buf[10];
- int i;
- for (i=p->workbuflen - 5; i<p->workbuflen; i++)
- if (p->workbuf[i] == '=') break;
- if (i < p->workbuflen)
- {
- int j=p->workbuflen-i;
- memcpy(buf, p->workbuf+i, j);
- buf[j]=0;
- p->workbuflen=i;
- }
- else buf[0]=0;
- if ((rc=do_decode_qp(p)) != 0) return (rc);
- rfc2045_add_workbuf(p, buf, strlen(buf));
- }
- start=i;
- }
- return (0);
- }
- static int decode_base64(struct rfc2045 *p, const char *s, size_t l)
- {
- if (!s)
- return (do_decode_base64(p));
- rfc2045_add_workbuf(p, s, l);
- if (p->workbuflen > 256)
- return (do_decode_base64(p));
- return (0);
- }
- void rfc2045_cdecode_start(struct rfc2045 *p,
- int (*u)(const char *, size_t, void *), void *miscptr)
- {
- p->misc_decode_ptr=miscptr;
- p->udecode_func=u;
- p->decode_func= &decode_raw;
- p->workbuflen=0;
- if (p->content_transfer_encoding)
- {
- if (strcmp(p->content_transfer_encoding,
- "quoted-printable") == 0)
- p->decode_func= &decode_qp;
- else if (strcmp(p->content_transfer_encoding, "base64") == 0)
- p->decode_func= &decode_base64;
- }
- }
- int rfc2045_cdecode_end(struct rfc2045 *p)
- {
- return ((*p->decode_func)(p, NULL, 0));
- }
- int rfc2045_cdecode(struct rfc2045 *p, const char *s, size_t l)
- {
- if (s && l) return ((*p->decode_func)(p, s, l));
- return (0);
- }