1 /*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2015-2019 Derick Rethans
5 * Copyright (c) 2018 MongoDB, Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include "timelib.h"
27 #include "timelib_private.h"
28
29 #define TIMELIB_SUPPORTS_V2DATA
30 #define TIMELIB_SUPPORT_SLIM_FILE
31 #include "timezonedb.h"
32
33 #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
34 # if defined(__LITTLE_ENDIAN__)
35 # undef WORDS_BIGENDIAN
36 # else
37 # if defined(__BIG_ENDIAN__)
38 # define WORDS_BIGENDIAN
39 # endif
40 # endif
41 #endif
42
43 #if (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN))
44 # if __BYTE_ORDER == __BIG_ENDIAN
45 # define WORDS_BIGENDIAN
46 # endif
47 #endif
48
49 #if defined(__s390__)
50 # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
51 # define WORDS_BIGENDIAN
52 # else
53 # undef WORDS_BIGENDIAN
54 # endif
55 #endif
56
57 #ifdef WORDS_BIGENDIAN
timelib_conv_int_unsigned(uint32_t value)58 static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
59 {
60 return value;
61 }
62
timelib_conv_int64_unsigned(uint64_t value)63 static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
64 {
65 return value;
66 }
67 #else
timelib_conv_int_unsigned(uint32_t value)68 static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
69 {
70 return
71 ((value & 0x000000ff) << 24) +
72 ((value & 0x0000ff00) << 8) +
73 ((value & 0x00ff0000) >> 8) +
74 ((value & 0xff000000) >> 24);
75 }
76
timelib_conv_int64_unsigned(uint64_t value)77 static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
78 {
79 return
80 ((value & 0x00000000000000ff) << 56) +
81 ((value & 0x000000000000ff00) << 40) +
82 ((value & 0x0000000000ff0000) << 24) +
83 ((value & 0x00000000ff000000) << 8) +
84 ((value & 0x000000ff00000000) >> 8) +
85 ((value & 0x0000ff0000000000) >> 24) +
86 ((value & 0x00ff000000000000) >> 40) +
87 ((value & 0xff00000000000000) >> 56);
88 }
89 #endif
90
91 #define timelib_conv_int_signed(value) ((int32_t) timelib_conv_int_unsigned((int32_t) value))
92 #define timelib_conv_int64_signed(value) ((int64_t) timelib_conv_int64_unsigned((int64_t) value))
93
read_php_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)94 static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
95 {
96 uint32_t version;
97
98 /* read ID */
99 version = (*tzf)[3] - '0';
100 *tzf += 4;
101
102 /* read BC flag */
103 tz->bc = (**tzf == '\1');
104 *tzf += 1;
105
106 /* read country code */
107 memcpy(tz->location.country_code, *tzf, 2);
108 tz->location.country_code[2] = '\0';
109 *tzf += 2;
110
111 /* skip rest of preamble */
112 *tzf += 13;
113
114 return version;
115 }
116
read_tzif_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)117 static int read_tzif_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
118 {
119 uint32_t version;
120
121 /* read ID */
122 switch ((*tzf)[4]) {
123 case '\0':
124 version = 0;
125 break;
126 case '2':
127 version = 2;
128 break;
129 case '3':
130 version = 3;
131 break;
132 case '4':
133 version = 4;
134 break;
135 default:
136 return -1;
137 }
138 *tzf += 5;
139
140 /* set BC flag and country code to default */
141 tz->bc = 0;
142 tz->location.country_code[0] = '?';
143 tz->location.country_code[1] = '?';
144 tz->location.country_code[2] = '\0';
145
146 /* skip rest of preamble */
147 *tzf += 15;
148
149 return version;
150 }
151
read_preamble(const unsigned char ** tzf,timelib_tzinfo * tz,unsigned int * type)152 static int read_preamble(const unsigned char **tzf, timelib_tzinfo *tz, unsigned int *type)
153 {
154 /* read marker (TZif) or (PHP) */
155 if (memcmp(*tzf, "PHP", 3) == 0) {
156 *type = TIMELIB_TZINFO_PHP;
157 return read_php_preamble(tzf, tz);
158 } else if (memcmp(*tzf, "TZif", 4) == 0) {
159 *type = TIMELIB_TZINFO_ZONEINFO;
160 return read_tzif_preamble(tzf, tz);
161 } else {
162 return -1;
163 }
164 }
165
read_32bit_header(const unsigned char ** tzf,timelib_tzinfo * tz)166 static void read_32bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
167 {
168 uint32_t buffer[6];
169
170 memcpy(&buffer, *tzf, sizeof(buffer));
171 tz->_bit32.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
172 tz->_bit32.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
173 tz->_bit32.leapcnt = timelib_conv_int_unsigned(buffer[2]);
174 tz->_bit32.timecnt = timelib_conv_int_unsigned(buffer[3]);
175 tz->_bit32.typecnt = timelib_conv_int_unsigned(buffer[4]);
176 tz->_bit32.charcnt = timelib_conv_int_unsigned(buffer[5]);
177
178 *tzf += sizeof(buffer);
179 }
180
detect_slim_file(timelib_tzinfo * tz)181 static int detect_slim_file(timelib_tzinfo *tz)
182 {
183 if (
184 (tz->_bit32.ttisgmtcnt == 0) &&
185 (tz->_bit32.ttisstdcnt == 0) &&
186 (tz->_bit32.leapcnt == 0) &&
187 (tz->_bit32.timecnt == 0) &&
188 (tz->_bit32.typecnt == 1) &&
189 (tz->_bit32.charcnt == 1)
190 ) {
191 return 1;
192 }
193
194 return 0;
195 }
196
read_64bit_transitions(const unsigned char ** tzf,timelib_tzinfo * tz)197 static int read_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
198 {
199 int64_t *buffer = NULL;
200 uint32_t i;
201 unsigned char *cbuffer = NULL;
202
203 if (tz->bit64.timecnt) {
204 buffer = (int64_t*) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
205 if (!buffer) {
206 return TIMELIB_ERROR_CANNOT_ALLOCATE;
207 }
208 memcpy(buffer, *tzf, sizeof(int64_t) * tz->bit64.timecnt);
209 *tzf += (sizeof(int64_t) * tz->bit64.timecnt);
210 for (i = 0; i < tz->bit64.timecnt; i++) {
211 buffer[i] = timelib_conv_int64_signed(buffer[i]);
212 /* Sanity check to see whether TS is just increasing */
213 if (i > 0 && !(buffer[i] > buffer[i - 1])) {
214 return TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE;
215 }
216 }
217
218 cbuffer = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
219 if (!cbuffer) {
220 timelib_free(buffer);
221 return TIMELIB_ERROR_CANNOT_ALLOCATE;
222 }
223 memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit64.timecnt);
224 *tzf += sizeof(unsigned char) * tz->bit64.timecnt;
225 }
226
227 tz->trans = buffer;
228 tz->trans_idx = cbuffer;
229
230 return 0;
231 }
232
skip_32bit_transitions(const unsigned char ** tzf,timelib_tzinfo * tz)233 static void skip_32bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
234 {
235 if (tz->_bit32.timecnt) {
236 *tzf += (sizeof(int32_t) * tz->_bit32.timecnt);
237 *tzf += sizeof(unsigned char) * tz->_bit32.timecnt;
238 }
239 }
240
read_64bit_types(const unsigned char ** tzf,timelib_tzinfo * tz)241 static int read_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
242 {
243 unsigned char *buffer;
244 int32_t *leap_buffer;
245 unsigned int i, j;
246
247 /* Offset Types */
248 buffer = (unsigned char*) timelib_malloc(tz->bit64.typecnt * sizeof(unsigned char) * 6);
249 if (!buffer) {
250 return TIMELIB_ERROR_CANNOT_ALLOCATE;
251 }
252 memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit64.typecnt);
253 *tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
254
255 // We add two extra to have space for potential new ttinfo entries due to new types defined in the
256 // POSIX string
257 tz->type = (ttinfo*) timelib_calloc(1, (tz->bit64.typecnt + 2) * sizeof(ttinfo));
258 if (!tz->type) {
259 timelib_free(buffer);
260 return TIMELIB_ERROR_CANNOT_ALLOCATE;
261 }
262
263 for (i = 0; i < tz->bit64.typecnt; i++) {
264 j = i * 6;
265 tz->type[i].offset = 0;
266 tz->type[i].offset += (int32_t) (((uint32_t) buffer[j]) << 24) + (buffer[j + 1] << 16) + (buffer[j + 2] << 8) + tz->type[i].offset + buffer[j + 3];
267 tz->type[i].isdst = buffer[j + 4];
268 tz->type[i].abbr_idx = buffer[j + 5];
269 }
270 timelib_free(buffer);
271
272 /* Abbreviations */
273 tz->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
274 if (!tz->timezone_abbr) {
275 return TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION;
276 }
277 memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit64.charcnt);
278 *tzf += sizeof(char) * tz->bit64.charcnt;
279
280 /* Leap seconds (only use in 'right/') format */
281 if (tz->bit64.leapcnt) {
282 leap_buffer = (int32_t *) timelib_malloc(tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
283 if (!leap_buffer) {
284 return TIMELIB_ERROR_CANNOT_ALLOCATE;
285 }
286 memcpy(leap_buffer, *tzf, tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
287 *tzf += tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t));
288
289 tz->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
290 if (!tz->leap_times) {
291 timelib_free(leap_buffer);
292 return TIMELIB_ERROR_CANNOT_ALLOCATE;
293 }
294 for (i = 0; i < tz->bit64.leapcnt; i++) {
295 tz->leap_times[i].trans = timelib_conv_int64_signed(leap_buffer[i * 3 + 1] * 4294967296 + leap_buffer[i * 3]);
296 tz->leap_times[i].offset = timelib_conv_int_signed(leap_buffer[i * 3 + 2]);
297 }
298 timelib_free(leap_buffer);
299 }
300
301 /* Standard/Wall Indicators (unused) */
302 if (tz->bit64.ttisstdcnt) {
303 buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisstdcnt * sizeof(unsigned char));
304 if (!buffer) {
305 return TIMELIB_ERROR_CANNOT_ALLOCATE;
306 }
307 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisstdcnt);
308 *tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
309
310 for (i = 0; i < tz->bit64.ttisstdcnt; i++) {
311 tz->type[i].isstdcnt = buffer[i];
312 }
313 timelib_free(buffer);
314 }
315
316 /* UT/Local Time Indicators (unused) */
317 if (tz->bit64.ttisgmtcnt) {
318 buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisgmtcnt * sizeof(unsigned char));
319 if (!buffer) {
320 return TIMELIB_ERROR_CANNOT_ALLOCATE;
321 }
322 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisgmtcnt);
323 *tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
324
325 for (i = 0; i < tz->bit64.ttisgmtcnt; i++) {
326 tz->type[i].isgmtcnt = buffer[i];
327 }
328 timelib_free(buffer);
329 }
330
331 return 0;
332 }
333
skip_32bit_types(const unsigned char ** tzf,timelib_tzinfo * tz)334 static void skip_32bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
335 {
336 /* Offset Types */
337 *tzf += sizeof(unsigned char) * 6 * tz->_bit32.typecnt;
338
339 /* Abbreviations */
340 *tzf += sizeof(char) * tz->_bit32.charcnt;
341
342 /* Leap seconds (only use in 'right/') format */
343 if (tz->_bit32.leapcnt) {
344 *tzf += sizeof(int32_t) * tz->_bit32.leapcnt * 2;
345 }
346
347 /* Standard/Wall Indicators (unused) */
348 if (tz->_bit32.ttisstdcnt) {
349 *tzf += sizeof(unsigned char) * tz->_bit32.ttisstdcnt;
350 }
351
352 /* UT/Local Time Indicators (unused) */
353 if (tz->_bit32.ttisgmtcnt) {
354 *tzf += sizeof(unsigned char) * tz->_bit32.ttisgmtcnt;
355 }
356 }
357
read_posix_string(const unsigned char ** tzf,timelib_tzinfo * tz)358 static void read_posix_string(const unsigned char **tzf, timelib_tzinfo *tz)
359 {
360 const unsigned char *begin;
361
362 // POSIX string is delimited by \n
363 (*tzf)++;
364 begin = *tzf;
365
366 while (*tzf[0] != '\n') {
367 (*tzf)++;
368 }
369
370 tz->posix_string = timelib_calloc(1, *tzf - begin + 1);
371 memcpy(tz->posix_string, begin, *tzf - begin);
372
373 // skip over closing \n
374 (*tzf)++;
375 }
376
find_ttinfo_index(timelib_tzinfo * tz,int32_t offset,int isdst,char * abbr)377 static signed int find_ttinfo_index(timelib_tzinfo *tz, int32_t offset, int isdst, char *abbr)
378 {
379 uint64_t i;
380
381 for (i = 0; i < tz->bit64.typecnt; i++) {
382 if (
383 (offset == tz->type[i].offset) &&
384 (isdst == tz->type[i].isdst) &&
385 (strcmp(abbr, &tz->timezone_abbr[tz->type[i].abbr_idx]) == 0)
386 ) {
387 return i;
388 }
389 }
390
391 return TIMELIB_UNSET;
392 }
393
add_abbr(timelib_tzinfo * tz,char * abbr)394 static unsigned int add_abbr(timelib_tzinfo *tz, char *abbr)
395 {
396 size_t old_length = tz->bit64.charcnt;
397 size_t new_length = old_length + strlen(abbr) + 1;
398 tz->timezone_abbr = (char*) timelib_realloc(tz->timezone_abbr, new_length);
399 memcpy(tz->timezone_abbr + old_length, abbr, strlen(abbr));
400 tz->bit64.charcnt = new_length;
401 tz->timezone_abbr[new_length - 1] = '\0';
402
403 return old_length;
404 }
405
add_new_ttinfo_index(timelib_tzinfo * tz,int32_t offset,int isdst,char * abbr)406 static signed int add_new_ttinfo_index(timelib_tzinfo *tz, int32_t offset, int isdst, char *abbr)
407 {
408 tz->type[tz->bit64.typecnt].offset = offset;
409 tz->type[tz->bit64.typecnt].isdst = isdst;
410 tz->type[tz->bit64.typecnt].abbr_idx = add_abbr(tz, abbr);
411 tz->type[tz->bit64.typecnt].isstdcnt = 0;
412 tz->type[tz->bit64.typecnt].isgmtcnt = 0;
413
414 ++tz->bit64.typecnt;
415
416 return tz->bit64.typecnt - 1;
417 }
418
integrate_posix_string(timelib_tzinfo * tz)419 static int integrate_posix_string(timelib_tzinfo *tz)
420 {
421 tz->posix_info = timelib_parse_posix_str(tz->posix_string);
422 if (!tz->posix_info) {
423 return 0;
424 }
425
426 tz->posix_info->type_index_std_type = find_ttinfo_index(tz, tz->posix_info->std_offset, 0, tz->posix_info->std);
427 if (tz->posix_info->type_index_std_type == TIMELIB_UNSET) {
428 tz->posix_info->type_index_std_type = add_new_ttinfo_index(tz, tz->posix_info->std_offset, 0, tz->posix_info->std);
429 return 1;
430 }
431
432 /* If there is no DST set for this zone, return */
433 if (!tz->posix_info->dst) {
434 return 1;
435 }
436
437 tz->posix_info->type_index_dst_type = find_ttinfo_index(tz, tz->posix_info->dst_offset, 1, tz->posix_info->dst);
438 if (tz->posix_info->type_index_dst_type == TIMELIB_UNSET) {
439 tz->posix_info->type_index_dst_type = add_new_ttinfo_index(tz, tz->posix_info->dst_offset, 1, tz->posix_info->dst);
440 return 1;
441 }
442
443 return 1;
444 }
445
read_location(const unsigned char ** tzf,timelib_tzinfo * tz)446 static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
447 {
448 uint32_t buffer[3];
449 uint32_t comments_len;
450
451 memcpy(&buffer, *tzf, sizeof(buffer));
452 tz->location.latitude = timelib_conv_int_unsigned(buffer[0]);
453 tz->location.latitude = (tz->location.latitude / 100000) - 90;
454 tz->location.longitude = timelib_conv_int_unsigned(buffer[1]);
455 tz->location.longitude = (tz->location.longitude / 100000) - 180;
456 comments_len = timelib_conv_int_unsigned(buffer[2]);
457 *tzf += sizeof(buffer);
458
459 tz->location.comments = timelib_malloc(comments_len + 1);
460 memcpy(tz->location.comments, *tzf, comments_len);
461 tz->location.comments[comments_len] = '\0';
462 *tzf += comments_len;
463 }
464
set_default_location_and_comments(const unsigned char ** tzf,timelib_tzinfo * tz)465 static void set_default_location_and_comments(const unsigned char **tzf, timelib_tzinfo *tz)
466 {
467 tz->location.latitude = 0;
468 tz->location.longitude = 0;
469 tz->location.comments = timelib_malloc(2);
470 tz->location.comments[0] = '?';
471 tz->location.comments[1] = '\0';
472 }
473
format_ut_time(timelib_sll ts,timelib_tzinfo * tz)474 static char *format_ut_time(timelib_sll ts, timelib_tzinfo *tz)
475 {
476 char *tmp = timelib_calloc(1, 64);
477 timelib_time *t = timelib_time_ctor();
478
479 timelib_unixtime2gmt(t, ts);
480 snprintf(
481 tmp, 64,
482 "%04lld-%02lld-%02lld %02lld:%02lld:%02lld UT",
483 t->y, t->m, t->d,
484 t->h, t->i, t->s
485 );
486
487 timelib_time_dtor(t);
488 return tmp;
489 }
490
format_offset_type(timelib_tzinfo * tz,int i)491 static char *format_offset_type(timelib_tzinfo *tz, int i)
492 {
493 char *tmp = timelib_calloc(1, 64);
494
495 snprintf(
496 tmp, 64,
497 "%3d [%6ld %1d %3d '%s' (%d,%d)]",
498 i,
499 (long int) tz->type[i].offset,
500 tz->type[i].isdst,
501 tz->type[i].abbr_idx,
502 &tz->timezone_abbr[tz->type[i].abbr_idx],
503 tz->type[i].isstdcnt,
504 tz->type[i].isgmtcnt
505 );
506
507 return tmp;
508 }
509
timelib_dump_tzinfo(timelib_tzinfo * tz)510 void timelib_dump_tzinfo(timelib_tzinfo *tz)
511 {
512 uint32_t i;
513 char *date_str, *trans_str;
514
515 printf("Country Code: %s\n", tz->location.country_code);
516 printf("Geo Location: %f,%f\n", tz->location.latitude, tz->location.longitude);
517 printf("Comments:\n%s\n", tz->location.comments);
518 printf("BC: %s\n", tz->bc ? "no" : "yes");
519 printf("Slim File: %s\n", detect_slim_file(tz) ? "yes" : "no");
520
521 printf("\n64-bit:\n");
522 printf("UTC/Local count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisgmtcnt);
523 printf("Std/Wall count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisstdcnt);
524 printf("Leap.sec. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.leapcnt);
525 printf("Trans. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.timecnt);
526 printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.typecnt);
527 printf("Zone Abbr. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.charcnt);
528
529 trans_str = format_offset_type(tz, 0);
530 printf("%22s (%20s) = %s\n", "", "", trans_str);
531 timelib_free(trans_str);
532
533 for (i = 0; i < tz->bit64.timecnt; i++) {
534 date_str = format_ut_time(tz->trans[i], tz);
535 trans_str = format_offset_type(tz, tz->trans_idx[i]);
536 printf(
537 "%s (%20" PRId64 ") = %s\n",
538 date_str,
539 tz->trans[i],
540 trans_str
541 );
542 timelib_free(date_str);
543 timelib_free(trans_str);
544 }
545 for (i = 0; i < tz->bit64.leapcnt; i++) {
546 date_str = format_ut_time(tz->trans[i], tz);
547 printf (
548 "%s (%20ld) = %d\n",
549 date_str,
550 (long) tz->leap_times[i].trans,
551 tz->leap_times[i].offset
552 );
553 timelib_free(date_str);
554 }
555
556 if (!tz->posix_string) {
557 printf("\n%43sNo POSIX string\n", "");
558 return;
559 }
560
561 if (strcmp("", tz->posix_string) == 0) {
562 printf("\n%43sEmpty POSIX string\n", "");
563 return;
564 }
565
566 printf("\n%43sPOSIX string: %s\n", "", tz->posix_string);
567 if (tz->posix_info && tz->posix_info->std) {
568 trans_str = format_offset_type(tz, tz->posix_info->type_index_std_type);
569 printf("%43sstd: %s\n", "", trans_str);
570 timelib_free(trans_str);
571
572 if (tz->posix_info->dst) {
573 trans_str = format_offset_type(tz, tz->posix_info->type_index_dst_type);
574 printf("%43sdst: %s\n", "", trans_str);
575 timelib_free(trans_str);
576 }
577 }
578 }
579
seek_to_tz_position(const unsigned char ** tzf,const char * timezone,const timelib_tzdb * tzdb)580 static int seek_to_tz_position(const unsigned char **tzf, const char *timezone, const timelib_tzdb *tzdb)
581 {
582 int left = 0, right = tzdb->index_size - 1;
583
584 if (tzdb->index_size == 0) {
585 return 0;
586 }
587
588 do {
589 int mid = ((unsigned)left + right) >> 1;
590 int cmp = timelib_strcasecmp(timezone, tzdb->index[mid].id);
591
592 if (cmp < 0) {
593 right = mid - 1;
594 } else if (cmp > 0) {
595 left = mid + 1;
596 } else { /* (cmp == 0) */
597 (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
598 return 1;
599 }
600
601 } while (left <= right);
602
603 return 0;
604 }
605
timelib_builtin_db(void)606 const timelib_tzdb *timelib_builtin_db(void)
607 {
608 return &timezonedb_builtin;
609 }
610
timelib_timezone_identifiers_list(const timelib_tzdb * tzdb,int * count)611 const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count)
612 {
613 *count = tzdb->index_size;
614 return tzdb->index;
615 }
616
timelib_timezone_id_is_valid(const char * timezone,const timelib_tzdb * tzdb)617 int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb)
618 {
619 const unsigned char *tzf;
620 return (seek_to_tz_position(&tzf, timezone, tzdb));
621 }
622
skip_64bit_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)623 static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
624 {
625 if (memcmp(*tzf, "TZif2", 5) == 0) {
626 *tzf += 20;
627 return 1;
628 } else if (memcmp(*tzf, "TZif3", 5) == 0) {
629 *tzf += 20;
630 return 1;
631 } else if (memcmp(*tzf, "TZif4", 5) == 0) {
632 *tzf += 20;
633 return 1;
634 } else {
635 return 0;
636 }
637 }
638
read_64bit_header(const unsigned char ** tzf,timelib_tzinfo * tz)639 static void read_64bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
640 {
641 uint32_t buffer[6];
642
643 memcpy(&buffer, *tzf, sizeof(buffer));
644 tz->bit64.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
645 tz->bit64.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
646 tz->bit64.leapcnt = timelib_conv_int_unsigned(buffer[2]);
647 tz->bit64.timecnt = timelib_conv_int_unsigned(buffer[3]);
648 tz->bit64.typecnt = timelib_conv_int_unsigned(buffer[4]);
649 tz->bit64.charcnt = timelib_conv_int_unsigned(buffer[5]);
650 *tzf += sizeof(buffer);
651 }
652
timelib_tzinfo_ctor(const char * name)653 static timelib_tzinfo* timelib_tzinfo_ctor(const char *name)
654 {
655 timelib_tzinfo *t;
656 t = timelib_calloc(1, sizeof(timelib_tzinfo));
657 t->name = timelib_strdup(name);
658
659 return t;
660 }
661
timelib_parse_tzfile(const char * timezone,const timelib_tzdb * tzdb,int * error_code)662 timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code)
663 {
664 const unsigned char *tzf;
665 timelib_tzinfo *tmp;
666 int version;
667 int transitions_result, types_result;
668 unsigned int type = TIMELIB_TZINFO_ZONEINFO; /* TIMELIB_TZINFO_PHP or TIMELIB_TZINFO_ZONEINFO */
669
670 *error_code = TIMELIB_ERROR_NO_ERROR;
671
672 if (seek_to_tz_position(&tzf, timezone, tzdb)) {
673 tmp = timelib_tzinfo_ctor(timezone);
674
675 version = read_preamble(&tzf, tmp, &type);
676 if (version < 2 || version > 4) {
677 *error_code = TIMELIB_ERROR_UNSUPPORTED_VERSION;
678 timelib_tzinfo_dtor(tmp);
679 return NULL;
680 }
681 //printf("- timezone: %s, version: %0d\n", timezone, version);
682
683 read_32bit_header(&tzf, tmp);
684 skip_32bit_transitions(&tzf, tmp);
685 skip_32bit_types(&tzf, tmp);
686
687 if (!skip_64bit_preamble(&tzf, tmp)) {
688 /* 64 bit preamble is not in place */
689 *error_code = TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE;
690 timelib_tzinfo_dtor(tmp);
691 return NULL;
692 }
693 read_64bit_header(&tzf, tmp);
694 if ((transitions_result = read_64bit_transitions(&tzf, tmp)) != 0) {
695 /* Corrupt file as transitions do not increase */
696 *error_code = transitions_result;
697 timelib_tzinfo_dtor(tmp);
698 return NULL;
699 }
700 if ((types_result = read_64bit_types(&tzf, tmp)) != 0) {
701 *error_code = types_result;
702 timelib_tzinfo_dtor(tmp);
703 return NULL;
704 }
705
706 read_posix_string(&tzf, tmp);
707 if (strcmp("", tmp->posix_string) == 0) {
708 *error_code = TIMELIB_ERROR_EMPTY_POSIX_STRING;
709 } else if (!integrate_posix_string(tmp)) {
710 *error_code = TIMELIB_ERROR_CORRUPT_POSIX_STRING;
711 timelib_tzinfo_dtor(tmp);
712 return NULL;
713 }
714
715 if (type == TIMELIB_TZINFO_PHP) {
716 read_location(&tzf, tmp);
717 } else {
718 set_default_location_and_comments(&tzf, tmp);
719 }
720 } else {
721 *error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE;
722 tmp = NULL;
723 }
724
725 return tmp;
726 }
727
timelib_tzinfo_dtor(timelib_tzinfo * tz)728 void timelib_tzinfo_dtor(timelib_tzinfo *tz)
729 {
730 TIMELIB_TIME_FREE(tz->name);
731 TIMELIB_TIME_FREE(tz->trans);
732 TIMELIB_TIME_FREE(tz->trans_idx);
733 TIMELIB_TIME_FREE(tz->type);
734 TIMELIB_TIME_FREE(tz->timezone_abbr);
735 TIMELIB_TIME_FREE(tz->leap_times);
736 TIMELIB_TIME_FREE(tz->location.comments);
737 TIMELIB_TIME_FREE(tz->posix_string);
738 if (tz->posix_info) {
739 timelib_posix_str_dtor(tz->posix_info);
740 }
741 TIMELIB_TIME_FREE(tz);
742 tz = NULL;
743 }
744
timelib_tzinfo_clone(timelib_tzinfo * tz)745 timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
746 {
747 timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
748 tmp->_bit32.ttisgmtcnt = tz->_bit32.ttisgmtcnt;
749 tmp->_bit32.ttisstdcnt = tz->_bit32.ttisstdcnt;
750 tmp->_bit32.leapcnt = tz->_bit32.leapcnt;
751 tmp->_bit32.timecnt = tz->_bit32.timecnt;
752 tmp->_bit32.typecnt = tz->_bit32.typecnt;
753 tmp->_bit32.charcnt = tz->_bit32.charcnt;
754 tmp->bit64.ttisgmtcnt = tz->bit64.ttisgmtcnt;
755 tmp->bit64.ttisstdcnt = tz->bit64.ttisstdcnt;
756 tmp->bit64.leapcnt = tz->bit64.leapcnt;
757 tmp->bit64.timecnt = tz->bit64.timecnt;
758 tmp->bit64.typecnt = tz->bit64.typecnt;
759 tmp->bit64.charcnt = tz->bit64.charcnt;
760
761 if (tz->bit64.timecnt) {
762 tmp->trans = (int64_t *) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
763 tmp->trans_idx = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
764 memcpy(tmp->trans, tz->trans, tz->bit64.timecnt * sizeof(int64_t));
765 memcpy(tmp->trans_idx, tz->trans_idx, tz->bit64.timecnt * sizeof(unsigned char));
766 }
767
768 tmp->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
769 memcpy(tmp->type, tz->type, tz->bit64.typecnt * sizeof(ttinfo));
770
771 tmp->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
772 memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit64.charcnt);
773
774 if (tz->bit64.leapcnt) {
775 tmp->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
776 memcpy(tmp->leap_times, tz->leap_times, tz->bit64.leapcnt * sizeof(tlinfo));
777 }
778
779 if (tz->posix_string) {
780 tmp->posix_string = timelib_strdup(tz->posix_string);
781 }
782
783 return tmp;
784 }
785
786 /**
787 * Algorithm From RFC 8536, Section 3.2
788 * https://tools.ietf.org/html/rfc8536#section-3.2
789 */
timelib_fetch_timezone_offset(timelib_tzinfo * tz,timelib_sll ts,timelib_sll * transition_time)790 ttinfo* timelib_fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
791 {
792 uint32_t left, right;
793
794 /* RFC 8536: If there are no transitions, local time for all timestamps is specified
795 * by the TZ string in the footer if present and nonempty; otherwise, it is specified
796 * by time type 0.
797 *
798 * timelib: If there is also no time type 0, return NULL.
799 */
800 if (!tz->bit64.timecnt || !tz->trans) {
801 if (tz->posix_info) {
802 *transition_time = INT64_MIN;
803 return timelib_fetch_posix_timezone_offset(tz, ts, NULL);
804 }
805
806 if (tz->bit64.typecnt == 1) {
807 *transition_time = INT64_MIN;
808 return &(tz->type[0]);
809 }
810 return NULL;
811 }
812
813 /* RFC 8536: Local time for timestamps before the first transition is specified by
814 * the first time type (time type 0). */
815 if (ts < tz->trans[0]) {
816 *transition_time = INT64_MIN;
817 return &(tz->type[0]);
818 }
819
820 /* RFC 8536: Local time for timestamps on or after the last transition is specified
821 * by the TZ string in the footer (Section 3.3) if present and nonempty; otherwise,
822 * it is unspecified.
823 *
824 * timelib: For 'unspecified', timelib assumes the last transition
825 */
826 if (ts >= tz->trans[tz->bit64.timecnt - 1]) {
827 if (tz->posix_info) {
828 return timelib_fetch_posix_timezone_offset(tz, ts, transition_time);
829 }
830
831 *transition_time = tz->trans[tz->bit64.timecnt - 1];
832 return &(tz->type[tz->trans_idx[tz->bit64.timecnt - 1]]);
833 }
834
835 /* RFC 8536: The type corresponding to a transition time specifies local time for
836 * timestamps starting at the given transition time and continuing up to, but not
837 * including, the next transition time. */
838 left = 0;
839 right = tz->bit64.timecnt - 1;
840
841 while (right - left > 1) {
842 uint32_t mid = (left + right) >> 1;
843
844 if (ts < tz->trans[mid]) {
845 right = mid;
846 } else {
847 left = mid;
848 }
849 }
850 *transition_time = tz->trans[left];
851 return &(tz->type[tz->trans_idx[left]]);
852 }
853
fetch_leaptime_offset(timelib_tzinfo * tz,timelib_sll ts)854 static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
855 {
856 int i;
857
858 if (!tz->bit64.leapcnt || !tz->leap_times) {
859 return NULL;
860 }
861
862 for (i = tz->bit64.leapcnt - 1; i > 0; i--) {
863 if (ts > tz->leap_times[i].trans) {
864 return &(tz->leap_times[i]);
865 }
866 }
867 return NULL;
868 }
869
timelib_timestamp_is_in_dst(timelib_sll ts,timelib_tzinfo * tz)870 int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
871 {
872 ttinfo *to;
873 timelib_sll dummy;
874
875 if ((to = timelib_fetch_timezone_offset(tz, ts, &dummy))) {
876 return to->isdst;
877 }
878 return -1;
879 }
880
timelib_get_time_zone_info(timelib_sll ts,timelib_tzinfo * tz)881 timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
882 {
883 ttinfo *to;
884 tlinfo *tl;
885 int32_t offset = 0, leap_secs = 0;
886 char *abbr;
887 timelib_time_offset *tmp = timelib_time_offset_ctor();
888 timelib_sll transition_time;
889
890 if ((to = timelib_fetch_timezone_offset(tz, ts, &transition_time))) {
891 offset = to->offset;
892 abbr = &(tz->timezone_abbr[to->abbr_idx]);
893 tmp->is_dst = to->isdst;
894 tmp->transition_time = transition_time;
895 } else {
896 offset = 0;
897 abbr = tz->timezone_abbr;
898 tmp->is_dst = 0;
899 tmp->transition_time = 0;
900 }
901
902 if ((tl = fetch_leaptime_offset(tz, ts))) {
903 leap_secs = -tl->offset;
904 }
905
906 tmp->offset = offset;
907 tmp->leap_secs = leap_secs;
908 tmp->abbr = abbr ? timelib_strdup(abbr) : timelib_strdup("GMT");
909
910 return tmp;
911 }
912
timelib_get_time_zone_offset_info(timelib_sll ts,timelib_tzinfo * tz,int32_t * offset,timelib_sll * transition_time,unsigned int * is_dst)913 int timelib_get_time_zone_offset_info(timelib_sll ts, timelib_tzinfo *tz, int32_t* offset, timelib_sll* transition_time, unsigned int* is_dst)
914 {
915 ttinfo *to;
916 timelib_sll tmp_transition_time;
917
918 if (tz == NULL) {
919 return 0;
920 }
921
922 if ((to = timelib_fetch_timezone_offset(tz, ts, &tmp_transition_time))) {
923 if (offset) {
924 *offset = to->offset;
925 }
926 if (is_dst) {
927 *is_dst = to->isdst;
928 }
929 if (transition_time) {
930 *transition_time = tmp_transition_time;
931 }
932 return 1;
933 }
934 return 0;
935 }
936
timelib_get_current_offset(timelib_time * t)937 timelib_sll timelib_get_current_offset(timelib_time *t)
938 {
939 switch (t->zone_type) {
940 case TIMELIB_ZONETYPE_ABBR:
941 case TIMELIB_ZONETYPE_OFFSET:
942 return t->z + (t->dst * 3600);
943
944 case TIMELIB_ZONETYPE_ID: {
945 int32_t offset = 0;
946 timelib_get_time_zone_offset_info(t->sse, t->tz_info, &offset, NULL, NULL);
947 return offset;
948 }
949
950 default:
951 return 0;
952 }
953 }
954
timelib_same_timezone(timelib_time * one,timelib_time * two)955 int timelib_same_timezone(timelib_time *one, timelib_time *two)
956 {
957 if (one->zone_type != two->zone_type) {
958 return 0;
959 }
960
961 if (one->zone_type == TIMELIB_ZONETYPE_ABBR || one->zone_type == TIMELIB_ZONETYPE_OFFSET) {
962 if ((one->z + (one->dst * 3600)) == (two->z + (two->dst * 3600))) {
963 return 1;
964 }
965 return 0;
966 }
967
968 if (one->zone_type == TIMELIB_ZONETYPE_ID && strcmp(one->tz_info->name, two->tz_info->name) == 0) {
969 return 1;
970 }
971
972 return 0;
973 }
974