PageRenderTime 68ms CodeModel.GetById 19ms RepoModel.GetById 3ms app.codeStats 0ms

/class_safesql.php

https://bitbucket.org/ladasoukup/sb_eventlogmonitor
PHP | 267 lines | 145 code | 27 blank | 95 comment | 28 complexity | d1f5fd14586b699c79895ddaa7eeb723 MD5 | raw file
Possible License(s): Unlicense
  1. <?php
  2. /*
  3. * Project: SafeSQL: db access library extension
  4. * File: SafeSQL.class.php
  5. * Author: Monte Ohrt <monte@ispi.net>
  6. *
  7. * Version: 2.1
  8. * Date: August 13, 2004
  9. * Copyright: 2001,2002,2003,2004 ispi of Lincoln, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation; either
  14. * version 2.1 of the License, or (at your option) any later version.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. *
  25. */
  26. class SafeSQL {
  27. // values that determine dropping bracketed sections
  28. var $_drop_values = array('');
  29. /*======================================================================*\
  30. Function: SafeSQL
  31. Purpose: constructor
  32. \*======================================================================*/
  33. function SafeSQL() { }
  34. /*======================================================================*\
  35. Function: buildquery
  36. Purpose: process the query string
  37. \*======================================================================*/
  38. function query($query_string, $query_vars)
  39. {
  40. if(is_array($query_vars)) {
  41. $_var_count = count($query_vars);
  42. if($_var_count != preg_match_all('!%[sSiIfFcClLqQ]!', $query_string, $_match)) {
  43. $this->_error_msg('unmatched number of vars and % placeholders: ' . $query_string);
  44. }
  45. // get string position for each element
  46. $_var_pos = array();
  47. $_curr_pos = 0;
  48. for( $_x = 0; $_x < $_var_count; $_x++ ) {
  49. $_var_pos[$_x] = strpos($query_string, $_match[0][$_x], $_curr_pos);
  50. $_curr_pos = $_var_pos[$_x] + 1;
  51. }
  52. // build query from passed in variables, escape them
  53. // start from end of query and work backwards so string
  54. // positions are not altered during replacement
  55. $_last_removed_pos = null;
  56. $_last_var_pos = null;
  57. for( $_x = $_var_count-1; $_x >= 0; $_x-- ) {
  58. if(isset($_last_removed_pos) && $_last_removed_pos < $_var_pos[$_x]) {
  59. // already removed, skip
  60. continue;
  61. }
  62. // escape string
  63. $query_vars[$_x] = $this->_sql_escape($query_vars[$_x]);
  64. if(in_array($_match[0][$_x], array('%S','%I','%F','%C','%L','%Q'))) {
  65. // get positions of [ and ]
  66. if(isset($_last_var_pos))
  67. $_right_pos = strpos($query_string, ']', $_last_var_pos);
  68. else
  69. $_right_pos = strpos($query_string, ']', $_var_pos[$_x]);
  70. // no way to get strpos from the right side starting in the middle
  71. // of the string, so slice the first part out then find it
  72. $_str_slice = substr($query_string, 0, $_var_pos[$_x]);
  73. $_left_pos = strrpos($_str_slice, '[');
  74. if($_right_pos === false || $_left_pos === false) {
  75. $this->_error_msg('missing or unmatched brackets: ' . $query_string);
  76. }
  77. if(in_array($query_vars[$_x], $this->_drop_values, true)) {
  78. $_last_removed_pos = $_left_pos;
  79. // remove entire part of string
  80. $query_string = substr_replace($query_string, '', $_left_pos, $_right_pos - $_left_pos + 1);
  81. $_last_var_pos = null;
  82. } else if ($_x > 0 && $_var_pos[$_x-1] > $_left_pos) {
  83. // still variables left in brackets, leave them and just replace var
  84. $_convert_var = $this->_convert_var($query_vars[$_x], $_match[0][$_x]);
  85. $query_string = substr_replace($query_string, $_convert_var, $_var_pos[$_x], 2);
  86. $_last_var_pos = $_var_pos[$_x] + strlen($_convert_var);
  87. } else {
  88. // remove the brackets only, and replace %S
  89. $query_string = substr_replace($query_string, '', $_right_pos, 1);
  90. $query_string = substr_replace($query_string, $this->_convert_var($query_vars[$_x], $_match[0][$_x]), $_var_pos[$_x], 2);
  91. $query_string = substr_replace($query_string, '', $_left_pos, 1);
  92. $_last_var_pos = null;
  93. }
  94. } else {
  95. $query_string = substr_replace($query_string, $this->_convert_var($query_vars[$_x], $_match[0][$_x]), $_var_pos[$_x], 2);
  96. }
  97. }
  98. }
  99. return $query_string;
  100. }
  101. /*======================================================================*\
  102. Function: _convert_var
  103. Purpose: convert a variable to the given type
  104. Input: $var - the variable
  105. $type - the type to convert to:
  106. %i, %I - cast to integer
  107. %f, %F - cast to float
  108. %c, %C - comma separate, cast each element to integer
  109. %l, %L - comma separate, no quotes, no casting
  110. %q, %Q - quote/comma separate
  111. \*======================================================================*/
  112. function _convert_var($var, $type) {
  113. switch($type) {
  114. case '%i':
  115. case '%I':
  116. // cast to integer
  117. settype($var, 'integer');
  118. break;
  119. case '%f':
  120. case '%F':
  121. // cast to float
  122. settype($var, 'float');
  123. break;
  124. case '%c':
  125. case '%C':
  126. // comma separate
  127. settype($var, 'array');
  128. for($_x = 0 , $_y = count($var); $_x < $_y; $_x++) {
  129. // cast to integers
  130. settype($var[$_x], 'integer');
  131. }
  132. $var = implode(',', $var);
  133. if($var == '') {
  134. // force 0, keep syntax from breaking
  135. $var = '0';
  136. }
  137. break;
  138. case '%l':
  139. case '%L':
  140. // comma separate
  141. settype($var, 'array');
  142. $var = implode(',', $var);
  143. break;
  144. case '%q':
  145. case '%Q':
  146. settype($var, 'array');
  147. // quote comma separate
  148. $var = "'" . implode("','", $var) . "'";
  149. break;
  150. }
  151. return $var;
  152. }
  153. /*======================================================================*\
  154. Function: error
  155. Purpose: handle error messages
  156. \*======================================================================*/
  157. function _error_msg($error_msg) {
  158. trigger_error('SafeSQL: ' . $error_msg);
  159. }
  160. /*======================================================================*\
  161. Function: SetDropValues
  162. Purpose:
  163. \*======================================================================*/
  164. function set_drop_values($drop_values) {
  165. if(is_array($drop_values)) {
  166. $this->_drop_values = $drop_values;
  167. } else {
  168. $this->_error_msg('drop values must be an array');
  169. }
  170. }
  171. /*======================================================================*\
  172. Function: GetDropValues
  173. Purpose:
  174. \*======================================================================*/
  175. function get_drop_values() {
  176. return $this->_drop_values;
  177. }
  178. /*======================================================================*\
  179. Function: _sql_escape
  180. Purpose: method overridden by subclass
  181. \*======================================================================*/
  182. function _sql_escape() { }
  183. }
  184. class SafeSQL_MySQL extends SafeSQL {
  185. var $_link_id;
  186. /*======================================================================*\
  187. Function: SafeSQL_MySQL
  188. Purpose: constructor
  189. \*======================================================================*/
  190. function SafeSQL_MySQL($link_id = null) {
  191. $this->_link_id = $link_id;
  192. }
  193. /*======================================================================*\
  194. Function: _sql_escape
  195. Purpose: recursively escape variables/arrays for SQL use
  196. \*======================================================================*/
  197. function _sql_escape($var) {
  198. if(is_array($var)) {
  199. foreach($var as $_element) {
  200. $_newvar[] = $this->_sql_escape($_element);
  201. }
  202. return $_newvar;
  203. }
  204. if(function_exists('mysql_real_escape_string')) {
  205. if(!isset($this->_link_id)) {
  206. return mysql_real_escape_string($var);
  207. } else {
  208. return mysql_real_escape_string($var, $this->_link_id);
  209. }
  210. } elseif(function_exists('mysql_escape_string')) {
  211. return mysql_escape_string($var);
  212. } else {
  213. return addslashes($var);
  214. }
  215. break;
  216. }
  217. }
  218. class SafeSQL_ANSI extends SafeSQL {
  219. /*======================================================================*\
  220. Function: SafeSQL_ANSI
  221. Purpose: constructor
  222. \*======================================================================*/
  223. function SafeSQL_ANSI() { }
  224. /*======================================================================*\
  225. Function: _sql_escape
  226. Purpose: recursively escape variables/arrays for SQL use
  227. \*======================================================================*/
  228. function _sql_escape($var) {
  229. if(is_array($var)) {
  230. foreach($var as $_element) {
  231. $_newvar[] = $this->_sql_escape($_element);
  232. }
  233. return $_newvar;
  234. }
  235. return str_replace("'", "''", $var);
  236. break;
  237. }
  238. }
  239. ?>