From 59cf3a2404dc5d678ee16249764b7effd6ecd485 Mon Sep 17 00:00:00 2001 From: Leigh Date: Fri, 15 Jun 2012 15:06:47 +0100 Subject: [PATCH 01/27] Add create_sid to session_set_save_handler and SessionHandler A lot of code already existed to allow a custom create_sid handler, but lacked a specific implementation. Therefore I have added a 7th (optional) argument session_set_save_handler, to allow a user function to be supplied for session id generation. If a create_sid function is not supplied, the default function is called in its absence to preserve backwards compatibility. Likewise create_sid only added to SessionHandler class, and not the interface to maintain backwards compatibility. If the result is not overridden, the default is called. --- ext/session/mod_user.c | 35 ++++++++++++++++++++++++++++++++++- ext/session/mod_user_class.c | 16 ++++++++++++++++ ext/session/php_session.h | 4 +++- ext/session/session.c | 29 ++++++++++++++++++----------- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c index 2ff5302f782..02b76218854 100644 --- a/ext/session/mod_user.c +++ b/ext/session/mod_user.c @@ -23,7 +23,7 @@ #include "mod_user.h" ps_module ps_mod_user = { - PS_MOD(user) + PS_MOD_SID(user) }; #define SESS_ZVAL_LONG(val, a) \ @@ -170,6 +170,39 @@ PS_GC_FUNC(user) FINISH; } +PS_CREATE_SID_FUNC(user) +{ + /* maintain backwards compatibility */ + if (PSF(create_sid) != NULL) { + zval *args[1]; + char *id = NULL; + STDVARS; + + retval = ps_call_handler(PSF(create_sid), 0, NULL TSRMLS_CC); + + if (retval) { + if (Z_TYPE_P(retval) == IS_STRING) { + id = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); + } + zval_ptr_dtor(&retval); + } + else { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "No session id returned by function"); + return NULL; + } + + if (!id) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Session id must be a string"); + return NULL; + } + + return id; + } + + /* function as defined by PS_MOD */ + return php_session_create_id(mod_data, newlen TSRMLS_CC); +} + /* * Local variables: * tab-width: 4 diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index 70d2f40df18..a996902dac5 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -142,3 +142,19 @@ PHP_METHOD(SessionHandler, gc) RETVAL_BOOL(SUCCESS == PS(default_mod)->s_gc(&PS(mod_data), maxlifetime, &nrdels TSRMLS_CC)); } /* }}} */ + +/* {{{ proto char SessionHandler::create_sid() + Wraps the old create_sid handler */ +PHP_METHOD(SessionHandler, create_sid) +{ + char *id; + + zend_parse_parameters_none(); + + id = PS(default_mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); + + RETVAL_STRING(id, 1); + efree(id); + return; +} +/* }}} */ diff --git a/ext/session/php_session.h b/ext/session/php_session.h index ba0195bec46..2a6ecf1cc87 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -138,7 +138,7 @@ typedef struct _php_ps_globals { int module_number; long cache_expire; union { - zval *names[6]; + zval *names[7]; struct { zval *ps_open; zval *ps_close; @@ -146,6 +146,7 @@ typedef struct _php_ps_globals { zval *ps_write; zval *ps_destroy; zval *ps_gc; + zval *ps_create_sid; } name; } mod_user_names; int mod_user_implemented; @@ -283,5 +284,6 @@ extern PHP_METHOD(SessionHandler, read); extern PHP_METHOD(SessionHandler, write); extern PHP_METHOD(SessionHandler, destroy); extern PHP_METHOD(SessionHandler, gc); +extern PHP_METHOD(SessionHandler, create_sid); #endif diff --git a/ext/session/session.c b/ext/session/session.c index 7a8199d8106..9026b108add 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1573,7 +1573,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, string create_sid) Sets user-level functions */ static PHP_FUNCTION(session_set_save_handler) { @@ -1585,11 +1585,7 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_FALSE; } - if (argc != 1 && argc != 2 && argc != 6) { - WRONG_PARAM_COUNT; - } - - if (argc <= 2) { + if (argc > 0 && argc <= 2) { zval *obj = NULL, *callback = NULL; zend_uint func_name_len; char *func_name; @@ -1657,6 +1653,10 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_TRUE; } + if (argc != 6 && argc != 7) { + WRONG_PARAM_COUNT; + } + if (zend_parse_parameters(argc TSRMLS_CC, "+", &args, &num_args) == FAILURE) { return; } @@ -1664,7 +1664,8 @@ static PHP_FUNCTION(session_set_save_handler) /* remove shutdown function */ remove_user_shutdown_function("session_shutdown", sizeof("session_shutdown") TSRMLS_CC); - for (i = 0; i < 6; i++) { + /* at this point argc can only be 6 or 7 */ + for (i = 0; i < argc; i++) { if (!zend_is_callable(*args[i], 0, &name TSRMLS_CC)) { efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument %d is not a valid callback", i+1); @@ -1678,7 +1679,7 @@ static PHP_FUNCTION(session_set_save_handler) zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); } - for (i = 0; i < 6; i++) { + for (i = 0; i < argc; i++) { if (PS(mod_user_names).names[i] != NULL) { zval_ptr_dtor(&PS(mod_user_names).names[i]); } @@ -1988,13 +1989,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 6) +ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 7) ZEND_ARG_INFO(0, open) ZEND_ARG_INFO(0, close) ZEND_ARG_INFO(0, read) ZEND_ARG_INFO(0, write) ZEND_ARG_INFO(0, destroy) ZEND_ARG_INFO(0, gc) + ZEND_ARG_INFO(0, create_sid) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_session_cache_limiter, 0, 0, 0) @@ -2037,6 +2039,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_session_class_gc, 0) ZEND_ARG_INFO(0, maxlifetime) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_session_class_create_sid, 0) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ session_functions[] @@ -2087,6 +2092,8 @@ static const zend_function_entry php_session_class_functions[] = { PHP_ME(SessionHandler, write, arginfo_session_class_write, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, destroy, arginfo_session_class_destroy, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, gc, arginfo_session_class_gc, ZEND_ACC_PUBLIC) +/* Added to the class but not the interface, to maintain backwards compatibility */ + PHP_ME(SessionHandler, create_sid, arginfo_session_class_create_sid, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; /* }}} */ @@ -2146,7 +2153,7 @@ static PHP_RSHUTDOWN_FUNCTION(session) /* {{{ */ php_rshutdown_session_globals(TSRMLS_C); /* this should NOT be done in php_rshutdown_session_globals() */ - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { if (PS(mod_user_names).names[i] != NULL) { zval_ptr_dtor(&PS(mod_user_names).names[i]); PS(mod_user_names).names[i] = NULL; @@ -2171,7 +2178,7 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */ ps_globals->default_mod = NULL; ps_globals->mod_user_implemented = 0; ps_globals->mod_user_is_open = 0; - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { ps_globals->mod_user_names.names[i] = NULL; } ps_globals->http_session_vars = NULL; From 6809c388b5d8bb03515f7b4ba391724f9a8df8e0 Mon Sep 17 00:00:00 2001 From: Leigh Date: Tue, 26 Jun 2012 14:57:10 +0100 Subject: [PATCH 02/27] Tests, fixes and optimisations * Amended existing tests to cater for new functionality. * Implemented fixes and optimisations recommended by NikiC * Added create_sid to the registered interface. This was breaking tests. It also now breaks BC for people implementing the interface directly instead of extending the class. --- ext/session/mod_user.h | 2 +- ext/session/mod_user_class.c | 8 ++++---- ext/session/session.c | 2 +- ext/session/tests/session_set_save_handler_class_002.phpt | 4 ++++ ext/session/tests/session_set_save_handler_iface_001.phpt | 4 ++++ 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ext/session/mod_user.h b/ext/session/mod_user.h index ea1980ab489..a25fa6d7673 100644 --- a/ext/session/mod_user.h +++ b/ext/session/mod_user.h @@ -24,6 +24,6 @@ extern ps_module ps_mod_user; #define ps_user_ptr &ps_mod_user -PS_FUNCS(user); +PS_FUNCS_SID(user); #endif diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index a996902dac5..4387bddadfc 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -149,12 +149,12 @@ PHP_METHOD(SessionHandler, create_sid) { char *id; - zend_parse_parameters_none(); + if (zend_parse_parameters_none() == FAILURE) { + return; + } id = PS(default_mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); - RETVAL_STRING(id, 1); - efree(id); - return; + RETURN_STRING(id, 0); } /* }}} */ diff --git a/ext/session/session.c b/ext/session/session.c index 9026b108add..d6ae64fbd2e 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -2079,6 +2079,7 @@ static const zend_function_entry php_session_iface_functions[] = { PHP_ABSTRACT_ME(SessionHandlerInterface, write, arginfo_session_class_write) PHP_ABSTRACT_ME(SessionHandlerInterface, destroy, arginfo_session_class_destroy) PHP_ABSTRACT_ME(SessionHandlerInterface, gc, arginfo_session_class_gc) + PHP_ABSTRACT_ME(SessionHandlerInterface, create_sid, arginfo_session_class_create_sid) { NULL, NULL, NULL } }; /* }}} */ @@ -2092,7 +2093,6 @@ static const zend_function_entry php_session_class_functions[] = { PHP_ME(SessionHandler, write, arginfo_session_class_write, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, destroy, arginfo_session_class_destroy, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, gc, arginfo_session_class_gc, ZEND_ACC_PUBLIC) -/* Added to the class but not the interface, to maintain backwards compatibility */ PHP_ME(SessionHandler, create_sid, arginfo_session_class_create_sid, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; diff --git a/ext/session/tests/session_set_save_handler_class_002.phpt b/ext/session/tests/session_set_save_handler_class_002.phpt index 6fb831f6957..4195a163a73 100644 --- a/ext/session/tests/session_set_save_handler_class_002.phpt +++ b/ext/session/tests/session_set_save_handler_class_002.phpt @@ -53,6 +53,10 @@ class MySession2 extends SessionHandler { } return true; } + + public function create_sid() { + return parent::create_sid(); + } } $handler = new MySession2; diff --git a/ext/session/tests/session_set_save_handler_iface_001.phpt b/ext/session/tests/session_set_save_handler_iface_001.phpt index 39a4b9975b5..0576341a109 100644 --- a/ext/session/tests/session_set_save_handler_iface_001.phpt +++ b/ext/session/tests/session_set_save_handler_iface_001.phpt @@ -53,6 +53,10 @@ class MySession2 implements SessionHandlerInterface { } return true; } + + public function create_sid() { + return md5(mt_rand()); + } } $handler = new MySession2; From a689fde2bf77d950901edb6be28dcfa9a8ff0b9c Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 25 Jun 2013 21:19:56 -0300 Subject: [PATCH 03/27] - BFN --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index d5e7ba298d3..116c79aa86b 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ PHP NEWS (Adam) . Fixed bug #62964 (Possible XSS on "Registered stream filters" info). (david at nnucomputerwhiz dot com) + . Fixed bug #62672 (Error on serialize of ArrayObject). + (lior dot k at zend dot com) . Fixed bug #60732 (php_error_docref links to invalid pages). (Jakub Vrana) - CLI server: From 12fdf8fb9570f1fef72be71e641441d500a33b60 Mon Sep 17 00:00:00 2001 From: Christopher Jones Date: Tue, 25 Jun 2013 17:30:21 -0700 Subject: [PATCH 04/27] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 116c79aa86b..b3ff18d0cf8 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,10 @@ PHP NEWS . Fixed bug #61387 (NULL valued anonymous column causes segfault in odbc_fetch_array). (Brandon Kirsch) +- PDO: + . Allowed PDO_OCI to compile with Oracle Database 12c client libraries. + (Chris Jones) + - Sockets: . Implemented FR #63472 (Setting SO_BINDTODEVICE with socket_set_option). (Damjan Cvetko) From 91bd2de85c368cc8d6b9d662279333a43a519778 Mon Sep 17 00:00:00 2001 From: Christopher Jones Date: Tue, 25 Jun 2013 17:31:13 -0700 Subject: [PATCH 05/27] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 18eedd3f3e6..7550fb5ed11 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,10 @@ PHP NEWS - Intl: . Fixed bug #62759: Buggy grapheme_substr() on edge case. (Stas) +- PDO: + . Allowed PDO_OCI to compile with Oracle Database 12c client libraries. + (Chris Jones) + - Sockets: . Implemented FR #63472 (Setting SO_BINDTODEVICE with socket_set_option). (Damjan Cvetko) From 42896968282a607a26e4aa152d3c8dc90dad5826 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 25 Jun 2013 21:36:50 -0300 Subject: [PATCH 06/27] - Fixed bug #62475 (variant_* functions causes crash when null given as an argument) --- ext/com_dotnet/com_variant.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index 8289322d6d1..556f356b977 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -102,8 +102,9 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep { OLECHAR *olestring; php_com_dotnet_object *obj; + zend_uchar ztype = (z == NULL ? IS_NULL : Z_TYPE_P(z)); - switch (Z_TYPE_P(z)) { + switch (ztype) { case IS_NULL: V_VT(v) = VT_NULL; break; From 12b75e3d3e67289c28cfc879716c476f0de04999 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 25 Jun 2013 21:43:23 -0300 Subject: [PATCH 07/27] - BFN --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index b3ff18d0cf8..e5819b1a70f 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS (david at nnucomputerwhiz dot com) . Fixed bug #62672 (Error on serialize of ArrayObject). (lior dot k at zend dot com) + . Fixed bug #62475 (variant_* functions causes crash when null given as an + argument). (Felipe) . Fixed bug #60732 (php_error_docref links to invalid pages). (Jakub Vrana) - CLI server: From 623386d79988d1aeea941bb463ece2c27f9ed5d0 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 25 Jun 2013 21:53:20 -0300 Subject: [PATCH 08/27] - Fixed typo on condition --- ext/curl/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 2d541403173..4b6e5e27dc6 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -958,7 +958,7 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD); #endif -#if LIBCURL_VERSION_NUM >- 0x070f04 /* Available since 7.15.4 */ +#if LIBCURL_VERSION_NUM >= 0x070f04 /* Available since 7.15.4 */ REGISTER_CURL_CONSTANT(CURLINFO_FTP_ENTRY_PATH); #endif From 6c8cef3ca49a11228d4dcd188170b943e03c3972 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Wed, 26 Jun 2013 16:17:57 +0900 Subject: [PATCH 09/27] Fixed bug #65015 (pg_send_query does not flush send buffer) patch submitted by: adam at vektah dot net --- ext/pgsql/pgsql.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index f90ba78780f..1b302668afc 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -4573,6 +4573,7 @@ PHP_FUNCTION(pg_send_query) PGconn *pgsql; PGresult *res; int leftover = 0; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &query, &len) == FAILURE) { @@ -4600,6 +4601,14 @@ PHP_FUNCTION(pg_send_query) RETURN_FALSE; } } + /* Wait to finish sending buffer */ + while ((ret = PQflush(pgsql))) { + if (ret == -1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not empty PostgreSQL send buffer"); + break; + } + usleep(10000); + } if (PQ_SETNONBLOCKING(pgsql, 0)) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode"); } @@ -4620,6 +4629,7 @@ PHP_FUNCTION(pg_send_query_params) PGconn *pgsql; PGresult *res; int leftover = 0; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa/", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) { return; @@ -4686,6 +4696,14 @@ PHP_FUNCTION(pg_send_query_params) } } _php_pgsql_free_params(params, num_params); + /* Wait to finish sending buffer */ + while ((ret = PQflush(pgsql))) { + if (ret == -1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not empty PostgreSQL send buffer"); + break; + } + usleep(10000); + } if (PQ_SETNONBLOCKING(pgsql, 0)) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode"); } @@ -4705,6 +4723,7 @@ PHP_FUNCTION(pg_send_prepare) PGconn *pgsql; PGresult *res; int leftover = 0; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) { return; @@ -4735,6 +4754,14 @@ PHP_FUNCTION(pg_send_prepare) RETURN_FALSE; } } + /* Wait to finish sending buffer */ + while ((ret = PQflush(pgsql))) { + if (ret == -1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not empty postgres send buffer"); + break; + } + usleep(10000); + } if (PQ_SETNONBLOCKING(pgsql, 0)) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode"); } @@ -4757,6 +4784,7 @@ PHP_FUNCTION(pg_send_execute) PGconn *pgsql; PGresult *res; int leftover = 0; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) { return; @@ -4823,6 +4851,14 @@ PHP_FUNCTION(pg_send_execute) } } _php_pgsql_free_params(params, num_params); + /* Wait to finish sending buffer */ + while ((ret = PQflush(pgsql))) { + if (ret == -1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not empty postgres send buffer"); + break; + } + usleep(10000); + } if (PQ_SETNONBLOCKING(pgsql, 0)) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode"); } From 8922c50ca41e94ab21b27e1b56fbe2bcbc7638ac Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Wed, 26 Jun 2013 16:31:34 +0900 Subject: [PATCH 10/27] Update NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index e5819b1a70f..0559d156fc6 100644 --- a/NEWS +++ b/NEWS @@ -85,6 +85,8 @@ PHP NEWS - pgsql: . Fixed bug #64609 (pg_convert enum type support). (Matteo) + . Fixed bug #65015 (pg_send_query does not flush send buffer) + patch submitted by: adam at vektah dot net (Yasuo) - Readline: . Implement FR #55694 (Expose additional readline variable to prevent From b34e8d2e3e892d8844cf9af7c0ce4bf3ed698fc6 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Wed, 26 Jun 2013 16:44:26 +0200 Subject: [PATCH 11/27] add new test --- .../tests/array/array_walk_closure.phpt | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 ext/standard/tests/array/array_walk_closure.phpt diff --git a/ext/standard/tests/array/array_walk_closure.phpt b/ext/standard/tests/array/array_walk_closure.phpt new file mode 100644 index 00000000000..7f6c8342e9f --- /dev/null +++ b/ext/standard/tests/array/array_walk_closure.phpt @@ -0,0 +1,251 @@ +--TEST-- +array_walk() closure tests +--FILE-- + 1, "two"=>2, "three" => 3]; +var_dump(array_walk($ar, function(){ var_dump(func_get_args());})); + +echo "\nclosure with array\n"; +$ar = ["one" => 1, "two"=>2, "three" => 3]; +$user_data = ["sum" => 42]; +$func = function($value, $key, &$udata) { + var_dump($udata); + $udata["sum"] += $value; +}; + +var_dump(array_walk($ar, $func, $user_data)); +echo "End result:"; +var_dump($user_data["sum"]); + +echo "\nclosure with use\n"; +$ar = ["one" => 1, "two"=>2, "three" => 3]; +$user_data = ["sum" => 42]; +$func = function($value, $key) use (&$user_data) { + var_dump($user_data); + $user_data["sum"] += $value; +}; + +var_dump(array_walk($ar, $func, $user_data)); +echo "End result:"; +var_dump($user_data["sum"]); + + +echo "\nclosure with object\n"; +$ar = ["one" => 1, "two"=>2, "three" => 3]; +$user_data = (object)["sum" => 42]; +$func = function($value, $key, &$udata) { + var_dump($udata); + $udata->sum += $value; +}; + +var_dump(array_walk($ar, $func, $user_data)); +echo "End result:"; +var_dump($user_data->sum); + + + +echo "\nfunction with object\n"; +function sum_it_up_object($value, $key, $udata) +{ + var_dump($udata); + $udata->sum += $value; +} + +$ar = ["one" => 1, "two"=>2, "three" => 3]; +$user_data = (object)["sum" => 42]; + +var_dump(array_walk($ar, "sum_it_up_object", $user_data)); +echo "End result:"; +var_dump($user_data->sum); + + +echo "\nfunction with array\n"; +function sum_it_up_array($value, $key, $udata) +{ + var_dump($udata); + $udata['sum'] += $value; +} + +$ar = ["one" => 1, "two"=>2, "three" => 3]; +$user_data = ["sum" => 42]; + +var_dump(array_walk($ar, "sum_it_up_array", $user_data)); +echo "End result:"; +var_dump($user_data['sum']); + +echo "\nclosure and exception\n"; +$ar = ["one" => 1, "two"=>2, "three" => 3]; +try { + var_dump(array_walk($ar, function($v, $k) { if ($v == 2) throw new Exception; } )); +} catch (Exception $e) { + var_dump($e->getTrace()); +} + + +echo "Done\n"; +?> +--EXPECTF-- +Warning: array_walk() expects at least 2 parameters, 0 given in %s on line %d +NULL + +Warning: array_walk() expects parameter 1 to be array, boolean given in %s on line %d +NULL + +Warning: array_walk() expects parameter 1 to be array, null given in %s on line %d +NULL +array(2) { + [0]=> + int(1) + [1]=> + string(3) "one" +} +array(2) { + [0]=> + int(2) + [1]=> + string(3) "two" +} +array(2) { + [0]=> + int(3) + [1]=> + string(5) "three" +} +bool(true) + +closure with array +array(1) { + ["sum"]=> + int(42) +} +array(1) { + ["sum"]=> + int(43) +} +array(1) { + ["sum"]=> + int(45) +} +bool(true) +End result:int(42) + +closure with use +array(1) { + ["sum"]=> + int(42) +} +array(1) { + ["sum"]=> + int(43) +} +array(1) { + ["sum"]=> + int(45) +} +bool(true) +End result:int(48) + +closure with object +object(stdClass)#1 (1) { + ["sum"]=> + int(42) +} +object(stdClass)#1 (1) { + ["sum"]=> + int(43) +} +object(stdClass)#1 (1) { + ["sum"]=> + int(45) +} +bool(true) +End result:int(48) + +function with object +object(stdClass)#2 (1) { + ["sum"]=> + int(42) +} +object(stdClass)#2 (1) { + ["sum"]=> + int(43) +} +object(stdClass)#2 (1) { + ["sum"]=> + int(45) +} +bool(true) +End result:int(48) + +function with array +array(1) { + ["sum"]=> + int(42) +} +array(1) { + ["sum"]=> + int(42) +} +array(1) { + ["sum"]=> + int(42) +} +bool(true) +End result:int(42) + +closure and exception +array(2) { + [0]=> + array(2) { + ["function"]=> + string(9) "{closure}" + ["args"]=> + array(2) { + [0]=> + int(2) + [1]=> + string(3) "two" + } + } + [1]=> + array(4) { + ["file"]=> + string(69) "%s" + ["line"]=> + int(%d) + ["function"]=> + string(10) "array_walk" + ["args"]=> + array(2) { + [0]=> + &array(3) { + ["one"]=> + int(1) + ["two"]=> + int(2) + ["three"]=> + int(3) + } + [1]=> + object(Closure)#2 (1) { + ["parameter"]=> + array(2) { + ["$v"]=> + string(10) "" + ["$k"]=> + string(10) "" + } + } + } + } +} +Done \ No newline at end of file From f477ad22c2c23a1237dcd3a2c67165b838315241 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 26 Jun 2013 13:36:36 -0300 Subject: [PATCH 12/27] - Fixed test --- ext/standard/tests/array/array_walk_closure.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/array/array_walk_closure.phpt b/ext/standard/tests/array/array_walk_closure.phpt index 7f6c8342e9f..4e22bb89464 100644 --- a/ext/standard/tests/array/array_walk_closure.phpt +++ b/ext/standard/tests/array/array_walk_closure.phpt @@ -219,7 +219,7 @@ array(2) { [1]=> array(4) { ["file"]=> - string(69) "%s" + string(%d) "%s" ["line"]=> int(%d) ["function"]=> @@ -248,4 +248,4 @@ array(2) { } } } -Done \ No newline at end of file +Done From 7e33b5d2fa89a6bf167fc4061dcf6aedab1cc6b8 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 26 Jun 2013 13:50:37 -0300 Subject: [PATCH 13/27] - Fixed bug #63409 (php-dba function test fails on big-endian machine) patch by: tianhonglouis at gmail dot com --- ext/dba/tests/bug38698.phpt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ext/dba/tests/bug38698.phpt b/ext/dba/tests/bug38698.phpt index 56dde852688..1d1ed674fef 100644 --- a/ext/dba/tests/bug38698.phpt +++ b/ext/dba/tests/bug38698.phpt @@ -8,10 +8,18 @@ Bug #38698 (Bug #38698 for some keys cdbmake creates corrupted db and cdb can't --FILE-- Date: Wed, 26 Jun 2013 15:06:27 -0300 Subject: [PATCH 14/27] - Fixed bug #63983 (enabling FPM borks compile on FreeBSD) patch by: chibisuke at web dot de --- sapi/fpm/fpm/fpm_sockets.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c index f959cf36d87..145b2550c3b 100644 --- a/sapi/fpm/fpm/fpm_sockets.c +++ b/sapi/fpm/fpm/fpm_sockets.c @@ -405,7 +405,19 @@ int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq) zlog(ZLOG_SYSERROR, "failed to retrieve TCP_INFO for socket"); return -1; } +#if defined(__FreeBSD__) + if (info.__tcpi_sacked == 0) { + return -1; + } + if (cur_lq) { + *cur_lq = info.__tcpi_unacked; + } + + if (max_lq) { + *max_lq = info.__tcpi_sacked; + } +#else /* kernel >= 2.6.24 return non-zero here, that means operation is supported */ if (info.tcpi_sacked == 0) { return -1; @@ -418,6 +430,7 @@ int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq) if (max_lq) { *max_lq = info.tcpi_sacked; } +#endif return 0; } From 891bd46f3d0130abea2513868699b5efaa7e1a29 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 26 Jun 2013 15:08:33 -0300 Subject: [PATCH 15/27] - BFN --- NEWS | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 0559d156fc6..48dcda88c75 100644 --- a/NEWS +++ b/NEWS @@ -7,10 +7,11 @@ PHP NEWS (David Soria Parra, Laruence) . Fixed bug #65088 (Generated configure script is malformed on OpenBSD). (Adam) + . Fixed bug #63983 (enabling FPM borks compile on FreeBSD). + (chibisuke at web dot de, Felipe) . Fixed bug #62964 (Possible XSS on "Registered stream filters" info). (david at nnucomputerwhiz dot com) - . Fixed bug #62672 (Error on serialize of ArrayObject). - (lior dot k at zend dot com) + . Fixed bug #62672 (Error on serialize of ArrayObject). (Lior Kaplan) . Fixed bug #62475 (variant_* functions causes crash when null given as an argument). (Felipe) . Fixed bug #60732 (php_error_docref links to invalid pages). (Jakub Vrana) From 02682f4169f8f61f0f72e302b5d9271ba6491c36 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 26 Jun 2013 15:15:37 -0300 Subject: [PATCH 16/27] - Reclassify bug --- NEWS | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 48dcda88c75..62fb5004951 100644 --- a/NEWS +++ b/NEWS @@ -7,8 +7,6 @@ PHP NEWS (David Soria Parra, Laruence) . Fixed bug #65088 (Generated configure script is malformed on OpenBSD). (Adam) - . Fixed bug #63983 (enabling FPM borks compile on FreeBSD). - (chibisuke at web dot de, Felipe) . Fixed bug #62964 (Possible XSS on "Registered stream filters" info). (david at nnucomputerwhiz dot com) . Fixed bug #62672 (Error on serialize of ArrayObject). (Lior Kaplan) @@ -19,6 +17,10 @@ PHP NEWS - CLI server: . Fixed bug #65066 (Cli server not responsive when responding with 422 http status code). (Adam) + +- FPM: + . Fixed bug #63983 (enabling FPM borks compile on FreeBSD). + (chibisuke at web dot de, Felipe) - Intl: . Fixed bug #62759: Buggy grapheme_substr() on edge case. (Stas) From 60dcc5851f0dd7cf387270d6ba243f9ac46bc396 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 26 Jun 2013 19:15:19 -0300 Subject: [PATCH 17/27] - Fixed bug #64467 (Segmentation fault after imap_reopen failure) patch by: askalski at gmail dot com --- ext/imap/php_imap.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c index b154cb86b04..d697fa79116 100644 --- a/ext/imap/php_imap.c +++ b/ext/imap/php_imap.c @@ -1270,7 +1270,6 @@ PHP_FUNCTION(imap_reopen) int mailbox_len; long options = 0, retries = 0; pils *imap_le_struct; - MAILSTREAM *imap_stream; long flags=NIL; long cl_flags=NIL; @@ -1298,12 +1297,12 @@ PHP_FUNCTION(imap_reopen) RETURN_FALSE; } - imap_stream = mail_open(imap_le_struct->imap_stream, mailbox, flags); - if (imap_stream == NIL) { + imap_le_struct->imap_stream = mail_open(imap_le_struct->imap_stream, mailbox, flags); + if (imap_le_struct->imap_stream == NIL) { + zend_list_delete(Z_RESVAL_P(streamind)); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't re-open stream"); RETURN_FALSE; } - imap_le_struct->imap_stream = imap_stream; RETURN_TRUE; } /* }}} */ From 76866e0a2e5e8175621edfce9b4c091d3007d42a Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 26 Jun 2013 19:16:13 -0300 Subject: [PATCH 18/27] - BFN --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 62fb5004951..c7e4c580f0e 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ PHP NEWS - FPM: . Fixed bug #63983 (enabling FPM borks compile on FreeBSD). (chibisuke at web dot de, Felipe) + +- Imap: + . Fixed bug #64467 (Segmentation fault after imap_reopen failure). + (askalski at gmail dot com) - Intl: . Fixed bug #62759: Buggy grapheme_substr() on edge case. (Stas) From fa8611c81ee72839cdff3e72b18cc586feb4aa29 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 27 Jun 2013 12:37:57 +0800 Subject: [PATCH 19/27] Fixed bug #65136 (RecursiveDirectoryIterator segfault) --- NEWS | 1 + ext/spl/spl_directory.c | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index c7e4c580f0e..a4295e8c526 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,7 @@ PHP NEWS (Damjan Cvetko) - SPL: + . Fixed bug #65136 (RecursiveDirectoryIterator segfault). (Laruence) . Fixed bug #61828 (Memleak when calling Directory(Recursive)Iterator /Spl(Temp)FileObject ctor twice). (Laruence) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 056e7e4f103..7f0ce631b10 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1510,7 +1510,7 @@ SPL_METHOD(RecursiveDirectoryIterator, hasChildren) Returns an iterator for the current entry if it is a directory */ SPL_METHOD(RecursiveDirectoryIterator, getChildren) { - zval zpath, zflags; + zval *zpath, *zflags; spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); spl_filesystem_object *subdir; char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; @@ -1524,11 +1524,13 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren) if (SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) { RETURN_STRINGL(intern->file_name, intern->file_name_len, 1); } else { - INIT_PZVAL(&zflags); - INIT_PZVAL(&zpath); - ZVAL_LONG(&zflags, intern->flags); - ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len, 0); - spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, &zpath, &zflags TSRMLS_CC); + MAKE_STD_ZVAL(zflags); + MAKE_STD_ZVAL(zpath); + ZVAL_LONG(zflags, intern->flags); + ZVAL_STRINGL(zpath, intern->file_name, intern->file_name_len, 1); + spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, zpath, zflags TSRMLS_CC); + zval_ptr_dtor(&zpath); + zval_ptr_dtor(&zflags); subdir = (spl_filesystem_object*)zend_object_store_get_object(return_value TSRMLS_CC); if (subdir) { From 60bbc78bde18d2d21cd4c0eaf86d348368c8aca9 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 27 Jun 2013 12:38:35 +0800 Subject: [PATCH 20/27] Update NEWS:w --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 7550fb5ed11..9cdd3e2f3e6 100644 --- a/NEWS +++ b/NEWS @@ -36,6 +36,7 @@ PHP NEWS (Damjan Cvetko) - SPL: + . Fixed bug #65136 (RecursiveDirectoryIterator segfault). (Laruence) . Fixed bug #61828 (Memleak when calling Directory(Recursive)Iterator /Spl(Temp)FileObject ctor twice). (Laruence) From 1e836cdd64dc715e855286b22f02316a4ecf5be7 Mon Sep 17 00:00:00 2001 From: Arpad Ray Date: Thu, 27 Jun 2013 12:33:56 +0100 Subject: [PATCH 21/27] BC fix for PR 109 merge - create_sid() method in SessionHandler Creates a new SessionIdInterface and moves create_sid() into it, so existing handlers implementing SessionHandlerInterface don't require create_sid(). SessionHandler still includes the method so the default mod can be called, but now implements both interfaces. Also added several more tests for this feature. --- ext/session/php_session.h | 3 + ext/session/session.c | 53 +++++++++-- .../session_set_save_handler_class_002.phpt | 4 - .../session_set_save_handler_class_016.phpt | 90 +++++++++++++++++++ .../session_set_save_handler_class_017.phpt | 90 +++++++++++++++++++ .../session_set_save_handler_iface_001.phpt | 4 - .../session_set_save_handler_iface_003.phpt | 90 +++++++++++++++++++ .../session_set_save_handler_sid_001.phpt | 85 ++++++++++++++++++ .../session_set_save_handler_sid_002.phpt | 77 ++++++++++++++++ 9 files changed, 480 insertions(+), 16 deletions(-) create mode 100644 ext/session/tests/session_set_save_handler_class_016.phpt create mode 100644 ext/session/tests/session_set_save_handler_class_017.phpt create mode 100644 ext/session/tests/session_set_save_handler_iface_003.phpt create mode 100644 ext/session/tests/session_set_save_handler_sid_001.phpt create mode 100644 ext/session/tests/session_set_save_handler_sid_002.phpt diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 210043582d9..1dd5b1a1a61 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -278,6 +278,9 @@ extern zend_class_entry *php_session_class_entry; #define PS_IFACE_NAME "SessionHandlerInterface" extern zend_class_entry *php_session_iface_entry; +#define PS_SID_IFACE_NAME "SessionIdInterface" +extern zend_class_entry *php_session_id_iface_entry; + extern PHP_METHOD(SessionHandler, open); extern PHP_METHOD(SessionHandler, close); extern PHP_METHOD(SessionHandler, read); diff --git a/ext/session/session.c b/ext/session/session.c index d8de5769fc1..78ecd8201c6 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -70,6 +70,9 @@ zend_class_entry *php_session_class_entry; /* SessionHandlerInterface */ zend_class_entry *php_session_iface_entry; +/* SessionIdInterface */ +zend_class_entry *php_session_id_iface_entry; + /* *********** * Helpers * *********** */ @@ -1603,11 +1606,11 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_FALSE; } - /* Find implemented methods */ - zend_hash_internal_pointer_reset_ex(&php_session_class_entry->function_table, &pos); + /* Find implemented methods - SessionHandlerInterface */ + zend_hash_internal_pointer_reset_ex(&php_session_iface_entry->function_table, &pos); i = 0; - while (zend_hash_get_current_data_ex(&php_session_class_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) { - zend_hash_get_current_key_ex(&php_session_class_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos); + while (zend_hash_get_current_data_ex(&php_session_iface_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) { + zend_hash_get_current_key_ex(&php_session_iface_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos); if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)¤t_mptr) == SUCCESS) { if (PS(mod_user_names).names[i] != NULL) { @@ -1625,7 +1628,29 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_FALSE; } - zend_hash_move_forward_ex(&php_session_class_entry->function_table, &pos); + zend_hash_move_forward_ex(&php_session_iface_entry->function_table, &pos); + ++i; + } + + /* Find implemented methods - SessionIdInterface (optional) */ + zend_hash_internal_pointer_reset_ex(&php_session_id_iface_entry->function_table, &pos); + while (zend_hash_get_current_data_ex(&php_session_id_iface_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) { + zend_hash_get_current_key_ex(&php_session_id_iface_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos); + + if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)¤t_mptr) == SUCCESS) { + if (PS(mod_user_names).names[i] != NULL) { + zval_ptr_dtor(&PS(mod_user_names).names[i]); + } + + MAKE_STD_ZVAL(callback); + array_init_size(callback, 2); + Z_ADDREF_P(obj); + add_next_index_zval(callback, obj); + add_next_index_stringl(callback, func_name, func_name_len - 1, 1); + PS(mod_user_names).names[i] = callback; + } + + zend_hash_move_forward_ex(&php_session_id_iface_entry->function_table, &pos); ++i; } @@ -1993,7 +2018,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 7) +ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 1) ZEND_ARG_INFO(0, open) ZEND_ARG_INFO(0, close) ZEND_ARG_INFO(0, read) @@ -2083,7 +2108,14 @@ static const zend_function_entry php_session_iface_functions[] = { PHP_ABSTRACT_ME(SessionHandlerInterface, write, arginfo_session_class_write) PHP_ABSTRACT_ME(SessionHandlerInterface, destroy, arginfo_session_class_destroy) PHP_ABSTRACT_ME(SessionHandlerInterface, gc, arginfo_session_class_gc) - PHP_ABSTRACT_ME(SessionHandlerInterface, create_sid, arginfo_session_class_create_sid) + { NULL, NULL, NULL } +}; +/* }}} */ + +/* {{{ SessionIdInterface functions[] +*/ +static const zend_function_entry php_session_id_iface_functions[] = { + PHP_ABSTRACT_ME(SessionIdInterface, create_sid, arginfo_session_class_create_sid) { NULL, NULL, NULL } }; /* }}} */ @@ -2206,15 +2238,20 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */ php_session_rfc1867_orig_callback = php_rfc1867_callback; php_rfc1867_callback = php_session_rfc1867_callback; - /* Register interface */ + /* Register interfaces */ INIT_CLASS_ENTRY(ce, PS_IFACE_NAME, php_session_iface_functions); php_session_iface_entry = zend_register_internal_class(&ce TSRMLS_CC); php_session_iface_entry->ce_flags |= ZEND_ACC_INTERFACE; + INIT_CLASS_ENTRY(ce, PS_SID_IFACE_NAME, php_session_id_iface_functions); + php_session_id_iface_entry = zend_register_internal_class(&ce TSRMLS_CC); + php_session_id_iface_entry->ce_flags |= ZEND_ACC_INTERFACE; + /* Register base class */ INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions); php_session_class_entry = zend_register_internal_class(&ce TSRMLS_CC); zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_iface_entry); + zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_id_iface_entry); REGISTER_LONG_CONSTANT("PHP_SESSION_DISABLED", php_session_disabled, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_SESSION_NONE", php_session_none, CONST_CS | CONST_PERSISTENT); diff --git a/ext/session/tests/session_set_save_handler_class_002.phpt b/ext/session/tests/session_set_save_handler_class_002.phpt index 4195a163a73..6fb831f6957 100644 --- a/ext/session/tests/session_set_save_handler_class_002.phpt +++ b/ext/session/tests/session_set_save_handler_class_002.phpt @@ -53,10 +53,6 @@ class MySession2 extends SessionHandler { } return true; } - - public function create_sid() { - return parent::create_sid(); - } } $handler = new MySession2; diff --git a/ext/session/tests/session_set_save_handler_class_016.phpt b/ext/session/tests/session_set_save_handler_class_016.phpt new file mode 100644 index 00000000000..2de03c0682e --- /dev/null +++ b/ext/session/tests/session_set_save_handler_class_016.phpt @@ -0,0 +1,90 @@ +--TEST-- +Test session_set_save_handler() function: class with create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return parent::create_sid(); + } +} + +$handler = new MySession2; +session_set_save_handler($handler); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: class with create_sid *** +string(%d) "%s" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_class_017.phpt b/ext/session/tests/session_set_save_handler_class_017.phpt new file mode 100644 index 00000000000..756dc55d030 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_class_017.phpt @@ -0,0 +1,90 @@ +--TEST-- +Test session_set_save_handler() function: class with create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return 'my_sid'; + } +} + +$handler = new MySession2; +session_set_save_handler($handler); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: class with create_sid *** +string(%d) "my_sid" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_iface_001.phpt b/ext/session/tests/session_set_save_handler_iface_001.phpt index 0576341a109..39a4b9975b5 100644 --- a/ext/session/tests/session_set_save_handler_iface_001.phpt +++ b/ext/session/tests/session_set_save_handler_iface_001.phpt @@ -53,10 +53,6 @@ class MySession2 implements SessionHandlerInterface { } return true; } - - public function create_sid() { - return md5(mt_rand()); - } } $handler = new MySession2; diff --git a/ext/session/tests/session_set_save_handler_iface_003.phpt b/ext/session/tests/session_set_save_handler_iface_003.phpt new file mode 100644 index 00000000000..bd757dce630 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_iface_003.phpt @@ -0,0 +1,90 @@ +--TEST-- +Test session_set_save_handler() function: id interface +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return 'my_sid'; + } +} + +$handler = new MySession2; +session_set_save_handler($handler); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: id interface *** +string(%d) "my_sid" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_sid_001.phpt b/ext/session/tests/session_set_save_handler_sid_001.phpt new file mode 100644 index 00000000000..0dc4fc11cf0 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_sid_001.phpt @@ -0,0 +1,85 @@ +--TEST-- +Test session_set_save_handler() function: create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return 'my_sid'; + } +} + +$handler = new MySession2; +session_set_save_handler(array($handler, 'open'), array($handler, 'close'), + array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'), array($handler, 'create_sid')); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: create_sid *** +string(%d) "my_sid" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_sid_002.phpt b/ext/session/tests/session_set_save_handler_sid_002.phpt new file mode 100644 index 00000000000..f9a72aebcaf --- /dev/null +++ b/ext/session/tests/session_set_save_handler_sid_002.phpt @@ -0,0 +1,77 @@ +--TEST-- +Test session_set_save_handler() function: create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return null; + } +} + +$handler = new MySession2; +session_set_save_handler(array($handler, 'open'), array($handler, 'close'), + array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'), array($handler, 'create_sid')); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: create_sid *** + +Fatal error: session_start(): Session id must be a string in %s on line %d From 41565a239f8138d750b5bab2a7267111ebcbb0bb Mon Sep 17 00:00:00 2001 From: Arpad Ray Date: Thu, 27 Jun 2013 12:49:16 +0100 Subject: [PATCH 22/27] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 9cdd3e2f3e6..dca43ccf074 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ PHP NEWS . Allowed PDO_OCI to compile with Oracle Database 12c client libraries. (Chris Jones) +- Session: + . Added optional create_sid() argument to session_set_save_handler(), + SessionHandler and new SessionIdInterface. (Leigh, Arpad) + - Sockets: . Implemented FR #63472 (Setting SO_BINDTODEVICE with socket_set_option). (Damjan Cvetko) From eb190bb57158e13a6ddcf8da0da7f7c79b52f2be Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 27 Jun 2013 14:00:56 +0200 Subject: [PATCH 23/27] Fixed symbol export That's needed for baabd1192973156ac79c35f6d1b0dced4af8e8fb to link properly. --- ext/pdo/pdo_dbh.c | 2 +- ext/pdo/php_pdo_error.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 25db6842f62..833c608f668 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -101,7 +101,7 @@ void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate } /* }}} */ -void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ +PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ { pdo_error_type *pdo_err = &dbh->error_code; const char *msg = "<>"; diff --git a/ext/pdo/php_pdo_error.h b/ext/pdo/php_pdo_error.h index 13d45ebcfe1..387436af8fd 100644 --- a/ext/pdo/php_pdo_error.h +++ b/ext/pdo/php_pdo_error.h @@ -23,7 +23,7 @@ #include "php_pdo_driver.h" -extern void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC); +PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC); #define PDO_DBH_CLEAR_ERR() do { \ strlcpy(dbh->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE)); \ From 074c26a68b9484cd51734a70bb91b8afb585c212 Mon Sep 17 00:00:00 2001 From: Leigh Date: Fri, 15 Jun 2012 15:06:47 +0100 Subject: [PATCH 24/27] Add create_sid to session_set_save_handler and SessionHandler A lot of code already existed to allow a custom create_sid handler, but lacked a specific implementation. Therefore I have added a 7th (optional) argument session_set_save_handler, to allow a user function to be supplied for session id generation. If a create_sid function is not supplied, the default function is called in its absence to preserve backwards compatibility. Likewise create_sid only added to SessionHandler class, and not the interface to maintain backwards compatibility. If the result is not overridden, the default is called. --- ext/session/mod_user.c | 35 ++++++++++++++++++++++++++++++++++- ext/session/mod_user_class.c | 16 ++++++++++++++++ ext/session/php_session.h | 4 +++- ext/session/session.c | 29 ++++++++++++++++++----------- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c index 57d7bd0edcd..e4261df2949 100644 --- a/ext/session/mod_user.c +++ b/ext/session/mod_user.c @@ -23,7 +23,7 @@ #include "mod_user.h" ps_module ps_mod_user = { - PS_MOD(user) + PS_MOD_SID(user) }; #define SESS_ZVAL_LONG(val, a) \ @@ -183,6 +183,39 @@ PS_GC_FUNC(user) FINISH; } +PS_CREATE_SID_FUNC(user) +{ + /* maintain backwards compatibility */ + if (PSF(create_sid) != NULL) { + zval *args[1]; + char *id = NULL; + STDVARS; + + retval = ps_call_handler(PSF(create_sid), 0, NULL TSRMLS_CC); + + if (retval) { + if (Z_TYPE_P(retval) == IS_STRING) { + id = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); + } + zval_ptr_dtor(&retval); + } + else { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "No session id returned by function"); + return NULL; + } + + if (!id) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Session id must be a string"); + return NULL; + } + + return id; + } + + /* function as defined by PS_MOD */ + return php_session_create_id(mod_data, newlen TSRMLS_CC); +} + /* * Local variables: * tab-width: 4 diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index 1ed1e7bbd50..340c2ca97ac 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -141,3 +141,19 @@ PHP_METHOD(SessionHandler, gc) RETVAL_BOOL(SUCCESS == PS(default_mod)->s_gc(&PS(mod_data), maxlifetime, &nrdels TSRMLS_CC)); } /* }}} */ + +/* {{{ proto char SessionHandler::create_sid() + Wraps the old create_sid handler */ +PHP_METHOD(SessionHandler, create_sid) +{ + char *id; + + zend_parse_parameters_none(); + + id = PS(default_mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); + + RETVAL_STRING(id, 1); + efree(id); + return; +} +/* }}} */ diff --git a/ext/session/php_session.h b/ext/session/php_session.h index adc5e70402c..210043582d9 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -138,7 +138,7 @@ typedef struct _php_ps_globals { int module_number; long cache_expire; union { - zval *names[6]; + zval *names[7]; struct { zval *ps_open; zval *ps_close; @@ -146,6 +146,7 @@ typedef struct _php_ps_globals { zval *ps_write; zval *ps_destroy; zval *ps_gc; + zval *ps_create_sid; } name; } mod_user_names; int mod_user_implemented; @@ -283,5 +284,6 @@ extern PHP_METHOD(SessionHandler, read); extern PHP_METHOD(SessionHandler, write); extern PHP_METHOD(SessionHandler, destroy); extern PHP_METHOD(SessionHandler, gc); +extern PHP_METHOD(SessionHandler, create_sid); #endif diff --git a/ext/session/session.c b/ext/session/session.c index 5e0565253f0..4b93ffa74ae 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1577,7 +1577,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, string create_sid) Sets user-level functions */ static PHP_FUNCTION(session_set_save_handler) { @@ -1589,11 +1589,7 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_FALSE; } - if (argc != 1 && argc != 2 && argc != 6) { - WRONG_PARAM_COUNT; - } - - if (argc <= 2) { + if (argc > 0 && argc <= 2) { zval *obj = NULL, *callback = NULL; zend_uint func_name_len; char *func_name; @@ -1661,6 +1657,10 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_TRUE; } + if (argc != 6 && argc != 7) { + WRONG_PARAM_COUNT; + } + if (zend_parse_parameters(argc TSRMLS_CC, "+", &args, &num_args) == FAILURE) { return; } @@ -1668,7 +1668,8 @@ static PHP_FUNCTION(session_set_save_handler) /* remove shutdown function */ remove_user_shutdown_function("session_shutdown", sizeof("session_shutdown") TSRMLS_CC); - for (i = 0; i < 6; i++) { + /* at this point argc can only be 6 or 7 */ + for (i = 0; i < argc; i++) { if (!zend_is_callable(*args[i], 0, &name TSRMLS_CC)) { efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument %d is not a valid callback", i+1); @@ -1682,7 +1683,7 @@ static PHP_FUNCTION(session_set_save_handler) zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); } - for (i = 0; i < 6; i++) { + for (i = 0; i < argc; i++) { if (PS(mod_user_names).names[i] != NULL) { zval_ptr_dtor(&PS(mod_user_names).names[i]); } @@ -1992,13 +1993,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 6) +ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 7) ZEND_ARG_INFO(0, open) ZEND_ARG_INFO(0, close) ZEND_ARG_INFO(0, read) ZEND_ARG_INFO(0, write) ZEND_ARG_INFO(0, destroy) ZEND_ARG_INFO(0, gc) + ZEND_ARG_INFO(0, create_sid) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_session_cache_limiter, 0, 0, 0) @@ -2041,6 +2043,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_session_class_gc, 0) ZEND_ARG_INFO(0, maxlifetime) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_session_class_create_sid, 0) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ session_functions[] @@ -2091,6 +2096,8 @@ static const zend_function_entry php_session_class_functions[] = { PHP_ME(SessionHandler, write, arginfo_session_class_write, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, destroy, arginfo_session_class_destroy, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, gc, arginfo_session_class_gc, ZEND_ACC_PUBLIC) +/* Added to the class but not the interface, to maintain backwards compatibility */ + PHP_ME(SessionHandler, create_sid, arginfo_session_class_create_sid, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; /* }}} */ @@ -2150,7 +2157,7 @@ static PHP_RSHUTDOWN_FUNCTION(session) /* {{{ */ php_rshutdown_session_globals(TSRMLS_C); /* this should NOT be done in php_rshutdown_session_globals() */ - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { if (PS(mod_user_names).names[i] != NULL) { zval_ptr_dtor(&PS(mod_user_names).names[i]); PS(mod_user_names).names[i] = NULL; @@ -2175,7 +2182,7 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */ ps_globals->default_mod = NULL; ps_globals->mod_user_implemented = 0; ps_globals->mod_user_is_open = 0; - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { ps_globals->mod_user_names.names[i] = NULL; } ps_globals->http_session_vars = NULL; From b794cce4fd4a6158002f3e8a814a30891cefbcde Mon Sep 17 00:00:00 2001 From: Leigh Date: Tue, 26 Jun 2012 14:57:10 +0100 Subject: [PATCH 25/27] Tests, fixes and optimisations * Amended existing tests to cater for new functionality. * Implemented fixes and optimisations recommended by NikiC * Added create_sid to the registered interface. This was breaking tests. It also now breaks BC for people implementing the interface directly instead of extending the class. --- ext/session/mod_user.h | 2 +- ext/session/mod_user_class.c | 8 ++++---- ext/session/session.c | 2 +- ext/session/tests/session_set_save_handler_class_002.phpt | 4 ++++ ext/session/tests/session_set_save_handler_iface_001.phpt | 4 ++++ 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ext/session/mod_user.h b/ext/session/mod_user.h index fd149ccff44..6b2998c4264 100644 --- a/ext/session/mod_user.h +++ b/ext/session/mod_user.h @@ -24,6 +24,6 @@ extern ps_module ps_mod_user; #define ps_user_ptr &ps_mod_user -PS_FUNCS(user); +PS_FUNCS_SID(user); #endif diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index 340c2ca97ac..ea53af9ebe1 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -148,12 +148,12 @@ PHP_METHOD(SessionHandler, create_sid) { char *id; - zend_parse_parameters_none(); + if (zend_parse_parameters_none() == FAILURE) { + return; + } id = PS(default_mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); - RETVAL_STRING(id, 1); - efree(id); - return; + RETURN_STRING(id, 0); } /* }}} */ diff --git a/ext/session/session.c b/ext/session/session.c index 4b93ffa74ae..d8de5769fc1 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -2083,6 +2083,7 @@ static const zend_function_entry php_session_iface_functions[] = { PHP_ABSTRACT_ME(SessionHandlerInterface, write, arginfo_session_class_write) PHP_ABSTRACT_ME(SessionHandlerInterface, destroy, arginfo_session_class_destroy) PHP_ABSTRACT_ME(SessionHandlerInterface, gc, arginfo_session_class_gc) + PHP_ABSTRACT_ME(SessionHandlerInterface, create_sid, arginfo_session_class_create_sid) { NULL, NULL, NULL } }; /* }}} */ @@ -2096,7 +2097,6 @@ static const zend_function_entry php_session_class_functions[] = { PHP_ME(SessionHandler, write, arginfo_session_class_write, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, destroy, arginfo_session_class_destroy, ZEND_ACC_PUBLIC) PHP_ME(SessionHandler, gc, arginfo_session_class_gc, ZEND_ACC_PUBLIC) -/* Added to the class but not the interface, to maintain backwards compatibility */ PHP_ME(SessionHandler, create_sid, arginfo_session_class_create_sid, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; diff --git a/ext/session/tests/session_set_save_handler_class_002.phpt b/ext/session/tests/session_set_save_handler_class_002.phpt index 6fb831f6957..4195a163a73 100644 --- a/ext/session/tests/session_set_save_handler_class_002.phpt +++ b/ext/session/tests/session_set_save_handler_class_002.phpt @@ -53,6 +53,10 @@ class MySession2 extends SessionHandler { } return true; } + + public function create_sid() { + return parent::create_sid(); + } } $handler = new MySession2; diff --git a/ext/session/tests/session_set_save_handler_iface_001.phpt b/ext/session/tests/session_set_save_handler_iface_001.phpt index 39a4b9975b5..0576341a109 100644 --- a/ext/session/tests/session_set_save_handler_iface_001.phpt +++ b/ext/session/tests/session_set_save_handler_iface_001.phpt @@ -53,6 +53,10 @@ class MySession2 implements SessionHandlerInterface { } return true; } + + public function create_sid() { + return md5(mt_rand()); + } } $handler = new MySession2; From ada46c75f42cda5a790a921413b6f9f69e2495b4 Mon Sep 17 00:00:00 2001 From: Arpad Ray Date: Thu, 27 Jun 2013 12:33:56 +0100 Subject: [PATCH 26/27] BC fix for PR 109 merge - create_sid() method in SessionHandler Creates a new SessionIdInterface and moves create_sid() into it, so existing handlers implementing SessionHandlerInterface don't require create_sid(). SessionHandler still includes the method so the default mod can be called, but now implements both interfaces. Also added several more tests for this feature. --- ext/session/php_session.h | 3 + ext/session/session.c | 53 +++++++++-- .../session_set_save_handler_class_002.phpt | 4 - .../session_set_save_handler_class_016.phpt | 90 +++++++++++++++++++ .../session_set_save_handler_class_017.phpt | 90 +++++++++++++++++++ .../session_set_save_handler_iface_001.phpt | 4 - .../session_set_save_handler_iface_003.phpt | 90 +++++++++++++++++++ .../session_set_save_handler_sid_001.phpt | 85 ++++++++++++++++++ .../session_set_save_handler_sid_002.phpt | 77 ++++++++++++++++ 9 files changed, 480 insertions(+), 16 deletions(-) create mode 100644 ext/session/tests/session_set_save_handler_class_016.phpt create mode 100644 ext/session/tests/session_set_save_handler_class_017.phpt create mode 100644 ext/session/tests/session_set_save_handler_iface_003.phpt create mode 100644 ext/session/tests/session_set_save_handler_sid_001.phpt create mode 100644 ext/session/tests/session_set_save_handler_sid_002.phpt diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 210043582d9..1dd5b1a1a61 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -278,6 +278,9 @@ extern zend_class_entry *php_session_class_entry; #define PS_IFACE_NAME "SessionHandlerInterface" extern zend_class_entry *php_session_iface_entry; +#define PS_SID_IFACE_NAME "SessionIdInterface" +extern zend_class_entry *php_session_id_iface_entry; + extern PHP_METHOD(SessionHandler, open); extern PHP_METHOD(SessionHandler, close); extern PHP_METHOD(SessionHandler, read); diff --git a/ext/session/session.c b/ext/session/session.c index d8de5769fc1..78ecd8201c6 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -70,6 +70,9 @@ zend_class_entry *php_session_class_entry; /* SessionHandlerInterface */ zend_class_entry *php_session_iface_entry; +/* SessionIdInterface */ +zend_class_entry *php_session_id_iface_entry; + /* *********** * Helpers * *********** */ @@ -1603,11 +1606,11 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_FALSE; } - /* Find implemented methods */ - zend_hash_internal_pointer_reset_ex(&php_session_class_entry->function_table, &pos); + /* Find implemented methods - SessionHandlerInterface */ + zend_hash_internal_pointer_reset_ex(&php_session_iface_entry->function_table, &pos); i = 0; - while (zend_hash_get_current_data_ex(&php_session_class_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) { - zend_hash_get_current_key_ex(&php_session_class_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos); + while (zend_hash_get_current_data_ex(&php_session_iface_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) { + zend_hash_get_current_key_ex(&php_session_iface_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos); if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)¤t_mptr) == SUCCESS) { if (PS(mod_user_names).names[i] != NULL) { @@ -1625,7 +1628,29 @@ static PHP_FUNCTION(session_set_save_handler) RETURN_FALSE; } - zend_hash_move_forward_ex(&php_session_class_entry->function_table, &pos); + zend_hash_move_forward_ex(&php_session_iface_entry->function_table, &pos); + ++i; + } + + /* Find implemented methods - SessionIdInterface (optional) */ + zend_hash_internal_pointer_reset_ex(&php_session_id_iface_entry->function_table, &pos); + while (zend_hash_get_current_data_ex(&php_session_id_iface_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) { + zend_hash_get_current_key_ex(&php_session_id_iface_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos); + + if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)¤t_mptr) == SUCCESS) { + if (PS(mod_user_names).names[i] != NULL) { + zval_ptr_dtor(&PS(mod_user_names).names[i]); + } + + MAKE_STD_ZVAL(callback); + array_init_size(callback, 2); + Z_ADDREF_P(obj); + add_next_index_zval(callback, obj); + add_next_index_stringl(callback, func_name, func_name_len - 1, 1); + PS(mod_user_names).names[i] = callback; + } + + zend_hash_move_forward_ex(&php_session_id_iface_entry->function_table, &pos); ++i; } @@ -1993,7 +2018,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 7) +ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 1) ZEND_ARG_INFO(0, open) ZEND_ARG_INFO(0, close) ZEND_ARG_INFO(0, read) @@ -2083,7 +2108,14 @@ static const zend_function_entry php_session_iface_functions[] = { PHP_ABSTRACT_ME(SessionHandlerInterface, write, arginfo_session_class_write) PHP_ABSTRACT_ME(SessionHandlerInterface, destroy, arginfo_session_class_destroy) PHP_ABSTRACT_ME(SessionHandlerInterface, gc, arginfo_session_class_gc) - PHP_ABSTRACT_ME(SessionHandlerInterface, create_sid, arginfo_session_class_create_sid) + { NULL, NULL, NULL } +}; +/* }}} */ + +/* {{{ SessionIdInterface functions[] +*/ +static const zend_function_entry php_session_id_iface_functions[] = { + PHP_ABSTRACT_ME(SessionIdInterface, create_sid, arginfo_session_class_create_sid) { NULL, NULL, NULL } }; /* }}} */ @@ -2206,15 +2238,20 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */ php_session_rfc1867_orig_callback = php_rfc1867_callback; php_rfc1867_callback = php_session_rfc1867_callback; - /* Register interface */ + /* Register interfaces */ INIT_CLASS_ENTRY(ce, PS_IFACE_NAME, php_session_iface_functions); php_session_iface_entry = zend_register_internal_class(&ce TSRMLS_CC); php_session_iface_entry->ce_flags |= ZEND_ACC_INTERFACE; + INIT_CLASS_ENTRY(ce, PS_SID_IFACE_NAME, php_session_id_iface_functions); + php_session_id_iface_entry = zend_register_internal_class(&ce TSRMLS_CC); + php_session_id_iface_entry->ce_flags |= ZEND_ACC_INTERFACE; + /* Register base class */ INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions); php_session_class_entry = zend_register_internal_class(&ce TSRMLS_CC); zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_iface_entry); + zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_id_iface_entry); REGISTER_LONG_CONSTANT("PHP_SESSION_DISABLED", php_session_disabled, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_SESSION_NONE", php_session_none, CONST_CS | CONST_PERSISTENT); diff --git a/ext/session/tests/session_set_save_handler_class_002.phpt b/ext/session/tests/session_set_save_handler_class_002.phpt index 4195a163a73..6fb831f6957 100644 --- a/ext/session/tests/session_set_save_handler_class_002.phpt +++ b/ext/session/tests/session_set_save_handler_class_002.phpt @@ -53,10 +53,6 @@ class MySession2 extends SessionHandler { } return true; } - - public function create_sid() { - return parent::create_sid(); - } } $handler = new MySession2; diff --git a/ext/session/tests/session_set_save_handler_class_016.phpt b/ext/session/tests/session_set_save_handler_class_016.phpt new file mode 100644 index 00000000000..2de03c0682e --- /dev/null +++ b/ext/session/tests/session_set_save_handler_class_016.phpt @@ -0,0 +1,90 @@ +--TEST-- +Test session_set_save_handler() function: class with create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return parent::create_sid(); + } +} + +$handler = new MySession2; +session_set_save_handler($handler); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: class with create_sid *** +string(%d) "%s" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_class_017.phpt b/ext/session/tests/session_set_save_handler_class_017.phpt new file mode 100644 index 00000000000..756dc55d030 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_class_017.phpt @@ -0,0 +1,90 @@ +--TEST-- +Test session_set_save_handler() function: class with create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return 'my_sid'; + } +} + +$handler = new MySession2; +session_set_save_handler($handler); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: class with create_sid *** +string(%d) "my_sid" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_iface_001.phpt b/ext/session/tests/session_set_save_handler_iface_001.phpt index 0576341a109..39a4b9975b5 100644 --- a/ext/session/tests/session_set_save_handler_iface_001.phpt +++ b/ext/session/tests/session_set_save_handler_iface_001.phpt @@ -53,10 +53,6 @@ class MySession2 implements SessionHandlerInterface { } return true; } - - public function create_sid() { - return md5(mt_rand()); - } } $handler = new MySession2; diff --git a/ext/session/tests/session_set_save_handler_iface_003.phpt b/ext/session/tests/session_set_save_handler_iface_003.phpt new file mode 100644 index 00000000000..bd757dce630 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_iface_003.phpt @@ -0,0 +1,90 @@ +--TEST-- +Test session_set_save_handler() function: id interface +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return 'my_sid'; + } +} + +$handler = new MySession2; +session_set_save_handler($handler); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: id interface *** +string(%d) "my_sid" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_sid_001.phpt b/ext/session/tests/session_set_save_handler_sid_001.phpt new file mode 100644 index 00000000000..0dc4fc11cf0 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_sid_001.phpt @@ -0,0 +1,85 @@ +--TEST-- +Test session_set_save_handler() function: create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return 'my_sid'; + } +} + +$handler = new MySession2; +session_set_save_handler(array($handler, 'open'), array($handler, 'close'), + array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'), array($handler, 'create_sid')); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: create_sid *** +string(%d) "my_sid" +string(4) "user" +array(1) { + ["foo"]=> + string(5) "hello" +} +array(1) { + ["foo"]=> + string(5) "hello" +} diff --git a/ext/session/tests/session_set_save_handler_sid_002.phpt b/ext/session/tests/session_set_save_handler_sid_002.phpt new file mode 100644 index 00000000000..f9a72aebcaf --- /dev/null +++ b/ext/session/tests/session_set_save_handler_sid_002.phpt @@ -0,0 +1,77 @@ +--TEST-- +Test session_set_save_handler() function: create_sid +--INI-- +session.save_handler=files +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +path = $path . '/u_sess_' . $name; + return true; + } + + public function close() { + return true; + } + + public function read($id) { + return @file_get_contents($this->path . $id); + } + + public function write($id, $data) { + return file_put_contents($this->path . $id, $data); + } + + public function destroy($id) { + @unlink($this->path . $id); + } + + public function gc($maxlifetime) { + foreach (glob($this->path . '*') as $filename) { + if (filemtime($filename) + $maxlifetime < time()) { + @unlink($filename); + } + } + return true; + } + + public function create_sid() { + return null; + } +} + +$handler = new MySession2; +session_set_save_handler(array($handler, 'open'), array($handler, 'close'), + array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'), array($handler, 'create_sid')); +session_start(); + +$_SESSION['foo'] = "hello"; + +var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); + +session_write_close(); +session_unset(); + +session_start(); +var_dump($_SESSION); + +session_write_close(); +session_unset(); + +--EXPECTF-- +*** Testing session_set_save_handler() function: create_sid *** + +Fatal error: session_start(): Session id must be a string in %s on line %d From ce8c023910562e84d5e00825a1e784174bcb3f1b Mon Sep 17 00:00:00 2001 From: Arpad Ray Date: Thu, 27 Jun 2013 19:05:23 +0100 Subject: [PATCH 27/27] Fix bug #62535 - $_SESSION[$key]["cancel_upload"] doesn't work as documented When uploading multiple files, the array in the session where the progress data is stored (and cancel_upload key is set) was overwritten whenever the progress data was updated, so pending uploads would proceed anyway. --- ext/session/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/session/session.c b/ext/session/session.c index d9989ba753f..a1309474195 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -2366,7 +2366,7 @@ static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, i php_session_initialize(TSRMLS_C); PS(session_status) = php_session_active; IF_SESSION_VARS() { - progress->cancel_upload = php_check_cancel_upload(progress TSRMLS_CC); + progress->cancel_upload |= php_check_cancel_upload(progress TSRMLS_CC); ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), progress->key.c, progress->key.len+1, progress->data, 2, 0); } php_session_flush(TSRMLS_C);