xref: /PHP-7.1/ext/session/mod_user.c (revision ccd4716e)
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 		return Z_LVAL(retval);
196 	}
197 	/* This is for older API compatibility */
198 	if (Z_TYPE(retval) == IS_TRUE) {
199 		return 1;
200 	}
201 	/* Anything else is some kind of error */
202 	return -1; // Error
203 }
204 
PS_CREATE_SID_FUNC(user)205 PS_CREATE_SID_FUNC(user)
206 {
207 	/* maintain backwards compatibility */
208 	if (!Z_ISUNDEF(PSF(create_sid))) {
209 		zend_string *id = NULL;
210 		zval retval;
211 
212 		ps_call_handler(&PSF(create_sid), 0, NULL, &retval);
213 
214 		if (!Z_ISUNDEF(retval)) {
215 			if (Z_TYPE(retval) == IS_STRING) {
216 				id = zend_string_copy(Z_STR(retval));
217 			}
218 			zval_ptr_dtor(&retval);
219 		} else {
220 			zend_throw_error(NULL, "No session id returned by function");
221 			return NULL;
222 		}
223 
224 		if (!id) {
225 			zend_throw_error(NULL, "Session id must be a string");
226 			return NULL;
227 		}
228 
229 		return id;
230 	}
231 
232 	/* function as defined by PS_MOD */
233 	return php_session_create_id(mod_data);
234 }
235 
PS_VALIDATE_SID_FUNC(user)236 PS_VALIDATE_SID_FUNC(user)
237 {
238 	/* maintain backwards compatibility */
239 	if (!Z_ISUNDEF(PSF(validate_sid))) {
240 		zval args[1];
241 		STDVARS;
242 
243 		ZVAL_STR_COPY(&args[0], key);
244 
245 		ps_call_handler(&PSF(validate_sid), 1, args, &retval);
246 
247 		FINISH;
248 	}
249 
250 	/* dummy function defined by PS_MOD */
251 	return php_session_validate_sid(mod_data, key);
252 }
253 
PS_UPDATE_TIMESTAMP_FUNC(user)254 PS_UPDATE_TIMESTAMP_FUNC(user)
255 {
256 	zval args[2];
257 	STDVARS;
258 
259 	ZVAL_STR_COPY(&args[0], key);
260 	ZVAL_STR_COPY(&args[1], val);
261 
262 	/* maintain backwards compatibility */
263 	if (!Z_ISUNDEF(PSF(update_timestamp))) {
264 		ps_call_handler(&PSF(update_timestamp), 2, args, &retval);
265 	} else {
266 		ps_call_handler(&PSF(write), 2, args, &retval);
267 	}
268 
269 	FINISH;
270 }
271 
272 /*
273  * Local variables:
274  * tab-width: 4
275  * c-basic-offset: 4
276  * End:
277  * vim600: sw=4 ts=4 fdm=marker
278  * vim<600: sw=4 ts=4
279  */
280