mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Add DateTimeZone's __serialize and __unserialize methods
This commit is contained in:
parent
8b2ee5388c
commit
181623f9c0
6 changed files with 151 additions and 21 deletions
|
@ -1969,10 +1969,20 @@ static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void date_timezone_object_to_hash(php_timezone_obj *tzobj, HashTable *props)
|
||||||
|
{
|
||||||
|
zval zv;
|
||||||
|
|
||||||
|
ZVAL_LONG(&zv, tzobj->type);
|
||||||
|
zend_hash_str_update(props, "timezone_type", strlen("timezone_type"), &zv);
|
||||||
|
|
||||||
|
php_timezone_to_string(tzobj, &zv);
|
||||||
|
zend_hash_str_update(props, "timezone", strlen("timezone"), &zv);
|
||||||
|
}
|
||||||
|
|
||||||
static HashTable *date_object_get_properties_for_timezone(zend_object *object, zend_prop_purpose purpose) /* {{{ */
|
static HashTable *date_object_get_properties_for_timezone(zend_object *object, zend_prop_purpose purpose) /* {{{ */
|
||||||
{
|
{
|
||||||
HashTable *props;
|
HashTable *props;
|
||||||
zval zv;
|
|
||||||
php_timezone_obj *tzobj;
|
php_timezone_obj *tzobj;
|
||||||
|
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
|
@ -1992,11 +2002,7 @@ static HashTable *date_object_get_properties_for_timezone(zend_object *object, z
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZVAL_LONG(&zv, tzobj->type);
|
date_timezone_object_to_hash(tzobj, props);
|
||||||
zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv);
|
|
||||||
|
|
||||||
php_timezone_to_string(tzobj, &zv);
|
|
||||||
zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv);
|
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
@ -3500,7 +3506,7 @@ PHP_FUNCTION(date_diff)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static zend_result timezone_initialize(php_timezone_obj *tzobj, const char *tz, size_t tz_len) /* {{{ */
|
static bool timezone_initialize(php_timezone_obj *tzobj, const char *tz, size_t tz_len) /* {{{ */
|
||||||
{
|
{
|
||||||
timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
|
timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
|
||||||
int dst, not_found;
|
int dst, not_found;
|
||||||
|
@ -3509,19 +3515,19 @@ static zend_result timezone_initialize(php_timezone_obj *tzobj, const char *tz,
|
||||||
if (strlen(tz) != tz_len) {
|
if (strlen(tz) != tz_len) {
|
||||||
php_error_docref(NULL, E_WARNING, "Timezone must not contain null bytes");
|
php_error_docref(NULL, E_WARNING, "Timezone must not contain null bytes");
|
||||||
efree(dummy_t);
|
efree(dummy_t);
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
|
dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
|
||||||
if (not_found) {
|
if (not_found) {
|
||||||
php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
|
php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
|
||||||
efree(dummy_t);
|
efree(dummy_t);
|
||||||
return FAILURE;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
set_timezone_from_timelib_time(tzobj, dummy_t);
|
set_timezone_from_timelib_time(tzobj, dummy_t);
|
||||||
timelib_free(dummy_t->tz_abbr);
|
timelib_free(dummy_t->tz_abbr);
|
||||||
efree(dummy_t);
|
efree(dummy_t);
|
||||||
return SUCCESS;
|
return true;
|
||||||
}
|
}
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
|
||||||
|
@ -3536,7 +3542,7 @@ PHP_FUNCTION(timezone_open)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
|
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
|
||||||
if (FAILURE == timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz))) {
|
if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz))) {
|
||||||
zval_ptr_dtor(return_value);
|
zval_ptr_dtor(return_value);
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -3561,25 +3567,25 @@ PHP_METHOD(DateTimeZone, __construct)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static zend_result php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht) /* {{{ */
|
static bool php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht) /* {{{ */
|
||||||
{
|
{
|
||||||
zval *z_timezone_type;
|
zval *z_timezone_type;
|
||||||
|
|
||||||
if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) == NULL) {
|
if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) == NULL) {
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zval *z_timezone;
|
zval *z_timezone;
|
||||||
|
|
||||||
if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone") - 1)) == NULL) {
|
if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone") - 1)) == NULL) {
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Z_TYPE_P(z_timezone_type) != IS_LONG) {
|
if (Z_TYPE_P(z_timezone_type) != IS_LONG) {
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
if (Z_TYPE_P(z_timezone) != IS_STRING) {
|
if (Z_TYPE_P(z_timezone) != IS_STRING) {
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
return timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone));
|
return timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone));
|
||||||
} /* }}} */
|
} /* }}} */
|
||||||
|
@ -3599,7 +3605,7 @@ PHP_METHOD(DateTimeZone, __set_state)
|
||||||
|
|
||||||
php_date_instantiate(date_ce_timezone, return_value);
|
php_date_instantiate(date_ce_timezone, return_value);
|
||||||
tzobj = Z_PHPTIMEZONE_P(return_value);
|
tzobj = Z_PHPTIMEZONE_P(return_value);
|
||||||
if (php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) == FAILURE) {
|
if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) {
|
||||||
zend_throw_error(NULL, "Timezone initialization failed");
|
zend_throw_error(NULL, "Timezone initialization failed");
|
||||||
zval_ptr_dtor(return_value);
|
zval_ptr_dtor(return_value);
|
||||||
}
|
}
|
||||||
|
@ -3619,12 +3625,51 @@ PHP_METHOD(DateTimeZone, __wakeup)
|
||||||
|
|
||||||
myht = Z_OBJPROP_P(object);
|
myht = Z_OBJPROP_P(object);
|
||||||
|
|
||||||
if (php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) == FAILURE) {
|
if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) {
|
||||||
zend_throw_error(NULL, "Timezone initialization failed");
|
zend_throw_error(NULL, "Timezone initialization failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ */
|
||||||
|
PHP_METHOD(DateTimeZone, __serialize)
|
||||||
|
{
|
||||||
|
zval *object = ZEND_THIS;
|
||||||
|
php_timezone_obj *tzobj;
|
||||||
|
HashTable *myht;
|
||||||
|
|
||||||
|
ZEND_PARSE_PARAMETERS_NONE();
|
||||||
|
|
||||||
|
tzobj = Z_PHPTIMEZONE_P(object);
|
||||||
|
DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone);
|
||||||
|
|
||||||
|
array_init(return_value);
|
||||||
|
myht = Z_ARRVAL_P(return_value);
|
||||||
|
date_timezone_object_to_hash(tzobj, myht);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ */
|
||||||
|
PHP_METHOD(DateTimeZone, __unserialize)
|
||||||
|
{
|
||||||
|
zval *object = ZEND_THIS;
|
||||||
|
php_timezone_obj *tzobj;
|
||||||
|
zval *array;
|
||||||
|
HashTable *myht;
|
||||||
|
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_ARRAY(array)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
tzobj = Z_PHPTIMEZONE_P(object);
|
||||||
|
myht = Z_ARRVAL_P(array);
|
||||||
|
|
||||||
|
if (!php_date_timezone_initialize_from_hash(&object, &tzobj, myht)) {
|
||||||
|
zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Returns the name of the timezone. */
|
/* {{{ Returns the name of the timezone. */
|
||||||
PHP_FUNCTION(timezone_name_get)
|
PHP_FUNCTION(timezone_name_get)
|
||||||
{
|
{
|
||||||
|
|
|
@ -453,6 +453,10 @@ class DateTimeZone
|
||||||
*/
|
*/
|
||||||
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array {}
|
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array {}
|
||||||
|
|
||||||
|
public function __serialize(): array {}
|
||||||
|
|
||||||
|
public function __unserialize(array $data): void {}
|
||||||
|
|
||||||
/** @tentative-return-type */
|
/** @tentative-return-type */
|
||||||
public function __wakeup(): void {}
|
public function __wakeup(): void {}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: ea354510fbf64c42ee1cdd6fd786ab937516226c */
|
* Stub hash: a157de6bca4bcf5a9ddace9e81ef700f132b4dda */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
|
||||||
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
|
||||||
|
@ -431,6 +431,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_lis
|
||||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, countryCode, IS_STRING, 1, "null")
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, countryCode, IS_STRING, 1, "null")
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
#define arginfo_class_DateTimeZone___serialize arginfo_timezone_abbreviations_list
|
||||||
|
|
||||||
|
#define arginfo_class_DateTimeZone___unserialize arginfo_class_DateTimeInterface___unserialize
|
||||||
|
|
||||||
#define arginfo_class_DateTimeZone___wakeup arginfo_class_DateTimeInterface___wakeup
|
#define arginfo_class_DateTimeZone___wakeup arginfo_class_DateTimeInterface___wakeup
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeZone___set_state, 0, 1, DateTimeZone, 0)
|
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeZone___set_state, 0, 1, DateTimeZone, 0)
|
||||||
|
@ -553,6 +557,8 @@ ZEND_METHOD(DateTimeImmutable, setTimestamp);
|
||||||
ZEND_METHOD(DateTimeImmutable, createFromMutable);
|
ZEND_METHOD(DateTimeImmutable, createFromMutable);
|
||||||
ZEND_METHOD(DateTimeImmutable, createFromInterface);
|
ZEND_METHOD(DateTimeImmutable, createFromInterface);
|
||||||
ZEND_METHOD(DateTimeZone, __construct);
|
ZEND_METHOD(DateTimeZone, __construct);
|
||||||
|
ZEND_METHOD(DateTimeZone, __serialize);
|
||||||
|
ZEND_METHOD(DateTimeZone, __unserialize);
|
||||||
ZEND_METHOD(DateTimeZone, __wakeup);
|
ZEND_METHOD(DateTimeZone, __wakeup);
|
||||||
ZEND_METHOD(DateTimeZone, __set_state);
|
ZEND_METHOD(DateTimeZone, __set_state);
|
||||||
ZEND_METHOD(DateInterval, __construct);
|
ZEND_METHOD(DateInterval, __construct);
|
||||||
|
@ -696,6 +702,8 @@ static const zend_function_entry class_DateTimeZone_methods[] = {
|
||||||
ZEND_ME_MAPPING(getLocation, timezone_location_get, arginfo_class_DateTimeZone_getLocation, ZEND_ACC_PUBLIC)
|
ZEND_ME_MAPPING(getLocation, timezone_location_get, arginfo_class_DateTimeZone_getLocation, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_class_DateTimeZone_listAbbreviations, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
ZEND_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_class_DateTimeZone_listAbbreviations, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||||
ZEND_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_class_DateTimeZone_listIdentifiers, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
ZEND_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_class_DateTimeZone_listIdentifiers, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||||
|
ZEND_ME(DateTimeZone, __serialize, arginfo_class_DateTimeZone___serialize, ZEND_ACC_PUBLIC)
|
||||||
|
ZEND_ME(DateTimeZone, __unserialize, arginfo_class_DateTimeZone___unserialize, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(DateTimeZone, __wakeup, arginfo_class_DateTimeZone___wakeup, ZEND_ACC_PUBLIC)
|
ZEND_ME(DateTimeZone, __wakeup, arginfo_class_DateTimeZone___wakeup, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(DateTimeZone, __set_state, arginfo_class_DateTimeZone___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
ZEND_ME(DateTimeZone, __set_state, arginfo_class_DateTimeZone___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
|
|
58
ext/date/tests/DateTimeZone_serialisation.phpt
Normal file
58
ext/date/tests/DateTimeZone_serialisation.phpt
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
--TEST--
|
||||||
|
Test DateTimeZone::__serialize and DateTime::__unserialize
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$tz = new DateTimeZone("CEST");
|
||||||
|
var_dump($tz->__serialize());
|
||||||
|
|
||||||
|
$tz = new DateTimeZone("UTC");
|
||||||
|
$tz->__unserialize(
|
||||||
|
[
|
||||||
|
'timezone_type' => 3,
|
||||||
|
'timezone' => 'Europe/London',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
var_dump($tz);
|
||||||
|
|
||||||
|
$tz->__unserialize(
|
||||||
|
[
|
||||||
|
'timezone_type' => 2,
|
||||||
|
'timezone' => 'CEST',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
var_dump($tz);
|
||||||
|
|
||||||
|
$tz->__unserialize(
|
||||||
|
[
|
||||||
|
'timezone_type' => 1,
|
||||||
|
'timezone' => '+0130',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
var_dump($tz);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
array(2) {
|
||||||
|
["timezone_type"]=>
|
||||||
|
int(2)
|
||||||
|
["timezone"]=>
|
||||||
|
string(4) "CEST"
|
||||||
|
}
|
||||||
|
object(DateTimeZone)#%d (%d) {
|
||||||
|
["timezone_type"]=>
|
||||||
|
int(3)
|
||||||
|
["timezone"]=>
|
||||||
|
string(13) "Europe/London"
|
||||||
|
}
|
||||||
|
object(DateTimeZone)#%d (%d) {
|
||||||
|
["timezone_type"]=>
|
||||||
|
int(2)
|
||||||
|
["timezone"]=>
|
||||||
|
string(4) "CEST"
|
||||||
|
}
|
||||||
|
object(DateTimeZone)#%d (%d) {
|
||||||
|
["timezone_type"]=>
|
||||||
|
int(1)
|
||||||
|
["timezone"]=>
|
||||||
|
string(6) "+01:30"
|
||||||
|
}
|
15
ext/date/tests/DateTimeZone_serialize_errors.phpt
Normal file
15
ext/date/tests/DateTimeZone_serialize_errors.phpt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
--TEST--
|
||||||
|
Test unserialization of DateTimeZone with null byte
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$serialized = 'O:12:"DateTimeZone":2:{s:13:"timezone_type";i:3;s:8:"timezone";s:17:"Ame' . "\0" .'rica/New_York";}';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$tz = unserialize($serialized);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: DateTimeZone::__unserialize(): Timezone must not contain null bytes in %s on line %d
|
||||||
|
Invalid serialization data for DateTimeZone object
|
|
@ -6,9 +6,9 @@ $data = unserialize('a:2:{i:0;O:12:"DateTimeZone":2:{s:13:"timezone_type";a:2:{i
|
||||||
var_dump($data);
|
var_dump($data);
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Timezone initialization failed in %s:%d
|
Fatal error: Uncaught Error: Invalid serialization data for DateTimeZone object in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 [internal function]: DateTimeZone->__wakeup()
|
#0 [internal function]: DateTimeZone->__unserialize(Array)
|
||||||
#1 %s(%d): unserialize('a:2:{i:0;O:12:"...')
|
#1 %s(%d): unserialize('a:2:{i:0;O:12:"...')
|
||||||
#2 {main}
|
#2 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue