Skip to content

Commit ada46c7

Browse files
committed
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.
1 parent b794cce commit ada46c7

9 files changed

+480
-16
lines changed

ext/session/php_session.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ extern zend_class_entry *php_session_class_entry;
278278
#define PS_IFACE_NAME "SessionHandlerInterface"
279279
extern zend_class_entry *php_session_iface_entry;
280280

281+
#define PS_SID_IFACE_NAME "SessionIdInterface"
282+
extern zend_class_entry *php_session_id_iface_entry;
283+
281284
extern PHP_METHOD(SessionHandler, open);
282285
extern PHP_METHOD(SessionHandler, close);
283286
extern PHP_METHOD(SessionHandler, read);

ext/session/session.c

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ zend_class_entry *php_session_class_entry;
7070
/* SessionHandlerInterface */
7171
zend_class_entry *php_session_iface_entry;
7272

73+
/* SessionIdInterface */
74+
zend_class_entry *php_session_id_iface_entry;
75+
7376
/* ***********
7477
* Helpers *
7578
*********** */
@@ -1603,11 +1606,11 @@ static PHP_FUNCTION(session_set_save_handler)
16031606
RETURN_FALSE;
16041607
}
16051608

1606-
/* Find implemented methods */
1607-
zend_hash_internal_pointer_reset_ex(&php_session_class_entry->function_table, &pos);
1609+
/* Find implemented methods - SessionHandlerInterface */
1610+
zend_hash_internal_pointer_reset_ex(&php_session_iface_entry->function_table, &pos);
16081611
i = 0;
1609-
while (zend_hash_get_current_data_ex(&php_session_class_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) {
1610-
zend_hash_get_current_key_ex(&php_session_class_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos);
1612+
while (zend_hash_get_current_data_ex(&php_session_iface_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) {
1613+
zend_hash_get_current_key_ex(&php_session_iface_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos);
16111614

16121615
if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)&current_mptr) == SUCCESS) {
16131616
if (PS(mod_user_names).names[i] != NULL) {
@@ -1625,7 +1628,29 @@ static PHP_FUNCTION(session_set_save_handler)
16251628
RETURN_FALSE;
16261629
}
16271630

1628-
zend_hash_move_forward_ex(&php_session_class_entry->function_table, &pos);
1631+
zend_hash_move_forward_ex(&php_session_iface_entry->function_table, &pos);
1632+
++i;
1633+
}
1634+
1635+
/* Find implemented methods - SessionIdInterface (optional) */
1636+
zend_hash_internal_pointer_reset_ex(&php_session_id_iface_entry->function_table, &pos);
1637+
while (zend_hash_get_current_data_ex(&php_session_id_iface_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) {
1638+
zend_hash_get_current_key_ex(&php_session_id_iface_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos);
1639+
1640+
if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)&current_mptr) == SUCCESS) {
1641+
if (PS(mod_user_names).names[i] != NULL) {
1642+
zval_ptr_dtor(&PS(mod_user_names).names[i]);
1643+
}
1644+
1645+
MAKE_STD_ZVAL(callback);
1646+
array_init_size(callback, 2);
1647+
Z_ADDREF_P(obj);
1648+
add_next_index_zval(callback, obj);
1649+
add_next_index_stringl(callback, func_name, func_name_len - 1, 1);
1650+
PS(mod_user_names).names[i] = callback;
1651+
}
1652+
1653+
zend_hash_move_forward_ex(&php_session_id_iface_entry->function_table, &pos);
16291654
++i;
16301655
}
16311656

@@ -1993,7 +2018,7 @@ ZEND_END_ARG_INFO()
19932018
ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0)
19942019
ZEND_END_ARG_INFO()
19952020

1996-
ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 7)
2021+
ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 1)
19972022
ZEND_ARG_INFO(0, open)
19982023
ZEND_ARG_INFO(0, close)
19992024
ZEND_ARG_INFO(0, read)
@@ -2083,7 +2108,14 @@ static const zend_function_entry php_session_iface_functions[] = {
20832108
PHP_ABSTRACT_ME(SessionHandlerInterface, write, arginfo_session_class_write)
20842109
PHP_ABSTRACT_ME(SessionHandlerInterface, destroy, arginfo_session_class_destroy)
20852110
PHP_ABSTRACT_ME(SessionHandlerInterface, gc, arginfo_session_class_gc)
2086-
PHP_ABSTRACT_ME(SessionHandlerInterface, create_sid, arginfo_session_class_create_sid)
2111+
{ NULL, NULL, NULL }
2112+
};
2113+
/* }}} */
2114+
2115+
/* {{{ SessionIdInterface functions[]
2116+
*/
2117+
static const zend_function_entry php_session_id_iface_functions[] = {
2118+
PHP_ABSTRACT_ME(SessionIdInterface, create_sid, arginfo_session_class_create_sid)
20872119
{ NULL, NULL, NULL }
20882120
};
20892121
/* }}} */
@@ -2206,15 +2238,20 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */
22062238
php_session_rfc1867_orig_callback = php_rfc1867_callback;
22072239
php_rfc1867_callback = php_session_rfc1867_callback;
22082240

2209-
/* Register interface */
2241+
/* Register interfaces */
22102242
INIT_CLASS_ENTRY(ce, PS_IFACE_NAME, php_session_iface_functions);
22112243
php_session_iface_entry = zend_register_internal_class(&ce TSRMLS_CC);
22122244
php_session_iface_entry->ce_flags |= ZEND_ACC_INTERFACE;
22132245

2246+
INIT_CLASS_ENTRY(ce, PS_SID_IFACE_NAME, php_session_id_iface_functions);
2247+
php_session_id_iface_entry = zend_register_internal_class(&ce TSRMLS_CC);
2248+
php_session_id_iface_entry->ce_flags |= ZEND_ACC_INTERFACE;
2249+
22142250
/* Register base class */
22152251
INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions);
22162252
php_session_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
22172253
zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_iface_entry);
2254+
zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_id_iface_entry);
22182255

22192256
REGISTER_LONG_CONSTANT("PHP_SESSION_DISABLED", php_session_disabled, CONST_CS | CONST_PERSISTENT);
22202257
REGISTER_LONG_CONSTANT("PHP_SESSION_NONE", php_session_none, CONST_CS | CONST_PERSISTENT);

ext/session/tests/session_set_save_handler_class_002.phpt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ class MySession2 extends SessionHandler {
5353
}
5454
return true;
5555
}
56-
57-
public function create_sid() {
58-
return parent::create_sid();
59-
}
6056
}
6157

6258
$handler = new MySession2;
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
--TEST--
2+
Test session_set_save_handler() function: class with create_sid
3+
--INI--
4+
session.save_handler=files
5+
session.name=PHPSESSID
6+
--SKIPIF--
7+
<?php include('skipif.inc'); ?>
8+
--FILE--
9+
<?php
10+
11+
ob_start();
12+
13+
/*
14+
* Prototype : bool session_set_save_handler(SessionHandlerInterface $handler [, bool $register_shutdown_function = true])
15+
* Description : Sets user-level session storage functions
16+
* Source code : ext/session/session.c
17+
*/
18+
19+
echo "*** Testing session_set_save_handler() function: class with create_sid ***\n";
20+
21+
class MySession2 extends SessionHandler {
22+
public $path;
23+
24+
public function open($path, $name) {
25+
if (!$path) {
26+
$path = sys_get_temp_dir();
27+
}
28+
$this->path = $path . '/u_sess_' . $name;
29+
return true;
30+
}
31+
32+
public function close() {
33+
return true;
34+
}
35+
36+
public function read($id) {
37+
return @file_get_contents($this->path . $id);
38+
}
39+
40+
public function write($id, $data) {
41+
return file_put_contents($this->path . $id, $data);
42+
}
43+
44+
public function destroy($id) {
45+
@unlink($this->path . $id);
46+
}
47+
48+
public function gc($maxlifetime) {
49+
foreach (glob($this->path . '*') as $filename) {
50+
if (filemtime($filename) + $maxlifetime < time()) {
51+
@unlink($filename);
52+
}
53+
}
54+
return true;
55+
}
56+
57+
public function create_sid() {
58+
return parent::create_sid();
59+
}
60+
}
61+
62+
$handler = new MySession2;
63+
session_set_save_handler($handler);
64+
session_start();
65+
66+
$_SESSION['foo'] = "hello";
67+
68+
var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
69+
70+
session_write_close();
71+
session_unset();
72+
73+
session_start();
74+
var_dump($_SESSION);
75+
76+
session_write_close();
77+
session_unset();
78+
79+
--EXPECTF--
80+
*** Testing session_set_save_handler() function: class with create_sid ***
81+
string(%d) "%s"
82+
string(4) "user"
83+
array(1) {
84+
["foo"]=>
85+
string(5) "hello"
86+
}
87+
array(1) {
88+
["foo"]=>
89+
string(5) "hello"
90+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
--TEST--
2+
Test session_set_save_handler() function: class with create_sid
3+
--INI--
4+
session.save_handler=files
5+
session.name=PHPSESSID
6+
--SKIPIF--
7+
<?php include('skipif.inc'); ?>
8+
--FILE--
9+
<?php
10+
11+
ob_start();
12+
13+
/*
14+
* Prototype : bool session_set_save_handler(SessionHandlerInterface $handler [, bool $register_shutdown_function = true])
15+
* Description : Sets user-level session storage functions
16+
* Source code : ext/session/session.c
17+
*/
18+
19+
echo "*** Testing session_set_save_handler() function: class with create_sid ***\n";
20+
21+
class MySession2 extends SessionHandler {
22+
public $path;
23+
24+
public function open($path, $name) {
25+
if (!$path) {
26+
$path = sys_get_temp_dir();
27+
}
28+
$this->path = $path . '/u_sess_' . $name;
29+
return true;
30+
}
31+
32+
public function close() {
33+
return true;
34+
}
35+
36+
public function read($id) {
37+
return @file_get_contents($this->path . $id);
38+
}
39+
40+
public function write($id, $data) {
41+
return file_put_contents($this->path . $id, $data);
42+
}
43+
44+
public function destroy($id) {
45+
@unlink($this->path . $id);
46+
}
47+
48+
public function gc($maxlifetime) {
49+
foreach (glob($this->path . '*') as $filename) {
50+
if (filemtime($filename) + $maxlifetime < time()) {
51+
@unlink($filename);
52+
}
53+
}
54+
return true;
55+
}
56+
57+
public function create_sid() {
58+
return 'my_sid';
59+
}
60+
}
61+
62+
$handler = new MySession2;
63+
session_set_save_handler($handler);
64+
session_start();
65+
66+
$_SESSION['foo'] = "hello";
67+
68+
var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
69+
70+
session_write_close();
71+
session_unset();
72+
73+
session_start();
74+
var_dump($_SESSION);
75+
76+
session_write_close();
77+
session_unset();
78+
79+
--EXPECTF--
80+
*** Testing session_set_save_handler() function: class with create_sid ***
81+
string(%d) "my_sid"
82+
string(4) "user"
83+
array(1) {
84+
["foo"]=>
85+
string(5) "hello"
86+
}
87+
array(1) {
88+
["foo"]=>
89+
string(5) "hello"
90+
}

ext/session/tests/session_set_save_handler_iface_001.phpt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ class MySession2 implements SessionHandlerInterface {
5353
}
5454
return true;
5555
}
56-
57-
public function create_sid() {
58-
return md5(mt_rand());
59-
}
6056
}
6157

6258
$handler = new MySession2;

0 commit comments

Comments
 (0)