Kylob /
BootPress
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 |
||
| 2 | |||
| 3 | namespace BootPress\Database; |
||
| 4 | |||
| 5 | class Driver |
||
| 6 | { |
||
| 7 | protected $id = 0; |
||
| 8 | protected static $drivers = array(); |
||
| 9 | protected static $logs = array(); |
||
| 10 | protected $connection; |
||
| 11 | private $construct; |
||
| 12 | |||
| 13 | /** |
||
| 14 | * Either implement an established PDO instance, or set up a lazy database connection that we only connect to if and when you actually use it. Every $dsn string with a '**dbname**' is saved in a databases.yml file so that you only need to spell everything out once, and then just refer to the 'dbname' in your code. |
||
| 15 | * |
||
| 16 | * @param string|object $dsn Either a PDO Instance, a DSN string that contains the information required to connect to the database, or the 'dbname' saved in the databases.yml file. Some examples are: |
||
| 17 | * |
||
| 18 | * - [MySQL](http://php.net/manual/en/ref.pdo-mysql.connection.php "mysql") |
||
| 19 | * - mysql:host=[name];port=[number];dbname=[database];unix_socket=[instead of host or port];charset=[utf-8] |
||
| 20 | * - MySQL v. <= 4.1 not supported in PHP v. >= 5.4.0 |
||
| 21 | * - charset is ignored in PHP v. < 5.3.6 |
||
| 22 | * - [SQLite](http://php.net/manual/en/ref.pdo-sqlite.connection.php "sqlite") |
||
| 23 | * - sqlite:[filepath OR ':memory:'] |
||
| 24 | * - [PostgreSQL](http://php.net/manual/en/ref.pdo-pgsql.connection.php "pgsql") |
||
| 25 | * - pgsql:host=[name];port=[number];dbname=[database];user=[name];password=[secret] |
||
| 26 | * - [Oracle](http://php.net/manual/en/ref.pdo-oci.connection.php "oci") |
||
| 27 | * - oci:dbname=[database];charset=[utf-8] |
||
| 28 | * - [MSSQL on Windows](http://php.net/manual/en/ref.pdo-sqlsrv.connection.php "sqlsrv") |
||
| 29 | * - sqlsrv:Server=[name,port];Database=[name] ... and a bunch of other options |
||
| 30 | * - [MSSQL on Linux / Unix](http://php.net/manual/en/ref.pdo-dblib.connection.php "dblib") |
||
| 31 | * - sybase:host=[name];dbname=[database];charset=[utf-8];appname=[application];secure=[currently unused] |
||
| 32 | * - [Sybase](http://php.net/manual/en/ref.pdo-dblib.connection.php "sybase") |
||
| 33 | * - sybase:host=[name];dbname=[database];charset=[utf-8];appname=[application];secure=[currently unused] |
||
| 34 | * - [Microsoft SQL Server](http://php.net/manual/en/ref.pdo-dblib.connection.php "mssql") |
||
| 35 | * - mssql:host=[name];dbname=[database];charset=[utf-8];appname=[application];secure=[currently unused] |
||
| 36 | * - [Cubrid](http://php.net/manual/en/ref.pdo-cubrid.connection.php "cubrid") |
||
| 37 | * - cubrid:host=[name];port=[number];dbname=[database]; |
||
| 38 | * |
||
| 39 | * @param string|null $username The user name for the DSN string. This parameter is optional for some PDO drivers. |
||
| 40 | * @param string|null $password The password for the DSN string. This parameter is optional for some PDO drivers. |
||
| 41 | * @param array $options An ``array('key'=>'value', ...)`` of driver-specific connection options. |
||
| 42 | * @param array $exec Queries you would like to execute upon connecting to the database. |
||
| 43 | * |
||
| 44 | * @see http://php.net/manual/en/pdo.construct.php |
||
| 45 | */ |
||
| 46 | 5 | public function __construct($dsn, $username = null, $password = null, array $options = array(), array $exec = array()) |
|
| 47 | { |
||
| 48 | 5 | if ($dsn instanceof \PDO) { |
|
| 49 | 1 | $this->connection = $dsn; |
|
| 50 | 1 | $this->driver('PDO'); |
|
| 51 | 1 | } else { |
|
| 52 | 5 | $driver = strstr($dsn, ':', true); |
|
| 53 | 5 | if (class_exists('BootPress\Page\Component') && class_exists('Symfony\Component\Yaml\Yaml')) { |
|
| 54 | 5 | $page = \BootPress\Page\Component::html(); |
|
| 55 | 5 | $databases = $page->file('databases.yml'); |
|
| 56 | 5 | $yaml = (is_file($databases)) ? \Symfony\Component\Yaml\Yaml::parse(file_get_contents($databases)) : array(); |
|
| 57 | 5 | if ($driver === false) { // Has no semicolon, and so is assumed to be a dbname in the databases.yml |
|
| 58 | 2 | if (isset($yaml[$dsn]['dsn'])) { |
|
| 59 | 1 | extract($yaml[$dsn]); |
|
| 60 | 1 | } else { |
|
| 61 | 1 | throw new \LogicException('The "'.$dsn.'" database is undefined.'); |
|
| 62 | } |
||
| 63 | 4 | } elseif (preg_match('/dbname=([a-z0-9._\-]+);?/i', $dsn, $matches)) { // Save to the databases.yml |
|
| 64 | 1 | $dbname = $matches[1]; |
|
| 65 | $config = array( |
||
| 66 | 1 | 'dsn' => $dsn, |
|
| 67 | 1 | 'username' => $username, |
|
| 68 | 1 | 'password' => $password, |
|
| 69 | 1 | 'options' => $options, |
|
| 70 | 1 | 'exec' => $exec, |
|
| 71 | 1 | ); |
|
| 72 | 1 | if (!isset($yaml[$dbname]) || $yaml[$dbname] != $config) { |
|
| 73 | 1 | $yaml[$dbname] = $config; |
|
| 74 | 1 | ksort($yaml); |
|
| 75 | 1 | $yaml = \Symfony\Component\Yaml\Yaml::dump($yaml, 3); |
|
| 76 | 1 | file_put_contents($databases, $yaml); |
|
| 77 | 1 | } |
|
| 78 | 1 | } |
|
| 79 | 4 | } |
|
| 80 | 4 | $this->driver($driver); |
|
| 81 | 4 | $this->construct = array($dsn, $username, $password, $options, $exec); |
|
| 82 | } |
||
| 83 | 4 | } |
|
| 84 | |||
| 85 | /** |
||
| 86 | * @return integer The current database's id. |
||
| 87 | */ |
||
| 88 | 1 | public function id() |
|
| 89 | { |
||
| 90 | 1 | return $this->id; |
|
| 91 | } |
||
| 92 | |||
| 93 | /** |
||
| 94 | * @param string $name Pass a value to set the database driver's name. |
||
| 95 | * |
||
| 96 | * @return string|null The current database driver's name. |
||
| 97 | */ |
||
| 98 | 53 | public function driver($name = null) |
|
| 99 | { |
||
| 100 | 53 | if (empty($this->id)) { |
|
| 101 | 53 | $this->id = count(static::$drivers) + 1; |
|
| 102 | 53 | static::$logs[$this->id] = array(); |
|
| 103 | 53 | } |
|
| 104 | 53 | if (is_string($name)) { |
|
| 105 | 52 | static::$drivers[$this->id] = $name; |
|
| 106 | 52 | } |
|
| 107 | 53 | return (isset(static::$drivers[$this->id])) ? static::$drivers[$this->id] : null; |
|
| 108 | } |
||
| 109 | |||
| 110 | /** |
||
| 111 | * @param integer $id To only return the data for a specific database connection. |
||
| 112 | * |
||
| 113 | * @return array Debug, error, and profile data for all of your database queries. |
||
| 114 | */ |
||
| 115 | 1 | public static function logs($id = null) |
|
| 116 | { |
||
| 117 | 1 | $logs = array(); |
|
| 118 | 1 | $ids = (is_null($id)) ? array_keys(static::$logs) : array($id); |
|
| 119 | 1 | foreach ($ids as $key) { |
|
| 120 | 1 | if (isset(static::$logs[$key])) { |
|
| 121 | 1 | $logs[$key] = array( |
|
| 122 | 1 | 'driver' => (isset(static::$drivers[$key])) ? static::$drivers[$key] : null, |
|
| 123 | 1 | 'duration' => 0, |
|
| 124 | 1 | 'queries' => array(), |
|
| 125 | ); |
||
| 126 | 1 | foreach (static::$logs[$key] as $log) { // 'sql', 'count', 'errors'?, 'duration' |
|
| 127 | 1 | $log['duration'] = $log['prepared'] + $log['executed']; |
|
| 128 | 1 | unset($log['prepared'], $log['executed']); |
|
| 129 | 1 | if (isset($log['errors'])) { |
|
| 130 | 1 | $log['errors'] = array_count_values($log['errors']); |
|
| 131 | 1 | } |
|
| 132 | 1 | $logs[$key]['duration'] += $log['duration']; |
|
| 133 | 1 | $logs[$key]['queries'][] = $log; |
|
| 134 | 1 | } |
|
| 135 | 1 | } |
|
| 136 | 1 | } |
|
| 137 | |||
| 138 | 1 | return (is_null($id)) ? $logs : array_shift($logs); |
|
| 139 | } |
||
| 140 | |||
| 141 | /** |
||
| 142 | * @return array All of the errors generated from all of your database connections. |
||
| 143 | */ |
||
| 144 | 1 | public static function errors() |
|
| 145 | { |
||
| 146 | 1 | $errors = self::logs(); |
|
| 147 | 1 | foreach ($errors as $id => $db) { |
|
| 148 | 1 | foreach ($db['queries'] as $num => $log) { |
|
| 149 | 1 | if (isset($log['errors'])) { |
|
| 150 | 1 | $errors[$id]['queries'][$num] = array_intersect_key($log, array( |
|
| 151 | 1 | 'sql' => '', |
|
| 152 | 1 | 'errors' => '', |
|
| 153 | 1 | )); |
|
| 154 | 1 | } else { |
|
| 155 | 1 | unset($errors[$id]['queries'][$num]); |
|
| 156 | } |
||
| 157 | 1 | } |
|
| 158 | 1 | if (empty($errors[$id]['queries'])) { |
|
| 159 | 1 | unset($errors[$id]); |
|
| 160 | 1 | } else { |
|
| 161 | 1 | unset($errors[$id]['total']); |
|
| 162 | } |
||
| 163 | 1 | } |
|
| 164 | |||
| 165 | 1 | return $errors; |
|
| 166 | } |
||
| 167 | |||
| 168 | /** |
||
| 169 | * @return object The database connection. This is how we create lazy connections. |
||
| 170 | */ |
||
| 171 | 79 | public function connection() |
|
| 172 | { |
||
| 173 | 79 | if (is_null($this->connection) && !is_null($this->construct)) { |
|
| 174 | 3 | list($dsn, $username, $password, $options, $exec) = $this->construct; |
|
| 175 | try { |
||
| 176 | 3 | $this->connection = new \PDO($dsn, $username, $password, $options); |
|
| 177 | 3 | } catch (\PDOException $e) { |
|
| 178 | 1 | throw new \Exception($e->getMessage()); |
|
| 179 | } |
||
| 180 | 2 | foreach ($exec as $sql) { |
|
| 181 | 1 | $this->connection->exec($sql); |
|
| 182 | 2 | } |
|
| 183 | 2 | } |
|
| 184 | |||
| 185 | 78 | return $this->connection; |
|
| 186 | } |
||
| 187 | |||
| 188 | 20 | protected function dbPrepare($query) |
|
| 189 | { |
||
| 190 | 20 | return $this->connection->prepare($query); // returns (mixed) $stmt object or false |
|
| 191 | } |
||
| 192 | |||
| 193 | 5 | protected function dbPrepareError() |
|
| 194 | { |
||
| 195 | 5 | return ($info = $this->connection->errorInfo()) ? "Code: {$info[0]} Error: ({$info[1]}) {$info[2]}" : false; // returns (string) error or false |
|
|
0 ignored issues
–
show
|
|||
| 196 | } |
||
| 197 | |||
| 198 | 20 | protected function dbExecute($stmt, array $values, $reference) |
|
| 199 | { |
||
| 200 | 20 | return $stmt->execute($values); // returns (bool) true or false |
|
| 201 | } |
||
| 202 | |||
| 203 | 1 | protected function dbExecuteError($stmt) |
|
| 204 | { |
||
| 205 | 1 | return ($info = $stmt->errorInfo()) ? "Code: {$info[0]} Error: ({$info[1]}) {$info[2]}" : false; // returns (string) error or false |
|
| 206 | } |
||
| 207 | |||
| 208 | 17 | protected function dbStyle($fetch) |
|
| 209 | { |
||
| 210 | switch ($fetch) { |
||
| 211 | 17 | case 'obj': |
|
| 212 | 1 | return \PDO::FETCH_OBJ; |
|
| 213 | break; |
||
|
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. Loading history...
|
|||
| 214 | 17 | case 'assoc': |
|
| 215 | 7 | return \PDO::FETCH_ASSOC; |
|
| 216 | break; |
||
|
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. Loading history...
|
|||
| 217 | 12 | case 'named': |
|
| 218 | 1 | return \PDO::FETCH_NAMED; |
|
| 219 | break; |
||
|
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. Loading history...
|
|||
| 220 | 12 | case 'both': |
|
| 221 | 1 | return \PDO::FETCH_BOTH; |
|
| 222 | break; |
||
|
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. Loading history...
|
|||
| 223 | 11 | default: |
|
| 224 | 11 | return \PDO::FETCH_NUM; |
|
| 225 | break; |
||
|
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. Loading history...
|
|||
| 226 | 11 | } |
|
| 227 | } |
||
| 228 | |||
| 229 | 17 | protected function dbFetch($stmt, $style, $reference) |
|
| 230 | { |
||
| 231 | 17 | return $stmt->fetch($style); // returns (mixed) $style or false |
|
| 232 | } |
||
| 233 | |||
| 234 | 4 | protected function dbInserted() |
|
| 235 | { |
||
| 236 | 4 | return (int) $this->connection->lastInsertId(); // returns (int) last inserted row id or sequence value |
|
|
0 ignored issues
–
show
The method
lastInsertId does only exist in PDO, but not in SQLite3.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 237 | } |
||
| 238 | |||
| 239 | 5 | protected function dbAffected($stmt) |
|
| 240 | { |
||
| 241 | 5 | return $stmt->rowCount(); // returns (int) number of rows affected by last $stmt |
|
| 242 | } |
||
| 243 | |||
| 244 | 20 | protected function dbClose($stmt, $reference) |
|
| 245 | { |
||
| 246 | 20 | return $stmt->closeCursor(); // returns (bool) true or false |
|
| 247 | } |
||
| 248 | |||
| 249 | 1 | protected function dbEscape($string) |
|
| 250 | { |
||
| 251 | 1 | return $this->connection->quote($string); |
|
|
0 ignored issues
–
show
The method
quote does only exist in PDO, but not in SQLite3.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 252 | } |
||
| 253 | } |
||
| 254 |
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: