xref: /PHP-7.4/ext/date/lib/parse_tz.c (revision aae5907c)
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 #include "timezonedb.h"
31 
32 #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
33 # if defined(__LITTLE_ENDIAN__)
34 #  undef WORDS_BIGENDIAN
35 # else
36 #  if defined(__BIG_ENDIAN__)
37 #   define WORDS_BIGENDIAN
38 #  endif
39 # endif
40 #endif
41 
42 #if defined(__s390__)
43 # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
44 #  define WORDS_BIGENDIAN
45 # else
46 #  undef WORDS_BIGENDIAN
47 # endif
48 #endif
49 
50 #ifdef WORDS_BIGENDIAN
timelib_conv_int_unsigned(uint32_t value)51 static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
52 {
53 	return value;
54 }
55 
timelib_conv_int64_unsigned(uint64_t value)56 static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
57 {
58 	return value;
59 }
60 #else
timelib_conv_int_unsigned(uint32_t value)61 static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
62 {
63 	return
64 		((value & 0x000000ff) << 24) +
65 		((value & 0x0000ff00) <<  8) +
66 		((value & 0x00ff0000) >>  8) +
67 		((value & 0xff000000) >> 24);
68 }
69 
timelib_conv_int64_unsigned(uint64_t value)70 static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
71 {
72 	return
73 		((value & 0x00000000000000ff) << 56) +
74 		((value & 0x000000000000ff00) << 40) +
75 		((value & 0x0000000000ff0000) << 24) +
76 		((value & 0x00000000ff000000) <<  8) +
77 		((value & 0x000000ff00000000) >>  8) +
78 		((value & 0x0000ff0000000000) >> 24) +
79 		((value & 0x00ff000000000000) >> 40) +
80 		((value & 0xff00000000000000) >> 56);
81 }
82 #endif
83 
84 #define timelib_conv_int_signed(value) ((int32_t) timelib_conv_int_unsigned((int32_t) value))
85 #define timelib_conv_int64_signed(value) ((int64_t) timelib_conv_int64_unsigned((int64_t) value))
86 
read_php_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)87 static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
88 {
89 	uint32_t version;
90 
91 	/* read ID */
92 	version = (*tzf)[3] - '0';
93 	*tzf += 4;
94 
95 	/* read BC flag */
96 	tz->bc = (**tzf == '\1');
97 	*tzf += 1;
98 
99 	/* read country code */
100 	memcpy(tz->location.country_code, *tzf, 2);
101 	tz->location.country_code[2] = '\0';
102 	*tzf += 2;
103 
104 	/* skip rest of preamble */
105 	*tzf += 13;
106 
107 	return version;
108 }
109 
read_tzif_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)110 static int read_tzif_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
111 {
112 	uint32_t version;
113 
114 	/* read ID */
115 	switch ((*tzf)[4]) {
116 		case '\0':
117 			version = 0;
118 			break;
119 		case '2':
120 			version = 2;
121 			break;
122 		case '3':
123 			version = 3;
124 			break;
125 		default:
126 			return -1;
127 	}
128 	*tzf += 5;
129 
130 	/* set BC flag and country code to default */
131 	tz->bc = 0;
132 	tz->location.country_code[0] = '?';
133 	tz->location.country_code[1] = '?';
134 	tz->location.country_code[2] = '\0';
135 
136 	/* skip rest of preamble */
137 	*tzf += 15;
138 
139 	return version;
140 }
141 
read_preamble(const unsigned char ** tzf,timelib_tzinfo * tz,unsigned int * type)142 static int read_preamble(const unsigned char **tzf, timelib_tzinfo *tz, unsigned int *type)
143 {
144 	/* read marker (TZif) or (PHP) */
145 	if (memcmp(*tzf, "PHP", 3) == 0) {
146 		*type = TIMELIB_TZINFO_PHP;
147 		return read_php_preamble(tzf, tz);
148 	} else if (memcmp(*tzf, "TZif", 4) == 0) {
149 		*type = TIMELIB_TZINFO_ZONEINFO;
150 		return read_tzif_preamble(tzf, tz);
151 	} else {
152 		return -1;
153 	}
154 }
155 
read_32bit_header(const unsigned char ** tzf,timelib_tzinfo * tz)156 static void read_32bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
157 {
158 	uint32_t buffer[6];
159 
160 	memcpy(&buffer, *tzf, sizeof(buffer));
161 	tz->_bit32.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
162 	tz->_bit32.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
163 	tz->_bit32.leapcnt    = timelib_conv_int_unsigned(buffer[2]);
164 	tz->_bit32.timecnt    = timelib_conv_int_unsigned(buffer[3]);
165 	tz->_bit32.typecnt    = timelib_conv_int_unsigned(buffer[4]);
166 	tz->_bit32.charcnt    = timelib_conv_int_unsigned(buffer[5]);
167 
168 	*tzf += sizeof(buffer);
169 }
170 
read_64bit_transitions(const unsigned char ** tzf,timelib_tzinfo * tz)171 static int read_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
172 {
173 	int64_t *buffer = NULL;
174 	uint32_t i;
175 	unsigned char *cbuffer = NULL;
176 
177 	if (tz->bit64.timecnt) {
178 		buffer = (int64_t*) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
179 		if (!buffer) {
180 			return TIMELIB_ERROR_CANNOT_ALLOCATE;
181 		}
182 		memcpy(buffer, *tzf, sizeof(int64_t) * tz->bit64.timecnt);
183 		*tzf += (sizeof(int64_t) * tz->bit64.timecnt);
184 		for (i = 0; i < tz->bit64.timecnt; i++) {
185 			buffer[i] = timelib_conv_int64_signed(buffer[i]);
186 			/* Sanity check to see whether TS is just increasing */
187 			if (i > 0 && !(buffer[i] > buffer[i - 1])) {
188 				return TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE;
189 			}
190 		}
191 
192 		cbuffer = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
193 		if (!cbuffer) {
194 			timelib_free(buffer);
195 			return TIMELIB_ERROR_CANNOT_ALLOCATE;
196 		}
197 		memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit64.timecnt);
198 		*tzf += sizeof(unsigned char) * tz->bit64.timecnt;
199 	}
200 
201 	tz->trans = buffer;
202 	tz->trans_idx = cbuffer;
203 
204 	return 0;
205 }
206 
skip_32bit_transitions(const unsigned char ** tzf,timelib_tzinfo * tz)207 static void skip_32bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
208 {
209 	if (tz->_bit32.timecnt) {
210 		*tzf += (sizeof(int32_t) * tz->_bit32.timecnt);
211 		*tzf += sizeof(unsigned char) * tz->_bit32.timecnt;
212 	}
213 }
214 
read_64bit_types(const unsigned char ** tzf,timelib_tzinfo * tz)215 static int read_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
216 {
217 	unsigned char *buffer;
218 	int32_t *leap_buffer;
219 	unsigned int i, j;
220 
221 	/* Offset Types */
222 	buffer = (unsigned char*) timelib_malloc(tz->bit64.typecnt * sizeof(unsigned char) * 6);
223 	if (!buffer) {
224 		return TIMELIB_ERROR_CANNOT_ALLOCATE;
225 	}
226 	memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit64.typecnt);
227 	*tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
228 
229 	tz->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
230 	if (!tz->type) {
231 		timelib_free(buffer);
232 		return TIMELIB_ERROR_CANNOT_ALLOCATE;
233 	}
234 
235 	for (i = 0; i < tz->bit64.typecnt; i++) {
236 		j = i * 6;
237 		tz->type[i].offset = 0;
238 		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];
239 		tz->type[i].isdst = buffer[j + 4];
240 		tz->type[i].abbr_idx = buffer[j + 5];
241 	}
242 	timelib_free(buffer);
243 
244 	/* Abbreviations */
245 	tz->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
246 	if (!tz->timezone_abbr) {
247 		return TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION;
248 	}
249 	memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit64.charcnt);
250 	*tzf += sizeof(char) * tz->bit64.charcnt;
251 
252 	/* Leap seconds (only use in 'right/') format */
253 	if (tz->bit64.leapcnt) {
254 		leap_buffer = (int32_t *) timelib_malloc(tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
255 		if (!leap_buffer) {
256 			return TIMELIB_ERROR_CANNOT_ALLOCATE;
257 		}
258 		memcpy(leap_buffer, *tzf, tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
259 		*tzf += tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t));
260 
261 		tz->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
262 		if (!tz->leap_times) {
263 			timelib_free(leap_buffer);
264 			return TIMELIB_ERROR_CANNOT_ALLOCATE;
265 		}
266 		for (i = 0; i < tz->bit64.leapcnt; i++) {
267 			tz->leap_times[i].trans = timelib_conv_int64_signed(leap_buffer[i * 3 + 1] * 4294967296 + leap_buffer[i * 3]);
268 			tz->leap_times[i].offset = timelib_conv_int_signed(leap_buffer[i * 3 + 2]);
269 		}
270 		timelib_free(leap_buffer);
271 	}
272 
273 	/* Standard/Wall Indicators (unused) */
274 	if (tz->bit64.ttisstdcnt) {
275 		buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisstdcnt * sizeof(unsigned char));
276 		if (!buffer) {
277 			return TIMELIB_ERROR_CANNOT_ALLOCATE;
278 		}
279 		memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisstdcnt);
280 		*tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
281 
282 		for (i = 0; i < tz->bit64.ttisstdcnt; i++) {
283 			tz->type[i].isstdcnt = buffer[i];
284 		}
285 		timelib_free(buffer);
286 	}
287 
288 	/* UT/Local Time Indicators (unused) */
289 	if (tz->bit64.ttisgmtcnt) {
290 		buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisgmtcnt * sizeof(unsigned char));
291 		if (!buffer) {
292 			return TIMELIB_ERROR_CANNOT_ALLOCATE;
293 		}
294 		memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisgmtcnt);
295 		*tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
296 
297 		for (i = 0; i < tz->bit64.ttisgmtcnt; i++) {
298 			tz->type[i].isgmtcnt = buffer[i];
299 		}
300 		timelib_free(buffer);
301 	}
302 
303 	return 0;
304 }
305 
skip_32bit_types(const unsigned char ** tzf,timelib_tzinfo * tz)306 static void skip_32bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
307 {
308 	/* Offset Types */
309 	*tzf += sizeof(unsigned char) * 6 * tz->_bit32.typecnt;
310 
311 	/* Abbreviations */
312 	*tzf += sizeof(char) * tz->_bit32.charcnt;
313 
314 	/* Leap seconds (only use in 'right/') format */
315 	if (tz->_bit32.leapcnt) {
316 		*tzf += sizeof(int32_t) * tz->_bit32.leapcnt * 2;
317 	}
318 
319 	/* Standard/Wall Indicators (unused) */
320 	if (tz->_bit32.ttisstdcnt) {
321 		*tzf += sizeof(unsigned char) * tz->_bit32.ttisstdcnt;
322 	}
323 
324 	/* UT/Local Time Indicators (unused) */
325 	if (tz->_bit32.ttisgmtcnt) {
326 		*tzf += sizeof(unsigned char) * tz->_bit32.ttisgmtcnt;
327 	}
328 }
329 
skip_posix_string(const unsigned char ** tzf,timelib_tzinfo * tz)330 static void skip_posix_string(const unsigned char **tzf, timelib_tzinfo *tz)
331 {
332 	int n_count = 0;
333 
334 	do {
335 		if (*tzf[0] == '\n') {
336 			n_count++;
337 		}
338 		(*tzf)++;
339 	} while (n_count < 2);
340 }
341 
read_location(const unsigned char ** tzf,timelib_tzinfo * tz)342 static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
343 {
344 	uint32_t buffer[3];
345 	uint32_t comments_len;
346 
347 	memcpy(&buffer, *tzf, sizeof(buffer));
348 	tz->location.latitude = timelib_conv_int_unsigned(buffer[0]);
349 	tz->location.latitude = (tz->location.latitude / 100000) - 90;
350 	tz->location.longitude = timelib_conv_int_unsigned(buffer[1]);
351 	tz->location.longitude = (tz->location.longitude / 100000) - 180;
352 	comments_len = timelib_conv_int_unsigned(buffer[2]);
353 	*tzf += sizeof(buffer);
354 
355 	tz->location.comments = timelib_malloc(comments_len + 1);
356 	memcpy(tz->location.comments, *tzf, comments_len);
357 	tz->location.comments[comments_len] = '\0';
358 	*tzf += comments_len;
359 }
360 
set_default_location_and_comments(const unsigned char ** tzf,timelib_tzinfo * tz)361 static void set_default_location_and_comments(const unsigned char **tzf, timelib_tzinfo *tz)
362 {
363 	tz->location.latitude = 0;
364 	tz->location.longitude = 0;
365 	tz->location.comments = timelib_malloc(2);
366 	tz->location.comments[0] = '?';
367 	tz->location.comments[1] = '\0';
368 }
369 
timelib_dump_tzinfo(timelib_tzinfo * tz)370 void timelib_dump_tzinfo(timelib_tzinfo *tz)
371 {
372 	uint32_t i;
373 
374 	printf("Country Code:      %s\n", tz->location.country_code);
375 	printf("Geo Location:      %f,%f\n", tz->location.latitude, tz->location.longitude);
376 	printf("Comments:\n%s\n",          tz->location.comments);
377 	printf("BC:                %s\n",  tz->bc ? "" : "yes");
378 
379 	printf("\n64-bit:\n");
380 	printf("UTC/Local count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisgmtcnt);
381 	printf("Std/Wall count:    " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisstdcnt);
382 	printf("Leap.sec. count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.leapcnt);
383 	printf("Trans. count:      " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.timecnt);
384 	printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.typecnt);
385 	printf("Zone Abbr. count:  " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.charcnt);
386 
387 	printf ("%16s (%20s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
388 		"", "", 0,
389 		(long int) tz->type[0].offset,
390 		tz->type[0].isdst,
391 		tz->type[0].abbr_idx,
392 		&tz->timezone_abbr[tz->type[0].abbr_idx],
393 		tz->type[0].isstdcnt,
394 		tz->type[0].isgmtcnt
395 		);
396 	for (i = 0; i < tz->bit64.timecnt; i++) {
397 		printf ("%016" PRIX64 " (%20" PRId64 ") = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
398 			tz->trans[i], tz->trans[i], tz->trans_idx[i],
399 			(long int) tz->type[tz->trans_idx[i]].offset,
400 			tz->type[tz->trans_idx[i]].isdst,
401 			tz->type[tz->trans_idx[i]].abbr_idx,
402 			&tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
403 			tz->type[tz->trans_idx[i]].isstdcnt,
404 			tz->type[tz->trans_idx[i]].isgmtcnt
405 			);
406 	}
407 	for (i = 0; i < tz->bit64.leapcnt; i++) {
408 		printf ("%016" PRIX64 " (%20ld) = %d\n",
409 			tz->leap_times[i].trans,
410 			(long) tz->leap_times[i].trans,
411 			tz->leap_times[i].offset);
412 	}
413 }
414 
seek_to_tz_position(const unsigned char ** tzf,char * timezone,const timelib_tzdb * tzdb)415 static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
416 {
417 	int left = 0, right = tzdb->index_size - 1;
418 
419 	if (tzdb->index_size == 0) {
420 		return 0;
421 	}
422 
423 	do {
424 		int mid = ((unsigned)left + right) >> 1;
425 		int cmp = timelib_strcasecmp(timezone, tzdb->index[mid].id);
426 
427 		if (cmp < 0) {
428 			right = mid - 1;
429 		} else if (cmp > 0) {
430 			left = mid + 1;
431 		} else { /* (cmp == 0) */
432 			(*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
433 			return 1;
434 		}
435 
436 	} while (left <= right);
437 
438 	return 0;
439 }
440 
timelib_builtin_db(void)441 const timelib_tzdb *timelib_builtin_db(void)
442 {
443 	return &timezonedb_builtin;
444 }
445 
timelib_timezone_identifiers_list(const timelib_tzdb * tzdb,int * count)446 const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count)
447 {
448 	*count = tzdb->index_size;
449 	return tzdb->index;
450 }
451 
timelib_timezone_id_is_valid(char * timezone,const timelib_tzdb * tzdb)452 int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
453 {
454 	const unsigned char *tzf;
455 	return (seek_to_tz_position(&tzf, timezone, tzdb));
456 }
457 
skip_64bit_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)458 static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
459 {
460 	if (memcmp(*tzf, "TZif2", 5) == 0) {
461 		*tzf += 20;
462 		return 1;
463 	} else if (memcmp(*tzf, "TZif3", 5) == 0) {
464 		*tzf += 20;
465 		return 1;
466 	} else {
467 		return 0;
468 	}
469 }
470 
read_64bit_header(const unsigned char ** tzf,timelib_tzinfo * tz)471 static void read_64bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
472 {
473 	uint32_t buffer[6];
474 
475 	memcpy(&buffer, *tzf, sizeof(buffer));
476 	tz->bit64.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
477 	tz->bit64.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
478 	tz->bit64.leapcnt    = timelib_conv_int_unsigned(buffer[2]);
479 	tz->bit64.timecnt    = timelib_conv_int_unsigned(buffer[3]);
480 	tz->bit64.typecnt    = timelib_conv_int_unsigned(buffer[4]);
481 	tz->bit64.charcnt    = timelib_conv_int_unsigned(buffer[5]);
482 	*tzf += sizeof(buffer);
483 }
484 
timelib_tzinfo_ctor(char * name)485 static timelib_tzinfo* timelib_tzinfo_ctor(char *name)
486 {
487 	timelib_tzinfo *t;
488 	t = timelib_calloc(1, sizeof(timelib_tzinfo));
489 	t->name = timelib_strdup(name);
490 
491 	return t;
492 }
493 
timelib_parse_tzfile(char * timezone,const timelib_tzdb * tzdb,int * error_code)494 timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, int *error_code)
495 {
496 	const unsigned char *tzf;
497 	timelib_tzinfo *tmp;
498 	int version;
499 	int transitions_result, types_result;
500 	unsigned int type; /* TIMELIB_TZINFO_PHP or TIMELIB_TZINFO_ZONEINFO */
501 
502 	if (seek_to_tz_position(&tzf, timezone, tzdb)) {
503 		tmp = timelib_tzinfo_ctor(timezone);
504 
505 		version = read_preamble(&tzf, tmp, &type);
506 		if (version < 2 || version > 3) {
507 			*error_code = TIMELIB_ERROR_UNSUPPORTED_VERSION;
508 			timelib_tzinfo_dtor(tmp);
509 			return NULL;
510 		}
511 //printf("- timezone: %s, version: %0d\n", timezone, version);
512 
513 		read_32bit_header(&tzf, tmp);
514 		skip_32bit_transitions(&tzf, tmp);
515 		skip_32bit_types(&tzf, tmp);
516 
517 		if (!skip_64bit_preamble(&tzf, tmp)) {
518 			/* 64 bit preamble is not in place */
519 			*error_code = TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE;
520 			timelib_tzinfo_dtor(tmp);
521 			return NULL;
522 		}
523 		read_64bit_header(&tzf, tmp);
524 		if ((transitions_result = read_64bit_transitions(&tzf, tmp)) != 0) {
525 			/* Corrupt file as transitions do not increase */
526 			*error_code = transitions_result;
527 			timelib_tzinfo_dtor(tmp);
528 			return NULL;
529 		}
530 		if ((types_result = read_64bit_types(&tzf, tmp)) != 0) {
531 			*error_code = types_result;
532 			timelib_tzinfo_dtor(tmp);
533 			return NULL;
534 		}
535 		skip_posix_string(&tzf, tmp);
536 
537 		if (type == TIMELIB_TZINFO_PHP) {
538 			read_location(&tzf, tmp);
539 		} else {
540 			set_default_location_and_comments(&tzf, tmp);
541 		}
542 	} else {
543 		*error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE;
544 		tmp = NULL;
545 	}
546 
547 	return tmp;
548 }
549 
timelib_tzinfo_dtor(timelib_tzinfo * tz)550 void timelib_tzinfo_dtor(timelib_tzinfo *tz)
551 {
552 	TIMELIB_TIME_FREE(tz->name);
553 	TIMELIB_TIME_FREE(tz->trans);
554 	TIMELIB_TIME_FREE(tz->trans_idx);
555 	TIMELIB_TIME_FREE(tz->type);
556 	TIMELIB_TIME_FREE(tz->timezone_abbr);
557 	TIMELIB_TIME_FREE(tz->leap_times);
558 	TIMELIB_TIME_FREE(tz->location.comments);
559 	TIMELIB_TIME_FREE(tz);
560 	tz = NULL;
561 }
562 
timelib_tzinfo_clone(timelib_tzinfo * tz)563 timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
564 {
565 	timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
566 	tmp->_bit32.ttisgmtcnt = tz->_bit32.ttisgmtcnt;
567 	tmp->_bit32.ttisstdcnt = tz->_bit32.ttisstdcnt;
568 	tmp->_bit32.leapcnt = tz->_bit32.leapcnt;
569 	tmp->_bit32.timecnt = tz->_bit32.timecnt;
570 	tmp->_bit32.typecnt = tz->_bit32.typecnt;
571 	tmp->_bit32.charcnt = tz->_bit32.charcnt;
572 	tmp->bit64.ttisgmtcnt = tz->bit64.ttisgmtcnt;
573 	tmp->bit64.ttisstdcnt = tz->bit64.ttisstdcnt;
574 	tmp->bit64.leapcnt = tz->bit64.leapcnt;
575 	tmp->bit64.timecnt = tz->bit64.timecnt;
576 	tmp->bit64.typecnt = tz->bit64.typecnt;
577 	tmp->bit64.charcnt = tz->bit64.charcnt;
578 
579 	if (tz->bit64.timecnt) {
580 		tmp->trans = (int64_t *) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
581 		tmp->trans_idx = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
582 		memcpy(tmp->trans, tz->trans, tz->bit64.timecnt * sizeof(int64_t));
583 		memcpy(tmp->trans_idx, tz->trans_idx, tz->bit64.timecnt * sizeof(unsigned char));
584 	}
585 
586 	tmp->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
587 	memcpy(tmp->type, tz->type, tz->bit64.typecnt * sizeof(ttinfo));
588 
589 	tmp->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
590 	memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit64.charcnt);
591 
592 	if (tz->bit64.leapcnt) {
593 		tmp->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
594 		memcpy(tmp->leap_times, tz->leap_times, tz->bit64.leapcnt * sizeof(tlinfo));
595 	}
596 
597 	return tmp;
598 }
599 
fetch_timezone_offset(timelib_tzinfo * tz,timelib_sll ts,timelib_sll * transition_time)600 static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
601 {
602 	uint32_t i;
603 
604 	/* If there is no transition time, we pick the first one, if that doesn't
605 	 * exist we return NULL */
606 	if (!tz->bit64.timecnt || !tz->trans) {
607 		if (tz->bit64.typecnt == 1) {
608 			*transition_time = INT64_MIN;
609 			return &(tz->type[0]);
610 		}
611 		return NULL;
612 	}
613 
614 	/* If the TS is lower than the first transition time, then we scan over
615 	 * all the transition times to find the first non-DST one, or the first
616 	 * one in case there are only DST entries. Not sure which smartass came up
617 	 * with this idea in the first though :) */
618 	if (ts < tz->trans[0]) {
619 		*transition_time = INT64_MIN;
620 		return &(tz->type[0]);
621 	}
622 
623 	/* In all other cases we loop through the available transition times to find
624 	 * the correct entry */
625 	for (i = 0; i < tz->bit64.timecnt; i++) {
626 		if (ts < tz->trans[i]) {
627 			*transition_time = tz->trans[i - 1];
628 			return &(tz->type[tz->trans_idx[i - 1]]);
629 		}
630 	}
631 	*transition_time = tz->trans[tz->bit64.timecnt - 1];
632 	return &(tz->type[tz->trans_idx[tz->bit64.timecnt - 1]]);
633 }
634 
fetch_leaptime_offset(timelib_tzinfo * tz,timelib_sll ts)635 static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
636 {
637 	int i;
638 
639 	if (!tz->bit64.leapcnt || !tz->leap_times) {
640 		return NULL;
641 	}
642 
643 	for (i = tz->bit64.leapcnt - 1; i > 0; i--) {
644 		if (ts > tz->leap_times[i].trans) {
645 			return &(tz->leap_times[i]);
646 		}
647 	}
648 	return NULL;
649 }
650 
timelib_timestamp_is_in_dst(timelib_sll ts,timelib_tzinfo * tz)651 int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
652 {
653 	ttinfo *to;
654 	timelib_sll dummy;
655 
656 	if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
657 		return to->isdst;
658 	}
659 	return -1;
660 }
661 
timelib_get_time_zone_info(timelib_sll ts,timelib_tzinfo * tz)662 timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
663 {
664 	ttinfo *to;
665 	tlinfo *tl;
666 	int32_t offset = 0, leap_secs = 0;
667 	char *abbr;
668 	timelib_time_offset *tmp = timelib_time_offset_ctor();
669 	timelib_sll                transition_time;
670 
671 	if ((to = fetch_timezone_offset(tz, ts, &transition_time))) {
672 		offset = to->offset;
673 		abbr = &(tz->timezone_abbr[to->abbr_idx]);
674 		tmp->is_dst = to->isdst;
675 		tmp->transition_time = transition_time;
676 	} else {
677 		offset = 0;
678 		abbr = tz->timezone_abbr;
679 		tmp->is_dst = 0;
680 		tmp->transition_time = 0;
681 	}
682 
683 	if ((tl = fetch_leaptime_offset(tz, ts))) {
684 		leap_secs = -tl->offset;
685 	}
686 
687 	tmp->offset = offset;
688 	tmp->leap_secs = leap_secs;
689 	tmp->abbr = abbr ? timelib_strdup(abbr) : timelib_strdup("GMT");
690 
691 	return tmp;
692 }
693 
timelib_get_current_offset(timelib_time * t)694 timelib_sll timelib_get_current_offset(timelib_time *t)
695 {
696 	timelib_time_offset *gmt_offset;
697 	timelib_sll retval;
698 
699 	switch (t->zone_type) {
700 		case TIMELIB_ZONETYPE_ABBR:
701 		case TIMELIB_ZONETYPE_OFFSET:
702 			return t->z + (t->dst * 3600);
703 
704 		case TIMELIB_ZONETYPE_ID:
705 			gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
706 			retval = gmt_offset->offset;
707 			timelib_time_offset_dtor(gmt_offset);
708 			return retval;
709 
710 		default:
711 			return 0;
712 	}
713 }
714