root/eaccelerator/tags/0.9.3-rc2/session.c

Revision 89, 12.4 kB (checked in by zoeloelip, 3 years ago)

Added some includes to satisfy VC.NET (thanks to dakalka, patch 1198522)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2    +----------------------------------------------------------------------+
3    | eAccelerator project                                                 |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 2004 - 2005 eAccelerator                               |
6    | http://eaccelerator.net                                                      |
7    +----------------------------------------------------------------------+
8    | This program is free software; you can redistribute it and/or        |
9    | modify it under the terms of the GNU General Public License          |
10    | as published by the Free Software Foundation; either version 2       |
11    | of the License, or (at your option) any later version.               |
12    |                                                                      |
13    | This program is distributed in the hope that it will be useful,      |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16    | GNU General Public License for more details.                         |
17    |                                                                      |
18    | You should have received a copy of the GNU General Public License    |
19    | along with this program; if not, write to the Free Software          |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21    | MA  02111-1307, USA.                                                 |
22    |                                                                      |
23    | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24    +----------------------------------------------------------------------+
25    | Author(s): Dmitry Stogov <dstogov@users.sourceforge.net>             |
26    +----------------------------------------------------------------------+
27    $Id$
28 */
29
30 #include "eaccelerator.h"
31 #include "session.h"
32
33 #ifdef WITH_EACCELERATOR_SESSIONS
34
35 #include "cache.h"
36 #include "ext/standard/md5.h"
37 #include <fcntl.h>
38
39 #ifdef WIN32
40 #       include "win32/time.h"
41 #endif
42
43 #if defined(HAVE_PHP_SESSIONS_SUPPORT) && defined(PS_CREATE_SID_ARGS)
44 #       include "ext/standard/php_lcg.h"
45 #endif
46
47 eaccelerator_cache_place eaccelerator_sessions_cache_place =
48         eaccelerator_shm_and_disk;
49 int eaccelerator_sessions_registered = 0;
50 extern eaccelerator_mm *eaccelerator_mm_instance;
51
52 /* set the updated ini value of the cache place */
53 PHP_INI_MH (eaccelerator_OnUpdateSessionCachePlace)
54 {
55         if (strncasecmp ("shm_and_disk", new_value, sizeof ("shm_and_disk")) == 0) {
56                 eaccelerator_sessions_cache_place = eaccelerator_shm_and_disk;
57         } else if (strncasecmp ("shm", new_value, sizeof ("shm")) == 0) {
58                 eaccelerator_sessions_cache_place = eaccelerator_shm;
59         } else if (strncasecmp ("shm_only", new_value, sizeof ("shm_only")) == 0) {
60                 eaccelerator_sessions_cache_place = eaccelerator_shm_only;
61         } else if (strncasecmp ("disk_only", new_value, sizeof ("disk_only")) == 0) {
62                 eaccelerator_sessions_cache_place = eaccelerator_disk_only;
63         } else if (strncasecmp ("none", new_value, sizeof ("none")) == 0) {
64                 eaccelerator_sessions_cache_place = eaccelerator_none;
65         }
66         return SUCCESS;
67 }
68
69 /* session unlock */
70 static int do_session_unlock (TSRMLS_D)
71 {
72         if (MMCG (session) != NULL) {
73                 eaccelerator_unlock (MMCG (session), strlen (MMCG (session)) TSRMLS_CC);
74                 efree (MMCG (session));
75                 MMCG (session) = NULL;
76         }
77         return 1;
78 }
79
80 /* session locking */
81 static int do_session_lock (const char *sess_name TSRMLS_DC)
82 {
83         if (MMCG (session) != NULL) {
84                 if (strcmp (MMCG (session), sess_name) == 0) {
85                         return 1;
86                 } else {
87                         do_session_unlock (TSRMLS_C);
88                 }
89         }
90         if (eaccelerator_lock (sess_name, strlen (sess_name) TSRMLS_CC)) {
91                 MMCG (session) = estrdup (sess_name);
92                 return 1;
93         } else {
94                 return 0;
95         }
96 }
97
98 #ifdef HAVE_PHP_SESSIONS_SUPPORT  /* PHP_SESSION_API >= 20020306 */
99 /******************************************************************************/
100 /* Session api functions                                                                                                          */
101 /******************************************************************************/
102
103 PS_OPEN_FUNC (eaccelerator)
104 {
105         if (eaccelerator_mm_instance == NULL) {
106                 return FAILURE;
107         }
108         PS_SET_MOD_DATA ((void *) 1);
109         return SUCCESS;
110 }
111
112 PS_CLOSE_FUNC (eaccelerator)
113 {
114         if (eaccelerator_mm_instance == NULL) {
115                 return FAILURE;
116         }
117         do_session_unlock (TSRMLS_C);
118         return SUCCESS;
119 }
120
121 PS_READ_FUNC (eaccelerator)
122 {
123         char *skey;
124         int len;
125         zval ret;
126
127         len = sizeof ("sess_") + strlen (key);
128         skey = do_alloca (len + 1);
129         strcpy (skey, "sess_");
130         strcat (skey, key);
131         do_session_lock (skey TSRMLS_CC);
132         if (eaccelerator_get
133                 (skey, len, &ret, eaccelerator_sessions_cache_place TSRMLS_CC)
134                 && ret.type == IS_STRING) {
135                 *val = estrdup (ret.value.str.val);
136                 *vallen = ret.value.str.len;
137                 zval_dtor (&ret);
138         } else {
139                 *val = emalloc (1);
140                 (*val)[0] = '\0';
141                 *vallen = 0;
142         }
143         free_alloca (skey);
144         return SUCCESS;
145 }
146
147 PS_WRITE_FUNC (eaccelerator)
148 {
149         char *skey;
150         int len;
151         char *tmp;
152         time_t ttl;
153         zval sval;
154
155         len = sizeof ("sess_") + strlen (key);
156         skey = do_alloca (len + 1);
157         strcpy (skey, "sess_");
158         strcat (skey, key);
159         if (cfg_get_string ("session.gc_maxlifetime", &tmp) == FAILURE) {
160                 ttl = 1440;
161         } else {
162                 ttl = atoi (tmp);
163         }
164         sval.type = IS_STRING;
165         sval.value.str.val = (char *) val;
166         sval.value.str.len = vallen;
167
168         do_session_lock (skey TSRMLS_CC);
169         if (eaccelerator_put
170                 (skey, len, &sval, ttl, eaccelerator_sessions_cache_place TSRMLS_CC)) {
171                 free_alloca (skey);
172                 return SUCCESS;
173         } else {
174                 free_alloca (skey);
175                 return FAILURE;
176         }
177 }
178
179 PS_DESTROY_FUNC (eaccelerator)
180 {
181         char *skey;
182         int len;
183
184         len = sizeof ("sess_") + strlen (key);
185         skey = do_alloca (len + 1);
186         strcpy (skey, "sess_");
187         strcat (skey, key);
188         if (eaccelerator_rm
189                 (skey, len, eaccelerator_sessions_cache_place TSRMLS_CC)) {
190                 free_alloca (skey);
191                 return SUCCESS;
192         } else {
193                 free_alloca (skey);
194                 return FAILURE;
195         }
196 }
197
198 PS_GC_FUNC (eaccelerator)
199 {
200         if (eaccelerator_mm_instance == NULL) {
201                 return FAILURE;
202         }
203         eaccelerator_gc (TSRMLS_C);
204         return SUCCESS;
205 }
206
207 #ifdef PS_CREATE_SID_ARGS
208 PS_CREATE_SID_FUNC (eaccelerator)
209 {
210         static char hexconvtab[] = "0123456789abcdef";
211         PHP_MD5_CTX context;
212         unsigned char digest[16];
213         char buf[256];
214         struct timeval tv;
215         int i;
216         int j = 0;
217         unsigned char c;
218
219         long entropy_length;
220         char *entropy_file;
221
222         if (cfg_get_string ("session.entropy_length", &entropy_file) == FAILURE) {
223                 entropy_length = 0;
224         } else {
225                 entropy_length = atoi (entropy_file);
226         }
227         if (cfg_get_string ("session.entropy_file", &entropy_file) == FAILURE) {
228                 entropy_file = empty_string;
229         }
230
231         gettimeofday (&tv, NULL);
232         PHP_MD5Init (&context);
233
234         sprintf (buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec,
235                          php_combined_lcg (TSRMLS_C) * 10);
236         PHP_MD5Update (&context, (unsigned char *) buf, strlen (buf));
237
238         if (entropy_length > 0) {
239                 int fd;
240
241                 fd = VCWD_OPEN (entropy_file, O_RDONLY);
242                 if (fd >= 0) {
243                         unsigned char buf[2048];
244                         int n;
245                         int to_read = entropy_length;
246
247                         while (to_read > 0) {
248                                 n = read (fd, buf, MIN (to_read, sizeof (buf)));
249                                 if (n <= 0)
250                                         break;
251                                 PHP_MD5Update (&context, buf, n);
252                                 to_read -= n;
253                         }
254                         close (fd);
255                 }
256         }
257
258         PHP_MD5Final (digest, &context);
259
260         for (i = 0; i < 16; i++) {
261                 c = digest[i];
262                 buf[j++] = hexconvtab[c >> 4];
263                 buf[j++] = hexconvtab[c & 15];
264         }
265         buf[j] = '\0';
266
267         if (newlen)
268                 *newlen = j;
269         return estrdup (buf);
270 }
271 #endif
272
273 #else
274 /******************************************************************************/
275 /* PHP function to register as user session handlers when the session api         */
276 /* available.                                                                                                                             */
277 /******************************************************************************/
278
279 PHP_FUNCTION (_eaccelerator_session_open)
280 {
281         if (eaccelerator_mm_instance == NULL) {
282                 RETURN_FALSE;
283         }
284         RETURN_TRUE;
285 }
286
287 PHP_FUNCTION (_eaccelerator_session_close)
288 {
289         if (eaccelerator_mm_instance == NULL) {
290                 RETURN_FALSE;
291         }
292         do_session_unlock (TSRMLS_C);
293         RETURN_TRUE;
294 }
295
296 PHP_FUNCTION (_eaccelerator_session_read)
297 {
298         zval **arg_key;
299         char *key;
300         int len;
301
302         if (ZEND_NUM_ARGS () != 1
303                 || zend_get_parameters_ex (1, &arg_key) == FAILURE) {
304                 WRONG_PARAM_COUNT;
305         }
306         len = sizeof ("sess_") + (*arg_key)->value.str.len;
307         key = do_alloca (len + 1);
308         strcpy (key, "sess_");
309         strcat (key, (*arg_key)->value.str.val);
310         do_session_lock (key TSRMLS_CC);
311         if (eaccelerator_get
312                 (key, len, return_value, eaccelerator_sessions_cache_place TSRMLS_CC)) {
313                 free_alloca (key);
314                 return;
315         } else {
316                 free_alloca (key);
317                 RETURN_EMPTY_STRING ();
318         }
319 }
320
321 PHP_FUNCTION (_eaccelerator_session_write)
322 {
323         zval **arg_key, **arg_val;
324         char *key;
325         int len;
326         char *tmp;
327         time_t ttl;
328
329         if (ZEND_NUM_ARGS () != 2
330                 || zend_get_parameters_ex (2, &arg_key, &arg_val) == FAILURE) {
331                 WRONG_PARAM_COUNT;
332         }
333         len = sizeof ("sess_") + (*arg_key)->value.str.len;
334         key = do_alloca (len + 1);
335         strcpy (key, "sess_");
336         strcat (key, (*arg_key)->value.str.val);
337         /* this will get the ini value but not the value set by the user with ini_set
338         /* php allows a user to set this, so we should allow this to
339         if (cfg_get_string ("session.gc_maxlifetime", &tmp) == FAILURE) {
340                 ttl = 1440;
341         } else {
342                 ttl = atoi (tmp);
343         }
344         */
345         ttl = PS(gc_maxlifetime);
346         if (ttl < 0)
347                 ttl = 1440;
348         do_session_lock (key TSRMLS_CC);
349         if (eaccelerator_put
350                 (key, len, *arg_val, ttl,
351                  eaccelerator_sessions_cache_place TSRMLS_CC)) {
352                 free_alloca (key);
353                 RETURN_TRUE;
354         } else {
355                 free_alloca (key);
356                 RETURN_FALSE;
357         }
358 }
359
360 PHP_FUNCTION (_eaccelerator_session_destroy)
361 {
362         zval **arg_key;
363         char *key;
364         int len;
365
366         if (ZEND_NUM_ARGS () != 1
367                 || zend_get_parameters_ex (1, &arg_key) == FAILURE) {
368                 WRONG_PARAM_COUNT;
369         }
370         len = sizeof ("sess_") + (*arg_key)->value.str.len;
371         key = do_alloca (len + 1);
372         strcpy (key, "sess_");
373         strcat (key, (*arg_key)->value.str.val);
374         if (eaccelerator_rm (key, len, eaccelerator_sessions_cache_place TSRMLS_CC)) {
375                 free_alloca (key);
376                 RETURN_TRUE;
377         } else {
378                 free_alloca (key);
379                 RETURN_FALSE;
380         }
381 }
382
383 PHP_FUNCTION (_eaccelerator_session_gc)
384 {
385         if (eaccelerator_mm_instance == NULL) {
386                 RETURN_FALSE;
387         }
388         eaccelerator_gc (TSRMLS_C);
389         RETURN_TRUE;
390 }
391 #endif                                                  /* ELSE HAVE_PHP_SESSIONS_SUPPORT */
392
393 ps_module ps_mod_eaccelerator = {
394 #ifdef PS_CREATE_SID_ARGS
395         PS_MOD_SID (eaccelerator)
396 #else
397         PS_MOD (eaccelerator)
398 #endif
399 };
400
401 /* is the eA registered as session handler */
402 int eaccelerator_session_registered ()
403 {
404         return !(eaccelerator_sessions_cache_place != eaccelerator_none &&
405                          eaccelerator_sessions_registered == 0);
406 }
407
408 /* register ea as session handler */
409 void eaccelerator_register_session ()
410 {
411         php_session_register_module (&ps_mod_eaccelerator);
412         eaccelerator_sessions_registered = 1;
413 }
414
415 /* register ea as the custom session handler */
416 int eaccelerator_set_session_handlers (TSRMLS_D)
417 {
418         zval func;
419         zval retval;
420         int ret = 1;
421 #ifdef HAVE_PHP_SESSIONS_SUPPORT // do it with the session api
422         zval param;
423         zval *params[1];
424 /*
425   if (php_session_register_module(&ps_mod_eaccelerator) != 0) {
426     return 0;
427   }
428 */
429         if (eaccelerator_sessions_cache_place == eaccelerator_none) {
430                 return 0;
431         }
432         ZVAL_STRING (&func, "session_module_name", 0);
433         INIT_ZVAL (param);
434         params[0] = &param;
435         ZVAL_STRING (params[0], "eaccelerator", 0);
436         if (call_user_function (EG (function_table), NULL, &func, &retval,
437                                                         1, params TSRMLS_CC) == FAILURE) {
438                 ret = 0;
439         }
440         zval_dtor (&retval);
441         return ret;
442 #else // register the functions as custom user functions
443         zval *params[6];
444         int i;
445
446         if (eaccelerator_sessions_cache_place == eaccelerator_none) {
447                 return 0;
448         }
449         if (eaccelerator_mm_instance == NULL) {
450                 return 0;
451         }
452         if (!zend_hash_exists
453                 (EG (function_table), "session_set_save_handler",
454                  sizeof ("session_set_save_handler"))) {
455                 return 0;
456         }
457
458         ZVAL_STRING (&func, "session_set_save_handler", 0);
459         MAKE_STD_ZVAL (params[0]);
460         ZVAL_STRING (params[0], "_eaccelerator_session_open", 1);
461         MAKE_STD_ZVAL (params[1]);
462         ZVAL_STRING (params[1], "_eaccelerator_session_close", 1);
463         MAKE_STD_ZVAL (params[2]);
464         ZVAL_STRING (params[2], "_eaccelerator_session_read", 1);
465         MAKE_STD_ZVAL (params[3]);
466         ZVAL_STRING (params[3], "_eaccelerator_session_write", 1);
467         MAKE_STD_ZVAL (params[4]);
468         ZVAL_STRING (params[4], "_eaccelerator_session_destroy", 1);
469         MAKE_STD_ZVAL (params[5]);
470         ZVAL_STRING (params[5], "_eaccelerator_session_gc", 1);
471         if (call_user_function (EG (function_table), NULL, &func, &retval,
472                                                         6, params TSRMLS_CC) == FAILURE) {
473                 ret = 0;
474         }
475         zval_dtor (&retval);
476         for (i = 0; i < 6; i++)
477                 zval_ptr_dtor (&params[i]);
478         return ret;
479 #endif
480 }
481
482 /* function to call from a php script to register ea as session handler */
483 PHP_FUNCTION (eaccelerator_set_session_handlers)
484 {
485         if (eaccelerator_set_session_handlers (TSRMLS_C)) {
486                 RETURN_TRUE;
487         } else {
488                 RETURN_FALSE;
489         }
490 }
491
492 #endif /* HAVE_EACCELERATOR_SESSIONS */
Note: See TracBrowser for help on using the browser.