On Wed, Dec 9, 2009 at 2:35 AM, Stanislav Malyshev <s...@zend.com> wrote:

> Hi!
>
>
>  By extending the new internal class SessionHandler, users can wrap or
>> override methods of whatever session handler is in use, or implement a
>> complete custom handler.
>>
>
>
Hi,

Thanks very much for your feedback, I've made some changes in the attached
patch.


>  Couple of notes:
>
> 1. I'd call mod_active something more clean - like session_active?
>

This flag indicates whether the mod should be called from the usual session
events. There might be a better name for it but there's already a
session_active with a different meaning.


> 2. What happens if session module is set to "user" in configuration - what
> old_mod will be then and how this patch will work?
>

It now raises an error rather than segfaulting if the user module is
selected but no handler has been registered. This should really halt
execution which it doesn't at the moment but I'll raise that separately.

old_mod is only set in the first call to session_set_save_handler(), so
subsequent calls just replace each other. Inheritance can be achieved by
extending the previous class or calling the previous functions from the new
class.

3. old_mod is also not a clear name - maybe default_mod?
>

Ok, changed.


> 4. I think it also makes sense to allow passing object instead of class.
>

I've allowed objects to be passed now but I think this should probably be
discouraged since it's going to be called in a static context anyway.


> 5. In fact, thinking about it - maybe it should be an interface and not a
> class?
>

I made it a class rather than an interface to allow easy inheritance of the
default handler. This way it's always parent::foo() whether extending
directly from SessionHandler or a child class. It also means users only need
to implement the methods they actually use.

Regards,

Arpad
Index: ext/session/config.w32
===================================================================
--- ext/session/config.w32	(revision 291922)
+++ ext/session/config.w32	(working copy)
@@ -4,7 +4,7 @@
 ARG_ENABLE("session", "session support", "yes");
 
 if (PHP_SESSION == "yes") {
-	EXTENSION("session", "session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */);
+	EXTENSION("session", "mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */);
 	AC_DEFINE("HAVE_PHP_SESSION", 1, "Session support");
 }
 
Index: ext/session/php_session.h
===================================================================
--- ext/session/php_session.h	(revision 291922)
+++ ext/session/php_session.h	(working copy)
@@ -128,6 +128,7 @@
 	zend_bool  cookie_secure;
 	zend_bool  cookie_httponly;
 	ps_module *mod;
+	ps_module *default_mod;
 	void *mod_data;
 	php_session_status session_status;
 	long gc_probability;
@@ -146,6 +147,7 @@
 			zval *ps_gc;
 		} name;
 	} mod_user_names;
+	int mod_active;
 	const struct ps_serializer_struct *serializer;
 	zval *http_session_vars;
 	zend_bool auto_start;
@@ -285,4 +287,14 @@
 void php_session_auto_start(void *data);
 void php_session_shutdown(void *data);
 
+#define PS_CLASS_NAME "SessionHandler"
+extern zend_class_entry *php_session_class_entry;
+
+extern PHP_METHOD(SessionHandler, open);
+extern PHP_METHOD(SessionHandler, close);
+extern PHP_METHOD(SessionHandler, read);
+extern PHP_METHOD(SessionHandler, write);
+extern PHP_METHOD(SessionHandler, destroy);
+extern PHP_METHOD(SessionHandler, gc);
+
 #endif
Index: ext/session/mod_user_class.c
===================================================================
--- ext/session/mod_user_class.c	(revision 0)
+++ ext/session/mod_user_class.c	(revision 0)
@@ -0,0 +1,120 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 6                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2009 The PHP Group                                |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Arpad Ray <ar...@php.net>
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "php.h"
+#include "php_session.h"
+
+#define PS_SANITY_CHECK						\
+	if (PS(default_mod) == NULL) {			\
+		RETURN_FALSE;						\
+	}							
+
+
+/* {{{ proto bool SessionHandler::open(string save_path, string session_name)
+   Wraps the old open handler */
+PHP_METHOD(SessionHandler, open)
+{
+	PS_SANITY_CHECK;
+
+	RETVAL_LONG(PS(default_mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::close()
+   Wraps the old close handler */
+PHP_METHOD(SessionHandler, close)
+{
+	PS_SANITY_CHECK;
+	
+	RETVAL_LONG(PS(default_mod)->s_close(&PS(mod_data)));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::read(save_path, session_name)
+   Wraps the old read handler */
+PHP_METHOD(SessionHandler, read)
+{
+	char *key, *val;
+	int key_len, val_len;
+
+	PS_SANITY_CHECK;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len, UG(utf8_conv)) == FAILURE) {
+		return;
+	}
+
+	if (PS(default_mod)->s_read(&PS(mod_data), key, &val, &val_len) == FAILURE) {
+		RETVAL_FALSE;
+		return;
+	}
+
+	RETVAL_STRINGL(val, val_len, 1);
+	efree(val);
+	return;
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::write(save_path, session_name)
+   Wraps the old write handler */
+PHP_METHOD(SessionHandler, write)
+{
+	char *key, *val;
+	int key_len, val_len;
+
+	PS_SANITY_CHECK;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &val, &val_len, UG(utf8_conv)) == FAILURE) {
+		return;
+	}
+
+	RETVAL_LONG(PS(default_mod)->s_write(&PS(mod_data), key, val, val_len));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::destroy()
+   Wraps the old destroy handler */
+PHP_METHOD(SessionHandler, destroy)
+{
+	char *key;
+	int key_len;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len, UG(utf8_conv)) == FAILURE) {
+		return;
+	}
+	
+	RETVAL_LONG(PS(default_mod)->s_destroy(&PS(mod_data), key));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::gc(int maxlifetime)
+   Wraps the old gc handler */
+PHP_METHOD(SessionHandler, gc)
+{
+	long maxlifetime;
+	int nrdels;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxlifetime, UG(utf8_conv)) == FAILURE) {
+		return;
+	}
+	
+	RETVAL_LONG(PS(default_mod)->s_gc(&PS(mod_data), maxlifetime, &nrdels));
+}
+/* }}} */
+
Index: ext/session/config.m4
===================================================================
--- ext/session/config.m4	(revision 291922)
+++ ext/session/config.m4	(working copy)
@@ -11,7 +11,7 @@
 if test "$PHP_SESSION" != "no"; then
   PHP_PWRITE_TEST
   PHP_PREAD_TEST
-  PHP_NEW_EXTENSION(session, session.c mod_files.c mod_mm.c mod_user.c, $ext_shared)
+  PHP_NEW_EXTENSION(session, mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared)
   PHP_ADD_EXTENSION_DEP(session, hash, true)
   PHP_SUBST(SESSION_SHARED_LIBADD)
   PHP_INSTALL_HEADERS(ext/session, [php_session.h mod_files.h mod_user.h])
Index: ext/session/package.xml
===================================================================
--- ext/session/package.xml	(revision 291922)
+++ ext/session/package.xml	(working copy)
@@ -40,6 +40,7 @@
    <file role="src" name="mod_mm.c"/>
    <file role="src" name="mod_mm.h"/>
    <file role="src" name="mod_user.c"/>
+   <file role="src" name="mod_user_class.c"/>
    <file role="src" name="mod_user.h"/>
    <file role="src" name="php_session.h"/>
    <file role="src" name="session.c"/>
Index: ext/session/mod_user.c
===================================================================
--- ext/session/mod_user.c	(revision 291922)
+++ ext/session/mod_user.c	(working copy)
@@ -62,15 +62,10 @@
 	return retval;
 }
 
-#define STDVARS1							\
+#define STDVARS								\
 	zval *retval;							\
 	int ret = FAILURE
 
-#define STDVARS								\
-	STDVARS1;								\
-	char *mdata = PS_GET_MOD_DATA();		\
-	if (!mdata) { return FAILURE; }
-
 #define PSF(a) PS(mod_user_names).name.ps_##a
 
 #define FINISH								\
@@ -84,33 +79,24 @@
 PS_OPEN_FUNC(user)
 {
 	zval *args[2];
-	static char dummy = 0;
-	STDVARS1;
+	STDVARS;
 
 	SESS_ZVAL_STRING((char*)save_path, args[0]);
 	SESS_ZVAL_STRING((char*)session_name, args[1]);
 
 	retval = ps_call_handler(PSF(open), 2, args TSRMLS_CC);
-	if (retval) {
-		/* This is necessary to fool the session module. Yes, it's safe to
-		 * use a static. Neither mod_user nor the session module itself will
-		 * ever touch this pointer. It could be set to 0xDEADBEEF for all the
-		 * difference it makes, but for the sake of paranoia it's set to some
-		 * valid value. */
-		PS_SET_MOD_DATA(&dummy);
-	}
+	PS(mod_active) = 1;
 
 	FINISH;
 }
 
 PS_CLOSE_FUNC(user)
 {
-	STDVARS1;
+	STDVARS;
 
 	retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC);
+	PS(mod_active) = 0;
 
-	PS_SET_MOD_DATA(NULL);
-
 	FINISH;
 }
 
Index: ext/session/tests/session_set_save_handler_class.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class.phpt	(revision 0)
@@ -0,0 +1,197 @@
+--TEST--
+Test session_set_save_handler() function : class handler
+--INI--
+session.save_path=
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(string $class)
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : class handler ***\n";
+
+echo "*** Testing session_set_save_handler() : basic class wrapping existing handler ***\n";
+
+class MySession extends SessionHandler {
+	public static $i = 0;
+	public static function open($path, $name) {
+		++self::$i;
+		echo 'Open ', session_id(), "\n";
+		return parent::open($path, $name);
+	}
+	public static function read($key) {
+		++self::$i;
+		echo 'Read ', session_id(), "\n";
+		return parent::read($key);
+	}
+}
+
+$path = dirname(__FILE__);
+session_save_path($path);
+
+$oldHandler = ini_get('session.save_handler');
+session_set_save_handler('MySession');
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), MySession::$i, $_SESSION);
+
+$_SESSION['foo'] = "\u263A";
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+echo "*** Testing session_set_save_handler() : full handler implementation ***\n";
+
+class MySession2 extends SessionHandler {
+	public static $path;
+
+	public static function open($path, $name) {
+		if (!$path) {
+			$path = '/tmp';
+		}
+		self::$path = $path . '/u_sess_' . $name;
+		return true;
+	}
+
+	public static function close() {
+		return true;
+	}
+
+	public static function read($id) {
+		return @file_get_contents(self::$path . $id);
+	}
+
+	public static function write($id, $data) {
+		return file_put_contents(self::$path . $id, $data);
+	}
+
+	public static function destroy($id) {
+		@unlink(self::$path . $id);
+	}
+
+	public static function gc($maxlifetime) {
+		foreach (glob(self::$path . '*') as $filename) {
+			if (filemtime($filename) + $maxlifetime < time()) {
+				@unlink($filename);
+			}
+		}
+		return true;
+	}
+}
+
+session_set_save_handler('MySession2');
+session_start();
+
+$_SESSION['foo'] = "\u263A";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+echo "*** Testing session_set_save_handler() : inheritance ***\n";
+
+class MySession3 extends SessionHandler {
+	public static $i = 0;
+	public static function open($path, $name) {
+		++MySession3::$i;
+		return parent::open($path, $name);
+	}
+	public static function read($key) {
+		++MySession3::$i;
+		return parent::read($key);
+	}
+}
+
+class MySession4 extends MySession3 {
+	public static function write($id, $data) {
+		MySession3::$i = "hai";
+		return parent::write($id, $data);
+	}
+}
+
+session_set_save_handler('MySession3');
+session_start();
+
+$_SESSION['foo'] = "\u263A";
+
+session_write_close();
+session_unset();
+
+session_start();
+
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+session_set_save_handler('MySession4');
+
+session_start();
+
+session_write_close();
+session_unset();
+
+var_dump(session_id(), $_SESSION, MySession3::$i);
+
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : class handler ***
+*** Testing session_set_save_handler() : basic class wrapping existing handler ***
+Open 
+Read %x
+string(32) "%x"
+unicode(5) "files"
+unicode(4) "user"
+int(2)
+array(0) {
+}
+Open %x
+Read %x
+array(1) {
+  [u"foo"]=>
+  unicode(1) "☺"
+}
+*** Testing session_set_save_handler() : full handler implementation ***
+string(32) "%x"
+unicode(4) "user"
+array(1) {
+  [u"foo"]=>
+  unicode(1) "☺"
+}
+array(1) {
+  [u"foo"]=>
+  unicode(1) "☺"
+}
+*** Testing session_set_save_handler() : inheritance ***
+array(1) {
+  [u"foo"]=>
+  unicode(1) "☺"
+}
+string(32) "%x"
+array(1) {
+  [u"foo"]=>
+  unicode(1) "☺"
+}
+unicode(3) "hai"
Index: ext/session/session.c
===================================================================
--- ext/session/session.c	(revision 291922)
+++ ext/session/session.c	(working copy)
@@ -94,9 +94,10 @@
 		PS(http_session_vars) = NULL;
 	}
 	/* Do NOT destroy PS(mod_user_names) here! */
-	if (PS(mod_data)) {
+	if (PS(mod_active)) {
 		zend_try {
 			PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
+			PS(mod_active) = 0;
 		} zend_end_try();
 	}
 	if (PS(id)) {
@@ -410,6 +411,8 @@
 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "No storage module chosen - failed to initialize session");
 		return;
 	}
+	
+	PS(mod_active) = 1;
 
 	/* Open session handler first */
 	if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name) TSRMLS_CC) == FAILURE) {
@@ -451,7 +454,7 @@
 
 	IF_SESSION_VARS() {
 
-		if (PS(mod_data)) {
+		if (PS(mod_active)) {
 			char *val;
 			int vallen;
 
@@ -473,8 +476,9 @@
 		}
 	}
 
-	if (PS(mod_data)) {
+	if (PS(mod_active)) {
 		PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
+		PS(mod_active) = 0;
 	}
 }
 /* }}} */
@@ -505,6 +509,15 @@
 		}
 		return FAILURE;
 	}
+
+	if (tmp == &ps_mod_user && !PS(mod_active)) {
+		if (stage != ZEND_INI_STAGE_DEACTIVATE) {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "User session handler selected but not implemented");
+		}
+		return FAILURE;
+	}
+
+	PS(default_mod) = PS(mod);
 	PS(mod) = tmp;
 
 	return SUCCESS;
@@ -1381,7 +1394,7 @@
 
 	php_session_cache_limiter(TSRMLS_C);
 
-	if (PS(mod_data) && PS(gc_probability) > 0) {
+	if (PS(mod_active) && PS(gc_probability) > 0) {
 		int nrdels = -1;
 
 		nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C));
@@ -1516,8 +1529,9 @@
 			zval_dtor(return_value);
 			RETURN_FALSE;
 		}
-		if (PS(mod_data)) {
+		if (PS(mod_active)) {
 			PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
+			PS(mod_active) = 0;
 		}
 		PS(mod_data) = NULL;
 
@@ -1526,6 +1540,19 @@
 }
 /* }}} */
 
+#define PS_METHOD_CALLBACK(x)							\
+	callback = PS(mod_user_names).name.ps_##x;			\
+	if (callback != NULL) {								\
+		zval_ptr_dtor(&callback);						\
+		callback = NULL;								\
+	}													\
+	MAKE_STD_ZVAL(callback);							\
+	array_init(callback);								\
+	zval_add_ref(class);								\
+	add_next_index_zval(callback, *class);				\
+	add_next_index_string(callback, #x, 1);				\
+	PS(mod_user_names).name.ps_##x = callback;
+
 /* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc) U
    Sets user-level functions */
 static PHP_FUNCTION(session_set_save_handler)
@@ -1534,14 +1561,63 @@
 	int i, num_args, argc = ZEND_NUM_ARGS();
 	zval name;
 
-	if (PS(session_status) != php_session_none) {
+	if (PS(session_status) != php_session_none && argc != 1) {
 		RETURN_FALSE;
 	}
 
-	if (argc != 6) {
+	if (argc != 1 && argc != 6) {
 		WRONG_PARAM_COUNT;
 	}
 
+	if (argc == 1) {
+		zval **class, *callback;
+		zend_class_entry **pce, *ce = NULL;
+
+		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &class) == FAILURE) {
+			return;
+		}
+
+		if (Z_TYPE_PP(class) == IS_STRING || Z_TYPE_PP(class) == IS_UNICODE) {
+			if (zend_u_lookup_class(Z_TYPE_PP(class), Z_UNIVAL_PP(class), Z_UNILEN_PP(class), &pce TSRMLS_CC) == FAILURE) {
+				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Session handler class '%Z' not found", *class);
+				RETURN_FALSE;
+			}
+
+			ce = *pce;
+		} else if (Z_TYPE_PP(class) == IS_OBJECT) {
+			ce = Z_OBJCE_PP(class);
+		} else {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Session handler must be an object or class descended from %s", PS_CLASS_NAME);
+			RETURN_FALSE;
+		}
+
+		while (ce->parent) {
+			ce = ce->parent;
+		}
+
+		if (ce != php_session_class_entry) {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "The session handler class must descend from %s", PS_CLASS_NAME);
+			RETURN_FALSE;
+		}
+		
+		PS_METHOD_CALLBACK(open);
+		PS_METHOD_CALLBACK(close);
+		PS_METHOD_CALLBACK(read);
+		PS_METHOD_CALLBACK(write);
+		PS_METHOD_CALLBACK(destroy);
+		PS_METHOD_CALLBACK(gc);
+
+		if (PS(mod) && PS(session_status) == php_session_none && PS(mod) != &ps_mod_user) {
+			PS(default_mod) = PS(mod);
+			PS(mod_active) = 1;
+			zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+		} else {
+			PS(mod_active) = 1;
+		}
+
+		RETURN_TRUE;
+	}
+
 	if (zend_parse_parameters(argc TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
 		return;
 	}
@@ -1555,7 +1631,8 @@
 		}
 		zval_dtor(&name);
 	}
-
+	
+	PS(mod_active) = 1;
 	zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
 
 	for (i = 0; i < 6; i++) {
@@ -1888,6 +1965,31 @@
 	ZEND_ARG_INFO(0, secure)
 	ZEND_ARG_INFO(0, httponly)
 ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_open, 0)
+	ZEND_ARG_INFO(0, save_path)
+	ZEND_ARG_INFO(0, session_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_close, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_read, 0)
+	ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_write, 0)
+	ZEND_ARG_INFO(0, key)
+	ZEND_ARG_INFO(0, val)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_destroy, 0)
+	ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_gc, 0)
+	ZEND_ARG_INFO(0, maxlifetime)
+ZEND_END_ARG_INFO()
 /* }}} */
 
 /* {{{ session_functions[]
@@ -1914,6 +2016,22 @@
 };
 /* }}} */
 
+/* session class */
+zend_class_entry *php_session_class_entry;
+
+/* {{{ session class functions[]
+ */
+static const zend_function_entry php_session_class_functions[] = {
+	PHP_ME(SessionHandler, open, arginfo_session_class_open, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(SessionHandler, close, arginfo_session_class_close, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(SessionHandler, read, arginfo_session_class_read, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(SessionHandler, write, arginfo_session_class_write, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(SessionHandler, destroy, arginfo_session_class_destroy, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(SessionHandler, gc, arginfo_session_class_gc, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	{ NULL, NULL, NULL }
+};
+/* }}} */
+
 /* ********************************
    * Module Setup and Destruction *
    ******************************** */
@@ -1989,15 +2107,19 @@
 	ps_globals->serializer = NULL;
 	ps_globals->mod_data = NULL;
 	ps_globals->session_status = php_session_none;
+	ps_globals->mod_active = 0;
 	for (i = 0; i < 6; i++) {
 		ps_globals->mod_user_names.names[i] = NULL;
 	}
+
 	ps_globals->http_session_vars = NULL;
 }
 /* }}} */
 
 static PHP_MINIT_FUNCTION(session) /* {{{ */
 {
+	zend_class_entry ce;
+
 	zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, NULL TSRMLS_CC);
 
 	PS(module_number) = module_number; /* if we really need this var we need to init it in zts mode as well! */
@@ -2010,6 +2132,10 @@
 #endif
 	php_session_rfc1867_orig_callback = php_rfc1867_callback;
 	php_rfc1867_callback = php_session_rfc1867_callback;
+
+	INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions);
+	php_session_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
+
 	return SUCCESS;
 }
 /* }}} */
-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to