Annotation of embedaddon/php/ext/date/lib/parse_tz.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2010 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 311110 2011-05-16 21:29:45Z johannes $ */
                     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_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
                     53: {
                     54:        /* skip ID */
                     55:        *tzf += 4;
                     56:        
                     57:        /* read BC flag */
                     58:        tz->bc = (**tzf == '\1');
                     59:        *tzf += 1;
                     60: 
                     61:        /* read country code */
                     62:        memcpy(tz->location.country_code, *tzf, 2);
                     63:        tz->location.country_code[2] = '\0';
                     64:        *tzf += 2;
                     65: 
                     66:        /* skip read of preamble */
                     67:        *tzf += 13;
                     68: }
                     69: 
                     70: static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
                     71: {
                     72:        uint32_t buffer[6];
                     73: 
                     74:        memcpy(&buffer, *tzf, sizeof(buffer));
                     75:        tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
                     76:        tz->ttisstdcnt = timelib_conv_int(buffer[1]);
                     77:        tz->leapcnt    = timelib_conv_int(buffer[2]);
                     78:        tz->timecnt    = timelib_conv_int(buffer[3]);
                     79:        tz->typecnt    = timelib_conv_int(buffer[4]);
                     80:        tz->charcnt    = timelib_conv_int(buffer[5]);
                     81:        *tzf += sizeof(buffer);
                     82: }
                     83: 
                     84: static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
                     85: {
                     86:        int32_t *buffer = NULL;
                     87:        uint32_t i;
                     88:        unsigned char *cbuffer = NULL;
                     89: 
                     90:        if (tz->timecnt) {
                     91:                buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
                     92:                if (!buffer) {
                     93:                        return;
                     94:                }
                     95:                memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
                     96:                *tzf += (sizeof(int32_t) * tz->timecnt);
                     97:                for (i = 0; i < tz->timecnt; i++) {
                     98:                        buffer[i] = timelib_conv_int(buffer[i]);
                     99:                }
                    100: 
                    101:                cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
                    102:                if (!cbuffer) {
                    103:                        free(buffer);
                    104:                        return;
                    105:                }
                    106:                memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
                    107:                *tzf += sizeof(unsigned char) * tz->timecnt;
                    108:        }
                    109:        
                    110:        tz->trans = buffer;
                    111:        tz->trans_idx = cbuffer;
                    112: }
                    113: 
                    114: static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
                    115: {
                    116:        unsigned char *buffer;
                    117:        int32_t *leap_buffer;
                    118:        unsigned int i, j;
                    119: 
                    120:        buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
                    121:        if (!buffer) {
                    122:                return;
                    123:        }
                    124:        memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
                    125:        *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
                    126: 
                    127:        tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
                    128:        if (!tz->type) {
                    129:                free(buffer);
                    130:                return;
                    131:        }
                    132: 
                    133:        for (i = 0; i < tz->typecnt; i++) {
                    134:                j = i * 6;
                    135:                tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
                    136:                tz->type[i].isdst = buffer[j + 4];
                    137:                tz->type[i].abbr_idx = buffer[j + 5];
                    138:        }
                    139:        free(buffer);
                    140: 
                    141:        tz->timezone_abbr = (char*) malloc(tz->charcnt);
                    142:        if (!tz->timezone_abbr) {
                    143:                return;
                    144:        }
                    145:        memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
                    146:        *tzf += sizeof(char) * tz->charcnt;
                    147: 
                    148:        if (tz->leapcnt) {
                    149:                leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
                    150:                if (!leap_buffer) {
                    151:                        return;
                    152:                }
                    153:                memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
                    154:                *tzf += sizeof(int32_t) * tz->leapcnt * 2;
                    155: 
                    156:                tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
                    157:                if (!tz->leap_times) {
                    158:                        free(leap_buffer);
                    159:                        return;
                    160:                }
                    161:                for (i = 0; i < tz->leapcnt; i++) {
                    162:                        tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
                    163:                        tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
                    164:                }
                    165:                free(leap_buffer);
                    166:        }
                    167: 
                    168:        if (tz->ttisstdcnt) {
                    169:                buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
                    170:                if (!buffer) {
                    171:                        return;
                    172:                }
                    173:                memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
                    174:                *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
                    175: 
                    176:                for (i = 0; i < tz->ttisstdcnt; i++) {
                    177:                        tz->type[i].isstdcnt = buffer[i];
                    178:                }
                    179:                free(buffer);
                    180:        }
                    181: 
                    182:        if (tz->ttisgmtcnt) {
                    183:                buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
                    184:                if (!buffer) {
                    185:                        return;
                    186:                }
                    187:                memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
                    188:                *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
                    189: 
                    190:                for (i = 0; i < tz->ttisgmtcnt; i++) {
                    191:                        tz->type[i].isgmtcnt = buffer[i];
                    192:                }
                    193:                free(buffer);
                    194:        }
                    195: }
                    196: 
                    197: static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
                    198: {
                    199:        uint32_t buffer[3];
                    200:        uint32_t comments_len;
                    201: 
                    202:        memcpy(&buffer, *tzf, sizeof(buffer));
                    203:        tz->location.latitude = timelib_conv_int(buffer[0]);
                    204:        tz->location.latitude = (tz->location.latitude / 100000) - 90;
                    205:        tz->location.longitude = timelib_conv_int(buffer[1]);
                    206:        tz->location.longitude = (tz->location.longitude / 100000) - 180;
                    207:        comments_len = timelib_conv_int(buffer[2]);
                    208:        *tzf += sizeof(buffer);
                    209: 
                    210:        tz->location.comments = malloc(comments_len + 1);
                    211:        memcpy(tz->location.comments, *tzf, comments_len);
                    212:        tz->location.comments[comments_len] = '\0';
                    213:        *tzf += comments_len;
                    214: }
                    215: 
                    216: void timelib_dump_tzinfo(timelib_tzinfo *tz)
                    217: {
                    218:        uint32_t i;
                    219: 
                    220:        printf("Country Code:      %s\n", tz->location.country_code);
                    221:        printf("Geo Location:      %f,%f\n", tz->location.latitude, tz->location.longitude);
                    222:        printf("Comments:\n%s\n",          tz->location.comments);
                    223:        printf("BC:                %s\n",  tz->bc ? "" : "yes");
                    224:        printf("UTC/Local count:   %lu\n", (unsigned long) tz->ttisgmtcnt);
                    225:        printf("Std/Wall count:    %lu\n", (unsigned long) tz->ttisstdcnt);
                    226:        printf("Leap.sec. count:   %lu\n", (unsigned long) tz->leapcnt);
                    227:        printf("Trans. count:      %lu\n", (unsigned long) tz->timecnt);
                    228:        printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
                    229:        printf("Zone Abbr. count:  %lu\n", (unsigned long) tz->charcnt);
                    230: 
                    231:        printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
                    232:                "", "", 0,
                    233:                (long int) tz->type[0].offset,
                    234:                tz->type[0].isdst,
                    235:                tz->type[0].abbr_idx,
                    236:                &tz->timezone_abbr[tz->type[0].abbr_idx],
                    237:                tz->type[0].isstdcnt,
                    238:                tz->type[0].isgmtcnt
                    239:                );
                    240:        for (i = 0; i < tz->timecnt; i++) {
                    241:                printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
                    242:                        tz->trans[i], tz->trans[i], tz->trans_idx[i],
                    243:                        (long int) tz->type[tz->trans_idx[i]].offset,
                    244:                        tz->type[tz->trans_idx[i]].isdst,
                    245:                        tz->type[tz->trans_idx[i]].abbr_idx,
                    246:                        &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
                    247:                        tz->type[tz->trans_idx[i]].isstdcnt,
                    248:                        tz->type[tz->trans_idx[i]].isgmtcnt
                    249:                        );
                    250:        }
                    251:        for (i = 0; i < tz->leapcnt; i++) {
                    252:                printf ("%08X (%12ld) = %d\n",
                    253:                        tz->leap_times[i].trans,
                    254:                        (long) tz->leap_times[i].trans,
                    255:                        tz->leap_times[i].offset);
                    256:        }
                    257: }
                    258: 
                    259: static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
                    260: {
                    261:        int left = 0, right = tzdb->index_size - 1;
                    262: #ifdef HAVE_SETLOCALE
                    263:        char *cur_locale = NULL, *tmp;
                    264: 
                    265:        tmp = setlocale(LC_CTYPE, NULL);
                    266:        if (tmp) {
                    267:                cur_locale = strdup(tmp);
                    268:        }
                    269:        setlocale(LC_CTYPE, "C");
                    270: #endif 
                    271: 
                    272:        do {
                    273:                int mid = ((unsigned)left + right) >> 1;
                    274:                int cmp = strcasecmp(timezone, tzdb->index[mid].id);
                    275: 
                    276:                if (cmp < 0) {
                    277:                        right = mid - 1;
                    278:                } else if (cmp > 0) {
                    279:                        left = mid + 1;
                    280:                } else { /* (cmp == 0) */
                    281:                        (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
                    282: #ifdef HAVE_SETLOCALE
                    283:                        setlocale(LC_CTYPE, cur_locale);
                    284:                        if (cur_locale) free(cur_locale);
                    285: #endif 
                    286:                        return 1;
                    287:                }
                    288: 
                    289:        } while (left <= right);
                    290: 
                    291: #ifdef HAVE_SETLOCALE
                    292:        setlocale(LC_CTYPE, cur_locale);
                    293:        if (cur_locale) free(cur_locale);
                    294: #endif 
                    295:        return 0;
                    296: }
                    297: 
                    298: const timelib_tzdb *timelib_builtin_db(void)
                    299: {
                    300:        return &timezonedb_builtin;
                    301: }
                    302: 
                    303: const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
                    304: {
                    305:        *count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin);
                    306:        return timezonedb_idx_builtin;
                    307: }
                    308: 
                    309: int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
                    310: {
                    311:        const unsigned char *tzf;
                    312:        return (seek_to_tz_position(&tzf, timezone, tzdb));
                    313: }
                    314: 
                    315: timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
                    316: {
                    317:        const unsigned char *tzf;
                    318:        timelib_tzinfo *tmp;
                    319: 
                    320:        if (seek_to_tz_position(&tzf, timezone, tzdb)) {
                    321:                tmp = timelib_tzinfo_ctor(timezone);
                    322: 
                    323:                read_preamble(&tzf, tmp);
                    324:                read_header(&tzf, tmp);
                    325:                read_transistions(&tzf, tmp);
                    326:                read_types(&tzf, tmp);
                    327:                read_location(&tzf, tmp);
                    328:        } else {
                    329:                tmp = NULL;
                    330:        }
                    331: 
                    332:        return tmp;
                    333: }
                    334: 
                    335: static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
                    336: {
                    337:        uint32_t i;
                    338: 
                    339:        /* If there is no transistion time, we pick the first one, if that doesn't
                    340:         * exist we return NULL */
                    341:        if (!tz->timecnt || !tz->trans) {
                    342:                *transition_time = 0;
                    343:                if (tz->typecnt == 1) {
                    344:                        return &(tz->type[0]);
                    345:                }
                    346:                return NULL;
                    347:        }
                    348: 
                    349:        /* If the TS is lower than the first transistion time, then we scan over
                    350:         * all the transistion times to find the first non-DST one, or the first
                    351:         * one in case there are only DST entries. Not sure which smartass came up
                    352:         * with this idea in the first though :) */
                    353:        if (ts < tz->trans[0]) {
                    354:                uint32_t j;
                    355: 
                    356:                *transition_time = 0;
                    357:                j = 0;
                    358:                while (j < tz->timecnt && tz->type[j].isdst) {
                    359:                        ++j;
                    360:                }
                    361:                if (j == tz->timecnt) {
                    362:                        j = 0;
                    363:                }
                    364:                return &(tz->type[j]);
                    365:        }
                    366: 
                    367:        /* In all other cases we loop through the available transtion times to find
                    368:         * the correct entry */
                    369:        for (i = 0; i < tz->timecnt; i++) {
                    370:                if (ts < tz->trans[i]) {
                    371:                        *transition_time = tz->trans[i - 1];
                    372:                        return &(tz->type[tz->trans_idx[i - 1]]);
                    373:                }
                    374:        }
                    375:        *transition_time = tz->trans[tz->timecnt - 1];
                    376:        return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
                    377: }
                    378: 
                    379: static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
                    380: {
                    381:        int i;
                    382: 
                    383:        if (!tz->leapcnt || !tz->leap_times) {
                    384:                return NULL;
                    385:        }
                    386: 
                    387:        for (i = tz->leapcnt - 1; i > 0; i--) {
                    388:                if (ts > tz->leap_times[i].trans) {
                    389:                        return &(tz->leap_times[i]);
                    390:                }
                    391:        }
                    392:        return NULL;
                    393: }
                    394: 
                    395: int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
                    396: {
                    397:        ttinfo *to;
                    398:        timelib_sll dummy;
                    399:        
                    400:        if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
                    401:                return to->isdst;
                    402:        }
                    403:        return -1;
                    404: }
                    405: 
                    406: timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
                    407: {
                    408:        ttinfo *to;
                    409:        tlinfo *tl;
                    410:        int32_t offset = 0, leap_secs = 0;
                    411:        char *abbr;
                    412:        timelib_time_offset *tmp = timelib_time_offset_ctor();
                    413:        timelib_sll                transistion_time;
                    414: 
                    415:        if ((to = fetch_timezone_offset(tz, ts, &transistion_time))) {
                    416:                offset = to->offset;
                    417:                abbr = &(tz->timezone_abbr[to->abbr_idx]);
                    418:                tmp->is_dst = to->isdst;
                    419:                tmp->transistion_time = transistion_time;
                    420:        } else {
                    421:                offset = 0;
                    422:                abbr = tz->timezone_abbr;
                    423:                tmp->is_dst = 0;
                    424:                tmp->transistion_time = 0;
                    425:        }
                    426: 
                    427:        if ((tl = fetch_leaptime_offset(tz, ts))) {
                    428:                leap_secs = -tl->offset;
                    429:        }
                    430: 
                    431:        tmp->offset = offset;
                    432:        tmp->leap_secs = leap_secs;
                    433:        tmp->abbr = abbr ? strdup(abbr) : strdup("GMT");
                    434: 
                    435:        return tmp;
                    436: }
                    437: 
                    438: timelib_sll timelib_get_current_offset(timelib_time *t)
                    439: {
                    440:        timelib_time_offset *gmt_offset;
                    441:        timelib_sll retval;
                    442:                        
                    443:        switch (t->zone_type) {
                    444:                case TIMELIB_ZONETYPE_ABBR:
                    445:                case TIMELIB_ZONETYPE_OFFSET:
                    446:                        return (t->z + t->dst) * -60;
                    447:                        
                    448:                case TIMELIB_ZONETYPE_ID:
                    449:                        gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
                    450:                        retval = gmt_offset->offset;
                    451:                        timelib_time_offset_dtor(gmt_offset);
                    452:                        return retval;
                    453: 
                    454:                default:
                    455:                        return 0;
                    456:        }
                    457: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>