You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.4 KiB

23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2008 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. | Authors: John Coggeshall <john@php.net> |
  16. | Wez Furlong <wez@thebrainroom.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. #include "php.h"
  21. #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
  22. #include "ext/session/php_session.h"
  23. #include "ext/standard/php_lcg.h"
  24. #include <sqlite.h>
  25. #define SQLITE_RETVAL(__r) ((__r) == SQLITE_OK ? SUCCESS : FAILURE)
  26. #define PS_SQLITE_DATA sqlite *db = (sqlite*)PS_GET_MOD_DATA()
  27. extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
  28. extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
  29. PS_FUNCS(sqlite);
  30. ps_module ps_mod_sqlite = {
  31. PS_MOD(sqlite)
  32. };
  33. PS_OPEN_FUNC(sqlite)
  34. {
  35. char *errmsg = NULL;
  36. sqlite *db;
  37. /* TODO: do we need a safe_mode check here? */
  38. db = sqlite_open(save_path, 0666, &errmsg);
  39. if (db == NULL) {
  40. php_error_docref(NULL TSRMLS_CC, E_WARNING,
  41. "SQLite: failed to open/create session database `%s' - %s", save_path, errmsg);
  42. sqlite_freemem(errmsg);
  43. return FAILURE;
  44. }
  45. /* allow up to 1 minute when busy */
  46. sqlite_busy_timeout(db, 60000);
  47. sqlite_exec(db, "PRAGMA default_synchronous = OFF", NULL, NULL, NULL);
  48. sqlite_exec(db, "PRAGMA count_changes = OFF", NULL, NULL, NULL);
  49. /* This will fail if the table already exists, but that's not a big problem. I'm
  50. unclear as to how to check for a table's existence in SQLite -- that would be better here. */
  51. sqlite_exec(db,
  52. "CREATE TABLE session_data ("
  53. " sess_id PRIMARY KEY,"
  54. " value TEXT, "
  55. " updated INTEGER "
  56. ")", NULL, NULL, NULL);
  57. PS_SET_MOD_DATA(db);
  58. return SUCCESS;
  59. }
  60. PS_CLOSE_FUNC(sqlite)
  61. {
  62. PS_SQLITE_DATA;
  63. sqlite_close(db);
  64. return SUCCESS;
  65. }
  66. PS_READ_FUNC(sqlite)
  67. {
  68. PS_SQLITE_DATA;
  69. char *query;
  70. const char *tail;
  71. sqlite_vm *vm;
  72. int colcount, result;
  73. const char **rowdata, **colnames;
  74. char *error;
  75. *val = NULL;
  76. *vallen = 0;
  77. query = sqlite_mprintf("SELECT value FROM session_data WHERE sess_id='%q' LIMIT 1", key);
  78. if (query == NULL) {
  79. /* no memory */
  80. return FAILURE;
  81. }
  82. if (sqlite_compile(db, query, &tail, &vm, &error) != SQLITE_OK) {
  83. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: Could not compile session read query: %s", error);
  84. sqlite_freemem(error);
  85. sqlite_freemem(query);
  86. return FAILURE;
  87. }
  88. switch ((result = sqlite_step(vm, &colcount, &rowdata, &colnames))) {
  89. case SQLITE_ROW:
  90. if (rowdata[0] != NULL) {
  91. *vallen = strlen(rowdata[0]);
  92. if (*vallen) {
  93. *val = emalloc(*vallen);
  94. *vallen = sqlite_decode_binary(rowdata[0], *val);
  95. (*val)[*vallen] = '\0';
  96. } else {
  97. *val = STR_EMPTY_ALLOC();
  98. }
  99. }
  100. break;
  101. default:
  102. sqlite_freemem(error);
  103. error = NULL;
  104. }
  105. if (SQLITE_OK != sqlite_finalize(vm, &error)) {
  106. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session read: error %s", error);
  107. sqlite_freemem(error);
  108. error = NULL;
  109. }
  110. sqlite_freemem(query);
  111. return *val == NULL ? FAILURE : SUCCESS;
  112. }
  113. PS_WRITE_FUNC(sqlite)
  114. {
  115. PS_SQLITE_DATA;
  116. char *error;
  117. time_t t;
  118. char *binary;
  119. int binlen;
  120. int rv;
  121. t = time(NULL);
  122. binary = safe_emalloc(1 + vallen / 254, 257, 3);
  123. binlen = sqlite_encode_binary((const unsigned char*)val, vallen, binary);
  124. rv = sqlite_exec_printf(db, "REPLACE INTO session_data VALUES('%q', '%q', %d)", NULL, NULL, &error, key, binary, t);
  125. if (rv != SQLITE_OK) {
  126. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session write query failed: %s", error);
  127. sqlite_freemem(error);
  128. }
  129. efree(binary);
  130. return SQLITE_RETVAL(rv);
  131. }
  132. PS_DESTROY_FUNC(sqlite)
  133. {
  134. int rv;
  135. PS_SQLITE_DATA;
  136. rv = sqlite_exec_printf(db, "DELETE FROM session_data WHERE sess_id='%q'", NULL, NULL, NULL, key);
  137. return SQLITE_RETVAL(rv);
  138. }
  139. PS_GC_FUNC(sqlite)
  140. {
  141. PS_SQLITE_DATA;
  142. int rv;
  143. time_t t = time(NULL);
  144. rv = sqlite_exec_printf(db,
  145. "DELETE FROM session_data WHERE (%d - updated) > %d",
  146. NULL, NULL, NULL, t, maxlifetime);
  147. /* because SQLite does not actually clear the deleted data from the database
  148. * we need to occassionaly do so manually to prevent the sessions database
  149. * from growing endlessly.
  150. */
  151. if ((int) ((float) PS(gc_divisor) * PS(gc_divisor) * php_combined_lcg(TSRMLS_C)) < PS(gc_probability)) {
  152. rv = sqlite_exec_printf(db, "VACUUM", NULL, NULL, NULL);
  153. }
  154. return SQLITE_RETVAL(rv);
  155. }
  156. #endif /* HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) */
  157. /*
  158. * Local variables:
  159. * tab-width: 4
  160. * c-basic-offset: 4
  161. * End:
  162. * vim600: sw=4 ts=4 fdm=marker
  163. * vim<600: sw=4 ts=4
  164. */