Skip to content

Commit 47cfae8

Browse files
committed
Implement object-oriented session handlers (https://wiki.php.net/rfc/session-oo)
1 parent 6e998b4 commit 47cfae8

24 files changed

+1279
-33
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ PHP NEWS
5454

5555
- Improved Session extension:
5656
. Expose session status via new function, session_status (FR #52982) (Arpad)
57+
. Added support for object-oriented session handlers. (Arpad)
5758

5859
- Improved SPL extension:
5960
. Immediately reject wrong usages of directories under Spl(Temp)FileObject

ext/session/config.m4

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ PHP_ARG_WITH(mm,for mm support,
1111
if test "$PHP_SESSION" != "no"; then
1212
PHP_PWRITE_TEST
1313
PHP_PREAD_TEST
14-
PHP_NEW_EXTENSION(session, session.c mod_files.c mod_mm.c mod_user.c, $ext_shared)
14+
PHP_NEW_EXTENSION(session, mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared)
1515
PHP_ADD_EXTENSION_DEP(session, hash, true)
1616
PHP_ADD_EXTENSION_DEP(session, spl)
1717
PHP_SUBST(SESSION_SHARED_LIBADD)

ext/session/config.w32

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
ARG_ENABLE("session", "session support", "yes");
55

66
if (PHP_SESSION == "yes") {
7-
EXTENSION("session", "session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */);
7+
EXTENSION("session", "mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */);
88
AC_DEFINE("HAVE_PHP_SESSION", 1, "Session support");
99
PHP_INSTALL_HEADERS("ext/session/", "mod_mm.h php_session.h mod_files.h mod_user.h");
1010
}

ext/session/mod_user.c

+10-19
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,10 @@ static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC)
6262
return retval;
6363
}
6464

65-
#define STDVARS1 \
65+
#define STDVARS \
6666
zval *retval; \
6767
int ret = FAILURE
6868

69-
#define STDVARS \
70-
STDVARS1; \
71-
char *mdata = PS_GET_MOD_DATA(); \
72-
if (!mdata) { return FAILURE; }
73-
7469
#define PSF(a) PS(mod_user_names).name.ps_##a
7570

7671
#define FINISH \
@@ -84,32 +79,28 @@ static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC)
8479
PS_OPEN_FUNC(user)
8580
{
8681
zval *args[2];
87-
static char dummy = 0;
88-
STDVARS1;
82+
STDVARS;
8983

9084
SESS_ZVAL_STRING((char*)save_path, args[0]);
9185
SESS_ZVAL_STRING((char*)session_name, args[1]);
9286

9387
retval = ps_call_handler(PSF(open), 2, args TSRMLS_CC);
94-
if (retval) {
95-
/* This is necessary to fool the session module. Yes, it's safe to
96-
* use a static. Neither mod_user nor the session module itself will
97-
* ever touch this pointer. It could be set to 0xDEADBEEF for all the
98-
* difference it makes, but for the sake of paranoia it's set to some
99-
* valid value. */
100-
PS_SET_MOD_DATA(&dummy);
101-
}
88+
PS(mod_user_implemented) = 1;
10289

10390
FINISH;
10491
}
10592

10693
PS_CLOSE_FUNC(user)
10794
{
108-
STDVARS1;
95+
STDVARS;
10996

110-
retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC);
97+
if (!PS(mod_user_implemented)) {
98+
/* already closed */
99+
return SUCCESS;
100+
}
111101

112-
PS_SET_MOD_DATA(NULL);
102+
retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC);
103+
PS(mod_user_implemented) = 0;
113104

114105
FINISH;
115106
}

ext/session/mod_user_class.c

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP Version 5 |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 1997-2011 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| license@php.net so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Author: Arpad Ray <arpad@php.net> |
16+
+----------------------------------------------------------------------+
17+
*/
18+
19+
/* $Id$ */
20+
21+
#include "php.h"
22+
#include "php_session.h"
23+
24+
#define PS_SANITY_CHECK \
25+
if (PS(default_mod) == NULL) { \
26+
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Called default SessionHandler but session.save_handler is user"); \
27+
RETURN_FALSE; \
28+
}
29+
30+
#define PS_SANITY_CHECK_IS_OPEN \
31+
PS_SANITY_CHECK; \
32+
if (!PS(mod_user_is_open)) { \
33+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parent session handler is not open"); \
34+
RETURN_FALSE; \
35+
}
36+
37+
/* {{{ proto bool SessionHandler::open(string save_path, string session_name)
38+
Wraps the old open handler */
39+
PHP_METHOD(SessionHandler, open)
40+
{
41+
char *save_path = NULL, *session_name = NULL;
42+
int save_path_len, session_name_len;
43+
44+
PS_SANITY_CHECK;
45+
46+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &save_path, &save_path_len, &session_name, &session_name_len) == FAILURE) {
47+
return;
48+
}
49+
50+
PS(mod_user_is_open) = 1;
51+
RETVAL_LONG(PS(default_mod)->s_open(&PS(mod_data), save_path, session_name TSRMLS_CC));
52+
}
53+
/* }}} */
54+
55+
/* {{{ proto bool SessionHandler::close()
56+
Wraps the old close handler */
57+
PHP_METHOD(SessionHandler, close)
58+
{
59+
PS_SANITY_CHECK_IS_OPEN;
60+
61+
// don't return on failure, since not closing the default handler
62+
// could result in memory leaks or other nasties
63+
zend_parse_parameters_none();
64+
65+
PS(mod_user_is_open) = 0;
66+
RETVAL_LONG(PS(default_mod)->s_close(&PS(mod_data) TSRMLS_CC));
67+
}
68+
/* }}} */
69+
70+
/* {{{ proto bool SessionHandler::read(string id)
71+
Wraps the old read handler */
72+
PHP_METHOD(SessionHandler, read)
73+
{
74+
char *key, *val;
75+
int key_len, val_len;
76+
77+
PS_SANITY_CHECK_IS_OPEN;
78+
79+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
80+
return;
81+
}
82+
83+
if (PS(default_mod)->s_read(&PS(mod_data), key, &val, &val_len TSRMLS_CC) == FAILURE) {
84+
RETVAL_FALSE;
85+
return;
86+
}
87+
88+
RETVAL_STRINGL(val, val_len, 1);
89+
efree(val);
90+
return;
91+
}
92+
/* }}} */
93+
94+
/* {{{ proto bool SessionHandler::write(string id, string data)
95+
Wraps the old write handler */
96+
PHP_METHOD(SessionHandler, write)
97+
{
98+
char *key, *val;
99+
int key_len, val_len;
100+
101+
PS_SANITY_CHECK_IS_OPEN;
102+
103+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &val, &val_len) == FAILURE) {
104+
return;
105+
}
106+
107+
RETVAL_LONG(PS(default_mod)->s_write(&PS(mod_data), key, val, val_len TSRMLS_CC));
108+
}
109+
/* }}} */
110+
111+
/* {{{ proto bool SessionHandler::destroy(string id)
112+
Wraps the old destroy handler */
113+
PHP_METHOD(SessionHandler, destroy)
114+
{
115+
char *key;
116+
int key_len;
117+
118+
PS_SANITY_CHECK_IS_OPEN;
119+
120+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
121+
return;
122+
}
123+
124+
PS(mod_user_is_open) = 0;
125+
RETVAL_LONG(PS(default_mod)->s_destroy(&PS(mod_data), key TSRMLS_CC));
126+
}
127+
/* }}} */
128+
129+
/* {{{ proto bool SessionHandler::gc(int maxlifetime)
130+
Wraps the old gc handler */
131+
PHP_METHOD(SessionHandler, gc)
132+
{
133+
long maxlifetime;
134+
int nrdels;
135+
136+
PS_SANITY_CHECK;
137+
138+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxlifetime) == FAILURE) {
139+
return;
140+
}
141+
142+
RETVAL_LONG(PS(default_mod)->s_gc(&PS(mod_data), maxlifetime, &nrdels TSRMLS_CC));
143+
}
144+
/* }}} */

ext/session/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ package.xml added to support installation using pear installer
4040
<file role="src" name="mod_mm.c"/>
4141
<file role="src" name="mod_mm.h"/>
4242
<file role="src" name="mod_user.c"/>
43+
<file role="src" name="mod_user_class.c"/>
4344
<file role="src" name="mod_user.h"/>
4445
<file role="src" name="php_session.h"/>
4546
<file role="src" name="session.c"/>

ext/session/php_session.h

+13
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ typedef struct _php_ps_globals {
129129
zend_bool cookie_secure;
130130
zend_bool cookie_httponly;
131131
ps_module *mod;
132+
ps_module *default_mod;
132133
void *mod_data;
133134
php_session_status session_status;
134135
long gc_probability;
@@ -147,6 +148,8 @@ typedef struct _php_ps_globals {
147148
zval *ps_gc;
148149
} name;
149150
} mod_user_names;
151+
int mod_user_implemented;
152+
int mod_user_is_open;
150153
const struct ps_serializer_struct *serializer;
151154
zval *http_session_vars;
152155
zend_bool auto_start;
@@ -268,4 +271,14 @@ PHPAPI ZEND_EXTERN_MODULE_GLOBALS(ps)
268271
void php_session_auto_start(void *data);
269272
void php_session_shutdown(void *data);
270273

274+
#define PS_CLASS_NAME "SessionHandler"
275+
extern zend_class_entry *php_session_class_entry;
276+
277+
extern PHP_METHOD(SessionHandler, open);
278+
extern PHP_METHOD(SessionHandler, close);
279+
extern PHP_METHOD(SessionHandler, read);
280+
extern PHP_METHOD(SessionHandler, write);
281+
extern PHP_METHOD(SessionHandler, destroy);
282+
extern PHP_METHOD(SessionHandler, gc);
283+
271284
#endif

0 commit comments

Comments
 (0)