mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +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) /* {{{ */
|
||||
{
|
||||
HashTable *props;
|
||||
zval zv;
|
||||
php_timezone_obj *tzobj;
|
||||
|
||||
switch (purpose) {
|
||||
|
@ -1992,11 +2002,7 @@ static HashTable *date_object_get_properties_for_timezone(zend_object *object, z
|
|||
return props;
|
||||
}
|
||||
|
||||
ZVAL_LONG(&zv, tzobj->type);
|
||||
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);
|
||||
date_timezone_object_to_hash(tzobj, 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));
|
||||
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) {
|
||||
php_error_docref(NULL, E_WARNING, "Timezone must not contain null bytes");
|
||||
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);
|
||||
if (not_found) {
|
||||
php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
|
||||
efree(dummy_t);
|
||||
return FAILURE;
|
||||
return false;
|
||||
} else {
|
||||
set_timezone_from_timelib_time(tzobj, dummy_t);
|
||||
timelib_free(dummy_t->tz_abbr);
|
||||
efree(dummy_t);
|
||||
return SUCCESS;
|
||||
return true;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
|
@ -3536,7 +3542,7 @@ PHP_FUNCTION(timezone_open)
|
|||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) == NULL) {
|
||||
return FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
zval *z_timezone;
|
||||
|
||||
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) {
|
||||
return FAILURE;
|
||||
return false;
|
||||
}
|
||||
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));
|
||||
} /* }}} */
|
||||
|
@ -3599,7 +3605,7 @@ PHP_METHOD(DateTimeZone, __set_state)
|
|||
|
||||
php_date_instantiate(date_ce_timezone, 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");
|
||||
zval_ptr_dtor(return_value);
|
||||
}
|
||||
|
@ -3619,12 +3625,51 @@ PHP_METHOD(DateTimeZone, __wakeup)
|
|||
|
||||
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");
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ */
|
||||
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. */
|
||||
PHP_FUNCTION(timezone_name_get)
|
||||
{
|
||||
|
|
|
@ -453,6 +453,10 @@ class DateTimeZone
|
|||
*/
|
||||
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 */
|
||||
public function __wakeup(): void {}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 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_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_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
|
||||
|
||||
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, createFromInterface);
|
||||
ZEND_METHOD(DateTimeZone, __construct);
|
||||
ZEND_METHOD(DateTimeZone, __serialize);
|
||||
ZEND_METHOD(DateTimeZone, __unserialize);
|
||||
ZEND_METHOD(DateTimeZone, __wakeup);
|
||||
ZEND_METHOD(DateTimeZone, __set_state);
|
||||
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(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(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, __set_state, arginfo_class_DateTimeZone___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
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);
|
||||
?>
|
||||
--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:
|
||||
#0 [internal function]: DateTimeZone->__wakeup()
|
||||
#0 [internal function]: DateTimeZone->__unserialize(Array)
|
||||
#1 %s(%d): unserialize('a:2:{i:0;O:12:"...')
|
||||
#2 {main}
|
||||
thrown in %s on line %d
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue