]> granicus.if.org Git - php/commitdiff
Unicode Updates
authorSara Golemon <pollita@php.net>
Fri, 5 Jan 2007 02:07:59 +0000 (02:07 +0000)
committerSara Golemon <pollita@php.net>
Fri, 5 Jan 2007 02:07:59 +0000 (02:07 +0000)
ext/session/mod_files.c
ext/session/mod_user.c
ext/session/php_session.h
ext/session/session.c
ext/session/tests/001.phpt
ext/session/tests/003.phpt
ext/session/tests/004.phpt
ext/session/tests/005.phpt

index bef732012152100a6864e07e6f88435c64a0daa9..a78fe72d80eea4d86209103cf09ea7a54d0977de 100644 (file)
@@ -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;
 }
index 8b39c21fb3ff0c0058562e2b84306a313a3a80e4..afe3280673f49589e710d2b9b968ff1171bdb476 100644 (file)
@@ -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);
        }
 
index 989740f1fe91b962bd38068cfebf4545d365a41c..3ef050210586b5a960ce677d42df46bceabd7164 100644 (file)
@@ -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);
index 782758339f1aca6afa970a1b80cb1231a40cc7fa..55d27f68b61ad7f776ca86583dc1f2bee24c7c2d 100644 (file)
@@ -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(&current, (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, &current, sizeof(zval *), NULL);
+                       } else {
+                               zval_ptr_dtor(&current);
                        }
-                       zval_ptr_dtor(&current);
                }
+
                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(&current, (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, &current, sizeof(zval *), NULL);
+                       } else {
+                               zval_ptr_dtor(&current);
                        }
-                       zval_ptr_dtor(&current);
                }
                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)
 {
index 8dfd6be9a618ab4aed156342dc53f1cb738be699..17703055ef9a3ec3d71fcb2b730ef7bda62cd7b4 100644 (file)
@@ -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";}}"
+
index 6fccc704267c7e44681faa39227b36cd7c3e61d9..94008257e64f7b043920045f7ed0faf34c276ac9 100644 (file)
@@ -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'];
 
index 5505ffe00d6749b45daae3e3df4410d800e425c4..668ab715b011bcef3d1680428d40851e5853f5e1 100644 (file)
@@ -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
index 9b8d5e3eb28c0dfb6de177dda559da7ee4ae1479..fa1ecf45d82e6c3a138ad5f85cedbdb47556c758 100644 (file)
@@ -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
+