From: Sara Golemon Date: Fri, 5 Jan 2007 02:07:59 +0000 (+0000) Subject: Unicode Updates X-Git-Tag: RELEASE_1_0_0RC1~397 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=344cda1666363bd6ff4475d30bd77bff40af28fc;p=php Unicode Updates --- diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index bef7320121..a78fe72d80 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -120,6 +120,28 @@ static char *ps_files_path_create(char *buf, size_t buflen, ps_files *data, cons memcpy(buf + n, key, key_len); n += key_len; buf[n] = '\0'; + + if (UG(unicode) && UG(filesystem_encoding_conv)) { + /* If there's a cheap way to see if filesystem_encoding_conv happens to be utf8, we should skip this reconversion */ + char *newbuf = NULL; + int newlen; + UErrorCode status = U_ZERO_ERROR; + + zend_convert_encodings(UG(filesystem_encoding_conv), UG(utf8_conv), &newbuf, &newlen, buf, n, &status); + + if (status != U_ZERO_ERROR) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failure converting savepath to local filesystem encoding, attempting to use utf8"); + } else { + if (newlen >= buflen) { + newlen = buflen - 1; + newbuf[newlen] = 0; + } + memcpy(buf, newbuf, newlen + 1); + } + if (newbuf) { + efree(newbuf); + } + } return buf; } diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c index 8b39c21fb3..afe3280673 100644 --- a/ext/session/mod_user.c +++ b/ext/session/mod_user.c @@ -32,17 +32,17 @@ ps_module ps_mod_user = { ZVAL_LONG(a, val); \ } -#define SESS_ZVAL_STRING(vl, a) \ + +#define SESS_ZVAL_STRINGN(vl, ln, a) \ { \ - int len = strlen(vl); \ MAKE_STD_ZVAL(a); \ - ZVAL_STRINGL(a, vl, len, 1); \ + ZVAL_UTF8_STRINGL(a, vl, ln, ZSTR_DUPLICATE); \ } -#define SESS_ZVAL_STRINGN(vl, ln, a) \ +#define SESS_ZVAL_STRING(vl, a) \ { \ - MAKE_STD_ZVAL(a); \ - ZVAL_STRINGL(a, vl, ln, 1); \ + char *__vl = vl; \ + SESS_ZVAL_STRINGN(__vl, strlen(__vl), a); \ } @@ -126,7 +126,23 @@ PS_READ_FUNC(user) *val = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); *vallen = Z_STRLEN_P(retval); ret = SUCCESS; + } else if (Z_TYPE_P(retval) == IS_UNICODE) { + char *sval = NULL; + int slen; + UErrorCode status = U_ZERO_ERROR; + + zend_unicode_to_string_ex(UG(utf8_conv), &sval, &slen, Z_USTRVAL_P(retval), Z_USTRLEN_P(retval), &status); + if (U_FAILURE(status)) { + if (sval) { + efree(sval); + } + } else { + *val = sval; + *vallen = slen; + ret = SUCCESS; + } } + zval_ptr_dtor(&retval); } diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 989740f1fe..3ef0502105 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -199,6 +199,7 @@ PHPAPI const ps_serializer *_php_find_ps_serializer(char *name TSRMLS_DC); ulong num_key; \ zval **struc; +/* (Possibly) needed for BC (e.g. by external modules using the session registry) */ #define PS_ENCODE_LOOP(code) do { \ HashTable *_ht = Z_ARRVAL_P(PS(http_session_vars)); \ \ @@ -212,6 +213,24 @@ PHPAPI const ps_serializer *_php_find_ps_serializer(char *name TSRMLS_DC); } \ } while(0) +#define PS_UENCODE_LOOP(code) do { \ + int key_type; \ + HashTable *_ht = Z_ARRVAL_P(PS(http_session_vars)); \ + HashPosition _pos; \ + \ + for (zend_hash_internal_pointer_reset_ex(_ht, &_pos); \ + (key_type = zend_hash_get_current_key_ex(_ht, &key, &key_length, &num_key, 0, &_pos)) != HASH_KEY_NON_EXISTANT; \ + zend_hash_move_forward_ex(_ht, &_pos)) { \ + if (key_type != HASH_KEY_IS_STRING && key_type != HASH_KEY_IS_UNICODE) { break; } \ + key_length--; \ + struc = NULL; \ + zend_hash_get_current_data_ex(_ht, (void**)&struc, &_pos); \ +\ + code; \ + } \ + } while(0) + + PHPAPI ZEND_EXTERN_MODULE_GLOBALS(ps) void php_session_auto_start(void *data); diff --git a/ext/session/session.c b/ext/session/session.c index 782758339f..55d27f68b6 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -140,9 +140,11 @@ PHPAPI void php_add_session_var(char *name, size_t namelen TSRMLS_DC) } } +/* BC? */ PHPAPI void php_set_session_var(char *name, size_t namelen, zval *state_val, php_unserialize_data_t *var_hash TSRMLS_DC) { - zend_set_hash_symbol(state_val, name, namelen, PZVAL_IS_REF(state_val), 1, Z_ARRVAL_P(PS(http_session_vars))); + zend_utf8_hash_update(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, &state_val, sizeof(zval *), NULL); + zval_add_ref(&state_val); } PHPAPI int php_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC) @@ -572,19 +574,22 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary) PHP_VAR_SERIALIZE_INIT(var_hash); - PS_ENCODE_LOOP( - if (key_length > PS_BIN_MAX) continue; - smart_str_appendc(&buf, (unsigned char) key_length); - smart_str_appendl(&buf, key.s, key_length); - - php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); - } else { - if (key_length > PS_BIN_MAX) continue; - smart_str_appendc(&buf, (unsigned char) (key_length & PS_BIN_UNDEF)); - smart_str_appendl(&buf, key.s, key_length); + PS_UENCODE_LOOP( + if (key_length > PS_BIN_MAX || key_type != HASH_KEY_IS_STRING) continue; + if (struc) { + smart_str_appendc(&buf, (unsigned char)key_length ); + smart_str_appendl(&buf, key.s, key_length); + php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); + } else { + smart_str_appendc(&buf, (unsigned char)key_length | PS_BIN_UNDEF); + smart_str_appendl(&buf, key.s, key_length); + } ); - if (newlen) *newlen = buf.len; + if (newlen) { + *newlen = buf.len; + } + smart_str_0(&buf); *newstr = buf.c; PHP_VAR_SERIALIZE_DESTROY(var_hash); @@ -605,7 +610,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) for (p = val; p < endptr; ) { zval **tmp; - namelen = *p & (~PS_BIN_UNDEF); + namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF); if (namelen > PS_BIN_MAX || (p + namelen) >= endptr) { return FAILURE; @@ -627,10 +632,12 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) if (has_value) { ALLOC_INIT_ZVAL(current); if (php_var_unserialize(¤t, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { - php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + zend_utf8_hash_update(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, ¤t, sizeof(zval *), NULL); + } else { + zval_ptr_dtor(¤t); } - zval_ptr_dtor(¤t); } + PS_ADD_VARL(name, namelen); efree(name); } @@ -651,23 +658,44 @@ PS_SERIALIZER_ENCODE_FUNC(php) PHP_VAR_SERIALIZE_INIT(var_hash); - PS_ENCODE_LOOP( - smart_str_appendl(&buf, key.s, (unsigned char) key_length); + PS_UENCODE_LOOP( + if (!struc) { + smart_str_appendc(&buf, PS_UNDEF_MARKER); + } + + if (key_type == HASH_KEY_IS_STRING) { if (memchr(key.s, PS_DELIMITER, key_length)) { PHP_VAR_SERIALIZE_DESTROY(var_hash); smart_str_free(&buf); return FAILURE; } - smart_str_appendc(&buf, PS_DELIMITER); - + smart_str_appendl(&buf, key.s, (unsigned char) key_length); + } else { + /* HASH_KEY_IS_UNICODE */ + char *str = NULL; + int len; + UErrorCode status = U_ZERO_ERROR; + + zend_unicode_to_string_ex(UG(utf8_conv), &str, &len, key.u, key_length, &status); + if (U_FAILURE(status) || memchr(str, PS_DELIMITER, key_length)) { + PHP_VAR_SERIALIZE_DESTROY(var_hash); + smart_str_free(&buf); + if (str) { efree(str); } + return FAILURE; + } + smart_str_appendl(&buf, str, len); + efree(str); + } + smart_str_appendc(&buf, PS_DELIMITER); + + if (struc) { php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); - } else { - smart_str_appendc(&buf, PS_UNDEF_MARKER); - smart_str_appendl(&buf, key.s, key_length); - smart_str_appendc(&buf, PS_DELIMITER); + } ); if (newlen) *newlen = buf.len; + + smart_str_0(&buf); *newstr = buf.c; PHP_VAR_SERIALIZE_DESTROY(var_hash); @@ -690,16 +718,17 @@ PS_SERIALIZER_DECODE_FUNC(php) while (p < endptr) { zval **tmp; + has_value = 1; + q = p; while (*q != PS_DELIMITER) { if (++q >= endptr) goto break_outer_loop; } - if (p[0] == PS_UNDEF_MARKER) { - p++; + if (*p == PS_UNDEF_MARKER) { + if (++p >= endptr) goto break_outer_loop; + has_value = 0; - } else { - has_value = 1; } namelen = q - p; @@ -715,9 +744,10 @@ PS_SERIALIZER_DECODE_FUNC(php) if (has_value) { ALLOC_INIT_ZVAL(current); if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { - php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + zend_utf8_hash_update(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, ¤t, sizeof(zval *), NULL); + } else { + zval_ptr_dtor(¤t); } - zval_ptr_dtor(¤t); } PS_ADD_VARL(name, namelen); skip: @@ -1236,7 +1266,7 @@ PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t ******************************** */ -/* {{{ proto void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly]]]]) +/* {{{ proto void session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure[, bool httponly]]]]) U Set session cookie parameters */ static PHP_FUNCTION(session_set_cookie_params) { @@ -1269,7 +1299,7 @@ static PHP_FUNCTION(session_set_cookie_params) } /* }}} */ -/* {{{ proto array session_get_cookie_params(void) +/* {{{ proto array session_get_cookie_params(void) U Return the session cookie parameters */ static PHP_FUNCTION(session_get_cookie_params) { @@ -1287,18 +1317,18 @@ static PHP_FUNCTION(session_get_cookie_params) } /* }}} */ -/* {{{ proto string session_name([string newname]) +/* {{{ proto string session_name([string newname]) U Return the current session name. If newname is given, the session name is replaced with newname */ static PHP_FUNCTION(session_name) { char *name = NULL; int name_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s&", &name, &name_len, UG(utf8_conv)) == FAILURE) { return; } - RETVAL_STRING(PS(session_name), 1); + RETVAL_UTF8_STRING(PS(session_name), ZSTR_DUPLICATE); if (name) { zend_alter_ini_entry("session.name", sizeof("session.name"), name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); @@ -1306,20 +1336,20 @@ static PHP_FUNCTION(session_name) } /* }}} */ -/* {{{ proto string session_module_name([string newname]) +/* {{{ proto string session_module_name([string newname]) U Return the current module name used for accessing session data. If newname is given, the module name is replaced with newname */ static PHP_FUNCTION(session_module_name) { char *name = NULL; int name_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s&", &name, &name_len, UG(utf8_conv)) == FAILURE) { return; } /* Set return_value to current module name */ if (PS(mod) && PS(mod)->s_name) { - RETVAL_STRING(safe_estrdup(PS(mod)->s_name), 0); + RETVAL_UTF8_STRING((char*)PS(mod)->s_name, ZSTR_DUPLICATE); } else { RETVAL_EMPTY_STRING(); } @@ -1341,7 +1371,7 @@ static PHP_FUNCTION(session_module_name) } /* }}} */ -/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc) +/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc) U Sets user-level functions */ static PHP_FUNCTION(session_set_save_handler) { @@ -1383,18 +1413,18 @@ static PHP_FUNCTION(session_set_save_handler) } /* }}} */ -/* {{{ proto string session_save_path([string newname]) +/* {{{ proto string session_save_path([string newname]) U Return the current save path passed to module_name. If newname is given, the save path is replaced with newname */ static PHP_FUNCTION(session_save_path) { char *name; int name_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s&", &name, &name_len, UG(utf8_conv)) == FAILURE) { return; } - RETVAL_STRING(PS(save_path), 1); + RETVAL_UTF8_STRING(PS(save_path), ZSTR_DUPLICATE); if (name) { if (memchr(name, '\0', name_len) != NULL) { @@ -1408,31 +1438,56 @@ static PHP_FUNCTION(session_save_path) } /* }}} */ -/* {{{ proto string session_id([string newid]) +/* {{{ proto string session_id([string newid]) U Return the current session id. If newid is given, the session id is replaced with newid */ static PHP_FUNCTION(session_id) { - char *name; + zstr name = NULL_ZSTR; int name_len; + zend_uchar name_type; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|t", &name, &name_len, &name_type) == FAILURE) { return; } - if (PS(id)) { - RETVAL_STRING(PS(id), name ? 0 : 1); - } else { - RETVAL_EMPTY_STRING(); - } + if (name.v) { + char *old = PS(id); - if (name) { - /* PS(id) was given to retval, doesn't need to be freed */ - PS(id) = estrndup(name, name_len); + if (name_type == IS_STRING) { + PS(id) = estrndup(name.s, name_len); + } else { + /* IS_UNICODE */ + char *id = NULL; + int id_len; + UErrorCode status = U_ZERO_ERROR; + + zend_unicode_to_string_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &id, &id_len, name.u, name_len, &status TSRMLS_CC); + + if (U_SUCCESS(status) && id) { + PS(id) = id; + } else { + if (id) { + efree(id); + } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session ID must be either binary or a unicode string made up exclusively of ASCII"); + RETURN_FALSE; + } + } + + if (old) { + RETURN_STRING(old, 0); + } else { + RETURN_EMPTY_STRING(); + } + } else if (PS(id)) { + RETURN_STRING(PS(id), 1); + } else { + RETURN_EMPTY_STRING(); } } /* }}} */ -/* {{{ proto bool session_regenerate_id([bool delete_old_session]) +/* {{{ proto bool session_regenerate_id([bool delete_old_session]) U Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session. */ static PHP_FUNCTION(session_regenerate_id) { @@ -1467,18 +1522,18 @@ static PHP_FUNCTION(session_regenerate_id) } /* }}} */ -/* {{{ proto string session_cache_limiter([string new_cache_limiter]) +/* {{{ proto string session_cache_limiter([string new_cache_limiter]) U Return the current cache limiter. If new_cache_limited is given, the current cache_limiter is replaced with new_cache_limiter */ static PHP_FUNCTION(session_cache_limiter) { char *limiter; int limiter_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &limiter, &limiter_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s&", &limiter, &limiter_len, UG(utf8_conv)) == FAILURE) { return; } - RETVAL_STRING(PS(cache_limiter), 1); + RETVAL_UTF8_STRING(PS(cache_limiter), 1); if (limiter) { zend_alter_ini_entry("session.cache_limiter", sizeof("session.cache_limiter"), limiter, limiter_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); @@ -1486,7 +1541,7 @@ static PHP_FUNCTION(session_cache_limiter) } /* }}} */ -/* {{{ proto int session_cache_expire([int new_cache_expire]) +/* {{{ proto int session_cache_expire([int new_cache_expire]) U Return the current cache expire. If new_cache_expire is given, the current cache_expire is replaced with new_cache_expire */ static PHP_FUNCTION(session_cache_expire) { @@ -1494,7 +1549,7 @@ static PHP_FUNCTION(session_cache_expire) char *expires; int expires_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &expires, &expires_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s&", &expires, &expires_len, UG(utf8_conv)) == FAILURE) { return; } @@ -1528,7 +1583,7 @@ static void php_register_var(zval** entry TSRMLS_DC) } /* }}} */ -/* {{{ proto string session_encode(void) +/* {{{ proto string session_encode(void) U Serializes the current setup and returns the serialized representation */ static PHP_FUNCTION(session_encode) { @@ -1544,11 +1599,11 @@ static PHP_FUNCTION(session_encode) RETURN_FALSE; } - RETVAL_STRINGL(enc, len, 0); + RETVAL_UTF8_STRINGL(enc, len, ZSTR_AUTOFREE); } /* }}} */ -/* {{{ proto bool session_decode(string data) +/* {{{ proto bool session_decode(string data) U Deserializes data and reinitializes the variables */ static PHP_FUNCTION(session_decode) { @@ -1559,7 +1614,7 @@ static PHP_FUNCTION(session_decode) RETURN_FALSE; } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &str, &str_len, UG(utf8_conv)) == FAILURE) { return; } @@ -1569,7 +1624,7 @@ static PHP_FUNCTION(session_decode) } /* }}} */ -/* {{{ proto bool session_start(void) +/* {{{ proto bool session_start(void) U Begin session - reinitializes freezed variables, registers browsers etc */ static PHP_FUNCTION(session_start) { @@ -1579,7 +1634,7 @@ static PHP_FUNCTION(session_start) } /* }}} */ -/* {{{ proto bool session_destroy(void) +/* {{{ proto bool session_destroy(void) U Destroy the current session and all data associated with it */ static PHP_FUNCTION(session_destroy) { @@ -1592,7 +1647,7 @@ static PHP_FUNCTION(session_destroy) /* }}} */ -/* {{{ proto void session_unset(void) +/* {{{ proto void session_unset(void) U Unset all registered variables */ static PHP_FUNCTION(session_unset) { @@ -1609,7 +1664,7 @@ static PHP_FUNCTION(session_unset) } /* }}} */ -/* {{{ proto void session_write_close(void) +/* {{{ proto void session_write_close(void) U Write session data and end session */ static PHP_FUNCTION(session_write_close) { diff --git a/ext/session/tests/001.phpt b/ext/session/tests/001.phpt index 8dfd6be9a6..17703055ef 100644 --- a/ext/session/tests/001.phpt +++ b/ext/session/tests/001.phpt @@ -30,3 +30,6 @@ session_destroy(); ?> --EXPECT-- string(126) "baz|O:3:"foo":2:{S:3:"bar";S:2:"ok";S:3:"yes";S:4:"done";}arr|a:1:{i:3;O:3:"foo":2:{S:3:"bar";S:2:"ok";S:3:"yes";S:4:"done";}}" +--UEXPECT-- +unicode(126) "baz|O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";U:4:"done";}arr|a:1:{i:3;O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";U:4:"done";}}" + diff --git a/ext/session/tests/003.phpt b/ext/session/tests/003.phpt index 6fccc70426..94008257e6 100644 --- a/ext/session/tests/003.phpt +++ b/ext/session/tests/003.phpt @@ -18,7 +18,11 @@ class foo { session_id("abtest"); session_start(); -session_decode('baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'); +if (ini_get("unicode.semantics")) { + session_decode('baz|O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:1;}}'); +} else { + session_decode('baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'); +} $baz = $_SESSION['baz']; $arr = $_SESSION['arr']; diff --git a/ext/session/tests/004.phpt b/ext/session/tests/004.phpt index 5505ffe00d..668ab715b0 100644 --- a/ext/session/tests/004.phpt +++ b/ext/session/tests/004.phpt @@ -12,7 +12,8 @@ session.serialize_handler=php error_reporting(E_ALL); class handler { - public $data = 'baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'; + public $data = 'baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'; + function open($save_path, $session_name) { print "OPEN: $session_name\n"; @@ -42,6 +43,14 @@ class handler { } function gc() { return true; } + + function __construct() + { + if (ini_get("unicode.semantics")) { + /* Setup proper deserialization data for unicode.semantics mode */ + $this->data = str_replace('s:', 'U:', $this->data); + } + } } $hnd = new handler; @@ -55,6 +64,7 @@ session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, session_id("abtest"); session_start(); + $baz = $_SESSION['baz']; $arr = $_SESSION['arr']; $baz->method(); @@ -110,3 +120,40 @@ array(1) { } } DESTROY: abtest +--UEXPECTF-- +OPEN: PHPSESSID +READ: abtest +object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(2) +} +array(1) { + [3]=> + object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(2) + } +} +WRITE: abtest, baz|O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:2;}} +OPEN: PHPSESSID +READ: abtest +object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(2) +} +array(1) { + [3]=> + object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(2) + } +} +DESTROY: abtest diff --git a/ext/session/tests/005.phpt b/ext/session/tests/005.phpt index 9b8d5e3eb2..fa1ecf45d8 100644 --- a/ext/session/tests/005.phpt +++ b/ext/session/tests/005.phpt @@ -13,7 +13,8 @@ session.serialize_handler=php error_reporting(E_ALL); class handler { - public $data = 'baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'; + public $data = 'baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'; + function open($save_path, $session_name) { print "OPEN: $session_name\n"; @@ -33,7 +34,7 @@ class handler { function write($key, $val) { print "WRITE: $key, $val\n"; - $GLOBALS["hnd"]->data = $val; + $GLOBALS["hnd"]->data = $val; return true; } @@ -44,6 +45,13 @@ class handler { } function gc() { return true; } + + function __construct() + { + if (ini_get("unicode.semantics")) { + $this->data = str_replace('s:', 'U:', $this->data); + } + } } $hnd = new handler; @@ -149,3 +157,64 @@ array(1) { int(123) DESTROY: abtest CLOSE +--UEXPECTF-- +OPEN: PHPSESSID +READ: abtest +object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(2) +} +array(1) { + [3]=> + object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(2) + } +} +WRITE: abtest, baz|O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:2;}} +CLOSE +OPEN: PHPSESSID +READ: abtest +object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(3) +} +array(1) { + [3]=> + object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(3) + } +} +int(123) +WRITE: abtest, baz|O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:3;}arr|a:1:{i:3;O:3:"foo":2:{U:3:"bar";U:2:"ok";U:3:"yes";i:3;}}c|i:123; +CLOSE +OPEN: PHPSESSID +READ: abtest +object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(3) +} +array(1) { + [3]=> + object(foo)#%d (2) { + [u"bar"]=> + unicode(2) "ok" + [u"yes"]=> + int(3) + } +} +int(123) +DESTROY: abtest +CLOSE +