1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Sascha Schumann <sascha@schumann.cx> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "php.h"
18 #include "php_session.h"
19 #include "mod_user.h"
20
21 const ps_module ps_mod_user = {
22 PS_MOD_UPDATE_TIMESTAMP(user)
23 };
24
25
ps_call_handler(zval * func,int argc,zval * argv,zval * retval)26 static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval)
27 {
28 int i;
29 if (PS(in_save_handler)) {
30 PS(in_save_handler) = 0;
31 ZVAL_UNDEF(retval);
32 php_error_docref(NULL, E_WARNING, "Cannot call session save handler in a recursive manner");
33 return;
34 }
35 PS(in_save_handler) = 1;
36 if (call_user_function(NULL, NULL, func, retval, argc, argv) == FAILURE) {
37 zval_ptr_dtor(retval);
38 ZVAL_UNDEF(retval);
39 } else if (Z_ISUNDEF_P(retval)) {
40 ZVAL_NULL(retval);
41 }
42 PS(in_save_handler) = 0;
43 for (i = 0; i < argc; i++) {
44 zval_ptr_dtor(&argv[i]);
45 }
46 }
47
48 #define STDVARS \
49 zval retval; \
50 zend_result ret = FAILURE
51
52 #define PSF(a) PS(mod_user_names).name.ps_##a
53
54 #define FINISH \
55 if (Z_TYPE(retval) != IS_UNDEF) { \
56 if (Z_TYPE(retval) == IS_TRUE) { \
57 ret = SUCCESS; \
58 } else if (Z_TYPE(retval) == IS_FALSE) { \
59 ret = FAILURE; \
60 } else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == -1)) { \
61 if (!EG(exception)) { \
62 php_error_docref(NULL, E_DEPRECATED, "Session callback must have a return value of type bool, %s returned", zend_zval_type_name(&retval)); \
63 } \
64 ret = FAILURE; \
65 } else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == 0)) { \
66 if (!EG(exception)) { \
67 php_error_docref(NULL, E_DEPRECATED, "Session callback must have a return value of type bool, %s returned", zend_zval_type_name(&retval)); \
68 } \
69 ret = SUCCESS; \
70 } else { \
71 if (!EG(exception)) { \
72 zend_type_error("Session callback must have a return value of type bool, %s returned", zend_zval_type_name(&retval)); \
73 } \
74 ret = FAILURE; \
75 zval_ptr_dtor(&retval); \
76 } \
77 } \
78 return ret
79
PS_OPEN_FUNC(user)80 PS_OPEN_FUNC(user)
81 {
82 zval args[2];
83 STDVARS;
84
85 if (Z_ISUNDEF(PSF(open))) {
86 php_error_docref(NULL, E_WARNING, "User session functions are not defined");
87
88 return FAILURE;
89 }
90
91 ZVAL_STRING(&args[0], (char*)save_path);
92 ZVAL_STRING(&args[1], (char*)session_name);
93
94 zend_try {
95 ps_call_handler(&PSF(open), 2, args, &retval);
96 } zend_catch {
97 PS(session_status) = php_session_none;
98 if (!Z_ISUNDEF(retval)) {
99 zval_ptr_dtor(&retval);
100 }
101 zend_bailout();
102 } zend_end_try();
103
104 PS(mod_user_implemented) = 1;
105
106 FINISH;
107 }
108
PS_CLOSE_FUNC(user)109 PS_CLOSE_FUNC(user)
110 {
111 bool bailout = 0;
112 STDVARS;
113
114 if (!PS(mod_user_implemented)) {
115 /* already closed */
116 return SUCCESS;
117 }
118
119 zend_try {
120 ps_call_handler(&PSF(close), 0, NULL, &retval);
121 } zend_catch {
122 bailout = 1;
123 } zend_end_try();
124
125 PS(mod_user_implemented) = 0;
126
127 if (bailout) {
128 if (!Z_ISUNDEF(retval)) {
129 zval_ptr_dtor(&retval);
130 }
131 zend_bailout();
132 }
133
134 FINISH;
135 }
136
PS_READ_FUNC(user)137 PS_READ_FUNC(user)
138 {
139 zval args[1];
140 STDVARS;
141
142 ZVAL_STR_COPY(&args[0], key);
143
144 ps_call_handler(&PSF(read), 1, args, &retval);
145
146 if (!Z_ISUNDEF(retval)) {
147 if (Z_TYPE(retval) == IS_STRING) {
148 *val = zend_string_copy(Z_STR(retval));
149 ret = SUCCESS;
150 }
151 zval_ptr_dtor(&retval);
152 }
153
154 return ret;
155 }
156
PS_WRITE_FUNC(user)157 PS_WRITE_FUNC(user)
158 {
159 zval args[2];
160 STDVARS;
161
162 ZVAL_STR_COPY(&args[0], key);
163 ZVAL_STR_COPY(&args[1], val);
164
165 ps_call_handler(&PSF(write), 2, args, &retval);
166
167 FINISH;
168 }
169
PS_DESTROY_FUNC(user)170 PS_DESTROY_FUNC(user)
171 {
172 zval args[1];
173 STDVARS;
174
175 ZVAL_STR_COPY(&args[0], key);
176
177 ps_call_handler(&PSF(destroy), 1, args, &retval);
178
179 FINISH;
180 }
181
PS_GC_FUNC(user)182 PS_GC_FUNC(user)
183 {
184 zval args[1];
185 zval retval;
186
187 ZVAL_LONG(&args[0], maxlifetime);
188
189 ps_call_handler(&PSF(gc), 1, args, &retval);
190
191 if (Z_TYPE(retval) == IS_LONG) {
192 *nrdels = Z_LVAL(retval);
193 } else if (Z_TYPE(retval) == IS_TRUE) {
194 /* This is for older API compatibility */
195 *nrdels = 1;
196 } else {
197 /* Anything else is some kind of error */
198 *nrdels = -1; // Error
199 }
200 return *nrdels;
201 }
202
PS_CREATE_SID_FUNC(user)203 PS_CREATE_SID_FUNC(user)
204 {
205 /* maintain backwards compatibility */
206 if (!Z_ISUNDEF(PSF(create_sid))) {
207 zend_string *id = NULL;
208 zval retval;
209
210 ps_call_handler(&PSF(create_sid), 0, NULL, &retval);
211
212 if (!Z_ISUNDEF(retval)) {
213 if (Z_TYPE(retval) == IS_STRING) {
214 id = zend_string_copy(Z_STR(retval));
215 }
216 zval_ptr_dtor(&retval);
217 } else {
218 zend_throw_error(NULL, "No session id returned by function");
219 return NULL;
220 }
221
222 if (!id) {
223 zend_throw_error(NULL, "Session id must be a string");
224 return NULL;
225 }
226
227 return id;
228 }
229
230 /* function as defined by PS_MOD */
231 return php_session_create_id(mod_data);
232 }
233
PS_VALIDATE_SID_FUNC(user)234 PS_VALIDATE_SID_FUNC(user)
235 {
236 /* maintain backwards compatibility */
237 if (!Z_ISUNDEF(PSF(validate_sid))) {
238 zval args[1];
239 STDVARS;
240
241 ZVAL_STR_COPY(&args[0], key);
242
243 ps_call_handler(&PSF(validate_sid), 1, args, &retval);
244
245 FINISH;
246 }
247
248 /* dummy function defined by PS_MOD */
249 return php_session_validate_sid(mod_data, key);
250 }
251
PS_UPDATE_TIMESTAMP_FUNC(user)252 PS_UPDATE_TIMESTAMP_FUNC(user)
253 {
254 zval args[2];
255 STDVARS;
256
257 ZVAL_STR_COPY(&args[0], key);
258 ZVAL_STR_COPY(&args[1], val);
259
260 /* maintain backwards compatibility */
261 if (!Z_ISUNDEF(PSF(update_timestamp))) {
262 ps_call_handler(&PSF(update_timestamp), 2, args, &retval);
263 } else {
264 ps_call_handler(&PSF(write), 2, args, &retval);
265 }
266
267 FINISH;
268 }
269