--- embedaddon/php/ext/date/php_date.c 2013/07/22 01:31:38 1.1.1.3 +++ embedaddon/php/ext/date/php_date.c 2014/06/15 20:03:41 1.1.1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | + | Copyright (c) 1997-2014 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_date.c,v 1.1.1.3 2013/07/22 01:31:38 misho Exp $ */ +/* $Id: php_date.c,v 1.1.1.5 2014/06/15 20:03:41 misho Exp $ */ #include "php.h" #include "php_streams.h" @@ -752,6 +752,14 @@ PHP_RSHUTDOWN_FUNCTION(date) #define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO" +/* + * This comes from various sources that like to contradict. I'm going with the + * format here because of: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa384321%28v=vs.85%29.aspx + * and http://curl.haxx.se/rfc/cookie_spec.html + */ +#define DATE_FORMAT_COOKIE "l, d-M-Y H:i:s T" + #define DATE_TZ_ERRMSG \ "It is not safe to rely on the system's timezone settings. You are " \ "*required* to use the date.timezone setting or the " \ @@ -783,7 +791,7 @@ PHP_MINIT_FUNCTION(date) * with the variations that the only legal time zone is GMT * and the separators between the elements of the date must be dashes." */ - REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_COOKIE, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("DATE_ISO8601", DATE_FORMAT_ISO8601, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("DATE_RFC822", DATE_FORMAT_RFC822, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("DATE_RFC850", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT); @@ -997,7 +1005,7 @@ char *php_date_short_day_name(timelib_sll y, timelib_s static char *date_format(char *format, int format_len, timelib_time *t, int localtime) { smart_str string = {0}; - int i, length; + int i, length = 0; char buffer[97]; timelib_time_offset *offset = NULL; timelib_sll isoweek, isoyear; @@ -1352,7 +1360,7 @@ PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb) } /* }}} */ -/* {{{ php_parse_date: Backwards compability function */ +/* {{{ php_parse_date: Backwards compatibility function */ PHPAPI signed long php_parse_date(char *string, signed long *now) { timelib_time *parsed_time; @@ -1362,6 +1370,7 @@ PHPAPI signed long php_parse_date(char *string, signed parsed_time = timelib_strtotime(string, strlen(string), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); if (error->error_count) { + timelib_time_dtor(parsed_time); timelib_error_container_dtor(error); return -1; } @@ -1947,7 +1956,7 @@ static void date_register_classes(TSRMLS_D) zend_declare_class_constant_stringl(date_ce_date, const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC); REGISTER_DATE_CLASS_CONST_STRING("ATOM", DATE_FORMAT_RFC3339); - REGISTER_DATE_CLASS_CONST_STRING("COOKIE", DATE_FORMAT_RFC850); + REGISTER_DATE_CLASS_CONST_STRING("COOKIE", DATE_FORMAT_COOKIE); REGISTER_DATE_CLASS_CONST_STRING("ISO8601", DATE_FORMAT_ISO8601); REGISTER_DATE_CLASS_CONST_STRING("RFC822", DATE_FORMAT_RFC822); REGISTER_DATE_CLASS_CONST_STRING("RFC850", DATE_FORMAT_RFC850); @@ -2113,13 +2122,13 @@ static HashTable *date_object_get_properties(zval *obj /* first we add the date and time in ISO format */ MAKE_STD_ZVAL(zv); ZVAL_STRING(zv, date_format("Y-m-d H:i:s", 12, dateobj->time, 1), 0); - zend_hash_update(props, "date", 5, &zv, sizeof(zval), NULL); + zend_hash_update(props, "date", 5, &zv, sizeof(zv), NULL); /* then we add the timezone name (or similar) */ if (dateobj->time->is_localtime) { MAKE_STD_ZVAL(zv); ZVAL_LONG(zv, dateobj->time->zone_type); - zend_hash_update(props, "timezone_type", 14, &zv, sizeof(zval), NULL); + zend_hash_update(props, "timezone_type", 14, &zv, sizeof(zv), NULL); MAKE_STD_ZVAL(zv); switch (dateobj->time->zone_type) { @@ -2142,7 +2151,7 @@ static HashTable *date_object_get_properties(zval *obj ZVAL_STRING(zv, dateobj->time->tz_abbr, 1); break; } - zend_hash_update(props, "timezone", 9, &zv, sizeof(zval), NULL); + zend_hash_update(props, "timezone", 9, &zv, sizeof(zv), NULL); } return props; @@ -2265,7 +2274,7 @@ static HashTable *date_object_get_properties_interval( #define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \ MAKE_STD_ZVAL(zv); \ ZVAL_LONG(zv, (long)intervalobj->diff->f); \ - zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zval), NULL); + zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zv), NULL); PHP_DATE_INTERVAL_ADD_PROPERTY("y", y); PHP_DATE_INTERVAL_ADD_PROPERTY("m", m); @@ -2282,7 +2291,7 @@ static HashTable *date_object_get_properties_interval( } else { MAKE_STD_ZVAL(zv); ZVAL_FALSE(zv); - zend_hash_update(props, "days", 5, &zv, sizeof(zval), NULL); + zend_hash_update(props, "days", 5, &zv, sizeof(zv), NULL); } PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type); PHP_DATE_INTERVAL_ADD_PROPERTY("special_amount", special.amount); @@ -2409,8 +2418,8 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, timelib_time *now; timelib_tzinfo *tzi = NULL; timelib_error_container *err = NULL; - int type = TIMELIB_ZONETYPE_ID, new_dst; - char *new_abbr; + int type = TIMELIB_ZONETYPE_ID, new_dst = 0; + char *new_abbr = NULL; timelib_sll new_offset; if (dateobj->time) { @@ -2478,6 +2487,7 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, timelib_fill_holes(dateobj->time, now, TIMELIB_NO_CLONE); timelib_update_ts(dateobj->time, tzi); + timelib_update_from_sse(dateobj->time); dateobj->time->have_relative = 0; @@ -2538,7 +2548,9 @@ PHP_METHOD(DateTime, __construct) zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone)) { - php_date_initialize(zend_object_store_get_object(getThis() TSRMLS_CC), time_str, time_str_len, NULL, timezone_object, 1 TSRMLS_CC); + if (!php_date_initialize(zend_object_store_get_object(getThis() TSRMLS_CC), time_str, time_str_len, NULL, timezone_object, 1 TSRMLS_CC)) { + ZVAL_NULL(getThis()); + } } zend_restore_error_handling(&error_handling TSRMLS_CC); } @@ -2577,6 +2589,10 @@ static int php_date_initialize_from_hash(zval **return tzi = php_date_parse_tzfile(Z_STRVAL_PP(z_timezone), DATE_TIMEZONEDB TSRMLS_CC); + if (tzi == NULL) { + return 0; + } + ALLOC_INIT_ZVAL(tmp_obj); tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, tmp_obj TSRMLS_CC) TSRMLS_CC); tzobj->type = TIMELIB_ZONETYPE_ID; @@ -2879,7 +2895,7 @@ PHP_FUNCTION(date_add) zval *object, *interval; php_date_obj *dateobj; php_interval_obj *intobj; - int bias = 1; + timelib_time *new_time; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) { RETURN_FALSE; @@ -2889,28 +2905,10 @@ PHP_FUNCTION(date_add) intobj = (php_interval_obj *) zend_object_store_get_object(interval TSRMLS_CC); DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval); + new_time = timelib_add(dateobj->time, intobj->diff); + timelib_time_dtor(dateobj->time); + dateobj->time = new_time; - if (intobj->diff->have_weekday_relative || intobj->diff->have_special_relative) { - memcpy(&dateobj->time->relative, intobj->diff, sizeof(struct timelib_rel_time)); - } else { - if (intobj->diff->invert) { - bias = -1; - } - memset(&dateobj->time->relative, 0, sizeof(struct timelib_rel_time)); - dateobj->time->relative.y = intobj->diff->y * bias; - dateobj->time->relative.m = intobj->diff->m * bias; - dateobj->time->relative.d = intobj->diff->d * bias; - dateobj->time->relative.h = intobj->diff->h * bias; - dateobj->time->relative.i = intobj->diff->i * bias; - dateobj->time->relative.s = intobj->diff->s * bias; - } - dateobj->time->have_relative = 1; - dateobj->time->sse_uptodate = 0; - - timelib_update_ts(dateobj->time, NULL); - timelib_update_from_sse(dateobj->time); - dateobj->time->have_relative = 0; - RETURN_ZVAL(object, 1, 0); } /* }}} */ @@ -2923,7 +2921,7 @@ PHP_FUNCTION(date_sub) zval *object, *interval; php_date_obj *dateobj; php_interval_obj *intobj; - int bias = 1; + timelib_time *new_time; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) { RETURN_FALSE; @@ -2938,25 +2936,10 @@ PHP_FUNCTION(date_sub) return; } - if (intobj->diff->invert) { - bias = -1; - } + new_time = timelib_sub(dateobj->time, intobj->diff); + timelib_time_dtor(dateobj->time); + dateobj->time = new_time; - memset(&dateobj->time->relative, 0, sizeof(struct timelib_rel_time)); - dateobj->time->relative.y = 0 - (intobj->diff->y * bias); - dateobj->time->relative.m = 0 - (intobj->diff->m * bias); - dateobj->time->relative.d = 0 - (intobj->diff->d * bias); - dateobj->time->relative.h = 0 - (intobj->diff->h * bias); - dateobj->time->relative.i = 0 - (intobj->diff->i * bias); - dateobj->time->relative.s = 0 - (intobj->diff->s * bias); - dateobj->time->have_relative = 1; - dateobj->time->sse_uptodate = 0; - - timelib_update_ts(dateobj->time, NULL); - timelib_update_from_sse(dateobj->time); - - dateobj->time->have_relative = 0; - RETURN_ZVAL(object, 1, 0); } /* }}} */ @@ -3015,11 +2998,18 @@ PHP_FUNCTION(date_timezone_set) dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); DATE_CHECK_INITIALIZED(dateobj->time, DateTime); tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC); - if (tzobj->type != TIMELIB_ZONETYPE_ID) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only do this for zones with ID for now"); - return; + + switch (tzobj->type) { + case TIMELIB_ZONETYPE_OFFSET: + timelib_set_timezone_from_offset(dateobj->time, tzobj->tzi.utc_offset); + break; + case TIMELIB_ZONETYPE_ABBR: + timelib_set_timezone_from_abbr(dateobj->time, tzobj->tzi.z); + break; + case TIMELIB_ZONETYPE_ID: + timelib_set_timezone(dateobj->time, tzobj->tzi.tz); + break; } - timelib_set_timezone(dateobj->time, tzobj->tzi.tz); timelib_unixtime2local(dateobj->time, dateobj->time->sse); RETURN_ZVAL(object, 1, 0); @@ -3568,7 +3558,11 @@ zval *date_interval_read_property(zval *object, zval * ALLOC_INIT_ZVAL(retval); Z_SET_REFCOUNT_P(retval, 0); - ZVAL_LONG(retval, value); + if (value != -99999) { + ZVAL_LONG(retval, value); + } else { + ZVAL_FALSE(retval); + } if (member == &tmp_member) { zval_dtor(member);