Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

calendar.cpp
Go to the documentation of this file.
1 /*
2 * Calendar Functions
3 * (C) 1999-2010 Jack Lloyd
4 * (C) 2015 Simon Warta (Kullo GmbH)
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9 #include <botan/calendar.h>
10 #include <botan/exceptn.h>
11 #include <ctime>
12 #include <sstream>
13 #include <iomanip>
14 #include <botan/mutex.h>
15 #include <stdlib.h>
16
17 #if defined(BOTAN_HAS_BOOST_DATETIME)
18 #include <boost/date_time/posix_time/posix_time_types.hpp>
19 #endif
20
21 namespace Botan {
22
23 namespace {
24
25 std::tm do_gmtime(std::time_t time_val)
26 {
27 std::tm tm;
28
29 #if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
30 gmtime_s(&tm, &time_val); // Windows
31 #elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
32 gmtime_r(&time_val, &tm); // Unix/SUSv2
33 #else
34 std::tm* tm_p = std::gmtime(&time_val);
35 if (tm_p == nullptr)
36 throw Encoding_Error("time_t_to_tm could not convert");
37 tm = *tm_p;
38 #endif
39
40 return tm;
41 }
42
43 #if !defined(BOTAN_TARGET_OS_HAS_TIMEGM) && !(defined(BOTAN_TARGET_OS_HAS_MKGMTIME) && defined(BOTAN_BUILD_COMPILER_IS_MSVC))
44
45 #if defined(BOTAN_HAS_BOOST_DATETIME)
46
47 std::time_t boost_timegm(std::tm *tm)
48 {
49 const int sec = tm->tm_sec;
50 const int min = tm->tm_min;
51 const int hour = tm->tm_hour;
52 const int day = tm->tm_mday;
53 const int mon = tm->tm_mon + 1;
54 const int year = tm->tm_year + 1900;
55
56 std::time_t out;
57
58 {
59 using namespace boost::posix_time;
60 using namespace boost::gregorian;
61 const auto epoch = ptime(date(1970, 01, 01));
62 const auto time = ptime(date(year, mon, day),
63 hours(hour) + minutes(min) + seconds(sec));
64 const time_duration diff(time - epoch);
65 out = diff.ticks() / diff.ticks_per_second();
66 }
67
68 return out;
69 }
70
71 #elif defined(BOTAN_OS_TYPE_IS_UNIX)
72
73 #pragma message "Caution! A fallback version of timegm() is used which is not thread-safe"
74
75 mutex_type ENV_TZ;
76
77 std::time_t fallback_timegm(std::tm *tm)
78 {
79 std::time_t out;
80 std::string tz_backup;
81
82 ENV_TZ.lock();
83
84 // Store current value of env variable TZ
85 const char* tz_env_pointer = ::getenv("TZ");
86 if (tz_env_pointer != nullptr)
87 tz_backup = std::string(tz_env_pointer);
88
89 // Clear value of TZ
90 ::setenv("TZ", "", 1);
91 ::tzset();
92
93 out = ::mktime(tm);
94
95 // Restore TZ
96 if (!tz_backup.empty())
97 {
98 // setenv makes a copy of the second argument
99 ::setenv("TZ", tz_backup.data(), 1);
100 }
101 else
102 {
103 ::unsetenv("TZ");
104 }
105 ::tzset();
106
107 ENV_TZ.unlock();
108
109 return out;
110 }
111 #endif // BOTAN_HAS_BOOST_DATETIME
112
113 #endif
114
115 }
116
117 std::chrono::system_clock::time_point calendar_point::to_std_timepoint() const
118 {
119 if (year < 1970)
120 throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years before 1970.");
121
122 // 32 bit time_t ends at January 19, 2038
123 // https://msdn.microsoft.com/en-us/library/2093ets1.aspx
124 // Throw after 2037 if 32 bit time_t is used
125 if (year > 2037 && sizeof(std::time_t) == 4)
126 {
127 throw Invalid_Argument("calendar_point::to_std_timepoint() does not support years after 2037.");
128 }
129
130 // std::tm: struct without any timezone information
131 std::tm tm;
132 tm.tm_isdst = -1; // i.e. no DST information available
133 tm.tm_sec = seconds;
134 tm.tm_min = minutes;
135 tm.tm_hour = hour;
136 tm.tm_mday = day;
137 tm.tm_mon = month - 1;
138 tm.tm_year = year - 1900;
139
140 // Define a function alias `botan_timegm`
141 #if defined(BOTAN_TARGET_OS_HAS_TIMEGM)
142 std::time_t (&botan_timegm)(std::tm *tm) = timegm;
143 #elif defined(BOTAN_TARGET_OS_HAS_MKGMTIME) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
144 // http://stackoverflow.com/questions/16647819/timegm-cross-platform
145 std::time_t (&botan_timegm)(std::tm *tm) = _mkgmtime;
146 #elif defined(BOTAN_HAS_BOOST_DATETIME)
147 std::time_t (&botan_timegm)(std::tm *tm) = boost_timegm;
148 #elif defined(BOTAN_OS_TYPE_IS_UNIX)
149 std::time_t (&botan_timegm)(std::tm *tm) = fallback_timegm;
150 #else
151 std::time_t (&botan_timegm)(std::tm *tm) = mktime; // localtime instead...
152 #endif
153
154 // Convert std::tm to std::time_t
155 std::time_t tt = botan_timegm(&tm);
156 if (tt == -1)
157 throw Invalid_Argument("calendar_point couldn't be converted: " + to_string());
158
159 return std::chrono::system_clock::from_time_t(tt);
160 }
161
162 std::string calendar_point::to_string() const
163 {
164 // desired format: <YYYY>-<MM>-<dd>T<HH>:<mm>:<ss>
165 std::stringstream output;
166 {
167 using namespace std;
168 output << setfill('0')
169 << setw(4) << year << "-" << setw(2) << month << "-" << setw(2) << day
170 << "T"
171 << setw(2) << hour << ":" << setw(2) << minutes << ":" << setw(2) << seconds;
172 }
173 return output.str();
174 }
175
176
177 calendar_point calendar_value(
178 const std::chrono::system_clock::time_point& time_point)
179 {
180 std::tm tm = do_gmtime(std::chrono::system_clock::to_time_t(time_point));
181
182 return calendar_point(tm.tm_year + 1900,
183 tm.tm_mon + 1,
184 tm.tm_mday,
185 tm.tm_hour,
186 tm.tm_min,
187 tm.tm_sec);
188 }
189
190 }
Botan::calendar_point::to_std_timepoint
std::chrono::system_clock::time_point to_std_timepoint() const
Definition: calendar.cpp:117
Botan::Invalid_Argument
Definition: exceptn.h:34
Botan::calendar_point::to_string
std::string to_string() const
Definition: calendar.cpp:162
Botan::calendar_point::day
uint32_t day
Definition: calendar.h:30
std
Definition: bigint.h:619
Botan::calendar_point::hour
uint32_t hour
Definition: calendar.h:33
Botan::calendar_point
Definition: calendar.h:21
Botan
Definition: alg_id.cpp:13
Botan::calendar_point::calendar_point
calendar_point(uint32_t y, uint32_t mon, uint32_t d, uint32_t h, uint32_t min, uint32_t sec)
Definition: calendar.h:52
Botan::calendar_point::month
uint32_t month
Definition: calendar.h:27
Botan::CT::min
T min(T a, T b)
Definition: ct_utils.h:180
Botan::calendar_point::minutes
uint32_t minutes
Definition: calendar.h:36
Botan::calendar_point::seconds
uint32_t seconds
Definition: calendar.h:41
Botan::calendar_value
calendar_point calendar_value(const std::chrono::system_clock::time_point &time_point)
Definition: calendar.cpp:177