vfs: check userland buffers before reading them.
[haiku.git] / src / kits / network / libnetapi / HttpTime.cpp
blob773c08fd75de48be0e57cba428381b34daca53d8
1 /*
2 * Copyright 2010-2016 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Christophe Huriaux, c.huriaux@gmail.com
7 * Adrien Destugues, pulkomandy@gmail.com
8 */
10 #include <HttpTime.h>
12 #include <new>
14 #include <cstdio>
17 // The formats used should be, in order of preference (according to RFC2616,
18 // section 3.3):
19 // RFC1123 / RFC822: "Sun, 06 Nov 1994 08:49:37 GMT"
20 // RFC1036 / RFC850: "Sunday, 06-Nov-94 08:49:37 GMT"
21 // asctime : "Sun Nov 6 08:49:37 1994"
23 // RFC1123 is the preferred one because it has 4 digit years.
25 // But of course in real life, all possible mixes of the formats are used.
26 // Believe it or not, it's even possible to find some website that gets this
27 // right and use one of the 3 formats above.
28 // Often seen variants are:
29 // - RFC1036 but with 4 digit year,
30 // - Missing or different timezone indicator
31 // - Invalid weekday
32 static const char* kDateFormats[] = {
33 // RFC1123
34 "%a, %d %b %Y %H:%M:%S", // without timezone
35 "%a, %d %b %Y %H:%M:%S GMT", // canonical
37 // RFC1036
38 "%A, %d-%b-%y %H:%M:%S", // without timezone
39 "%A, %d-%b-%y %H:%M:%S GMT", // canonical
41 // RFC1036 with 4 digit year
42 "%a, %d-%b-%Y %H:%M:%S", // without timezone
43 "%a, %d-%b-%Y %H:%M:%S GMT", // with 4-digit year
44 "%a, %d-%b-%Y %H:%M:%S UTC", // "UTC" timezone
46 // asctime
47 "%a %d %b %H:%M:%S %Y"
50 using namespace BPrivate;
53 BHttpTime::BHttpTime()
55 fDate(0),
56 fDateFormat(B_HTTP_TIME_FORMAT_PREFERRED)
61 BHttpTime::BHttpTime(BDateTime date)
63 fDate(date),
64 fDateFormat(B_HTTP_TIME_FORMAT_PREFERRED)
69 BHttpTime::BHttpTime(const BString& dateString)
71 fDateString(dateString),
72 fDate(0),
73 fDateFormat(B_HTTP_TIME_FORMAT_PREFERRED)
78 // #pragma mark Date modification
81 void
82 BHttpTime::SetString(const BString& string)
84 fDateString = string;
88 void
89 BHttpTime::SetDate(BDateTime date)
91 fDate = date;
95 // #pragma mark Date conversion
98 BDateTime
99 BHttpTime::Parse()
101 struct tm expireTime;
103 if (fDateString.Length() < 4)
104 return 0;
106 memset(&expireTime, 0, sizeof(struct tm));
108 fDateFormat = B_HTTP_TIME_FORMAT_PARSED;
109 unsigned int i;
110 for (i = 0; i < sizeof(kDateFormats) / sizeof(const char*);
111 i++) {
112 const char* result = strptime(fDateString.String(), kDateFormats[i],
113 &expireTime);
115 // We need to parse the complete value for the "Expires" key.
116 // Otherwise, we consider this to be a session cookie (or try another
117 // one of the date formats).
118 if (result == fDateString.String() + fDateString.Length()) {
119 fDateFormat = i;
120 break;
124 // Did we identify some valid format?
125 if (fDateFormat == B_HTTP_TIME_FORMAT_PARSED)
126 return 0;
128 // Now convert the struct tm from strptime into a BDateTime.
129 BTime time(expireTime.tm_hour, expireTime.tm_min, expireTime.tm_sec);
130 BDate date(expireTime.tm_year + 1900, expireTime.tm_mon + 1,
131 expireTime.tm_mday);
132 BDateTime dateTime(date, time);
133 return dateTime;
137 BString
138 BHttpTime::ToString(int8 format)
140 BString expirationFinal;
141 struct tm expirationTm;
142 expirationTm.tm_sec = fDate.Time().Second();
143 expirationTm.tm_min = fDate.Time().Minute();
144 expirationTm.tm_hour = fDate.Time().Hour();
145 expirationTm.tm_mday = fDate.Date().Day();
146 expirationTm.tm_mon = fDate.Date().Month() - 1;
147 expirationTm.tm_year = fDate.Date().Year() - 1900;
148 // strftime starts weekday count at 0 for Sunday,
149 // while DayOfWeek starts at 1 for Monday and thus uses 7 for Sunday
150 expirationTm.tm_wday = fDate.Date().DayOfWeek() % 7;
151 expirationTm.tm_yday = 0;
152 expirationTm.tm_isdst = 0;
154 if (format == B_HTTP_TIME_FORMAT_PARSED)
155 format = fDateFormat;
157 if (format != B_HTTP_TIME_FORMAT_PARSED) {
158 static const uint16 kTimetToStringMaxLength = 128;
159 char expirationString[kTimetToStringMaxLength + 1];
160 size_t strLength;
162 strLength = strftime(expirationString, kTimetToStringMaxLength,
163 kDateFormats[format], &expirationTm);
165 expirationFinal.SetTo(expirationString, strLength);
167 return expirationFinal;