This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php defined('SYSPATH') or die('No direct access allowed.'); |
||
2 | /** |
||
3 | * Database API driver |
||
4 | * |
||
5 | * $Id: Database.php 4343 2009-05-08 17:04:48Z jheathco $ |
||
6 | * |
||
7 | * @package Core |
||
8 | * @author Kohana Team |
||
9 | * @copyright (c) 2007-2008 Kohana Team |
||
10 | * @license http://kohanaphp.com/license.html |
||
11 | */ |
||
12 | abstract class Database_Driver |
||
13 | { |
||
14 | protected $query_cache; |
||
15 | |||
16 | /** |
||
17 | * Connect to our database. |
||
18 | * Returns FALSE on failure or a MySQL resource. |
||
19 | * |
||
20 | * @return mixed |
||
21 | */ |
||
22 | abstract public function connect(); |
||
23 | |||
24 | /** |
||
25 | * Perform a query based on a manually written query. |
||
26 | * |
||
27 | * @param string SQL query to execute |
||
28 | * @return Database_Result |
||
29 | */ |
||
30 | abstract public function query($sql); |
||
31 | |||
32 | /** |
||
33 | * Builds a DELETE query. |
||
34 | * |
||
35 | * @param string table name |
||
36 | * @param array where clause |
||
37 | * @return string |
||
38 | */ |
||
39 | public function delete($table, $where) |
||
40 | { |
||
41 | return 'DELETE FROM '.$this->escape_table($table).' WHERE '.implode(' ', $where); |
||
42 | } |
||
43 | |||
44 | /** |
||
45 | * Builds an UPDATE query. |
||
46 | * |
||
47 | * @param string table name |
||
48 | * @param array key => value pairs |
||
49 | * @param array where clause |
||
50 | * @return string |
||
51 | */ |
||
52 | View Code Duplication | public function update($table, $values, $where) |
|
0 ignored issues
–
show
|
|||
53 | { |
||
54 | foreach ($values as $key => $val) { |
||
55 | $valstr[] = $this->escape_column($key).' = '.$val; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$valstr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $valstr = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
56 | } |
||
57 | return 'UPDATE '.$this->escape_table($table).' SET '.implode(', ', $valstr).' WHERE '.implode(' ', $where); |
||
0 ignored issues
–
show
The variable
$valstr does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
58 | } |
||
59 | |||
60 | /** |
||
61 | * Set the charset using 'SET NAMES <charset>'. |
||
62 | * |
||
63 | * @param string character set to use |
||
64 | */ |
||
65 | public function set_charset($charset) |
||
66 | { |
||
67 | throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * Wrap the tablename in backticks, has support for: table.field syntax. |
||
72 | * |
||
73 | * @param string table name |
||
74 | * @return string |
||
75 | */ |
||
76 | abstract public function escape_table($table); |
||
77 | |||
78 | /** |
||
79 | * Escape a column/field name, has support for special commands. |
||
80 | * |
||
81 | * @param string column name |
||
82 | * @return string |
||
83 | */ |
||
84 | abstract public function escape_column($column); |
||
85 | |||
86 | /** |
||
87 | * Builds a WHERE portion of a query. |
||
88 | * |
||
89 | * @param mixed key |
||
90 | * @param string value |
||
91 | * @param string type |
||
92 | * @param int number of where clauses |
||
93 | * @param boolean escape the value |
||
94 | * @return string |
||
95 | */ |
||
96 | public function where($key, $value, $type, $num_wheres, $quote) |
||
97 | { |
||
98 | $prefix = ($num_wheres == 0) ? '' : $type; |
||
99 | |||
100 | if ($quote === -1) { |
||
101 | $value = ''; |
||
102 | } else { |
||
103 | if ($value === null) { |
||
104 | if (! $this->has_operator($key)) { |
||
105 | $key .= ' IS'; |
||
106 | } |
||
107 | |||
108 | $value = ' NULL'; |
||
109 | } elseif (is_bool($value)) { |
||
110 | if (! $this->has_operator($key)) { |
||
111 | $key .= ' ='; |
||
112 | } |
||
113 | |||
114 | $value = ($value == true) ? ' 1' : ' 0'; |
||
0 ignored issues
–
show
|
|||
115 | } else { |
||
116 | if (! $this->has_operator($key) and ! empty($key)) { |
||
117 | $key = $this->escape_column($key).' ='; |
||
118 | } else { |
||
119 | preg_match('/^(.+?)([<>!=]+|\bIS(?:\s+NULL))\s*$/i', $key, $matches); |
||
120 | if (isset($matches[1]) and isset($matches[2])) { |
||
121 | $key = $this->escape_column(trim($matches[1])).' '.trim($matches[2]); |
||
122 | } |
||
123 | } |
||
124 | |||
125 | $value = ' '.(($quote == true) ? $this->escape($value) : $value); |
||
126 | } |
||
127 | } |
||
128 | |||
129 | return $prefix.$key.$value; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Builds a LIKE portion of a query. |
||
134 | * |
||
135 | * @param mixed field name |
||
136 | * @param string value to match with field |
||
137 | * @param boolean add wildcards before and after the match |
||
138 | * @param string clause type (AND or OR) |
||
139 | * @param int number of likes |
||
140 | * @return string |
||
141 | */ |
||
142 | View Code Duplication | public function like($field, $match, $auto, $type, $num_likes) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
143 | { |
||
144 | $prefix = ($num_likes == 0) ? '' : $type; |
||
145 | |||
146 | $match = $this->escape_str($match); |
||
147 | |||
148 | if ($auto === true) { |
||
149 | // Add the start and end quotes |
||
150 | $match = '%'.str_replace('%', '\\%', $match).'%'; |
||
151 | } |
||
152 | |||
153 | return $prefix.' '.$this->escape_column($field).' LIKE \''.$match . '\''; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Builds a NOT LIKE portion of a query. |
||
158 | * |
||
159 | * @param mixed field name |
||
160 | * @param string value to match with field |
||
161 | * @param string clause type (AND or OR) |
||
162 | * @param int number of likes |
||
163 | * @return string |
||
164 | */ |
||
165 | View Code Duplication | public function notlike($field, $match, $auto, $type, $num_likes) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
166 | { |
||
167 | $prefix = ($num_likes == 0) ? '' : $type; |
||
168 | |||
169 | $match = $this->escape_str($match); |
||
170 | |||
171 | if ($auto === true) { |
||
172 | // Add the start and end quotes |
||
173 | $match = '%'.$match.'%'; |
||
174 | } |
||
175 | |||
176 | return $prefix.' '.$this->escape_column($field).' NOT LIKE \''.$match.'\''; |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * Builds a REGEX portion of a query. |
||
181 | * |
||
182 | * @param string field name |
||
183 | * @param string value to match with field |
||
184 | * @param string clause type (AND or OR) |
||
185 | * @param integer number of regexes |
||
186 | * @return string |
||
0 ignored issues
–
show
|
|||
187 | */ |
||
188 | public function regex($field, $match, $type, $num_regexs) |
||
189 | { |
||
190 | throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Builds a NOT REGEX portion of a query. |
||
195 | * |
||
196 | * @param string field name |
||
197 | * @param string value to match with field |
||
198 | * @param string clause type (AND or OR) |
||
199 | * @param integer number of regexes |
||
200 | * @return string |
||
0 ignored issues
–
show
|
|||
201 | */ |
||
202 | public function notregex($field, $match, $type, $num_regexs) |
||
203 | { |
||
204 | throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * Builds an INSERT query. |
||
209 | * |
||
210 | * @param string table name |
||
211 | * @param array keys |
||
212 | * @param array values |
||
213 | * @return string |
||
214 | */ |
||
215 | View Code Duplication | public function insert($table, $keys, $values) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
216 | { |
||
217 | // Escape the column names |
||
218 | foreach ($keys as $key => $value) { |
||
219 | $keys[$key] = $this->escape_column($value); |
||
220 | } |
||
221 | return 'INSERT INTO '.$this->escape_table($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * Builds a MERGE portion of a query. |
||
226 | * |
||
227 | * @param string table name |
||
228 | * @param array keys |
||
229 | * @param array values |
||
230 | * @return string |
||
0 ignored issues
–
show
|
|||
231 | */ |
||
232 | public function merge($table, $keys, $values) |
||
233 | { |
||
234 | throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); |
||
235 | } |
||
236 | |||
237 | /** |
||
238 | * Builds a LIMIT portion of a query. |
||
239 | * |
||
240 | * @param integer limit |
||
241 | * @param integer offset |
||
242 | * @return string |
||
243 | */ |
||
244 | abstract public function limit($limit, $offset = 0); |
||
245 | |||
246 | /** |
||
247 | * Creates a prepared statement. |
||
248 | * |
||
249 | * @param string SQL query |
||
250 | * @return Database_Stmt |
||
0 ignored issues
–
show
|
|||
251 | */ |
||
252 | public function stmt_prepare($sql = '') |
||
0 ignored issues
–
show
|
|||
253 | { |
||
254 | throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Compiles the SELECT statement. |
||
259 | * Generates a query string based on which functions were used. |
||
260 | * Should not be called directly, the get() function calls it. |
||
261 | * |
||
262 | * @param array select query values |
||
263 | * @return string |
||
264 | */ |
||
265 | abstract public function compile_select($database); |
||
266 | |||
267 | /** |
||
268 | * Determines if the string has an arithmetic operator in it. |
||
269 | * |
||
270 | * @param string string to check |
||
271 | * @return boolean |
||
272 | */ |
||
273 | public function has_operator($str) |
||
274 | { |
||
275 | return (bool) preg_match('/[<>!=]|\sIS(?:\s+NOT\s+)?\b|BETWEEN/i', trim($str)); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Escapes any input value. |
||
280 | * |
||
281 | * @param mixed value to escape |
||
282 | * @return string |
||
283 | */ |
||
284 | public function escape($value) |
||
285 | { |
||
286 | if (! $this->db_config['escape']) { |
||
0 ignored issues
–
show
The property
db_config does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
287 | return $value; |
||
288 | } |
||
289 | |||
290 | switch (gettype($value)) { |
||
291 | case 'string': |
||
292 | $value = '\''.$this->escape_str($value).'\''; |
||
293 | break; |
||
294 | case 'boolean': |
||
295 | $value = (int) $value; |
||
296 | break; |
||
297 | case 'double': |
||
298 | // Convert to non-locale aware float to prevent possible commas |
||
299 | $value = sprintf('%F', $value); |
||
300 | break; |
||
301 | default: |
||
302 | $value = ($value === null) ? 'NULL' : $value; |
||
303 | break; |
||
304 | } |
||
305 | |||
306 | return (string) $value; |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Escapes a string for a query. |
||
311 | * |
||
312 | * @param mixed value to escape |
||
313 | * @return string |
||
314 | */ |
||
315 | abstract public function escape_str($str); |
||
316 | |||
317 | /** |
||
318 | * Lists all tables in the database. |
||
319 | * |
||
320 | * @return array |
||
321 | */ |
||
322 | abstract public function list_tables(); |
||
323 | |||
324 | /** |
||
325 | * Lists all fields in a table. |
||
326 | * |
||
327 | * @param string table name |
||
328 | * @return array |
||
329 | */ |
||
330 | abstract public function list_fields($table); |
||
331 | |||
332 | /** |
||
333 | * Returns the last database error. |
||
334 | * |
||
335 | * @return string |
||
336 | */ |
||
337 | abstract public function show_error(); |
||
338 | |||
339 | /** |
||
340 | * Returns field data about a table. |
||
341 | * |
||
342 | * @param string table name |
||
343 | * @return array |
||
344 | */ |
||
345 | abstract public function field_data($table); |
||
346 | |||
347 | /** |
||
348 | * Fetches SQL type information about a field, in a generic format. |
||
349 | * |
||
350 | * @param string field datatype |
||
351 | * @return string |
||
352 | */ |
||
353 | protected function sql_type($str) |
||
354 | { |
||
355 | static $sql_types; |
||
356 | |||
357 | if ($sql_types === null) { |
||
358 | // Load SQL data types |
||
359 | $sql_types = Kohana::config('sql_types'); |
||
360 | } |
||
361 | |||
362 | $str = strtolower(trim($str)); |
||
363 | |||
364 | if (($open = strpos($str, '(')) !== false) { |
||
365 | // Find closing bracket |
||
366 | $close = strpos($str, ')', $open) - 1; |
||
367 | |||
368 | // Find the type without the size |
||
369 | $type = substr($str, 0, $open); |
||
370 | } else { |
||
371 | // No length |
||
372 | $type = $str; |
||
373 | } |
||
374 | |||
375 | empty($sql_types[$type]) and exit( |
||
0 ignored issues
–
show
The method
sql_type() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
376 | 'Unknown field type: '.$type.'. '. |
||
377 | 'Please report this: http://trac.kohanaphp.com/newticket' |
||
378 | ); |
||
379 | |||
380 | // Fetch the field definition |
||
381 | $field = $sql_types[$type]; |
||
382 | |||
383 | switch ($field['type']) { |
||
384 | case 'string': |
||
385 | case 'float': |
||
386 | if (isset($close)) { |
||
387 | // Add the length to the field info |
||
388 | $field['length'] = substr($str, $open + 1, $close - $open); |
||
389 | } |
||
390 | break; |
||
391 | case 'int': |
||
392 | // Add unsigned value |
||
393 | $field['unsigned'] = (strpos($str, 'unsigned') !== false); |
||
394 | break; |
||
395 | } |
||
396 | |||
397 | return $field; |
||
398 | } |
||
399 | |||
400 | /** |
||
401 | * Clears the internal query cache. |
||
402 | * |
||
403 | * @param string SQL query |
||
404 | */ |
||
405 | public function clear_cache($sql = null) |
||
406 | { |
||
407 | if (empty($sql)) { |
||
408 | $this->query_cache = array(); |
||
409 | } else { |
||
410 | unset($this->query_cache[$this->query_hash($sql)]); |
||
411 | } |
||
412 | |||
413 | Kohana::log('debug', 'Database cache cleared: '.get_class($this)); |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * Creates a hash for an SQL query string. Replaces newlines with spaces, |
||
418 | * trims, and hashes. |
||
419 | * |
||
420 | * @param string SQL query |
||
421 | * @return string |
||
422 | */ |
||
423 | protected function query_hash($sql) |
||
424 | { |
||
425 | return sha1(str_replace("\n", ' ', trim($sql))); |
||
426 | } |
||
427 | } // End Database Driver Interface |
||
428 | |||
429 | /** |
||
430 | * Database_Result |
||
431 | * |
||
432 | */ |
||
433 | abstract class Database_Result implements ArrayAccess, Iterator, Countable |
||
434 | { |
||
435 | |||
436 | // Result resource, insert id, and SQL |
||
437 | protected $result; |
||
438 | protected $insert_id; |
||
439 | protected $sql; |
||
440 | |||
441 | // Current and total rows |
||
442 | protected $current_row = 0; |
||
443 | protected $total_rows = 0; |
||
444 | |||
445 | // Fetch function and return type |
||
446 | protected $fetch_type; |
||
447 | protected $return_type; |
||
448 | |||
449 | /** |
||
450 | * Returns the SQL used to fetch the result. |
||
451 | * |
||
452 | * @return string |
||
453 | */ |
||
454 | public function sql() |
||
455 | { |
||
456 | return $this->sql; |
||
457 | } |
||
458 | |||
459 | /** |
||
460 | * Returns the insert id from the result. |
||
461 | * |
||
462 | * @return integer |
||
0 ignored issues
–
show
|
|||
463 | */ |
||
464 | public function insert_id() |
||
465 | { |
||
466 | return $this->insert_id; |
||
467 | } |
||
468 | |||
469 | /** |
||
470 | * Prepares the query result. |
||
471 | * |
||
472 | * @param boolean return rows as objects |
||
473 | * @param mixed type |
||
474 | * @return Database_Result |
||
475 | */ |
||
476 | abstract public function result($object = true, $type = false); |
||
477 | |||
478 | /** |
||
479 | * Builds an array of query results. |
||
480 | * |
||
481 | * @param boolean return rows as objects |
||
482 | * @param mixed type |
||
483 | * @param boolean $object |
||
0 ignored issues
–
show
Should the type for parameter
$object not be boolean|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
484 | * @return array |
||
485 | */ |
||
486 | abstract public function result_array($object = null, $type = false); |
||
487 | |||
488 | /** |
||
489 | * Gets the fields of an already run query. |
||
490 | * |
||
491 | * @return array |
||
492 | */ |
||
493 | abstract public function list_fields(); |
||
494 | |||
495 | /** |
||
496 | * Seek to an offset in the results. |
||
497 | * |
||
498 | * @return boolean |
||
499 | */ |
||
500 | abstract public function seek($offset); |
||
501 | |||
502 | /** |
||
503 | * Countable: count |
||
504 | */ |
||
505 | public function count() |
||
506 | { |
||
507 | return $this->total_rows; |
||
508 | } |
||
509 | |||
510 | /** |
||
511 | * ArrayAccess: offsetExists |
||
512 | */ |
||
513 | public function offsetExists($offset) |
||
514 | { |
||
515 | if ($this->total_rows > 0) { |
||
516 | $min = 0; |
||
517 | $max = $this->total_rows - 1; |
||
518 | |||
519 | return ! ($offset < $min or $offset > $max); |
||
520 | } |
||
521 | |||
522 | return false; |
||
523 | } |
||
524 | |||
525 | /** |
||
526 | * ArrayAccess: offsetGet |
||
527 | */ |
||
528 | View Code Duplication | public function offsetGet($offset) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
529 | { |
||
530 | if (! $this->seek($offset)) { |
||
531 | return false; |
||
532 | } |
||
533 | |||
534 | // Return the row by calling the defined fetching callback |
||
535 | return call_user_func($this->fetch_type, $this->result, $this->return_type); |
||
536 | } |
||
537 | |||
538 | /** |
||
539 | * ArrayAccess: offsetSet |
||
540 | * |
||
541 | * @throws Kohana_Database_Exception |
||
542 | */ |
||
543 | final public function offsetSet($offset, $value) |
||
544 | { |
||
545 | throw new Kohana_Database_Exception('database.result_read_only'); |
||
546 | } |
||
547 | |||
548 | /** |
||
549 | * ArrayAccess: offsetUnset |
||
550 | * |
||
551 | * @throws Kohana_Database_Exception |
||
552 | */ |
||
553 | final public function offsetUnset($offset) |
||
554 | { |
||
555 | throw new Kohana_Database_Exception('database.result_read_only'); |
||
556 | } |
||
557 | |||
558 | /** |
||
559 | * Iterator: current |
||
560 | */ |
||
561 | public function current() |
||
562 | { |
||
563 | return $this->offsetGet($this->current_row); |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * Iterator: key |
||
568 | */ |
||
569 | public function key() |
||
570 | { |
||
571 | return $this->current_row; |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Iterator: next |
||
576 | */ |
||
577 | public function next() |
||
578 | { |
||
579 | ++$this->current_row; |
||
580 | return $this; |
||
581 | } |
||
582 | |||
583 | /** |
||
584 | * Iterator: prev |
||
585 | */ |
||
586 | public function prev() |
||
587 | { |
||
588 | --$this->current_row; |
||
589 | return $this; |
||
590 | } |
||
591 | |||
592 | /** |
||
593 | * Iterator: rewind |
||
594 | */ |
||
595 | public function rewind() |
||
596 | { |
||
597 | $this->current_row = 0; |
||
598 | return $this; |
||
599 | } |
||
600 | |||
601 | /** |
||
602 | * Iterator: valid |
||
603 | */ |
||
604 | public function valid() |
||
605 | { |
||
606 | return $this->offsetExists($this->current_row); |
||
607 | } |
||
608 | } // End Database Result Interface |
||
609 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.