rfc1123.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:6k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: rfc1123.c,v 1.21.2.1 1999/02/12 19:38:15 wessels Exp $
  3.  *
  4.  * DEBUG: 
  5.  * AUTHOR: Harvest Derived
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "config.h"
  35. /*
  36.  *  Adapted from HTSUtils.c in CERN httpd 3.0 (http://info.cern.ch/httpd/)
  37.  *  by Darren Hardy <hardy@cs.colorado.edu>, November 1994.
  38.  */
  39. #if HAVE_STDIO_H
  40. #include <stdio.h>
  41. #endif
  42. #if HAVE_STDLIB_H
  43. #include <stdlib.h>
  44. #endif
  45. #if HAVE_STRING_H
  46. #include <string.h>
  47. #endif
  48. #if HAVE_CTYPE_H
  49. #include <ctype.h>
  50. #endif
  51. #if HAVE_SYS_TYPES_H
  52. #include <sys/types.h>
  53. #endif
  54. #if HAVE_TIME_H
  55. #include <time.h>
  56. #endif
  57. #if HAVE_SYS_TIME_H
  58. #include <sys/time.h>
  59. #endif
  60. #include "util.h"
  61. #include "snprintf.h"
  62. #define RFC850_STRFTIME "%A, %d-%b-%y %H:%M:%S GMT"
  63. #define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
  64. static int make_month(const char *s);
  65. static int make_num(const char *s);
  66. static char *month_names[12] =
  67. {
  68.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  69.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  70. };
  71. static int
  72. make_num(const char *s)
  73. {
  74.     if (*s >= '0' && *s <= '9')
  75. return 10 * (*s - '0') + *(s + 1) - '0';
  76.     else
  77. return *(s + 1) - '0';
  78. }
  79. static int
  80. make_month(const char *s)
  81. {
  82.     int i;
  83.     char month[3];
  84.     month[0] = xtoupper(*s);
  85.     month[1] = xtolower(*(s + 1));
  86.     month[2] = xtolower(*(s + 2));
  87.     for (i = 0; i < 12; i++)
  88. if (!strncmp(month_names[i], month, 3))
  89.     return i;
  90.     return 0;
  91. }
  92. time_t
  93. parse_rfc1123(const char *str)
  94. {
  95.     const char *s;
  96.     struct tm tm;
  97.     time_t t;
  98.     if (!str)
  99. return -1;
  100.     memset(&tm, '', sizeof(struct tm));
  101.     if ((s = strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */
  102. s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */
  103. while (*s == ' ')
  104.     s++;
  105. if (xisdigit(*s) && !xisdigit(*(s+1))) /* backoff if only one digit */
  106.     s--;
  107. if (strchr(s, '-')) { /* First format */
  108.     if ((int) strlen(s) < 18)
  109. return -1;
  110.     tm.tm_mday = make_num(s);
  111.     tm.tm_mon = make_month(s + 3);
  112.     tm.tm_year = make_num(s + 7);
  113.     /*
  114.      * Y2K: Arjan de Vet <Arjan.deVet@adv.IAEhv.nl>
  115.      * if tm.tm_year < 70, assume it's after the year 2000.
  116.      */
  117.     if (tm.tm_year < 70)
  118. tm.tm_year += 100;
  119.     tm.tm_hour = make_num(s + 10);
  120.     tm.tm_min = make_num(s + 13);
  121.     tm.tm_sec = make_num(s + 16);
  122. } else { /* Second format */
  123.     if ((int) strlen(s) < 20)
  124. return -1;
  125.     tm.tm_mday = make_num(s);
  126.     tm.tm_mon = make_month(s + 3);
  127.     tm.tm_year = (100 * make_num(s + 7) - 1900) + make_num(s + 9);
  128.     tm.tm_hour = make_num(s + 12);
  129.     tm.tm_min = make_num(s + 15);
  130.     tm.tm_sec = make_num(s + 18);
  131. }
  132.     } else { /* Try the other format:        */
  133. s = str; /* Wed Jun  9 01:29:59 1993 GMT */
  134. while (*s && *s == ' ')
  135.     s++;
  136. if ((int) strlen(s) < 24)
  137.     return -1;
  138. tm.tm_mday = make_num(s + 8);
  139. tm.tm_mon = make_month(s + 4);
  140. /* Y2K fix, richard.kettlewell@kewill.com */
  141. tm.tm_year = atoi(s + 20) - 1900;
  142. tm.tm_hour = make_num(s + 11);
  143. tm.tm_min = make_num(s + 14);
  144. tm.tm_sec = make_num(s + 17);
  145.     }
  146.     if (tm.tm_sec < 0 || tm.tm_sec > 59 ||
  147. tm.tm_min < 0 || tm.tm_min > 59 ||
  148. tm.tm_hour < 0 || tm.tm_hour > 23 ||
  149. tm.tm_mday < 1 || tm.tm_mday > 31 ||
  150. tm.tm_mon < 0 || tm.tm_mon > 11 ||
  151. tm.tm_year < 70 || tm.tm_year > 120) {
  152. return -1;
  153.     }
  154.     tm.tm_isdst = -1;
  155. #ifdef HAVE_TIMEGM
  156.     t = timegm(&tm);
  157. #elif HAVE_TM_GMTOFF
  158.     t = mktime(&tm);
  159.     {
  160. struct tm *local = localtime(&t);
  161. t += local->tm_gmtoff;
  162.     }
  163. #else
  164.     /* some systems do not have tm_gmtoff so we fake it */
  165.     t = mktime(&tm);
  166.     {
  167. time_t dst = 0;
  168. #if defined (_TIMEZONE)
  169. #elif defined (_timezone)
  170. #elif defined(_SQUID_AIX_)
  171. #else
  172. extern time_t timezone;
  173. #endif
  174. /*
  175.  * The following assumes a fixed DST offset of 1 hour,
  176.  * which is probably wrong.
  177.  */
  178. if (tm.tm_isdst > 0)
  179.     dst = -3600;
  180. #ifdef _timezone
  181. t -= (_timezone + dst);
  182. #else
  183. t -= (timezone + dst);
  184. #endif
  185.     }
  186. #endif
  187.     return t;
  188. }
  189. const char *
  190. mkrfc1123(time_t t)
  191. {
  192.     static char buf[128];
  193.     struct tm *gmt = gmtime(&t);
  194.     buf[0] = '';
  195.     strftime(buf, 127, RFC1123_STRFTIME, gmt);
  196.     return buf;
  197. }
  198. const char *
  199. mkhttpdlogtime(const time_t * t)
  200. {
  201.     static char buf[128];
  202.     struct tm *gmt = gmtime(t);
  203. #ifndef USE_GMT
  204.     int gmt_min, gmt_hour, gmt_yday, day_offset;
  205.     size_t len;
  206.     struct tm *lt;
  207.     int min_offset;
  208.     /* localtime & gmtime may use the same static data */
  209.     gmt_min = gmt->tm_min;
  210.     gmt_hour = gmt->tm_hour;
  211.     gmt_yday = gmt->tm_yday;
  212.     lt = localtime(t);
  213.     day_offset = lt->tm_yday - gmt_yday;
  214.     min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60
  215. + (lt->tm_min - gmt_min);
  216.     /* wrap round on end of year */
  217.     if (day_offset > 1)
  218. day_offset = -1;
  219.     else if (day_offset < -1)
  220. day_offset = 1;
  221.     len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt);
  222.     snprintf(buf + len, 128 - len, "%+03d%02d",
  223. (min_offset / 60) % 24,
  224. min_offset % 60);
  225. #else /* USE_GMT */
  226.     buf[0] = '';
  227.     strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt);
  228. #endif /* USE_GMT */
  229.     return buf;
  230. }
  231. #if 0
  232. int
  233. main()
  234. {
  235.     char *x;
  236.     time_t t, pt;
  237.     t = time(NULL);
  238.     x = mkrfc1123(t);
  239.     printf("HTTP Time: %sn", x);
  240.     pt = parse_rfc1123(x);
  241.     printf("Parsed: %d vs. %dn", pt, t);
  242. }
  243. #endif