|
1 <?php |
|
2 |
|
3 /* |
|
4 * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between |
|
5 * Version 1.0 (Banshee) |
|
6 * Copyright (C) 2006-2007 Dan Fuhry |
|
7 * |
|
8 * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License |
|
9 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
|
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
|
13 */ |
|
14 |
|
15 function db_error_handler($errno, $errstr, $errfile = false, $errline = false, $errcontext = Array() ) |
|
16 { |
|
17 if ( !defined('ENANO_DEBUG') ) |
|
18 return; |
|
19 $e = error_reporting(0); |
|
20 error_reporting($e); |
|
21 if ( $e < $errno ) |
|
22 return; |
|
23 $errtype = 'Notice'; |
|
24 switch ( $errno ) |
|
25 { |
|
26 case E_ERROR: case E_USER_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: $errtype = 'Error'; break; |
|
27 case E_WARNING: case E_USER_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: $errtype = 'Warning'; break; |
|
28 } |
|
29 $debug = debug_backtrace(); |
|
30 $debug = $debug[2]['file'] . ', line ' . $debug[2]['line']; |
|
31 echo "<b>$errtype:</b> $errstr<br />Error source:<pre>$debug</pre>"; |
|
32 } |
|
33 |
|
34 class mysql { |
|
35 var $num_queries, $query_backtrace, $latest_result, $latest_query, $_conn, $sql_stack_fields, $sql_stack_values; |
|
36 var $row = array(); |
|
37 var $rowset = array(); |
|
38 var $errhandler; |
|
39 |
|
40 function enable_errorhandler() |
|
41 { |
|
42 if ( function_exists('debug_backtrace') ) |
|
43 { |
|
44 $this->errhandler = set_error_handler('db_error_handler'); |
|
45 } |
|
46 } |
|
47 |
|
48 function disable_errorhandler() |
|
49 { |
|
50 if ( $this->errhandler ) |
|
51 { |
|
52 set_error_handler($this->errhandler); |
|
53 } |
|
54 else |
|
55 { |
|
56 restore_error_handler(); |
|
57 } |
|
58 } |
|
59 |
|
60 function sql_backtrace() { |
|
61 $qb = explode("\n", $this->query_backtrace); |
|
62 $bt = ''; |
|
63 //for($i=sizeof($qb)-1;$i>=0;$i--) { |
|
64 for($i=0;$i<sizeof($qb);$i++) { |
|
65 $bt .= $qb[$i]."\n"; |
|
66 } |
|
67 return $bt; |
|
68 } |
|
69 |
|
70 function ensure_connection() |
|
71 { |
|
72 if(!$this->_conn) |
|
73 { |
|
74 $this->connect(); |
|
75 } |
|
76 } |
|
77 |
|
78 function _die($t = '') { |
|
79 if(defined('ENANO_HEADERS_SENT')) { |
|
80 ob_clean(); |
|
81 } |
|
82 header('HTTP/1.1 500 Internal Server Error'); |
|
83 $bt = $this->sql_backtrace(); |
|
84 $e = htmlspecialchars(mysql_error()); |
|
85 if($e=='') $e='<none>'; |
|
86 if(defined('ENANO_CONFIG_FETCHED')) die_semicritical('Database error', '<h3>An error occurred during a database query.</h3><p>'.$t.'<br />Error returned by MySQL: '.$e.'<br />SQL Backtrace:</p><pre>'.$bt.'</pre>'); |
|
87 else grinding_halt('Database error', '<h3>An error occurred during a database query.</h3><p>'.$t.'<br />Error returned by MySQL: '.$e.'<br />SQL Backtrace:</p><pre>'.$bt.'</pre>'); |
|
88 exit; |
|
89 } |
|
90 |
|
91 function die_json() |
|
92 { |
|
93 $e = addslashes(htmlspecialchars(mysql_error())); |
|
94 $q = addslashes($this->latest_query); |
|
95 $t = "{'mode':'error','error':'An error occurred during database query.\nQuery was:\n $q\n\nError returned by MySQL: $e'}"; |
|
96 die($t); |
|
97 } |
|
98 |
|
99 function get_error($t = '') { |
|
100 header('HTTP/1.1 500 Internal Server Error'); |
|
101 $bt = $this->sql_backtrace(); |
|
102 $e = htmlspecialchars(mysql_error()); |
|
103 if($e=='') $e='<none>'; |
|
104 $text = '<h3>An error occurred during a database query.</h3><p>'.$t.'<br />Error returned by MySQL: '.$e.'<br />SQL Backtrace:</p><pre>'.$bt.'</pre>'; |
|
105 return $text; |
|
106 } |
|
107 |
|
108 function connect() { |
|
109 $this->enable_errorhandler(); |
|
110 dc_here('dbal: trying to connect....'); |
|
111 @include(ENANO_ROOT.'/config.php'); |
|
112 if(isset($crypto_key)) |
|
113 unset($crypto_key); // Get this sucker out of memory fast |
|
114 if(!defined('ENANO_INSTALLED') && !defined('MIDGET_INSTALLED') && !defined('IN_ENANO_INSTALL') ) |
|
115 { |
|
116 dc_here('dbal: oops, looks like Enano isn\'t set up. Constants ENANO_INSTALLED, MIDGET_INSTALLED, and IN_ENANO_INSTALL are all undefined.'); |
|
117 header('Location: install.php'); |
|
118 exit; |
|
119 } |
|
120 $this->_conn = @mysql_connect($dbhost, $dbuser, $dbpasswd); |
|
121 unset($dbuser); |
|
122 unset($dbpasswd); // Security |
|
123 if(!$this->_conn) { dc_here('dbal: uhoh!<br />'.mysql_error()); grinding_halt('Enano is having a problem', '<p>Error: couldn\'t connect to MySQL.<br />'.mysql_error().'</p>'); } |
|
124 $this->query_backtrace = ''; |
|
125 $this->num_queries = 0; |
|
126 dc_here('dbal: we\'re in, selecting database...'); |
|
127 $q = $this->sql_query('USE '.$dbname.';'); |
|
128 if(!$q) $this->_die('The database could not be selected.'); |
|
129 dc_here('dbal: connected to MySQL'); |
|
130 $this->disable_errorhandler(); |
|
131 } |
|
132 |
|
133 function sql_query($q) { |
|
134 $this->enable_errorhandler(); |
|
135 $this->num_queries++; |
|
136 $this->query_backtrace .= $q."\n"; |
|
137 $this->latest_query = $q; |
|
138 dc_here('dbal: making SQL query:<br /><tt>'.$q.'</tt>'); |
|
139 if(!$this->_conn) $this->_die('A database connection has not yet been established.'); |
|
140 if(!$this->check_query($q)) |
|
141 { |
|
142 $this->report_query($q); |
|
143 grinding_halt('SQL Injection attempt', '<p>Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.</p><p>Query was:</p><pre>'.htmlspecialchars($q).'</pre>'); |
|
144 } |
|
145 $r = mysql_query($q, $this->_conn); |
|
146 $this->latest_result = $r; |
|
147 $this->disable_errorhandler(); |
|
148 return $r; |
|
149 } |
|
150 |
|
151 function sql_unbuffered_query($q) { |
|
152 $this->enable_errorhandler(); |
|
153 $this->num_queries++; |
|
154 $this->query_backtrace .= '(UNBUFFERED) ' . $q."\n"; |
|
155 $this->latest_query = $q; |
|
156 dc_here('dbal: making SQL query:<br /><tt>'.$q.'</tt>'); |
|
157 if(!$this->_conn) $this->_die('A database connection has not yet been established.'); |
|
158 if(!$this->check_query($q)) |
|
159 { |
|
160 $this->report_query($q); |
|
161 grinding_halt('SQL Injection attempt', '<p>Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.</p><p>Query was:</p><pre>'.htmlspecialchars($q).'</pre>'); |
|
162 } |
|
163 $r = mysql_unbuffered_query($q, $this->_conn); |
|
164 $this->latest_result = $r; |
|
165 $this->disable_errorhandler(); |
|
166 return $r; |
|
167 } |
|
168 |
|
169 /** |
|
170 * Checks a SQL query for possible signs of injection attempts |
|
171 * @param string $q the query to check |
|
172 * @return bool true if query passed check, otherwise false |
|
173 */ |
|
174 |
|
175 function check_query($q, $debug = false) |
|
176 { |
|
177 if($debug) echo "\$db->check_query(): checking query: ".htmlspecialchars($q).'<br />'."\n"; |
|
178 $sz = strlen($q); |
|
179 $quotechar = false; |
|
180 $quotepos = 0; |
|
181 $prev_is_quote = false; |
|
182 $just_started = false; |
|
183 for($i=0;$i<strlen($q);$i++,$c=substr($q, $i, 1)) |
|
184 { |
|
185 $next = substr($q, $i+1, 1); |
|
186 $next2 = substr($q, $i+2, 1); |
|
187 $prev = substr($q, $i-1, 1); |
|
188 $prev2 = substr($q, $i-2, 1); |
|
189 if(isset($c) && in_array($c, Array('"', "'", '`'))) |
|
190 { |
|
191 if($quotechar) |
|
192 { |
|
193 if( |
|
194 ( $quotechar == $c && $quotechar != $next && ( $quotechar != $prev || $just_entered ) && $prev != '\\') || |
|
195 ( $prev2 == '\\' && $prev == $quotechar && $quotechar == $c ) |
|
196 ) |
|
197 { |
|
198 $quotechar = false; |
|
199 if($debug) echo('$db->check_query(): just finishing a quote section, quoted string: '.htmlspecialchars(substr($q, $quotepos, $i - $quotepos + 1)) . '<br />'); |
|
200 $q = substr($q, 0, $quotepos) . 'SAFE_QUOTE' . substr($q, $i + 1, strlen($q)); |
|
201 if($debug) echo('$db->check_query(): Filtered query: '.$q.'<br />'); |
|
202 $i = $quotepos; |
|
203 } |
|
204 } |
|
205 else |
|
206 { |
|
207 $quotechar = $c; |
|
208 $quotepos = $i; |
|
209 $just_entered = true; |
|
210 } |
|
211 if($debug) echo '$db->check_query(): found quote char as pos: '.$i.'<br />'; |
|
212 continue; |
|
213 } |
|
214 $just_entered = false; |
|
215 } |
|
216 if(substr(trim($q), strlen(trim($q))-1, 1) == ';') $q = substr(trim($q), 0, strlen(trim($q))-1); |
|
217 for($i=0;$i<strlen($q);$i++,$c=substr($q, $i, 1)) |
|
218 { |
|
219 if( ( $c == ';' && $i != $sz-1 ) || $c . substr($q, $i+1, 1) == '--') // Don't permit semicolons in mid-query, and never allow comments |
|
220 { |
|
221 // Injection attempt! |
|
222 if($debug) |
|
223 { |
|
224 $e = ''; |
|
225 for($j=$i-5;$j<$i+5;$j++) |
|
226 { |
|
227 if($j == $i) $e .= '<span style="color: red; text-decoration: underline;">' . $c . '</span>'; |
|
228 else $e .= $c; |
|
229 } |
|
230 echo 'Injection attempt caught at pos: '.$i.'<br />'; |
|
231 } |
|
232 return false; |
|
233 } |
|
234 } |
|
235 return true; |
|
236 } |
|
237 |
|
238 /** |
|
239 * Set the internal result pointer to X |
|
240 * @param int $pos The number of the row |
|
241 * @param resource $result The MySQL result resource - if not given, the latest cached query is assumed |
|
242 * @return true on success, false on failure |
|
243 */ |
|
244 |
|
245 function sql_data_seek($pos, $result = false) |
|
246 { |
|
247 $this->enable_errorhandler(); |
|
248 if(!$result) |
|
249 $result = $this->latest_result; |
|
250 if(!$result) |
|
251 { |
|
252 $this->disable_errorhandler(); |
|
253 return false; |
|
254 } |
|
255 if(mysql_data_seek($result, $pos)) |
|
256 { |
|
257 $this->disable_errorhandler(); |
|
258 return true; |
|
259 } |
|
260 else |
|
261 { |
|
262 $this->disable_errorhandler(); |
|
263 return false; |
|
264 } |
|
265 } |
|
266 |
|
267 /** |
|
268 * Reports a bad query to the admin |
|
269 * @param string $query the naughty query |
|
270 * @access private |
|
271 */ |
|
272 |
|
273 function report_query($query) |
|
274 { |
|
275 global $session; |
|
276 if(is_object($session) && defined('ENANO_MAINSTREAM')) |
|
277 $username = $session->username; |
|
278 else |
|
279 $username = 'Unavailable'; |
|
280 $query = $this->escape($query); |
|
281 $q = $this->sql_query('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, page_text, author, edit_summary) |
|
282 VALUES(\'security\', \'sql_inject\', '.time().', \'\', \''.$query.'\', \''.$username.'\', \''.$_SERVER['REMOTE_ADDR'].'\');'); |
|
283 } |
|
284 |
|
285 function fetchrow($r = false) { |
|
286 $this->enable_errorhandler(); |
|
287 if(!$this->_conn) return false; |
|
288 if(!$r) $r = $this->latest_result; |
|
289 if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); |
|
290 $row = mysql_fetch_assoc($r); |
|
291 $this->disable_errorhandler(); |
|
292 return $row; |
|
293 } |
|
294 |
|
295 function fetchrow_num($r = false) { |
|
296 $this->enable_errorhandler(); |
|
297 if(!$r) $r = $this->latest_result; |
|
298 if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); |
|
299 $row = mysql_fetch_row($r); |
|
300 $this->disable_errorhandler(); |
|
301 return $row; |
|
302 } |
|
303 |
|
304 function numrows($r = false) { |
|
305 $this->enable_errorhandler(); |
|
306 if(!$r) $r = $this->latest_result; |
|
307 if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); |
|
308 $n = mysql_num_rows($r); |
|
309 $this->disable_errorhandler(); |
|
310 return $n; |
|
311 } |
|
312 |
|
313 function escape($str) |
|
314 { |
|
315 $this->enable_errorhandler(); |
|
316 $str = mysql_real_escape_string($str); |
|
317 $this->disable_errorhandler(); |
|
318 return $str; |
|
319 } |
|
320 |
|
321 function free_result($result = false) |
|
322 { |
|
323 $this->enable_errorhandler(); |
|
324 if(!$result) |
|
325 $result = $this->latest_result; |
|
326 if(!$result) |
|
327 { |
|
328 $this->disable_errorhandler(); |
|
329 return null; |
|
330 } |
|
331 mysql_free_result($result); |
|
332 $this->disable_errorhandler(); |
|
333 return null; |
|
334 } |
|
335 |
|
336 function close() { |
|
337 dc_here('dbal: closing MySQL connection'); |
|
338 mysql_close($this->_conn); |
|
339 unset($this->_conn); |
|
340 } |
|
341 |
|
342 // phpBB DBAL compatibility |
|
343 function sql_fetchrow($r = false) |
|
344 { |
|
345 return $this->fetchrow($r); |
|
346 } |
|
347 function sql_freeresult($r = false) |
|
348 { |
|
349 if(!$this->_conn) return false; |
|
350 if(!$r) $r = $this->latest_result; |
|
351 if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); |
|
352 mysql_free_result($r); |
|
353 } |
|
354 function sql_numrows($r = false) |
|
355 { |
|
356 if(!$this->_conn) return false; |
|
357 if(!$r) $r = $this->latest_result; |
|
358 if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); |
|
359 return mysql_num_rows($r); |
|
360 } |
|
361 function sql_affectedrows($r = false, $f, $n) |
|
362 { |
|
363 if(!$this->_conn) return false; |
|
364 if(!$r) $r = $this->latest_result; |
|
365 if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.'); |
|
366 return mysql_affected_rows(); |
|
367 } |
|
368 |
|
369 function sql_type_cast(&$value) |
|
370 { |
|
371 if ( is_float($value) ) |
|
372 { |
|
373 return doubleval($value); |
|
374 } |
|
375 if ( is_integer($value) || is_bool($value) ) |
|
376 { |
|
377 return intval($value); |
|
378 } |
|
379 if ( is_string($value) || empty($value) ) |
|
380 { |
|
381 return '\'' . $this->sql_escape_string($value) . '\''; |
|
382 } |
|
383 // uncastable var : let's do a basic protection on it to prevent sql injection attempt |
|
384 return '\'' . $this->sql_escape_string(htmlspecialchars($value)) . '\''; |
|
385 } |
|
386 |
|
387 function sql_statement(&$fields, $fields_inc='') |
|
388 { |
|
389 // init result |
|
390 $this->sql_fields = $this->sql_values = $this->sql_update = ''; |
|
391 if ( empty($fields) && empty($fields_inc) ) |
|
392 { |
|
393 return; |
|
394 } |
|
395 |
|
396 // process |
|
397 if ( !empty($fields) ) |
|
398 { |
|
399 $first = true; |
|
400 foreach ( $fields as $field => $value ) |
|
401 { |
|
402 // field must contain a field name |
|
403 if ( !empty($field) && is_string($field) ) |
|
404 { |
|
405 $value = $this->sql_type_cast($value); |
|
406 $this->sql_fields .= ( $first ? '' : ', ' ) . $field; |
|
407 $this->sql_values .= ( $first ? '' : ', ' ) . $value; |
|
408 $this->sql_update .= ( $first ? '' : ', ' ) . $field . ' = ' . $value; |
|
409 $first = false; |
|
410 } |
|
411 } |
|
412 } |
|
413 if ( !empty($fields_inc) ) |
|
414 { |
|
415 foreach ( $fields_inc as $field => $indent ) |
|
416 { |
|
417 if ( $indent != 0 ) |
|
418 { |
|
419 $this->sql_update .= (empty($this->sql_update) ? '' : ', ') . $field . ' = ' . $field . ($indent < 0 ? ' - ' : ' + ') . abs($indent); |
|
420 } |
|
421 } |
|
422 } |
|
423 } |
|
424 |
|
425 function sql_stack_reset($id='') |
|
426 { |
|
427 if ( empty($id) ) |
|
428 { |
|
429 $this->sql_stack_fields = array(); |
|
430 $this->sql_stack_values = array(); |
|
431 } |
|
432 else |
|
433 { |
|
434 $this->sql_stack_fields[$id] = array(); |
|
435 $this->sql_stack_values[$id] = array(); |
|
436 } |
|
437 } |
|
438 |
|
439 function sql_stack_statement(&$fields, $id='') |
|
440 { |
|
441 $this->sql_statement($fields); |
|
442 if ( empty($id) ) |
|
443 { |
|
444 $this->sql_stack_fields = $this->sql_fields; |
|
445 $this->sql_stack_values[] = '(' . $this->sql_values . ')'; |
|
446 } |
|
447 else |
|
448 { |
|
449 $this->sql_stack_fields[$id] = $this->sql_fields; |
|
450 $this->sql_stack_values[$id][] = '(' . $this->sql_values . ')'; |
|
451 } |
|
452 } |
|
453 |
|
454 function sql_stack_insert($table, $transaction=false, $line='', $file='', $break_on_error=true, $id='') |
|
455 { |
|
456 if ( (empty($id) && empty($this->sql_stack_values)) || (!empty($id) && empty($this->sql_stack_values[$id])) ) |
|
457 { |
|
458 return false; |
|
459 } |
|
460 switch( SQL_LAYER ) |
|
461 { |
|
462 case 'mysql': |
|
463 case 'mysql4': |
|
464 if ( empty($id) ) |
|
465 { |
|
466 $sql = 'INSERT INTO ' . $table . ' |
|
467 (' . $this->sql_stack_fields . ') VALUES ' . implode(",\n", $this->sql_stack_values); |
|
468 } |
|
469 else |
|
470 { |
|
471 $sql = 'INSERT INTO ' . $table . ' |
|
472 (' . $this->sql_stack_fields[$id] . ') VALUES ' . implode(",\n", $this->sql_stack_values[$id]); |
|
473 } |
|
474 $this->sql_stack_reset($id); |
|
475 return $this->sql_query($sql, $transaction, $line, $file, $break_on_error); |
|
476 break; |
|
477 default: |
|
478 $count_sql_stack_values = empty($id) ? count($this->sql_stack_values) : count($this->sql_stack_values[$id]); |
|
479 $result = !empty($count_sql_stack_values); |
|
480 for ( $i = 0; $i < $count_sql_stack_values; $i++ ) |
|
481 { |
|
482 if ( empty($id) ) |
|
483 { |
|
484 $sql = 'INSERT INTO ' . $table . ' |
|
485 (' . $this->sql_stack_fields . ') VALUES ' . $this->sql_stack_values[$i]; |
|
486 } |
|
487 else |
|
488 { |
|
489 $sql = 'INSERT INTO ' . $table . ' |
|
490 (' . $this->sql_stack_fields[$id] . ') VALUES ' . $this->sql_stack_values[$id][$i]; |
|
491 } |
|
492 $result &= $this->sql_query($sql, $transaction, $line, $file, $break_on_error); |
|
493 } |
|
494 $this->sql_stack_reset($id); |
|
495 return $result; |
|
496 break; |
|
497 } |
|
498 } |
|
499 |
|
500 function sql_subquery($field, $sql, $line='', $file='', $break_on_error=true, $type=TYPE_INT) |
|
501 { |
|
502 // sub-queries doable |
|
503 $this->sql_get_version(); |
|
504 if ( !in_array(SQL_LAYER, array('mysql', 'mysql4')) || (($this->sql_version[0] + ($this->sql_version[1] / 100)) >= 4.01) ) |
|
505 { |
|
506 return $sql; |
|
507 } |
|
508 |
|
509 // no sub-queries |
|
510 $ids = array(); |
|
511 $result = $this->sql_query(trim($sql), false, $line, $file, $break_on_error); |
|
512 while ( $row = $this->sql_fetchrow($result) ) |
|
513 { |
|
514 $ids[] = $type == TYPE_INT ? intval($row[$field]) : '\'' . $this->sql_escape_string($row[$field]) . '\''; |
|
515 } |
|
516 $this->sql_freeresult($result); |
|
517 return empty($ids) ? 'NULL' : implode(', ', $ids); |
|
518 } |
|
519 |
|
520 function sql_col_id($expr, $alias) |
|
521 { |
|
522 $this->sql_get_version(); |
|
523 return in_array(SQL_LAYER, array('mysql', 'mysql4')) && (($this->sql_version[0] + ($this->sql_version[1] / 100)) <= 4.01) ? $alias : $expr; |
|
524 } |
|
525 |
|
526 function sql_get_version() |
|
527 { |
|
528 if ( empty($this->sql_version) ) |
|
529 { |
|
530 $this->sql_version = array(0, 0, 0); |
|
531 switch ( SQL_LAYER ) |
|
532 { |
|
533 case 'mysql': |
|
534 case 'mysql4': |
|
535 if ( function_exists('mysql_get_server_info') ) |
|
536 { |
|
537 $lo_version = explode('-', mysql_get_server_info()); |
|
538 $this->sql_version = explode('.', $lo_version[0]); |
|
539 $this->sql_version = array(intval($this->sql_version[0]), intval($this->sql_version[1]), intval($this->sql_version[2]), $lo_version[1]); |
|
540 } |
|
541 break; |
|
542 |
|
543 case 'postgresql': |
|
544 case 'mssql': |
|
545 case 'mssql-odbc': |
|
546 default: |
|
547 break; |
|
548 } |
|
549 } |
|
550 return $this->sql_version; |
|
551 } |
|
552 |
|
553 function sql_error() |
|
554 { |
|
555 if ( $this->_conn ) |
|
556 { |
|
557 return mysql_error(); |
|
558 } |
|
559 else |
|
560 { |
|
561 return array(); |
|
562 } |
|
563 } |
|
564 function sql_escape_string($t) |
|
565 { |
|
566 return mysql_real_escape_string($t); |
|
567 } |
|
568 function sql_close() |
|
569 { |
|
570 $this->close(); |
|
571 } |
|
572 function sql_fetchrowset($query_id = 0) |
|
573 { |
|
574 if( !$query_id ) |
|
575 { |
|
576 $query_id = $this->query_result; |
|
577 } |
|
578 |
|
579 if( $query_id ) |
|
580 { |
|
581 unset($this->rowset[$query_id]); |
|
582 unset($this->row[$query_id]); |
|
583 |
|
584 while($this->rowset[$query_id] = mysql_fetch_array($query_id, MYSQL_ASSOC)) |
|
585 { |
|
586 $result[] = $this->rowset[$query_id]; |
|
587 } |
|
588 |
|
589 return $result; |
|
590 } |
|
591 else |
|
592 { |
|
593 return false; |
|
594 } |
|
595 } |
|
596 } |
|
597 |
|
598 ?> |