rfc2045cdecode.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:4k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. #include "rfc2045.h"
  6. #include <ctype.h>
  7. #include <string.h>
  8. /* $Id: rfc2045cdecode.c,v 1.3 1999/12/06 13:29:02 mrsam Exp $ */
  9. extern void rfc2045_add_buf( char **, size_t *, size_t *,
  10. const char *, size_t);
  11. extern void rfc2045_add_workbuf(struct rfc2045 *, const char *, size_t);
  12. extern void rfc2045_add_workbufch(struct rfc2045 *, int);
  13. static int decode_raw(struct rfc2045 *p, const char *s, size_t l)
  14. {
  15. if (s && l) return ((*p->udecode_func)(s,l,p->misc_decode_ptr));
  16. return (0);
  17. }
  18. static const char xdigit[]="0123456789ABCDEF";
  19. static int do_decode_qp(struct rfc2045 *p)
  20. {
  21. char *a, *b, *c, *end;
  22. int d;
  23. end=p->workbuf + p->workbuflen;
  24. for (a=b=p->workbuf; a < end; )
  25. {
  26. if (*a != '=')
  27. {
  28. *b++ = *a++;
  29. continue;
  30. }
  31. ++a;
  32. if (!*a || a >= end || isspace((int)(unsigned char)*a))
  33. break;
  34. if ((c=strchr(xdigit, *a)) == 0) continue;
  35. d= (c-xdigit)*16;
  36. ++a;
  37. if (!*a || a >= end)
  38. break;
  39. if ((c=strchr(xdigit, *a)) == 0) continue;
  40. d += c-xdigit;
  41. ++a;
  42. *b++=d;
  43. }
  44. p->workbuflen= b-p->workbuf;
  45. d=(*p->udecode_func)(p->workbuf, p->workbuflen, p->misc_decode_ptr);
  46. p->workbuflen=0;
  47. return (d);
  48. }
  49. static unsigned char decode64tab[256];
  50. static int decode64tab_init=0;
  51. /* When we have enough base64-encoded data in the buffer, decode it. */
  52. static int do_decode_base64(struct rfc2045 *p)
  53. {
  54. size_t i, j;
  55. char a,b,c;
  56. size_t k;
  57. int rc;
  58. if (!decode64tab_init)
  59. {
  60. for (i=0; i<256; i++) decode64tab[i]=100;
  61. for (i=0; i<64; i++)
  62. decode64tab[ (int)
  63. ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]) ]=i;
  64. decode64tab[ (int)'=' ] = 99;
  65. }
  66. /* Remove everything except base64encoded data */
  67. for (i=j=0; i<p->workbuflen; i++)
  68. if (decode64tab[(int)(unsigned char)p->workbuf[i]] < 100)
  69. p->workbuf[j++]=p->workbuf[i];
  70. p->workbuflen=j;
  71. /* Decode the data, in 4-byte pieces */
  72. i=j / 4;
  73. i=i*4;
  74. k=0;
  75. for (j=0; j<i; j += 4)
  76. {
  77. int w=decode64tab[(int)(unsigned char)p->workbuf[j]];
  78. int x=decode64tab[(int)(unsigned char)p->workbuf[j+1]];
  79. int y=decode64tab[(int)(unsigned char)p->workbuf[j+2]];
  80. int z=decode64tab[(int)(unsigned char)p->workbuf[j+3]];
  81. a= (w << 2) | (x >> 4);
  82. b= (x << 4) | (y >> 2);
  83. c= (y << 6) | z;
  84. p->workbuf[k++]=a;
  85. if ( p->workbuf[j+2] != '=')
  86. p->workbuf[k++]=b;
  87. if ( p->workbuf[j+3] != '=')
  88. p->workbuf[k++]=c;
  89. }
  90. rc=(*p->udecode_func)(p->workbuf, k, p->misc_decode_ptr);
  91. /* Anything left?  Move it to the start of the buffer */
  92. k=0;
  93. while (j < p->workbuflen)
  94. p->workbuf[k++]=p->workbuf[j++];
  95. p->workbuflen=k;
  96. return (0);
  97. }
  98. static int decode_qp(struct rfc2045 *p, const char *s, size_t l)
  99. {
  100. size_t start,i;
  101. int rc;
  102. if (!s)
  103. return (do_decode_qp(p));
  104. for (start=0; start<l; )
  105. {
  106. for (i=start; i<l; i++)
  107. {
  108. if (s[i] != 'n') continue;
  109. rfc2045_add_workbuf(p, s+start, i-start);
  110. rfc2045_add_workbufch(p, 'n');
  111. if ((rc=do_decode_qp(p)) != 0) return (rc);
  112. start= ++i;
  113. break;
  114. }
  115. rfc2045_add_workbuf(p, s+start, i-start);
  116. if (p->workbuflen > 1024)
  117. {
  118. char buf[10];
  119. int i;
  120. for (i=p->workbuflen - 5; i<p->workbuflen; i++)
  121. if (p->workbuf[i] == '=') break;
  122. if (i < p->workbuflen)
  123. {
  124. int j=p->workbuflen-i;
  125. memcpy(buf, p->workbuf+i, j);
  126. buf[j]=0;
  127. p->workbuflen=i;
  128. }
  129. else buf[0]=0;
  130. if ((rc=do_decode_qp(p)) != 0) return (rc);
  131. rfc2045_add_workbuf(p, buf, strlen(buf));
  132. }
  133. start=i;
  134. }
  135. return (0);
  136. }
  137. static int decode_base64(struct rfc2045 *p, const char *s, size_t l)
  138. {
  139. if (!s)
  140. return (do_decode_base64(p));
  141. rfc2045_add_workbuf(p, s, l);
  142. if (p->workbuflen > 256)
  143. return (do_decode_base64(p));
  144. return (0);
  145. }
  146. void rfc2045_cdecode_start(struct rfc2045 *p,
  147. int (*u)(const char *, size_t, void *), void *miscptr)
  148. {
  149. p->misc_decode_ptr=miscptr;
  150. p->udecode_func=u;
  151. p->decode_func= &decode_raw;
  152. p->workbuflen=0;
  153. if (p->content_transfer_encoding)
  154. {
  155. if (strcmp(p->content_transfer_encoding,
  156. "quoted-printable") == 0)
  157. p->decode_func= &decode_qp;
  158. else if (strcmp(p->content_transfer_encoding, "base64") == 0)
  159. p->decode_func= &decode_base64;
  160. }
  161. }
  162. int rfc2045_cdecode_end(struct rfc2045 *p)
  163. {
  164. return ((*p->decode_func)(p, NULL, 0));
  165. }
  166. int rfc2045_cdecode(struct rfc2045 *p, const char *s, size_t l)
  167. {
  168. if (s && l) return ((*p->decode_func)(p, s, l));
  169. return (0);
  170. }