source: squid-ssl/trunk/fuentes/lib/rfc1123.c @ 5495

Last change on this file since 5495 was 5495, checked in by Juanma, 2 years ago

Initial release

File size: 5.0 KB
Line 
1/*
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "rfc1123.h"
11
12/*
13 *  Adapted from HTSUtils.c in CERN httpd 3.0 (http://info.cern.ch/httpd/)
14 *  by Darren Hardy <hardy@cs.colorado.edu>, November 1994.
15 */
16#if HAVE_STRING_H
17#include <string.h>
18#endif
19#if HAVE_CTYPE_H
20#include <ctype.h>
21#endif
22#if HAVE_TIME_H
23#include <time.h>
24#endif
25
26#define RFC850_STRFTIME "%A, %d-%b-%y %H:%M:%S GMT"
27#define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
28
29static int make_month(const char *s);
30static int make_num(const char *s);
31
32static const char *month_names[12] = {
33    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
34    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
35};
36
37static int
38make_num(const char *s)
39{
40    if (*s >= '0' && *s <= '9')
41        return 10 * (*s - '0') + *(s + 1) - '0';
42    else
43        return *(s + 1) - '0';
44}
45
46static int
47make_month(const char *s)
48{
49    int i;
50    char month[3];
51
52    month[0] = xtoupper(*s);
53    month[1] = xtolower(*(s + 1));
54    month[2] = xtolower(*(s + 2));
55
56    for (i = 0; i < 12; i++)
57        if (!strncmp(month_names[i], month, 3))
58            return i;
59    return -1;
60}
61
62static int
63tmSaneValues(struct tm *tm)
64{
65    if (tm->tm_sec < 0 || tm->tm_sec > 59)
66        return 0;
67    if (tm->tm_min < 0 || tm->tm_min > 59)
68        return 0;
69    if (tm->tm_hour < 0 || tm->tm_hour > 23)
70        return 0;
71    if (tm->tm_mday < 1 || tm->tm_mday > 31)
72        return 0;
73    if (tm->tm_mon < 0 || tm->tm_mon > 11)
74        return 0;
75    return 1;
76}
77
78static struct tm *
79parse_date_elements(const char *day, const char *month, const char *year,
80                    const char *aTime, const char *zone) {
81    static struct tm tm;
82    char *t;
83    memset(&tm, 0, sizeof(tm));
84
85    if (!day || !month || !year || !aTime || (zone && strcmp(zone, "GMT")))
86        return NULL;
87    tm.tm_mday = atoi(day);
88    tm.tm_mon = make_month(month);
89    if (tm.tm_mon < 0)
90        return NULL;
91    tm.tm_year = atoi(year);
92    if (strlen(year) == 4)
93        tm.tm_year -= 1900;
94    else if (tm.tm_year < 70)
95        tm.tm_year += 100;
96    else if (tm.tm_year > 19000)
97        tm.tm_year -= 19000;
98    tm.tm_hour = make_num(aTime);
99    t = strchr(aTime, ':');
100    if (!t)
101        return NULL;
102    t++;
103    tm.tm_min = atoi(t);
104    t = strchr(t, ':');
105    if (t)
106        tm.tm_sec = atoi(t + 1);
107    return tmSaneValues(&tm) ? &tm : NULL;
108}
109
110static struct tm *
111parse_date(const char *str) {
112    struct tm *tm;
113    static char tmp[64];
114    char *t;
115    char *wday = NULL;
116    char *day = NULL;
117    char *month = NULL;
118    char *year = NULL;
119    char *timestr = NULL;
120    char *zone = NULL;
121
122    xstrncpy(tmp, str, 64);
123
124    for (t = strtok(tmp, ", "); t; t = strtok(NULL, ", ")) {
125        if (xisdigit(*t)) {
126            if (!day) {
127                day = t;
128                t = strchr(t, '-');
129                if (t) {
130                    *t++ = '\0';
131                    month = t;
132                    t = strchr(t, '-');
133                    if (!t)
134                        return NULL;
135                    *t++ = '\0';
136                    year = t;
137                }
138            } else if (strchr(t, ':'))
139                timestr = t;
140            else if (!year)
141                year = t;
142            else
143                return NULL;
144        } else if (!wday)
145            wday = t;
146        else if (!month)
147            month = t;
148        else if (!zone)
149            zone = t;
150        else
151            return NULL;
152    }
153    tm = parse_date_elements(day, month, year, timestr, zone);
154
155    return tm;
156}
157
158time_t
159parse_rfc1123(const char *str)
160{
161    struct tm *tm;
162    time_t t;
163    if (NULL == str)
164        return -1;
165    tm = parse_date(str);
166    if (!tm)
167        return -1;
168    tm->tm_isdst = -1;
169#if HAVE_TIMEGM
170    t = timegm(tm);
171#elif HAVE_TM_TM_GMTOFF
172    t = mktime(tm);
173    if (t != -1) {
174        struct tm *local = localtime(&t);
175        t += local->tm_gmtoff;
176    }
177#else
178    /* some systems do not have tm_gmtoff so we fake it */
179    t = mktime(tm);
180    if (t != -1) {
181        time_t dst = 0;
182#if !(defined(_TIMEZONE) || defined(_timezone) || _SQUID_AIX_ || _SQUID_WINDOWS_ || _SQUID_SGI_)
183        extern long timezone;
184#endif
185        /*
186         * The following assumes a fixed DST offset of 1 hour,
187         * which is probably wrong.
188         */
189        if (tm->tm_isdst > 0)
190            dst = -3600;
191#if defined(_timezone) || _SQUID_WINDOWS_
192        t -= (_timezone + dst);
193#else
194        t -= (timezone + dst);
195#endif
196    }
197#endif
198    return t;
199}
200
201const char *
202mkrfc1123(time_t t)
203{
204    static char buf[128];
205
206    struct tm *gmt = gmtime(&t);
207
208    buf[0] = '\0';
209    strftime(buf, 127, RFC1123_STRFTIME, gmt);
210    return buf;
211}
212
213#if 0
214int
215main()
216{
217    char *x;
218    time_t t, pt;
219
220    t = time(NULL);
221    x = mkrfc1123(t);
222    printf("HTTP Time: %s\n", x);
223
224    pt = parse_rfc1123(x);
225    printf("Parsed: %d vs. %d\n", pt, t);
226}
227
228#endif
229
Note: See TracBrowser for help on using the repository browser.