xref: /PHP-7.2/ext/session/mod_user.c (revision a6d21963)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 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: Sascha Schumann <sascha@schumann.cx>                         |
16    +----------------------------------------------------------------------+
17  */
18 
19 /* $Id$ */
20 
21 #include "php.h"
22 #include "php_session.h"
23 #include "mod_user.h"
24 
25 ps_module ps_mod_user = {
26 	PS_MOD_UPDATE_TIMESTAMP(user)
27 };
28 
29 
ps_call_handler(zval * func,int argc,zval * argv,zval * retval)30 static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval)
31 {
32 	int i;
33 	if (PS(in_save_handler)) {
34 		PS(in_save_handler) = 0;
35 		ZVAL_UNDEF(retval);
36 		php_error_docref(NULL, E_WARNING, "Cannot call session save handler in a recursive manner");
37 		return;
38 	}
39 	PS(in_save_handler) = 1;
40 	if (call_user_function(EG(function_table), NULL, func, retval, argc, argv) == FAILURE) {
41 		zval_ptr_dtor(retval);
42 		ZVAL_UNDEF(retval);
43 	} else if (Z_ISUNDEF_P(retval)) {
44 		ZVAL_NULL(retval);
45 	}
46 	PS(in_save_handler) = 0;
47 	for (i = 0; i < argc; i++) {
48 		zval_ptr_dtor(&argv[i]);
49 	}
50 }
51 
52 #define STDVARS								\
53 	zval retval;							\
54 	int ret = FAILURE
55 
56 #define PSF(a) PS(mod_user_names).name.ps_##a
57 
58 #define FINISH \
59 	if (Z_TYPE(retval) != IS_UNDEF) { \
60 		if (Z_TYPE(retval) == IS_TRUE) { \
61 			ret = SUCCESS; \
62 		} else if (Z_TYPE(retval) == IS_FALSE) { \
63 			ret = FAILURE; \
64         }  else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == -1)) { \
65 			/* BC for clever users - Deprecate me */ \
66 			ret = FAILURE; \
67 		} else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == 0)) { \
68 			/* BC for clever users - Deprecate me */ \
69 			ret = SUCCESS; \
70 		} else { \
71 			if (!EG(exception)) { \
72 				php_error_docref(NULL, E_WARNING, \
73 				                 "Session callback expects true/false return value"); \
74 			} \
75 			ret = FAILURE; \
76 			zval_ptr_dtor(&retval); \
77 		} \
78 	} \
79 	return ret
80 
PS_OPEN_FUNC(user)81 PS_OPEN_FUNC(user)
82 {
83 	zval args[2];
84 	STDVARS;
85 
86 	if (Z_ISUNDEF(PSF(open))) {
87 		php_error_docref(NULL, E_WARNING,
88 			"user session functions not defined");
89 
90 		return FAILURE;
91 	}
92 
93 	ZVAL_STRING(&args[0], (char*)save_path);
94 	ZVAL_STRING(&args[1], (char*)session_name);
95 
96 	zend_try {
97 		ps_call_handler(&PSF(open), 2, args, &retval);
98 	} zend_catch {
99 		PS(session_status) = php_session_none;
100 		if (!Z_ISUNDEF(retval)) {
101 			zval_ptr_dtor(&retval);
102 		}
103 		zend_bailout();
104 	} zend_end_try();
105 
106 	PS(mod_user_implemented) = 1;
107 
108 	FINISH;
109 }
110 
PS_CLOSE_FUNC(user)111 PS_CLOSE_FUNC(user)
112 {
113 	zend_bool bailout = 0;
114 	STDVARS;
115 
116 	if (!PS(mod_user_implemented)) {
117 		/* already closed */
118 		return SUCCESS;
119 	}
120 
121 	zend_try {
122 		ps_call_handler(&PSF(close), 0, NULL, &retval);
123 	} zend_catch {
124 		bailout = 1;
125 	} zend_end_try();
126 
127 	PS(mod_user_implemented) = 0;
128 
129 	if (bailout) {
130 		if (!Z_ISUNDEF(retval)) {
131 			zval_ptr_dtor(&retval);
132 		}
133 		zend_bailout();
134 	}
135 
136 	FINISH;
137 }
138 
PS_READ_FUNC(user)139 PS_READ_FUNC(user)
140 {
141 	zval args[1];
142 	STDVARS;
143 
144 	ZVAL_STR_COPY(&args[0], key);
145 
146 	ps_call_handler(&PSF(read), 1, args, &retval);
147 
148 	if (!Z_ISUNDEF(retval)) {
149 		if (Z_TYPE(retval) == IS_STRING) {
150 			*val = zend_string_copy(Z_STR(retval));
151 			ret = SUCCESS;
152 		}
153 		zval_ptr_dtor(&retval);
154 	}
155 
156 	return ret;
157 }
158 
PS_WRITE_FUNC(user)159 PS_WRITE_FUNC(user)
160 {
161 	zval args[2];
162 	STDVARS;
163 
164 	ZVAL_STR_COPY(&args[0], key);
165 	ZVAL_STR_COPY(&args[1], val);
166 
167 	ps_call_handler(&PSF(write), 2, args, &retval);
168 
169 	FINISH;
170 }
171 
PS_DESTROY_FUNC(user)172 PS_DESTROY_FUNC(user)
173 {
174 	zval args[1];
175 	STDVARS;
176 
177 	ZVAL_STR_COPY(&args[0], key);
178 
179 	ps_call_handler(&PSF(destroy), 1, args, &retval);
180 
181 	FINISH;
182 }
183 
PS_GC_FUNC(user)184 PS_GC_FUNC(user)
185 {
186 	zval args[1];
187 	zval retval;
188 
189 	ZVAL_LONG(&args[0], maxlifetime);
190 
191 	ps_call_handler(&PSF(gc), 1, args, &retval);
192 
193 	if (Z_TYPE(retval) == IS_LONG) {
194 		convert_to_long(&retval);
195 		*nrdels = Z_LVAL(retval);
196 	} else if (Z_TYPE(retval) == IS_TRUE) {
197 		/* This is for older API compatibility */
198 		*nrdels = 1;
199 	} else {
200 		/* Anything else is some kind of error */
201 		*nrdels = -1; // Error
202 	}
203 	return *nrdels;
204 }
205 
PS_CREATE_SID_FUNC(user)206 PS_CREATE_SID_FUNC(user)
207 {
208 	/* maintain backwards compatibility */
209 	if (!Z_ISUNDEF(PSF(create_sid))) {
210 		zend_string *id = NULL;
211 		zval retval;
212 
213 		ps_call_handler(&PSF(create_sid), 0, NULL, &retval);
214 
215 		if (!Z_ISUNDEF(retval)) {
216 			if (Z_TYPE(retval) == IS_STRING) {
217 				id = zend_string_copy(Z_STR(retval));
218 			}
219 			zval_ptr_dtor(&retval);
220 		} else {
221 			zend_throw_error(NULL, "No session id returned by function");
222 			return NULL;
223 		}
224 
225 		if (!id) {
226 			zend_throw_error(NULL, "Session id must be a string");
227 			return NULL;
228 		}
229 
230 		return id;
231 	}
232 
233 	/* function as defined by PS_MOD */
234 	return php_session_create_id(mod_data);
235 }
236 
PS_VALIDATE_SID_FUNC(user)237 PS_VALIDATE_SID_FUNC(user)
238 {
239 	/* maintain backwards compatibility */
240 	if (!Z_ISUNDEF(PSF(validate_sid))) {
241 		zval args[1];
242 		STDVARS;
243 
244 		ZVAL_STR_COPY(&args[0], key);
245 
246 		ps_call_handler(&PSF(validate_sid), 1, args, &retval);
247 
248 		FINISH;
249 	}
250 
251 	/* dummy function defined by PS_MOD */
252 	return php_session_validate_sid(mod_data, key);
253 }
254 
PS_UPDATE_TIMESTAMP_FUNC(user)255 PS_UPDATE_TIMESTAMP_FUNC(user)
256 {
257 	zval args[2];
258 	STDVARS;
259 
260 	ZVAL_STR_COPY(&args[0], key);
261 	ZVAL_STR_COPY(&args[1], val);
262 
263 	/* maintain backwards compatibility */
264 	if (!Z_ISUNDEF(PSF(update_timestamp))) {
265 		ps_call_handler(&PSF(update_timestamp), 2, args, &retval);
266 	} else {
267 		ps_call_handler(&PSF(write), 2, args, &retval);
268 	}
269 
270 	FINISH;
271 }
272 
273 /*
274  * Local variables:
275  * tab-width: 4
276  * c-basic-offset: 4
277  * End:
278  * vim600: sw=4 ts=4 fdm=marker
279  * vim<600: sw=4 ts=4
280  */
281