Completed
Push — work-fleets ( 3cd948...da4c88 )
by SuperNova.WS
07:01
created

db_mysql::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
ccs 0
cts 2
cp 0
crap 2
1
<?php
2
3
/**
4
 * User: Gorlum
5
 * Date: 01.09.2015
6
 * Time: 15:58
7
 */
8
class db_mysql {
9
  const TRANSACTION_SERIALIZABLE = 'SERIALIZABLE';
10
  const TRANSACTION_REPEATABLE_READ = 'REPEATABLE READ';
11
  const TRANSACTION_READ_COMMITTED = 'READ COMMITTED';
12
  const TRANSACTION_READ_UNCOMMITTED = 'READ UNCOMMITTED';
13
14
  /**
15
   * Статус соеднения с MySQL
16
   *
17
   * @var bool
18
   */
19
  public $connected = false;
20
  /**
21
   * Префикс названий таблиц в БД
22
   *
23
   * @var string
24
   */
25
  public $db_prefix = '';
26
  /**
27
   * Список таблиц в БД
28
   *
29
   * @var array
30
   */
31
  public $table_list = array();
32
33
  /**
34
   * Настройки БД
35
   *
36
   * @var array
37
   */
38
  protected $dbsettings = array();
39
  /**
40
   * Драйвер для прямого обращения к MySQL
41
   *
42
   * @var db_mysql_v5 $driver
43
   */
44
  public $driver = null;
45
46
  /**
47
   * Общее время запросов
48
   *
49
   * @var float $time_mysql_total
50
   */
51
  public $time_mysql_total = 0.0;
52
53
  /**
54
   * Amount of queries on this DB
55
   *
56
   * @var int
57
   */
58
  public $queryCount = 0;
59
60
  public $isWatching = false;
61
62
  public function __construct() {
63
  }
64
65
  public function load_db_settings() {
66
    $dbsettings = array();
67
68
    require(SN_ROOT_PHYSICAL . "config" . DOT_PHP_EX);
69
70
    $this->dbsettings = $dbsettings;
71
  }
72
73
  public function sn_db_connect($external_db_settings = null) {
74
    $this->db_disconnect();
75
76
    if (!empty($external_db_settings) && is_array($external_db_settings)) {
77
      $this->dbsettings = $external_db_settings;
78
    }
79
80
    if (empty($this->dbsettings)) {
81
      $this->load_db_settings();
82
    }
83
84
    // TODO - фатальные (?) ошибки на каждом шагу. Хотя - скорее Эксепшны
85
    if (!empty($this->dbsettings)) {
86
      $driver_name = empty($this->dbsettings['sn_driver']) ? 'db_mysql_v5' : $this->dbsettings['sn_driver'];
87
      $this->driver = new $driver_name();
88
      $this->db_prefix = $this->dbsettings['prefix'];
89
90
      $this->connected = $this->connected || $this->driver_connect();
91
92
      if ($this->connected) {
93
        $this->table_list = $this->db_get_table_list();
94
        // TODO Проверка на пустоту
95
      }
96
    } else {
97
      $this->connected = false;
98
    }
99
100
    return $this->connected;
101
  }
102
103
  protected function driver_connect() {
104
    if (!is_object($this->driver)) {
105
      classSupernova::$debug->error_fatal('DB Error - No driver for MySQL found!');
106
    }
107
108
    if (!method_exists($this->driver, 'mysql_connect')) {
109
      classSupernova::$debug->error_fatal('DB Error - WRONG MySQL driver!');
110
    }
111
112
    return $this->driver->mysql_connect($this->dbsettings);
113
  }
114
115
  public function db_disconnect() {
116
    if ($this->connected) {
117
      $this->connected = !$this->driver_disconnect();
118
      $this->connected = false;
119
    }
120
121
    return !$this->connected;
122
  }
123
124
  /**
125
   * @param string $query
126
   *
127
   * @return mixed|string
128
   */
129
  public function replaceTablePlaceholders($query) {
130
    $sql = $query;
131
    if (strpos($sql, '{{') !== false) {
132
      foreach ($this->table_list as $tableName) {
133
        $sql = str_replace("{{{$tableName}}}", $this->db_prefix . $tableName, $sql);
134
      }
135
    }
136
137
    return $sql;
138
  }
139
140
  /**
141
   * @param       $query
142
   * @param       $fetch
143
   */
144
  protected function logQuery($query, $fetch) {
145
    if (!classSupernova::$config->debug) {
146
      return;
147
    }
148
149
    $this->queryCount++;
150
    $arr = debug_backtrace();
151
    $file = end(explode('/', $arr[0]['file']));
0 ignored issues
show
Bug introduced by
explode('/', $arr[0]['file']) cannot be passed to end() as the parameter $array expects a reference.
Loading history...
152
    $line = $arr[0]['line'];
153
    classSupernova::$debug->add("<tr><th>Query {$this->queryCount}: </th><th>$query</th><th>{$file} @ {$line}</th><th>&nbsp;</th><th> " . ($fetch ? '+' : '&nbsp;') . " </th></tr>");
154
  }
155
156
157
  /**
158
   * @return string
159
   */
160
  public function queryTrace() {
161
    if (!defined('DEBUG_SQL_COMMENT') || constant('DEBUG_SQL_ERROR') !== true) {
162
      return '';
163
    }
164
165
    $backtrace = debug_backtrace();
166
    $sql_comment = classSupernova::$debug->compact_backtrace($backtrace, defined('DEBUG_SQL_COMMENT_LONG'));
167
168
    if (defined('DEBUG_SQL_ERROR') && constant('DEBUG_SQL_ERROR') === true) {
169
      classSupernova::$debug->add_to_array($sql_comment);
170
    }
171
172
    $sql_commented = implode("\r\n", $sql_comment);
173
    if (defined('DEBUG_SQL_ONLINE') && constant('DEBUG_SQL_ONLINE') === true) {
174
      classSupernova::$debug->warning($sql_commented, 'SQL Debug', LOG_DEBUG_SQL);
175
    }
176
177
    return $sql_commented;
178
  }
179
180
  /**
181
   * @param string $query
182
   * @param string $table
183
   * @param bool   $fetch
184
   * @param bool   $skip_query_check
185
   *
186
   * @return array|bool|mysqli_result|null
187
   */
188
  public function doquery($query, $table = '', $fetch = false, $skip_query_check = false) {
189
    if (!is_string($table)) {
190
      $fetch = $table;
191
    }
192
193
    if (!$this->connected) {
194
      $this->sn_db_connect();
195
    }
196
197
//    $stringQuery = $query instanceof DbSqlPrepare ? $query->query : $query;
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
198
    $stringQuery = $query;
199
    $stringQuery = trim($stringQuery);
200
    // You can't do it - 'cause you can break commented statement with line-end comments
201
    // $stringQuery = preg_replace("/\s+/", ' ', $stringQuery);
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
202
203
    $this->security_watch_user_queries($stringQuery);
204
    $this->security_query_check_bad_words($stringQuery, $skip_query_check);
205
    $this->logQuery($stringQuery, $fetch);
206
207
    $stringQuery = $this->replaceTablePlaceholders($stringQuery);
208
209
    $queryTrace = $this->queryTrace();
210
211
    $queryResult = null;
212
    try {
213
      $queryResult = $this->db_sql_query($stringQuery . DbSqlHelper::quoteComment($queryTrace));
214
      if (!$queryResult) {
215
        throw new Exception();
216
      }
217
    } catch (Exception $e) {
218
      classSupernova::$debug->error($this->db_error() . "<br />{$query}<br />", 'SQL Error');
219
    }
220
221
    if ($fetch) {
222
      $queryResult = $this->db_fetch($queryResult);
0 ignored issues
show
Bug introduced by
It seems like $queryResult defined by $this->db_fetch($queryResult) on line 222 can also be of type boolean; however, db_mysql::db_fetch() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
223
      // DO NOT CLOSE STATEMENT HERE TO MAKE STATEMENT CACHING WORK!
224
    }
225
226
    return $queryResult;
227
  }
228
229
  /**
230
   * @param string $query
231
   * @param bool   $skip_query_check
232
   *
233
   * @return array|null
234
   */
235
  public function doQueryFetch($query, $skip_query_check = false) {
236
    $queryResult = $this->doquery($query, '', false, $skip_query_check);
237
238
    return $this->db_fetch($queryResult);
239
  }
240
241
  /**
242
   * @param string $query
243
   * @param bool   $skip_query_check
244
   *
245
   * @return mixed|null
246
   */
247
  public function doQueryFetchValue($query, $skip_query_check = false) {
248
    $row = $this->doQueryFetch($query, $skip_query_check);
249
250
    return is_array($row) ? reset($row) : null;
251
  }
252
253
  /**
254
   * Returns iterator to iterate through mysqli_result
255
   *
256
   * @param string $query
257
   * @param bool   $skip_query_check
258
   *
259
   * return DbResultIterator
260
   *
261
   * @return DbEmptyIterator|DbMysqliResultIterator
262
   */
263
  public function doQueryIterator($query, $skip_query_check = false) {
264
    $queryResult = $this->doquery($query, '', false, $skip_query_check);
265
266
    if ($queryResult instanceof mysqli_result) {
267
      $result = new DbMysqliResultIterator($queryResult);
268
    } else {
269
      $result = new DbEmptyIterator();
270
    }
271
272
    return $result;
273
  }
274
275
  /**
276
   * @param DbQueryConstructor $stmt
277
   * @param bool               $skip_query_check
278
   *
279
   * @return DbEmptyIterator|DbMysqliResultIterator
280
   */
281
  public function doStmtSelectIterator($stmt, $skip_query_check = false) {
282
    return $this->doQueryIterator($stmt->select()->__toString(), $skip_query_check);
283
  }
284
285
  /**
286
   * @param DbQueryConstructor $stmt
287
   * @param bool               $skip_query_check
288
   *
289
   * @return array
290
   */
291
  public function doStmtSelectRow($stmt, $skip_query_check = false) {
292
    $result = $this->doQueryFetch($stmt->select()->setFetchOne()->__toString(), $skip_query_check);
293
294
    return is_array($result) ? $result : array();
295
  }
296
297
  /**
298
   * @param DbQueryConstructor $stmt
299
   * @param bool               $skip_query_check
300
   *
301
   * @return mixed|null
302
   */
303
  public function doStmtSelectValue($stmt, $skip_query_check = false) {
304
    $result = $this->doStmtSelectRow($stmt, $skip_query_check);
305
306
    return is_array($result) ? reset($result) : null;
307
  }
308
309
  /**
310
   * @param DbQueryConstructor $stmt
311
   * @param bool               $skip_query_check
312
   */
313
  public function doStmtLockAll($stmt, $skip_query_check = false) {
314
    $this->doquery(
315
      $stmt
316
        ->select()
317
        ->field(1)
318
        ->setForUpdate()
319
        ->__toString(),
320
      '',
321
      false,
322
      $skip_query_check
323
    );
324
  }
325
326
  // TODO Заменить это на новый логгер
327
  protected function security_watch_user_queries($query) {
328
    global $user;
329
330
    if (
331
      !$this->isWatching // Not already watching
332
      && !empty(classSupernova::$config->game_watchlist_array) // There is some players in watchlist
333
      && in_array($user['id'], classSupernova::$config->game_watchlist_array) // Current player is in watchlist
334
      && !preg_match('/^(select|commit|rollback|start transaction)/i', $query) // Current query should be watched
335
    ) {
336
      $this->isWatching = true;
337
      $msg = "\$query = \"{$query}\"\n\r";
338
      if (!empty($_POST)) {
339
        $msg .= "\n\r" . dump($_POST, '$_POST');
340
      }
341
      if (!empty($_GET)) {
342
        $msg .= "\n\r" . dump($_GET, '$_GET');
343
      }
344
      classSupernova::$debug->warning($msg, "Watching user {$user['id']}", 399, array('base_dump' => true));
0 ignored issues
show
Documentation introduced by
array('base_dump' => true) is of type array<string,boolean,{"base_dump":"boolean"}>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
345
      $this->isWatching = false;
346
    }
347
  }
348
349
350
  public function security_query_check_bad_words($query, $skip_query_check = false) {
351
    if ($skip_query_check) {
352
      return;
353
    }
354
355
    global $user, $dm_change_legit, $mm_change_legit;
356
357
    switch (true) {
358
      case stripos($query, 'RUNCATE TABL') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'RUNCATE TABL') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
359
      case stripos($query, 'ROP TABL') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'ROP TABL') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
360
      case stripos($query, 'ENAME TABL') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'ENAME TABL') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
361
      case stripos($query, 'REATE DATABAS') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'REATE DATABAS') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
362
      case stripos($query, 'REATE TABL') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'REATE TABL') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
363
      case stripos($query, 'ET PASSWOR') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'ET PASSWOR') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
364
      case stripos($query, 'EOAD DAT') != false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'EOAD DAT') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
365
      case stripos($query, 'RPG_POINTS') != false && stripos(trim($query), 'UPDATE ') === 0 && !$dm_change_legit:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'RPG_POINTS') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
366
      case stripos($query, 'METAMATTER') != false && stripos(trim($query), 'UPDATE ') === 0 && !$mm_change_legit:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'METAMATTER') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
367
      case stripos($query, 'AUTHLEVEL') != false && $user['authlevel'] < 3 && stripos($query, 'SELECT') !== 0:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stripos($query, 'AUTHLEVEL') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
368
        $report = "Hacking attempt (" . date("d.m.Y H:i:s") . " - [" . time() . "]):\n";
369
        $report .= ">Database Inforamation\n";
370
        $report .= "\tID - " . $user['id'] . "\n";
371
        $report .= "\tUser - " . $user['username'] . "\n";
372
        $report .= "\tAuth level - " . $user['authlevel'] . "\n";
373
        $report .= "\tAdmin Notes - " . $user['adminNotes'] . "\n";
374
        $report .= "\tCurrent Planet - " . $user['current_planet'] . "\n";
375
        $report .= "\tUser IP - " . $user['user_lastip'] . "\n";
376
        $report .= "\tUser IP at Reg - " . $user['ip_at_reg'] . "\n";
377
        $report .= "\tUser Agent- " . $_SERVER['HTTP_USER_AGENT'] . "\n";
378
        $report .= "\tCurrent Page - " . $user['current_page'] . "\n";
379
        $report .= "\tRegister Time - " . $user['register_time'] . "\n";
380
        $report .= "\n";
381
382
        $report .= ">Query Information\n";
383
        $report .= "\tQuery - " . $query . "\n";
384
        $report .= "\n";
385
386
        $report .= ">\$_SERVER Information\n";
387
        $report .= "\tIP - " . $_SERVER['REMOTE_ADDR'] . "\n";
388
        $report .= "\tHost Name - " . $_SERVER['HTTP_HOST'] . "\n";
389
        $report .= "\tUser Agent - " . $_SERVER['HTTP_USER_AGENT'] . "\n";
390
        $report .= "\tRequest Method - " . $_SERVER['REQUEST_METHOD'] . "\n";
391
        $report .= "\tCame From - " . $_SERVER['HTTP_REFERER'] . "\n";
392
        $report .= "\tPage is - " . $_SERVER['SCRIPT_NAME'] . "\n";
393
        $report .= "\tUses Port - " . $_SERVER['REMOTE_PORT'] . "\n";
394
        $report .= "\tServer Protocol - " . $_SERVER['SERVER_PROTOCOL'] . "\n";
395
396
        $report .= "\n--------------------------------------------------------------------------------------------------\n";
397
398
        $fp = fopen(SN_ROOT_PHYSICAL . 'badqrys.txt', 'a');
399
        fwrite($fp, $report);
0 ignored issues
show
Security File Manipulation introduced by
$report can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

7 paths for user data to reach this point

  1. Path: Fetching key HTTP_REFERER from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 391
  1. Fetching key HTTP_REFERER from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 391
  2. Path: Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 389
  1. Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 389
  2. $report is assigned
    in includes/classes/db_mysql.php on line 391
  3. Path: Fetching key HTTP_HOST from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 388
  1. Fetching key HTTP_HOST from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 388
  2. $report is assigned
    in includes/classes/db_mysql.php on line 389
  3. $report is assigned
    in includes/classes/db_mysql.php on line 391
  4. Path: Read from $_POST in includes/general.php on line 258
  1. Read from $_POST
    in includes/general.php on line 258
  2. sys_get_param() returns tainted data, and $value is assigned
    in includes/general.php on line 266
  3. sys_get_param_id() returns tainted data, and $fleetid is assigned
    in includes/includes/flt_page4.inc on line 9
  4. $fleetid is passed to DBStaticFleetACS::db_acs_insert()
    in includes/includes/flt_page4.inc on line 50
  5. ``'INSERT INTO {{aks}} SET `name` = \'' . db_escape(classLocale::$lang['flt_acs_prefix'] . $fleetid) . '\', `teilnehmer` = \'' . $user['id'] . '\', `flotten` = \'' . $fleetid . '\', `ankunft` = \'' . $objFleet->time_arrive_to_target . '\', `galaxy` = \'' . $objFleet->fleet_end_galaxy . '\', `system` = \'' . $objFleet->fleet_end_system . '\', `planet` = \'' . $objFleet->fleet_end_planet . '\', `planet_type` = \'' . $objFleet->fleet_end_type . '\', `eingeladen` = \'' . $user['id'] . '\', `fleet_end_time` = \'' . $objFleet->time_return_to_source . '\''`` is passed to doquery()
    in includes/classes/DBStaticFleetACS.php on line 53
  6. $query is passed to db_mysql::doquery()
    in includes/db.php on line 183
  7. $stringQuery is assigned
    in includes/classes/db_mysql.php on line 198
  8. $stringQuery is passed through trim(), and $stringQuery is assigned
    in includes/classes/db_mysql.php on line 199
  9. $stringQuery is passed to db_mysql::security_query_check_bad_words()
    in includes/classes/db_mysql.php on line 204
  10. $report is assigned
    in includes/classes/db_mysql.php on line 383
  11. $report is assigned
    in includes/classes/db_mysql.php on line 388
  12. $report is assigned
    in includes/classes/db_mysql.php on line 389
  13. $report is assigned
    in includes/classes/db_mysql.php on line 391
  5. Path: Read from $_GET in includes/classes/db_mysql.php on line 342
  1. Read from $_GET
    in includes/classes/db_mysql.php on line 342
  2. Data is passed through gettype()
    in vendor/docs/txt2html.php on line 18
  3. $msg is assigned
    in includes/classes/db_mysql.php on line 342
  4. $msg is passed to debug::warning()
    in includes/classes/db_mysql.php on line 344
  5. Data is escaped by mysqli_real_escape_string() for sql context(s)
    in vendor/includes/classes/db_mysql_v5.php on line 89
  6. $query is assigned
    in includes/classes/debug.php on line 256
  7. $query is passed to doquery()
    in includes/classes/debug.php on line 261
  8. $query is passed to db_mysql::doquery()
    in includes/db.php on line 183
  9. $stringQuery is assigned
    in includes/classes/db_mysql.php on line 198
  10. $stringQuery is passed through trim(), and $stringQuery is assigned
    in includes/classes/db_mysql.php on line 199
  11. $stringQuery is passed to db_mysql::security_query_check_bad_words()
    in includes/classes/db_mysql.php on line 204
  12. $report is assigned
    in includes/classes/db_mysql.php on line 383
  13. $report is assigned
    in includes/classes/db_mysql.php on line 388
  14. $report is assigned
    in includes/classes/db_mysql.php on line 389
  15. $report is assigned
    in includes/classes/db_mysql.php on line 391
  6. Path: Read from $_POST in includes/classes/db_mysql.php on line 339
  1. Read from $_POST
    in includes/classes/db_mysql.php on line 339
  2. Data is passed through gettype()
    in vendor/docs/txt2html.php on line 18
  3. $msg is assigned
    in includes/classes/db_mysql.php on line 339
  4. $msg is passed to debug::warning()
    in includes/classes/db_mysql.php on line 344
  5. Data is escaped by mysqli_real_escape_string() for sql context(s)
    in vendor/includes/classes/db_mysql_v5.php on line 89
  6. $query is assigned
    in includes/classes/debug.php on line 256
  7. $query is passed to doquery()
    in includes/classes/debug.php on line 261
  8. $query is passed to db_mysql::doquery()
    in includes/db.php on line 183
  9. $stringQuery is assigned
    in includes/classes/db_mysql.php on line 198
  10. $stringQuery is passed through trim(), and $stringQuery is assigned
    in includes/classes/db_mysql.php on line 199
  11. $stringQuery is passed to db_mysql::security_query_check_bad_words()
    in includes/classes/db_mysql.php on line 204
  12. $report is assigned
    in includes/classes/db_mysql.php on line 383
  13. $report is assigned
    in includes/classes/db_mysql.php on line 388
  14. $report is assigned
    in includes/classes/db_mysql.php on line 389
  15. $report is assigned
    in includes/classes/db_mysql.php on line 391
  7. Path: Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 377
  1. Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 377
  2. $report is assigned
    in includes/classes/db_mysql.php on line 383
  3. $report is assigned
    in includes/classes/db_mysql.php on line 388
  4. $report is assigned
    in includes/classes/db_mysql.php on line 389
  5. $report is assigned
    in includes/classes/db_mysql.php on line 391

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
400
        fclose($fp);
401
402
        $message = 'Привет, я не знаю то, что Вы пробовали сделать, но команда, которую Вы только послали базе данных, не выглядела очень дружественной и она была заблокированна.<br /><br />Ваш IP, и другие данные переданны администрации сервера. Удачи!.';
403
        die($message);
404
      break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
405
    }
406
  }
407
408
  /**
409
   * @param bool $prefixed_only
410
   *
411
   * @return array
412
   */
413
  public function db_get_table_list($prefixed_only = true) {
414
    $query = $this->mysql_get_table_list();
415
416
    $prefix_length = strlen($this->db_prefix);
417
418
    $tl = array();
419
    while ($row = $this->db_fetch($query)) {
0 ignored issues
show
Bug introduced by
It seems like $query defined by $this->mysql_get_table_list() on line 414 can also be of type boolean; however, db_mysql::db_fetch() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
420
      foreach ($row as $table_name) {
421
        if (strpos($table_name, $this->db_prefix) === 0) {
422
          $table_name = substr($table_name, $prefix_length);
423
        } elseif ($prefixed_only) {
424
          continue;
425
        }
426
        // $table_name = str_replace($db_prefix, '', $table_name);
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
427
        $tl[$table_name] = $table_name;
428
      }
429
    }
430
431
    return $tl;
432
  }
433
434
  /**
435
   * @param string $statement
436
   *
437
   * @return bool|mysqli_stmt
438
   */
439 View Code Duplication
  public function db_prepare($statement) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
440
    $microtime = microtime(true);
441
    $result = $this->driver->mysql_prepare($statement);
442
    $this->time_mysql_total += microtime(true) - $microtime;
443
444
    return $result;
445
  }
446
447
448
  /**
449
   * L1 perform the query
450
   *
451
   * @param $query_string
452
   *
453
   * @return bool|mysqli_result
454
   */
455 View Code Duplication
  public function db_sql_query($query_string) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
456
    $microtime = microtime(true);
457
    $result = $this->driver->mysql_query($query_string);
458
    $this->time_mysql_total += microtime(true) - $microtime;
459
460
    return $result;
461
  }
462
463
  /**
464
   * L1 fetch assoc array
465
   *
466
   * @param mysqli_result $query
467
   *
468
   * @return array|null
469
   */
470 View Code Duplication
  public function db_fetch(&$query) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
471
    $microtime = microtime(true);
472
    $result = $this->driver->mysql_fetch_assoc($query);
473
    $this->time_mysql_total += microtime(true) - $microtime;
474
475
    return $result;
476
  }
477
478
  public function db_fetch_row(&$query) {
479
    return $this->driver->mysql_fetch_row($query);
480
  }
481
482
  public function db_escape($unescaped_string) {
483
    return $this->driver->mysql_real_escape_string($unescaped_string);
484
  }
485
486
  public function driver_disconnect() {
487
    return $this->driver->mysql_close_link();
488
  }
489
490
  public function db_error() {
491
    return $this->driver->mysql_error();
492
  }
493
494
  public function db_insert_id() {
495
    return $this->driver->mysql_insert_id();
496
  }
497
498
  public function db_num_rows(&$result) {
499
    return $this->driver->mysql_num_rows($result);
500
  }
501
502
  public function db_affected_rows() {
503
    return $this->driver->mysql_affected_rows();
504
  }
505
506
  /**
507
   * @return string
508
   */
509
  public function db_get_client_info() {
510
    return $this->driver->mysql_get_client_info();
511
  }
512
513
  /**
514
   * @return string
515
   */
516
  public function db_get_server_info() {
517
    return $this->driver->mysql_get_server_info();
518
  }
519
520
  /**
521
   * @return string
522
   */
523
  public function db_get_host_info() {
524
    return $this->driver->mysql_get_host_info();
525
  }
526
527
  public function db_get_server_stat() {
528
    $result = array();
529
530
    $status = explode('  ', $this->driver->mysql_stat());
531
    foreach ($status as $value) {
532
      $row = explode(': ', $value);
533
      $result[$row[0]] = $row[1];
534
    }
535
536
    return $result;
537
  }
538
539
  /**
540
   * @return array
541
   * @throws Exception
542
   */
543
  public function db_core_show_status() {
544
    $result = array();
545
546
    $query = $this->db_sql_query('SHOW STATUS;');
547
    if (is_bool($query)) {
548
      throw new Exception('Result of SHOW STATUS command is boolean - which should never happen. Connection to DB is lost?');
549
    }
550
    while ($row = db_fetch($query)) {
551
      $result[$row['Variable_name']] = $row['Value'];
552
    }
553
554
    return $result;
555
  }
556
557
  public function mysql_get_table_list() {
558
    return $this->db_sql_query('SHOW TABLES;');
559
  }
560
561
  public function mysql_get_innodb_status() {
562
    return $this->db_sql_query('SHOW ENGINE INNODB STATUS;');
563
  }
564
565
}
566