1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Derick Rethans <derick@derickrethans.nl> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: parse_tz.c 272374 2008-12-31 11:17:49Z sebastian $ */
20 :
21 : #include "timelib.h"
22 :
23 : #include <stdio.h>
24 :
25 : #ifdef HAVE_LOCALE_H
26 : #include <locale.h>
27 : #endif
28 :
29 : #ifdef HAVE_STRING_H
30 : #include <string.h>
31 : #else
32 : #include <strings.h>
33 : #endif
34 : #include "timezonedb.h"
35 :
36 : #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
37 : # if defined(__LITTLE_ENDIAN__)
38 : # undef WORDS_BIGENDIAN
39 : # else
40 : # if defined(__BIG_ENDIAN__)
41 : # define WORDS_BIGENDIAN
42 : # endif
43 : # endif
44 : #endif
45 :
46 : #ifdef WORDS_BIGENDIAN
47 : #define timelib_conv_int(l) (l)
48 : #else
49 : #define timelib_conv_int(l) ((l & 0x000000ff) << 24) + ((l & 0x0000ff00) << 8) + ((l & 0x00ff0000) >> 8) + ((l & 0xff000000) >> 24)
50 : #endif
51 :
52 : static void read_header(char **tzf, timelib_tzinfo *tz)
53 673 : {
54 : uint32_t buffer[6];
55 :
56 673 : memcpy(&buffer, *tzf, sizeof(buffer));
57 673 : tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
58 673 : tz->ttisstdcnt = timelib_conv_int(buffer[1]);
59 673 : tz->leapcnt = timelib_conv_int(buffer[2]);
60 673 : tz->timecnt = timelib_conv_int(buffer[3]);
61 673 : tz->typecnt = timelib_conv_int(buffer[4]);
62 673 : tz->charcnt = timelib_conv_int(buffer[5]);
63 673 : *tzf += sizeof(buffer);
64 673 : }
65 :
66 : static void read_transistions(char **tzf, timelib_tzinfo *tz)
67 673 : {
68 673 : int32_t *buffer = NULL;
69 : uint32_t i;
70 673 : unsigned char *cbuffer = NULL;
71 :
72 673 : if (tz->timecnt) {
73 334 : buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
74 334 : if (!buffer) {
75 0 : return;
76 : }
77 334 : memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
78 334 : *tzf += (sizeof(int32_t) * tz->timecnt);
79 47517 : for (i = 0; i < tz->timecnt; i++) {
80 47183 : buffer[i] = timelib_conv_int(buffer[i]);
81 : }
82 :
83 334 : cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
84 334 : if (!cbuffer) {
85 0 : return;
86 : }
87 334 : memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
88 334 : *tzf += sizeof(unsigned char) * tz->timecnt;
89 : }
90 :
91 673 : tz->trans = buffer;
92 673 : tz->trans_idx = cbuffer;
93 : }
94 :
95 : static void read_types(char **tzf, timelib_tzinfo *tz)
96 673 : {
97 : unsigned char *buffer;
98 : int32_t *leap_buffer;
99 : unsigned int i, j;
100 :
101 673 : buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
102 673 : if (!buffer) {
103 0 : return;
104 : }
105 673 : memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
106 673 : *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
107 :
108 673 : tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
109 673 : if (!tz->type) {
110 0 : return;
111 : }
112 :
113 2915 : for (i = 0; i < tz->typecnt; i++) {
114 2242 : j = i * 6;
115 2242 : tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
116 2242 : tz->type[i].isdst = buffer[j + 4];
117 2242 : tz->type[i].abbr_idx = buffer[j + 5];
118 : }
119 673 : free(buffer);
120 :
121 673 : tz->timezone_abbr = (char*) malloc(tz->charcnt);
122 673 : if (!tz->timezone_abbr) {
123 0 : return;
124 : }
125 673 : memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
126 673 : *tzf += sizeof(char) * tz->charcnt;
127 :
128 673 : if (tz->leapcnt) {
129 0 : leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
130 0 : if (!leap_buffer) {
131 0 : return;
132 : }
133 0 : memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
134 0 : *tzf += sizeof(int32_t) * tz->leapcnt * 2;
135 :
136 0 : tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
137 0 : if (!tz->leap_times) {
138 0 : return;
139 : }
140 0 : for (i = 0; i < tz->leapcnt; i++) {
141 0 : tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
142 0 : tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
143 : }
144 0 : free(leap_buffer);
145 : }
146 :
147 673 : if (tz->ttisstdcnt) {
148 673 : buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
149 673 : if (!buffer) {
150 0 : return;
151 : }
152 673 : memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
153 673 : *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
154 :
155 2915 : for (i = 0; i < tz->ttisstdcnt; i++) {
156 2242 : tz->type[i].isstdcnt = buffer[i];
157 : }
158 673 : free(buffer);
159 : }
160 :
161 673 : if (tz->ttisgmtcnt) {
162 673 : buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
163 673 : if (!buffer) {
164 0 : return;
165 : }
166 673 : memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
167 673 : *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
168 :
169 2915 : for (i = 0; i < tz->ttisgmtcnt; i++) {
170 2242 : tz->type[i].isgmtcnt = buffer[i];
171 : }
172 673 : free(buffer);
173 : }
174 : }
175 :
176 : void timelib_dump_tzinfo(timelib_tzinfo *tz)
177 0 : {
178 : uint32_t i;
179 :
180 0 : printf("UTC/Local count: %lu\n", (unsigned long) tz->ttisgmtcnt);
181 0 : printf("Std/Wall count: %lu\n", (unsigned long) tz->ttisstdcnt);
182 0 : printf("Leap.sec. count: %lu\n", (unsigned long) tz->leapcnt);
183 0 : printf("Trans. count: %lu\n", (unsigned long) tz->timecnt);
184 0 : printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
185 0 : printf("Zone Abbr. count: %lu\n", (unsigned long) tz->charcnt);
186 :
187 0 : printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
188 : "", "", 0,
189 : (long int) tz->type[0].offset,
190 : tz->type[0].isdst,
191 : tz->type[0].abbr_idx,
192 : &tz->timezone_abbr[tz->type[0].abbr_idx],
193 : tz->type[0].isstdcnt,
194 : tz->type[0].isgmtcnt
195 : );
196 0 : for (i = 0; i < tz->timecnt; i++) {
197 0 : printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
198 : tz->trans[i], tz->trans[i], tz->trans_idx[i],
199 : (long int) tz->type[tz->trans_idx[i]].offset,
200 : tz->type[tz->trans_idx[i]].isdst,
201 : tz->type[tz->trans_idx[i]].abbr_idx,
202 : &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
203 : tz->type[tz->trans_idx[i]].isstdcnt,
204 : tz->type[tz->trans_idx[i]].isgmtcnt
205 : );
206 : }
207 0 : for (i = 0; i < tz->leapcnt; i++) {
208 0 : printf ("%08X (%12ld) = %d\n",
209 : tz->leap_times[i].trans,
210 : (long) tz->leap_times[i].trans,
211 : tz->leap_times[i].offset);
212 : }
213 0 : }
214 :
215 : static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
216 2223 : {
217 2223 : int left = 0, right = tzdb->index_size - 1;
218 : #ifdef HAVE_SETLOCALE
219 2223 : char *cur_locale = NULL, *tmp;
220 :
221 2223 : tmp = setlocale(LC_CTYPE, NULL);
222 2223 : if (tmp) {
223 2223 : cur_locale = strdup(tmp);
224 : }
225 2223 : setlocale(LC_CTYPE, "C");
226 : #endif
227 :
228 : do {
229 18266 : int mid = ((unsigned)left + right) >> 1;
230 18266 : int cmp = strcasecmp(timezone, tzdb->index[mid].id);
231 :
232 18266 : if (cmp < 0) {
233 6726 : right = mid - 1;
234 11540 : } else if (cmp > 0) {
235 9389 : left = mid + 1;
236 : } else { /* (cmp == 0) */
237 2151 : (*tzf) = &(tzdb->data[tzdb->index[mid].pos + 20]);
238 : #ifdef HAVE_SETLOCALE
239 2151 : setlocale(LC_CTYPE, cur_locale);
240 2151 : if (cur_locale) free(cur_locale);
241 : #endif
242 2151 : return 1;
243 : }
244 :
245 16115 : } while (left <= right);
246 :
247 : #ifdef HAVE_SETLOCALE
248 72 : setlocale(LC_CTYPE, cur_locale);
249 72 : if (cur_locale) free(cur_locale);
250 : #endif
251 72 : return 0;
252 : }
253 :
254 : const timelib_tzdb *timelib_builtin_db(void)
255 17834 : {
256 17834 : return &timezonedb_builtin;
257 : }
258 :
259 : const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
260 0 : {
261 0 : *count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin);
262 0 : return timezonedb_idx_builtin;
263 : }
264 :
265 : int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
266 1505 : {
267 : const unsigned char *tzf;
268 1505 : return (seek_to_tz_position(&tzf, timezone, tzdb));
269 : }
270 :
271 : timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
272 718 : {
273 : const unsigned char *tzf;
274 : timelib_tzinfo *tmp;
275 :
276 718 : if (seek_to_tz_position(&tzf, timezone, tzdb)) {
277 673 : tmp = timelib_tzinfo_ctor(timezone);
278 :
279 673 : read_header((char**) &tzf, tmp);
280 673 : read_transistions((char**) &tzf, tmp);
281 673 : read_types((char**) &tzf, tmp);
282 : } else {
283 45 : tmp = NULL;
284 : }
285 :
286 718 : return tmp;
287 : }
288 :
289 : static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
290 23996 : {
291 : uint32_t i;
292 :
293 : /* If there is no transistion time, we pick the first one, if that doesn't
294 : * exist we return NULL */
295 23996 : if (!tz->timecnt || !tz->trans) {
296 16093 : *transition_time = 0;
297 16093 : if (tz->typecnt == 1) {
298 16093 : return &(tz->type[0]);
299 : }
300 0 : return NULL;
301 : }
302 :
303 : /* If the TS is lower than the first transistion time, then we scan over
304 : * all the transistion times to find the first non-DST one, or the first
305 : * one in case there are only DST entries. Not sure which smartass came up
306 : * with this idea in the first though :) */
307 7903 : if (ts < tz->trans[0]) {
308 : uint32_t j;
309 :
310 323 : *transition_time = 0;
311 323 : j = 0;
312 868 : while (j < tz->timecnt && tz->type[j].isdst) {
313 222 : ++j;
314 : }
315 323 : if (j == tz->timecnt) {
316 0 : j = 0;
317 : }
318 323 : return &(tz->type[j]);
319 : }
320 :
321 : /* In all other cases we loop through the available transtion times to find
322 : * the correct entry */
323 618992 : for (i = 0; i < tz->timecnt; i++) {
324 616513 : if (ts < tz->trans[i]) {
325 5101 : *transition_time = tz->trans[i - 1];
326 5101 : return &(tz->type[tz->trans_idx[i - 1]]);
327 : }
328 : }
329 2479 : *transition_time = tz->trans[tz->timecnt - 1];
330 2479 : return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
331 : }
332 :
333 : static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
334 23996 : {
335 : int i;
336 :
337 23996 : if (!tz->leapcnt || !tz->leap_times) {
338 23996 : return NULL;
339 : }
340 :
341 0 : for (i = tz->leapcnt - 1; i > 0; i--) {
342 0 : if (ts > tz->leap_times[i].trans) {
343 0 : return &(tz->leap_times[i]);
344 : }
345 : }
346 0 : return NULL;
347 : }
348 :
349 : int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
350 0 : {
351 : ttinfo *to;
352 : timelib_sll dummy;
353 :
354 0 : if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
355 0 : return to->isdst;
356 : }
357 0 : return -1;
358 : }
359 :
360 : timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
361 23996 : {
362 : ttinfo *to;
363 : tlinfo *tl;
364 23996 : int32_t offset = 0, leap_secs = 0;
365 : char *abbr;
366 23996 : timelib_time_offset *tmp = timelib_time_offset_ctor();
367 : timelib_sll transistion_time;
368 :
369 23996 : if ((to = fetch_timezone_offset(tz, ts, &transistion_time))) {
370 23996 : offset = to->offset;
371 23996 : abbr = &(tz->timezone_abbr[to->abbr_idx]);
372 23996 : tmp->is_dst = to->isdst;
373 23996 : tmp->transistion_time = transistion_time;
374 : } else {
375 0 : offset = 0;
376 0 : abbr = tz->timezone_abbr;
377 0 : tmp->is_dst = 0;
378 0 : tmp->transistion_time = 0;
379 : }
380 :
381 23996 : if ((tl = fetch_leaptime_offset(tz, ts))) {
382 0 : leap_secs = -tl->offset;
383 : }
384 :
385 23996 : tmp->offset = offset;
386 23996 : tmp->leap_secs = leap_secs;
387 23996 : tmp->abbr = abbr ? strdup(abbr) : strdup("GMT");
388 :
389 23996 : return tmp;
390 : }
391 :
392 : timelib_sll timelib_get_current_offset(timelib_time *t)
393 36 : {
394 : timelib_time_offset *gmt_offset;
395 : timelib_sll retval;
396 :
397 36 : switch (t->zone_type) {
398 : case TIMELIB_ZONETYPE_ABBR:
399 : case TIMELIB_ZONETYPE_OFFSET:
400 0 : return (t->z + t->dst) * -60;
401 :
402 : case TIMELIB_ZONETYPE_ID:
403 36 : gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
404 36 : retval = gmt_offset->offset;
405 36 : timelib_time_offset_dtor(gmt_offset);
406 36 : return retval;
407 :
408 : default:
409 0 : return 0;
410 : }
411 : }
|