Issues (195)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

risoluto/lib/vendor/Risoluto/Db.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Db
4
 *
5
 * コンフィグ操作のためのファンクション群
6
 *
7
 * @package           risoluto
8
 * @author            Risoluto Developers
9
 * @license           http://opensource.org/licenses/bsd-license.php new BSD license
10
 * @copyright     (C) 2008-2015 Risoluto Developers / All Rights Reserved.
11
 */
12
13
//------------------------------------------------------//
14
// 名前空間の定義
15
//------------------------------------------------------//
16
namespace Risoluto;
17
18
//------------------------------------------------------//
19
// クラス定義
20
//------------------------------------------------------//
21
class Db
22
{ //------------------------------------------------------//
23
    // クラス変数定義
24
    //------------------------------------------------------//
25
    /**
26
     * $pdo_instance
27
     * @access private
28
     * @var    object    PDOクラスインスタンスを保持
29
     * @instanceof \PDO
30
     */
31
    private $pdo_instance = '';
32
33
    /**
34
     * $pdostatement_instance
35
     * @access private
36
     * @var    object    PDOStatementクラスインスタンスを保持
37
     * @instanceof \PDOStatement
38
     */
39
    private $pdostatement_instance = '';
40
41
    /**
42
     * $dbinfo
43
     * @access private
44
     * @var    array    DB接続に必要な情報
45
     */
46
    private $dbinfo = [ ];
47
48
    //------------------------------------------------------//
49
    // クラスメソッド定義
50
    //------------------------------------------------------//
51
    use RisolutoErrorLogTrait;
52
53
    /**
54
     * connect(array $param)
55
     *
56
     * DBへの接続を開始する
57
     *
58
     * @param     array $param DB接続に必要となる情報を含んだ配列
59
     * @param     array $option DB接続に指定するオプション情報を含んだ配列
60
     *
61
     * @return    boolean 実行結果(true: 成功 / false: 失敗)
62
     *
63
     */
64
    public function connect( array $param, array $option = [ ] )
65
    {
66
        // 戻り値を初期化
67
        $retval = true;
68
69
        // 接続情報をクラス変数へセット
70
        $this->dbinfo = $param;
71
72
        // DSNを生成しクラス変数へセット
73
        if (!array_key_exists( 'dsn', $this->dbinfo ) or empty( $this->dbinfo[ 'dsn' ] )) {
74
            $this->dbinfo[ 'dsn' ] = $this->genDSN();
75
        }
76
77
        // DBへの接続を試みる
78
        try {
79
            if (empty( $option )) {
80
                // オプションが指定されていなければそのまま指定する
81
                $this->pdo_instance = new \PDO(
82
                    $this->dbinfo[ 'dsn' ], $this->dbinfo[ 'user' ], $this->dbinfo[ 'pass' ],
83
                    [
84
                        \PDO::ATTR_PERSISTENT => ( $this->dbinfo[ 'persistent' ] ? true : false ),
85
                        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
86
                    ]
87
                );
88
            } else {
89
                // オプションが指定されていればそれを指定して接続する
90
                $this->pdo_instance = new \PDO( $this->dbinfo[ 'dsn' ], $this->dbinfo[ 'user' ],
91
                    $this->dbinfo[ 'pass' ],
92
                    $option );
93
            }
94
        } catch ( \PDOException $e ) {
95
            // 接続に失敗したらエラーメッセージを生成
96
            $this->genErrorMsg( 'pdo', $e->getMessage() );
97
            $retval = false;
98
        }
99
100
        return $retval;
101
    }
102
103
    /**
104
     * disConnect($force = false)
105
     *
106
     * DBへの接続を終了する
107
     *
108
     * @param     boolean $force 持続的接続時に切断するか(true: 切断する / false: 切断しない(デフォルト))
109
     *
110
     * @return    boolean 常にtrue
111
     *
112
     */
113
    public function disConnect( $force = false )
114
    {
115
        // 持続的接続が無効か強制切断が有効なときのみ接続を解除
116
        if (!$this->dbinfo[ 'persistent' ] or $force) {
117
            $this->pdo_instance = null;
118
        }
119
120
        return true;
121
    }
122
123
    /**
124
     * getAttribute($attribute)
125
     *
126
     * DB接続に関する属性値を取得する
127
     *
128
     * @param     string $attribute 取得対象となるアトリビュート(PDO::ATTR_*から「PDO::ATTR_*」を除いたもの、または「ALL」)
129
     *
130
     * @return    array 属性値が格納された連想配列
131
     *
132
     */
133
    public function getAttribute( $attribute = 'ALL' )
134
    {
135
        // 接頭語をセット
136
        $prefix = 'PDO::ATTR_';
137
138
        // 引数値をすべて大文字に変更
139
        $attribute = strtoupper( $attribute );
140
141
        // 属性値を取得
142
        switch ($attribute) {
143
            case 'AUTOCOMMIT': // FALL THRU
144
            case 'PREFETCH': // FALL THRU
145
            case 'TIMEOUT': // FALL THRU
146
            case 'ERRMODE': // FALL THRU
147
            case 'SERVER_VERSION': // FALL THRU
148
            case 'CLIENT_VERSION': // FALL THRU
149
            case 'SERVER_INFO': // FALL THRU
150
            case 'CONNECTION_STATUS': // FALL THRU
151
            case 'CASE': // FALL THRU
152
            case 'DRIVER_NAME': // FALL THRU
153
            case 'ORACLE_NULLS': // FALL THRU
154
            case 'PERSISTENT': // FALL THRU
155
            case 'STATEMENT_CLASS': // FALL THRU
156
            case 'DEFAULT_FETCH_MODE': // FALL THRU
157
                if ($this->dbinfo[ 'driver' ] == 'mysql' and ( $attribute == 'PREFETCH' or $attribute == 'TIMEOUT' )) {
158
                    $retval = [ $attribute => 'Not Supported' ];
159
                } else {
160
                    $retval = [
161
                        $attribute => $this->pdo_instance->getAttribute( constant( $prefix . $attribute ) )
162
                    ];
163
                }
164
                break;
165
166
            case 'ALL': // FALL THRU
167
            default:
168
                $retval = [
169
                    'AUTOCOMMIT' => $this->pdo_instance->getAttribute( constant( $prefix . 'AUTOCOMMIT' ) ),
170
                    'PREFETCH' => ( $this->dbinfo[ 'driver' ] == 'mysql' ) ? 'Not Supported' : $this->pdo_instance->getAttribute( constant( $prefix . 'PREFETCH' ) ),
171
                    'TIMEOUT' => ( $this->dbinfo[ 'driver' ] == 'mysql' ) ? 'Not Supported' : $this->pdo_instance->getAttribute( constant( $prefix . 'TIMEOUT' ) ),
172
                    'ERRMODE' => $this->pdo_instance->getAttribute( constant( $prefix . 'ERRMODE' ) ),
173
                    'SERVER_VERSION' => $this->pdo_instance->getAttribute( constant( $prefix . 'SERVER_VERSION' ) ),
174
                    'CLIENT_VERSION' => $this->pdo_instance->getAttribute( constant( $prefix . 'CLIENT_VERSION' ) ),
175
                    'SERVER_INFO' => $this->pdo_instance->getAttribute( constant( $prefix . 'SERVER_INFO' ) ),
176
                    'CONNECTION_STATUS' => $this->pdo_instance->getAttribute( constant( $prefix . 'CONNECTION_STATUS' ) ),
177
                    'CASE' => $this->pdo_instance->getAttribute( constant( $prefix . 'CASE' ) ),
178
                    'DRIVER_NAME' => $this->pdo_instance->getAttribute( constant( $prefix . 'DRIVER_NAME' ) ),
179
                    'ORACLE_NULLS' => $this->pdo_instance->getAttribute( constant( $prefix . 'ORACLE_NULLS' ) ),
180
                    'PERSISTENT' => $this->pdo_instance->getAttribute( constant( $prefix . 'PERSISTENT' ) ),
181
                    'STATEMENT_CLASS' => $this->pdo_instance->getAttribute( constant( $prefix . 'STATEMENT_CLASS' ) ),
182
                    'DEFAULT_FETCH_MODE' => $this->pdo_instance->getAttribute( constant( $prefix . 'DEFAULT_FETCH_MODE' ) ),
183
                ];
184
                break;
185
        }
186
187
        return $retval;
188
    }
189
190
    /**
191
     * setAttribute($attribute, $value)
192
     *
193
     * DB接続に関する属性値をセットする
194
     *
195
     * @param     integer $attribute 設定対象となるアトリビュート
196
     * @param     mixed   $value 設定する値
197
     *
198
     * @return    boolean true:正常終了/false:異常終了
199
     *
200
     */
201
    public function setAttribute( $attribute, $value )
202
    {
203
        if (!empty( $attribute ) and !empty( $value )) {
204
            return $this->pdo_instance->setAttribute( $attribute, $value );
205
        } else {
206
            return false;
207
        }
208
    }
209
210
    /**
211
     * beginTransaction()
212
     *
213
     * トランザクションを開始する
214
     *
215
     * @param     void
216
     *
217
     * @return    boolean true:正常終了/false:異常終了
218
     *
219
     */
220
    public function beginTransaction()
221
    {
222
        return $this->pdo_instance->beginTransaction();
223
    }
224
225
    /**
226
     * inTransaction()
227
     *
228
     * トランザクションが開始しているかを判定する
229
     *
230
     * @param     void
231
     *
232
     * @return    boolean true:トランザクションが開始している/false:トランザクションが開始していない
233
     *
234
     */
235
    public function inTransaction()
236
    {
237
        return $this->pdo_instance->InTransaction();
238
    }
239
240
    /**
241
     * commit()
242
     *
243
     * トランザクションをコミットする
244
     *
245
     * @param     void
246
     *
247
     * @return    boolean true:正常終了/false:異常終了
248
     *
249
     */
250
    public function commit()
251
    {
252
        return $this->pdo_instance->commit();
253
    }
254
255
    /**
256
     * rollBack()
257
     *
258
     * トランザクションをロールバックする
259
     *
260
     * @param     void
261
     *
262
     * @return    boolean true:正常終了/false:異常終了
263
     *
264
     */
265
    public function rollBack()
266
    {
267
        try {
268
            return $this->pdo_instance->rollBack();
269
        } catch ( \PDOException $e ) {
270
            // ロールバックに失敗したらエラーメッセージを生成
271
            $this->genErrorMsg( 'pdo', $e->getMessage() );
272
273
            return false;
274
        }
275
    }
276
277
    /**
278
     * lastInsertId($name)
279
     *
280
     * 最後に挿入されたID値を取得する
281
     *
282
     * @param     string $name 取得対象となるID値のカラム名
283
     *
284
     * @return    string 取得したID値
285
     *
286
     */
287
    public function lastInsertId( $name = null )
288
    {
289
        try {
290
            return $this->pdo_instance->lastInsertId( $name );
291
        } catch ( \PDOException $e ) {
292
            // 取得に失敗したらエラーメッセージを生成
293
            $this->genErrorMsg( 'pdo', $e->getMessage() );
294
295
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by Risoluto\Db::lastInsertId of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
296
        }
297
    }
298
299
    /**
300
     * exec($sql)
301
     *
302
     * SQLを実行する
303
     *
304
     * @param     string $sql 実行するSQL
305
     *
306
     * @return    boolean true:正常終了/false:異常終了
307
     *
308
     */
309
    public function exec( $sql )
310
    {
311
        if (!empty( $sql )) {
312
            return ( $this->pdo_instance->exec( $sql ) === false ? false : true );
313
        } else {
314
            return false;
315
        }
316
    }
317
318
    /**
319
     * doQuery($sql = '', array $param = [], array $query_options = [], $fetch_style = \PDO::FETCH_ASSOC)
320
     *
321
     * SQLを実行する
322
     *
323
     * @param     string  $sql 実行するSQL("clear"が指定された場合はPDOStatementのインスタンスをクリア)
324
     * @param     array   $param PDOStatement::bindParam()へ渡すバインドする値(array(id, value, type[, length]))
325
     * @param     array   $query_options PDO::prepare()へ渡すオプション
326
     * @param     integer $fetch_style PDOStatement::fetchAll()へ渡すオプション(\PDO::FETCH_**のいずれか)
327
     *
328
     * @return    mixed   SQLの実行結果/false:異常終了
329
     *
330
     */
331
    public function doQuery(
332
        $sql = '',
333
        array $param = [ ],
334
        array $query_options = [ ],
335
        $fetch_style = \PDO::FETCH_ASSOC
336
    ) {
337
        // SQLの前後についている余分な空白を排除
338
        $sql = trim( $sql );
339
340
        // SQLを判定し、SELECTだったときのみデータ取得モードにする
341
        $tmp_mode = false;
342
        if (!empty( $sql ) AND preg_match( '/^SELECT/i', $sql )) {
343
            $tmp_mode = true;
344
        } elseif (
345
            empty( $sql ) AND
346
            !empty( $this->pdostatement_instance->queryString ) AND
347
            preg_match( '/^SELECT/i', $this->pdostatement_instance->queryString )
348
        ) {
349
            $tmp_mode = true;
350
        }
351
352
        // SQLが渡されたときはPDOStatementのインスタンスを更新する(既存のインスタンスがなくSQL未指定の場合はfalseを返す)
353
        try {
354
            if (strtolower( $sql ) == 'clear') {
355
                $this->pdostatement_instance = null;
356
            } elseif (!empty( $sql )) {
357
                $this->pdostatement_instance = null;
358
                $this->pdostatement_instance = $this->pdo_instance->prepare( $sql, $query_options );
359
            }
360
361
            // PDOStatementクラスのインスタンスが生成済みの時だけSQLを実行
362
            if (!empty( $this->pdostatement_instance )) {
363
                // パラメタが指定されている時はバインドする
364
                if (!empty( $param ) and is_array( $param )) {
365
                    foreach ($param as $dat) {
366
                        // lengthがセットされているかどうかでbindParam()のコールを変更する
367
                        if (isset( $dat[ 'length' ] ) and !empty( $dat[ 'length' ] )) {
368
                            /** @noinspection PhpUndefinedMethodInspection */
369
                            $this->pdostatement_instance->bindParam( $dat[ 'id' ], $dat[ 'value' ], $dat[ 'type' ],
370
                                $dat[ 'length' ] );
371
                        } else {
372
                            /** @noinspection PhpUndefinedMethodInspection */
373
                            $this->pdostatement_instance->bindParam( $dat[ 'id' ], $dat[ 'value' ], $dat[ 'type' ] );
374
                        }
375
                    }
376
                }
377
378
                // SQLを実行し結果を取得する
379
                /** @noinspection PhpUndefinedMethodInspection */
380
                $retval_execute = $this->pdostatement_instance->execute();
381
                // データ取得モードの時のみfetchする
382
                if ($tmp_mode) {
383
                    /** @noinspection PhpUndefinedMethodInspection */
384
                    $retval_fetch = ( ( $fetch_dat = $this->pdostatement_instance->fetchAll( $fetch_style ) ) === false ? false : true );
385
                } else {
386
                    $retval_fetch = true;
387
                    $fetch_dat = true;
388
                }
389
                $retval = ( ( $retval_execute and $retval_fetch ) ? $fetch_dat : false );
390
391
                return $retval;
392
            } else {
393
                $retval = false;
394
            }
395
        } catch ( \PDOException $e ) {
396
            // 取得に失敗したらエラーメッセージを生成
397
            $this->genErrorMsg( 'pdo', $e->getMessage() );
398
399
            return false;
400
        }
401
402
        return $retval;
403
    }
404
405
    /**
406
     * genDSN()
407
     *
408
     * DSN文字列を生成する
409
     *
410
     * @access    private
411
     *
412
     * @param     void
413
     *
414
     * @return    string DSN文字列
415
     */
416
    private function genDSN()
417
    {
418
        // 変数の初期化
419
        $retval = '';
420
421
        // ドライバ名のセット
422
        if (isset( $this->dbinfo[ 'driver' ] ) and !empty( $this->dbinfo[ 'driver' ] ) and in_array( $this->dbinfo[ 'driver' ],
423
                \PDO::getAvailableDrivers() )
424
        ) {
425
            $retval .= $this->dbinfo[ 'driver' ] . ':';
426
        } else {
427
            $this->genErrorMsg( "undefined", 'driver' );
428
        }
429
430
        // DB名のセット
431 View Code Duplication
        if (isset( $this->dbinfo[ 'dbname' ] ) and !empty( $this->dbinfo[ 'dbname' ] )) {
432
            $retval .= 'dbname=' . $this->dbinfo[ 'dbname' ] . ';';
433
        } else {
434
            $this->genErrorMsg( "undefined", 'dbname' );
435
        }
436
437
        // ホスト名のセット
438 View Code Duplication
        if (isset( $this->dbinfo[ 'host' ] ) and !empty( $this->dbinfo[ 'host' ] )) {
439
            $retval .= 'hostname=' . $this->dbinfo[ 'host' ] . ';';
440
        } else {
441
            $this->genErrorMsg( "undefined", 'host' );
442
        }
443
444
        // キャラクタセットのセット
445 View Code Duplication
        if (isset( $this->dbinfo[ 'charset' ] ) and !empty( $this->dbinfo[ 'charset' ] )) {
446
            $retval .= 'charset=' . $this->dbinfo[ 'charset' ];
447
        } else {
448
            $this->genErrorMsg( "undefined", 'charset' );
449
        }
450
451
        return $retval;
452
    }
453
454
    /**
455
     * genErrorMsg($key = '')
456
     *
457
     * クラス内で発生したエラーに対するエラーメッセージを生成する
458
     *
459
     * @access    private
460
     *
461
     * @param     string $key エラーを示すキー文字列
462
     * @param     string $optional_text オプションの文字列
463
     *
464
     * @return    string    エラーメッセージ
465
     */
466
    private function genErrorMsg( $key = '', $optional_text = '' )
467
    {
468
        // 引数の値に応じてエラーメッセージをセットする
469
        switch ($key) {
470
            // 未定義エラーの場合
471 View Code Duplication
            case 'undefined':
472
                $msg = 'Value not set - ' . ( ( isset( $optional_text ) and !empty( $optional_text ) ) ? $optional_text : 'unknown' );
473
                break;
474
475
            // PDO関連エラーの場合
476 View Code Duplication
            case 'pdo':
477
                $msg = 'PDO error happened - ' . ( ( isset( $optional_text ) and !empty( $optional_text ) ) ? $optional_text : 'unknown' );
478
                break;
479
480
481
            // 未定義のエラーの場合
482
            default:
483
                $msg = 'Unknown Error occurred';
484
                break;
485
        }
486
487
        // ログ出力しエラーメッセージを返却
488
        $this->risolutoErrorLog( 'error', $msg );
489
490
        return $msg;
491
    }
492
}
493