rfc1123.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 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 "time/gadgets.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 const char *t;
83 memset(&tm, 0, sizeof(tm));
84
85 if (!day || !month || !year || !aTime || (zone && strcmp(zone, "GMT")))
86 return nullptr;
87 tm.tm_mday = atoi(day);
88 tm.tm_mon = make_month(month);
89 if (tm.tm_mon < 0)
90 return nullptr;
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 nullptr;
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 : nullptr;
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 = nullptr;
116 char *day = nullptr;
117 char *month = nullptr;
118 char *year = nullptr;
119 char *timestr = nullptr;
120 char *zone = nullptr;
121
122 xstrncpy(tmp, str, 64);
123
124 for (t = strtok(tmp, ", "); t; t = strtok(nullptr, ", ")) {
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 nullptr;
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 nullptr;
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 nullptr;
152 }
153 tm = parse_date_elements(day, month, year, timestr, zone);
154
155 return tm;
156}
157
158time_t
159Time::ParseRfc1123(const char *str)
160{
161 struct tm *tm;
162 time_t t;
163 if (nullptr == 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 *
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
time_t ParseRfc1123(const char *)
Convert from RFC 1123 style time: "www, DD MMM YYYY hh:mm:ss ZZZ".
Definition: rfc1123.cc:159
const char * FormatRfc1123(time_t)
Definition: rfc1123.cc:202
static struct tm * parse_date(const char *str)
Definition: rfc1123.cc:111
static struct tm * parse_date_elements(const char *day, const char *month, const char *year, const char *aTime, const char *zone)
Definition: rfc1123.cc:79
static int make_month(const char *s)
Definition: rfc1123.cc:47
#define RFC1123_STRFTIME
Definition: rfc1123.cc:27
static int tmSaneValues(struct tm *tm)
Definition: rfc1123.cc:63
static int make_num(const char *s)
Definition: rfc1123.cc:38
static const char * month_names[12]
Definition: rfc1123.cc:32
#define xtoupper(x)
Definition: xis.h:18
#define xisdigit(x)
Definition: xis.h:20
#define xtolower(x)
Definition: xis.h:19
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors