php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | |
Patch bugs-53713-sqlite3-session-win32-plus-test for SQLite related Bug #53713Patch version 2011-05-02 12:03 UTC Return to Bug #53713 | Download this patchThis patch is obsolete Obsoleted by patches: Patch Revisions:Developer: jinmoku@hotmail.comIndex: ext/sqlite3/tests/sqlite3_session_002.phpt =================================================================== --- ext/sqlite3/tests/sqlite3_session_002.phpt (revision 0) +++ ext/sqlite3/tests/sqlite3_session_002.phpt (revision 0) @@ -0,0 +1,54 @@ +--TEST-- +sqlite3, session destroy test +--CREDITS-- +Mats Lindh <mats at lindh.no> +#Testfest php.no +--INI-- +session.save_handler = sqlite3 +--SKIPIF-- +if (!extension_loaded("session")) +{ + die("skip Session module not loaded"); +} +if (!extension_loaded("sqlite3")) +{ + die("skip sqlite3 module not loaded"); +} +--FILE-- +<?php +/* Description: Tests that sqlite will destroy a session when used as a session handler +* Source code: ext/sqlite/sess_sqlite3.c +*/ +ob_start(); +session_save_path(__DIR__ . "/sessiondb.sdb"); + +// start a session and save a value to it before commiting the session to the database +session_start(); +$_SESSION["test"] = "foo_bar"; +session_write_close(); + +// remove the session value +unset($_SESSION["test"]); +var_dump(isset($_SESSION["test"])); + +// start the session again and destroy it +session_start(); +var_dump($_SESSION["test"]); +session_destroy(); +session_write_close(); + +unset($_SESSION["test"]); + +// check that the session has been destroyed +session_start(); +var_dump(isset($_SESSION["test"])); +ob_end_flush(); +?> +--EXPECTF-- +bool(false) +%unicode|string%(7) "foo_bar" +bool(false) +--CLEAN-- +<?php + unlink(__DIR__ . "/sessiondb.sdb") +?> Index: ext/sqlite3/tests/sqlite3_session_001.phpt =================================================================== --- ext/sqlite3/tests/sqlite3_session_001.phpt (revision 0) +++ ext/sqlite3/tests/sqlite3_session_001.phpt (revision 0) @@ -0,0 +1,46 @@ +--TEST-- +sqlite3, session storage test +--CREDITS-- +Mats Lindh <mats at lindh.no> +#Testfest php.no +--INI-- +session.save_handler = sqlite3 +--SKIPIF-- +if (!extension_loaded("session")) +{ + die("skip Session module not loaded"); +} +if (!extension_loaded("sqlite3")) +{ + die("skip Session module not loaded"); +} +--FILE-- +<?php +/* Description: Tests that sqlite can be used as a session save handler +* Source code: ext/sqlite/sess_sqlite3.c +*/ + +ob_start(); +session_save_path(__DIR__ . "/sessiondb.sdb"); + +// create the session and set a session value +session_start(); +$_SESSION["test"] = "foo_bar"; + +// close the session and unset the value +session_write_close(); +unset($_SESSION["test"]); +var_dump(isset($_SESSION["test"])); + +// start the session again and check that we have the proper value +session_start(); +var_dump($_SESSION["test"]); +ob_end_flush(); +?> +--EXPECTF-- +bool(false) +%unicode|string%(7) "foo_bar" +--CLEAN-- +<?php + unlink(__DIR__ . "/sessiondb.sdb") +?> Index: ext/sqlite3/config.w32 =================================================================== --- ext/sqlite3/config.w32 (revision 310704) +++ ext/sqlite3/config.w32 (working copy) @@ -5,7 +5,7 @@ if (PHP_SQLITE3 != "no") { ADD_FLAG("CFLAGS_SQLITE3", "/D SQLITE_THREADSAFE=" + (PHP_ZTS == "yes" ? "1" : "0") + " /D SQLITE_ENABLE_FTS3=1 /D SQLITE_ENABLE_COLUMN_METADATA=1 /D SQLITE_CORE=1 "); - EXTENSION("sqlite3", "sqlite3.c", null, "/I" + configure_module_dirname + "/libsqlite /I" + configure_module_dirname); + EXTENSION("sqlite3", "sqlite3.c sess_sqlite3.c", null, "/I" + configure_module_dirname + "/libsqlite /I" + configure_module_dirname); ADD_SOURCES(configure_module_dirname + "/libsqlite", "sqlite3.c", "sqlite3"); Index: ext/sqlite3/sqlite3.c =================================================================== --- ext/sqlite3/sqlite3.c (revision 310704) +++ ext/sqlite3/sqlite3.c (working copy) @@ -25,6 +25,9 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" +#include "ext/standard/info.h" +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) +#include "ext/session/php_session.h" #include "php_sqlite3.h" #include "php_sqlite3_structs.h" #include "main/SAPI.h" @@ -38,6 +41,12 @@ ZEND_DECLARE_MODULE_GLOBALS(sqlite3) static PHP_GINIT_FUNCTION(sqlite3); + +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) +extern ps_module ps_mod_sqlite3; +#define ps_sqlite3_ptr &ps_mod_sqlite3 +#endif + static int php_sqlite3_authorizer(void *autharg, int access_type, const char *arg3, const char *arg4, const char *arg5, const char *arg6); static void sqlite3_param_dtor(void *data); static int php_sqlite3_compare_stmt_zval_free(php_sqlite3_free_list **free_list, zval *statement); @@ -2114,6 +2123,10 @@ php_sqlite3_result_entry = zend_register_internal_class(&ce TSRMLS_CC); REGISTER_INI_ENTRIES(); + +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) + php_session_register_module(ps_sqlite3_ptr); +#endif REGISTER_LONG_CONSTANT("SQLITE3_ASSOC", PHP_SQLITE3_ASSOC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQLITE3_NUM", PHP_SQLITE3_NUM, CONST_CS | CONST_PERSISTENT); @@ -2165,6 +2178,16 @@ } /* }}} */ +/* {{{ sqlite3_module_dep +*/ +static const zend_module_dep sqlite3_deps[] = { +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) + ZEND_MOD_REQUIRED("session") +#endif + {NULL, NULL, NULL} +}; +/* }}} */ + /* {{{ sqlite3_module_entry */ zend_module_entry sqlite3_module_entry = { Index: ext/sqlite3/sess_sqlite3.c =================================================================== --- ext/sqlite3/sess_sqlite3.c (revision 0) +++ ext/sqlite3/sess_sqlite3.c (revision 0) @@ -0,0 +1,190 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2011 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 | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: John Coggeshall <john@php.net> | + | Wez Furlong <wez@thebrainroom.com> | + | Stealth35 <jinmoku@hotmail.com> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#include "php.h" + +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) + +#include "ext/session/php_session.h" +#include "ext/standard/php_lcg.h" +#include <sqlite3.h> +#define SQLITE_RETVAL(__r) ((__r) == SQLITE_OK ? SUCCESS : FAILURE) +#define PS_SQLITE_DATA sqlite3 *db = (sqlite3*)PS_GET_MOD_DATA() + +PS_FUNCS(sqlite3); + +extern ps_module ps_mod_sqlite3 = { + PS_MOD(sqlite3) +}; + +PS_OPEN_FUNC(sqlite3) +{ + int rc; + sqlite3 *db; + + /* TODO: do we need a safe_mode check here? */ + rc = sqlite3_open(save_path, &db); + if (rc) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SQLite: failed to open/create session database `%s' - %s", save_path, sqlite3_errmsg(db)); + return FAILURE; + } + + /* allow up to 1 minute when busy */ + sqlite3_busy_timeout(db, 60000); + + sqlite3_exec(db, "PRAGMA default_synchronous = OFF", NULL, NULL, NULL); + sqlite3_exec(db, "PRAGMA count_changes = OFF", NULL, NULL, NULL); + + /* This will fail if the table already exists, but that's not a big problem. I'm + unclear as to how to check for a table's existence in SQLite -- that would be better here. */ + sqlite3_exec(db, + "CREATE TABLE session_data (" + " sess_id PRIMARY KEY," + " value TEXT, " + " updated INTEGER " + ")", NULL, NULL, NULL); + + PS_SET_MOD_DATA(db); + + return SUCCESS; +} + +PS_CLOSE_FUNC(sqlite3) +{ + PS_SQLITE_DATA; + + sqlite3_close(db); + + return SUCCESS; +} + +PS_READ_FUNC(sqlite3) +{ + PS_SQLITE_DATA; + char *query; + const char *tail; + sqlite3_stmt *stmt; + int result; + const char *rowdata; + + *val = NULL; + + query = sqlite3_mprintf("SELECT value FROM session_data WHERE sess_id='%q' LIMIT 1", key); + if (query == NULL) { + /* no memory */ + return FAILURE; + } + + if (sqlite3_prepare(db, query, strlen(query) + 1, &stmt, &tail) != SQLITE_OK) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: Could not compile session read query: %s", sqlite3_errmsg(db)); + sqlite3_free(query); + return FAILURE; + } + + result = sqlite3_step(stmt); + if(result == SQLITE_ROW) { + *vallen = sqlite3_column_bytes(stmt, 0); + rowdata = sqlite3_column_text(stmt, 0); + if (*vallen) { + *val = emalloc(*vallen); + memcpy(*val, rowdata, *vallen); + (*val)[*vallen] = '\0'; + } else { + *val = STR_EMPTY_ALLOC(); + } + } + + if (SQLITE_OK != sqlite3_finalize(stmt)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session read: error %s", sqlite3_errmsg(db)); + } + + sqlite3_free(query); + + return *val == NULL ? FAILURE : SUCCESS; +} + +PS_WRITE_FUNC(sqlite3) +{ + PS_SQLITE_DATA; + char *error; + char *query; + time_t t; + int rv; + + t = time(NULL); + + query = sqlite3_mprintf("REPLACE INTO session_data VALUES('%q', '%q', %d)", key, val, t); + rv = sqlite3_exec(db, query, NULL, NULL, &error); + if (rv != SQLITE_OK) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session write query failed: %s", error); + sqlite3_free(error); + } + sqlite3_free(query); + + return SQLITE_RETVAL(rv); +} + +PS_DESTROY_FUNC(sqlite3) +{ + char *query; + int rv; + PS_SQLITE_DATA; + + query = sqlite3_mprintf("DELETE FROM session_data WHERE sess_id='%q'", key); + rv = sqlite3_exec(db, query, NULL, NULL, NULL); +sqlite3_free(query); + + return SQLITE_RETVAL(rv); +} + +PS_GC_FUNC(sqlite3) +{ + PS_SQLITE_DATA; + char *query; + int rv; + time_t t = time(NULL); + + query = sqlite3_mprintf("DELETE FROM session_data WHERE (%d - updated) > %d", t, maxlifetime); + rv = sqlite3_exec(db, query, NULL, NULL, NULL); + sqlite3_free(query); + + /* because SQLite does not actually clear the deleted data from the database + * we need to occassionaly do so manually to prevent the sessions database + * from growing endlessly. + */ + if ((int) ((float) PS(gc_divisor) * PS(gc_divisor) * php_combined_lcg(TSRMLS_C)) < PS(gc_probability)) { + rv = sqlite3_exec(db, "VACUUM", NULL, NULL, NULL); + } + return SQLITE_RETVAL(rv); +} + +#endif /* HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ \ No newline at end of file |
Copyright © 2001-2024 The PHP Group All rights reserved. |
Last updated: Thu Nov 21 23:01:29 2024 UTC |