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

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.
  3. ** See COPYING for distribution information.
  4. */
  5. /*
  6. ** $Id: rfc822_parsedt.c,v 1.3 1999/12/06 13:29:49 mrsam Exp $
  7. */
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <time.h>
  12. /*
  13. ** time_t rfc822_parsedate(const char *p)
  14. **
  15. ** p - contents of the Date: header, attempt to parse it into a time_t.
  16. **
  17. ** returns - time_t, or 0 if the date cannot be parsed
  18. */
  19. static unsigned parsedig(const char **p)
  20. {
  21. unsigned i=0;
  22. while (isdigit((int)(unsigned char)**p))
  23. {
  24. i=i*10 + **p - '0';
  25. ++*p;
  26. }
  27. return (i);
  28. }
  29. static const char * const weekdays[7]={
  30. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  31. } ;
  32. static const char * const mnames[13]={
  33. "Jan", "Feb", "Mar", "Apr",
  34. "May", "Jun", "Jul", "Aug",
  35. "Sep", "Oct", "Nov", "Dec", NULL};
  36. #define leap(y) ( 
  37. ((y) % 400) == 0 || 
  38. (((y) % 4) == 0 && (y) % 100) )
  39. static unsigned mlength[]={31,28,31,30,31,30,31,31,30,31,30,31};
  40. #define mdays(m,y) ( (m) != 2 ? mlength[(m)-1] : leap(y) ? 29:28)
  41. static const char * const zonenames[] = {
  42. "UT","GMT",
  43. "EST","EDT",
  44. "CST","CDT",
  45. "MST","MDT",
  46. "PST","PDT",
  47. "Z",
  48. "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M", 
  49. "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
  50. NULL};
  51. #define ZH(n) ( (n) * 60 * 60 )
  52. static int zoneoffset[] = {
  53. 0, 0,
  54. ZH(-5), ZH(-4),
  55. ZH(-6), ZH(-5),
  56. ZH(-7), ZH(-6),
  57. ZH(-8), ZH(-7),
  58. 0,
  59. ZH(-1), ZH(-2), ZH(-3), ZH(-4), ZH(-5), ZH(-6), ZH(-7), ZH(-8), ZH(-9), ZH(-10), ZH(-11), ZH(-12),
  60. ZH(1), ZH(2), ZH(3), ZH(4), ZH(5), ZH(6), ZH(7), ZH(8), ZH(9), ZH(10), ZH(11), ZH(12) };
  61. static unsigned parsekey(const char **mon, const char * const *ary)
  62. {
  63. unsigned m, j;
  64. for (m=0; ary[m]; m++)
  65. {
  66. for (j=0; ary[m][j]; j++)
  67. if (tolower(ary[m][j]) != tolower((*mon)[j]))
  68. break;
  69. if (!ary[m][j])
  70. {
  71. *mon += j;
  72. return (m+1);
  73. }
  74. }
  75. return (0);
  76. }
  77. static int parsetime(const char **t)
  78. {
  79. unsigned h,m,s=0;
  80. if (!isdigit((int)(unsigned char)**t)) return (-1);
  81. h=parsedig(t);
  82. if (h > 23) return (-1);
  83. if (**t != ':') return (-1);
  84. ++*t;
  85. if (!isdigit((int)(unsigned char)**t)) return (-1);
  86. m=parsedig(t);
  87. if (**t == ':')
  88. {
  89. ++*t;
  90. if (!isdigit((int)(unsigned char)**t)) return (-1);
  91. s=parsedig(t);
  92. }
  93. if (m > 59 || s > 59) return (-1);
  94. return (h * 60 * 60 + m * 60 + s);
  95. }
  96. time_t rfc822_parsedt(const char *rfcdt)
  97. {
  98. unsigned day=0, mon=0, year;
  99. int secs;
  100. int offset;
  101. time_t t;
  102. unsigned y;
  103. /* Ignore day of the week.  Tolerate "Tue, 25 Feb 1997 ... "
  104. ** without the comma.  Tolerate "Feb 25 1997 ...".
  105. */
  106. while (!day || !mon)
  107. {
  108. if (!*rfcdt) return (0);
  109. if (isalpha((int)(unsigned char)*rfcdt))
  110. {
  111. if (mon) return (0);
  112. mon=parsekey(&rfcdt, mnames);
  113. if (!mon)
  114. while (*rfcdt && isalpha((int)(unsigned char)*rfcdt))
  115. ++rfcdt;
  116. continue;
  117. }
  118. if (isdigit((int)(unsigned char)*rfcdt))
  119. {
  120. if (day) return (0);
  121. day=parsedig(&rfcdt);
  122. if (!day) return (0);
  123. continue;
  124. }
  125. ++rfcdt;
  126. }
  127. while (*rfcdt && isspace((int)(unsigned char)*rfcdt))
  128. ++rfcdt;
  129. if (!isdigit((int)(unsigned char)*rfcdt)) return (0);
  130. year=parsedig(&rfcdt);
  131. if (year < 70) year += 2000;
  132. if (year < 100) year += 1900;
  133. while (*rfcdt && isspace((int)(unsigned char)*rfcdt))
  134. ++rfcdt;
  135. if (day == 0 || mon == 0 || mon > 12 || day > mdays(mon,year))
  136. return (0);
  137. secs=parsetime(&rfcdt);
  138. if (secs < 0) return (0);
  139. offset=0;
  140. /* RFC822 sez no parenthesis, but I've seen (EST) */
  141. while ( *rfcdt )
  142. {
  143. if (isalnum((int)(unsigned char)*rfcdt) || *rfcdt == '+' || *rfcdt == '-')
  144. break;
  145. ++rfcdt;
  146. }
  147. if (isalpha((int)(unsigned char)*rfcdt))
  148. {
  149. int n=parsekey(&rfcdt, zonenames);
  150. if (n > 0) offset= zoneoffset[n-1];
  151. }
  152. else
  153. {
  154. int sign=1;
  155. unsigned n;
  156. switch (*rfcdt) {
  157. case '-':
  158. sign= -1;
  159. case '+':
  160. ++rfcdt;
  161. }
  162. if (isdigit((int)(unsigned char)*rfcdt))
  163. {
  164. n=parsedig(&rfcdt);
  165. if (n > 2359 || (n % 100) > 59) n=0;
  166. offset = sign * ( (n % 100) * 60 + n / 100 * 60 * 60);
  167. }
  168. }
  169. if (year < 1970) return (0);
  170. t=0;
  171. for (y=1970; y<year; y++)
  172. {
  173. if ( leap(y) )
  174. {
  175. if (year-y >= 4)
  176. {
  177. y += 3;
  178. t += ( 365*3+366 ) * 24 * 60 * 60;
  179. continue;
  180. }
  181. t += 24 * 60 * 60;
  182. }
  183. t += 365 * 24 * 60 * 60;
  184. }
  185. for (y=1; y < mon; y++)
  186. t += mdays(y, year) * 24 * 60 * 60;
  187. return ( t + (day-1) * 24 * 60 * 60 + secs - offset );
  188. }
  189. const char *rfc822_mkdt(time_t t)
  190. {
  191. static char buf[80];
  192. struct tm *tmptr=gmtime(&t);
  193. buf[0]=0;
  194. if (tmptr)
  195. {
  196. sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
  197. weekdays[tmptr->tm_wday],
  198. tmptr->tm_mday,
  199. mnames[tmptr->tm_mon],
  200. tmptr->tm_year + 1900,
  201. tmptr->tm_hour,
  202. tmptr->tm_min,
  203. tmptr->tm_sec);
  204. }
  205. return (buf);
  206. }