Completed
Push — work-fleets ( 2bd11a...17dd3b )
by SuperNova.WS
06:36
created

db_mysql::doUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
ccs 0
cts 1
cp 0
crap 2
1
<?php
2
3
/**
4
 * Created by Gorlum 01.09.2015 15:58
5
 */
6
class db_mysql {
7
  const TRANSACTION_SERIALIZABLE = 'SERIALIZABLE';
8
  const TRANSACTION_REPEATABLE_READ = 'REPEATABLE READ';
9
  const TRANSACTION_READ_COMMITTED = 'READ COMMITTED';
10
  const TRANSACTION_READ_UNCOMMITTED = 'READ UNCOMMITTED';
11
12
  /**
13
   * Статус соеднения с MySQL
14
   *
15
   * @var bool
16
   */
17
  public $connected = false;
18
  /**
19
   * Префикс названий таблиц в БД
20
   *
21
   * @var string
22
   */
23
  public $db_prefix = '';
24
  /**
25
   * Список таблиц в БД
26
   *
27
   * @var array
28
   */
29
  public $table_list = array();
30
31
  /**
32
   * Настройки БД
33
   *
34
   * @var array
35
   */
36
  protected $dbsettings = array();
37
  /**
38
   * Драйвер для прямого обращения к MySQL
39
   *
40
   * @var db_mysql_v5 $driver
41
   */
42
  public $driver = null;
43
44
  /**
45
   * Общее время запросов
46
   *
47
   * @var float $time_mysql_total
48
   */
49
  public $time_mysql_total = 0.0;
50
51
  /**
52
   * Amount of queries on this DB
53
   *
54
   * @var int
55
   */
56
  public $queryCount = 0;
57
58
  public $isWatching = false;
59
60
  /**
61
   * @var \DBAL\DbTransaction $transaction
62
   */
63
  protected $transaction;
64
65
  /**
66
   * Should query check be skipped?
67
   *
68
   * Used for altering sheme of DB
69
   *
70
   * @var bool $skipQueryCheck
71
   */
72
  protected $skipQueryCheck = false;
73
74
  /**
75
   * db_mysql constructor.
76
   *
77
   * @param \Common\GlobalContainer $gc
78
   */
79
  public function __construct($gc) {
0 ignored issues
show
Unused Code introduced by
The parameter $gc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
80
    $this->transaction = new \DBAL\DbTransaction($this);
81
  }
82
83
  public function load_db_settings($configFile = '') {
84
    $dbsettings = array();
85
86
    empty($configFile) ? $configFile = SN_ROOT_PHYSICAL . "config" . DOT_PHP_EX : false;
87
88
    require $configFile;
89
90
    $this->dbsettings = $dbsettings;
91
  }
92
93
  /**
94
   * @param null|array $external_db_settings
95
   *
96
   * @return bool
97
   */
98
  public function sn_db_connect($external_db_settings = null) {
99
    $this->db_disconnect();
100
101
    if (!empty($external_db_settings) && is_array($external_db_settings)) {
102
      $this->dbsettings = $external_db_settings;
103
    }
104
105
    if (empty($this->dbsettings)) {
106
      $this->load_db_settings(SN_ROOT_PHYSICAL . "config" . DOT_PHP_EX);
107
    }
108
109
    // TODO - фатальные (?) ошибки на каждом шагу. Хотя - скорее Эксепшны
110
    if (!empty($this->dbsettings)) {
111
      $driver_name = empty($this->dbsettings['sn_driver']) ? 'db_mysql_v5' : $this->dbsettings['sn_driver'];
112
      $this->driver = new $driver_name();
113
      $this->db_prefix = $this->dbsettings['prefix'];
114
115
      $this->connected = $this->connected || $this->driver_connect();
116
117
      if ($this->connected) {
118
        $this->table_list = $this->db_get_table_list();
119
        // TODO Проверка на пустоту
120
      }
121
    } else {
122
      $this->connected = false;
123
    }
124
125
    return $this->connected;
126
  }
127
128
  protected function driver_connect() {
129
    if (!is_object($this->driver)) {
130
      classSupernova::$debug->error_fatal('DB Error - No driver for MySQL found!');
131
    }
132
133
    if (!method_exists($this->driver, 'mysql_connect')) {
134
      classSupernova::$debug->error_fatal('DB Error - WRONG MySQL driver!');
135
    }
136
137
    return $this->driver->mysql_connect($this->dbsettings);
138
  }
139
140
  public function db_disconnect() {
141
    if ($this->connected) {
142
      $this->connected = !$this->driver_disconnect();
143
      $this->connected = false;
144
    }
145
146
    return !$this->connected;
147
  }
148
149
  /**
150
   * @param string $query
151
   *
152
   * @return mixed|string
153
   */
154
  public function replaceTablePlaceholders($query) {
155
    $sql = $query;
156
    if (strpos($sql, '{{') !== false) {
157
      foreach ($this->table_list as $tableName) {
158
        $sql = str_replace("{{{$tableName}}}", $this->db_prefix . $tableName, $sql);
159
      }
160
    }
161
162
    return $sql;
163
  }
164
165
  /**
166
   * @param $query
167
   */
168
  protected function logQuery($query) {
169
    if (!classSupernova::$config->debug) {
170
      return;
171
    }
172
173
    $this->queryCount++;
174
    $arr = debug_backtrace();
175
    $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...
176
    $line = $arr[0]['line'];
177
    classSupernova::$debug->add("<tr><th>Query {$this->queryCount}: </th><th>$query</th><th>{$file} @ {$line}</th><th>&nbsp;</th></tr>");
178
  }
179
180
181
  /**
182
   * @return string
183
   */
184
  public function queryTrace() {
185
    if (!defined('DEBUG_SQL_COMMENT') || constant('DEBUG_SQL_ERROR') !== true) {
186
      return '';
187
    }
188
189
    $backtrace = debug_backtrace();
190
    $sql_comment = classSupernova::$debug->compact_backtrace($backtrace, defined('DEBUG_SQL_COMMENT_LONG'));
191
192
    if (defined('DEBUG_SQL_ERROR') && constant('DEBUG_SQL_ERROR') === true) {
193
      classSupernova::$debug->add_to_array($sql_comment);
194
    }
195
196
    $sql_commented = implode("\r\n", $sql_comment);
197
    if (defined('DEBUG_SQL_ONLINE') && constant('DEBUG_SQL_ONLINE') === true) {
198
      classSupernova::$debug->warning($sql_commented, 'SQL Debug', LOG_DEBUG_SQL);
199
    }
200
201
    return $sql_commented;
202
  }
203
204
  /**
205
   * @param string $query
206
   *
207
   * @return array|bool|mysqli_result|null
208
   * @internal param bool $skip_query_check
209
   *
210
   */
211
  protected function doquery($query) {
212
    if (!$this->connected) {
213
      $this->sn_db_connect();
214
    }
215
216
    $stringQuery = $query;
217
    $stringQuery = trim($stringQuery);
218
    // You can't do it - 'cause you can break commented statement with line-end comments
219
    // $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...
220
221
    $this->security_watch_user_queries($stringQuery);
222
    $this->security_query_check_bad_words($stringQuery);
223
    $this->logQuery($stringQuery);
224
225
    $stringQuery = $this->replaceTablePlaceholders($stringQuery);
226
227
    $queryTrace = $this->queryTrace();
228
229
    $queryResult = null;
230
    try {
231
      $queryResult = $this->db_sql_query($stringQuery . DbSqlHelper::quoteComment($queryTrace));
232
      if (!$queryResult) {
233
        throw new Exception();
234
      }
235
    } catch (Exception $e) {
236
      classSupernova::$debug->error($this->db_error() . "<br />{$query}<br />", 'SQL Error');
237
    }
238
239
    return $queryResult;
240
  }
241
242
243
  // Just wrappers to distinguish query types
244
  /**
245
   * Executes non-data manipulation statements
246
   *
247
   * Can execute queries with check skip
248
   * Honor current state of query checking
249
   *
250
   * @param string $query
251
   * @param bool   $skip_query_check
252
   *
253
   * @return array|bool|mysqli_result|null
254
   */
255
  public function doExecute($query, $skip_query_check = false) {
256
    $prevState = false;
257
    if ($skip_query_check) {
258
      $prevState = $this->skipQueryCheck;
259
      $this->skipQueryCheck = true;
260
    }
261
    $result = $this->doquery($query);
262
    if ($skip_query_check) {
263
      $this->skipQueryCheck = $prevState;
264
    }
265
266
    return $result;
267
  }
268
269
270
  public function doSelect($query) {
271
    return $this->doExecute($query);
272
  }
273
274
  /**
275
   * @param string $query
276
   *
277
   * @return array|null
278
   */
279
  public function doSelectFetch($query) {
280
    return $this->db_fetch($this->doSelect($query));
0 ignored issues
show
Bug introduced by
$this->doSelect($query) cannot be passed to db_fetch() as the parameter $query expects a reference.
Loading history...
Bug introduced by
It seems like $this->doSelect($query) targeting db_mysql::doSelect() 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?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
281
  }
282
283
284
  public function doInsert($query) {
285
    return $this->doExecute($query);
286
  }
287
288
  public function doReplace($query) {
289
    return $this->doExecute($query);
290
  }
291
292
293
  public function doUpdate($query) {
294
    return $this->doExecute($query);
295
  }
296
297
298
  public function doDelete($query) {
299
    return $this->doExecute($query);
300
  }
301
302
  public function doDeleteRow($query) {
303
    return $this->doExecute($query);
304
  }
305
306
307
  /**
308
   * @param string $query
309
   *
310
   * @return mixed|null
311
   */
312
  public function doQueryFetchValue($query) {
313
    $row = $this->doSelectFetch($query);
314
315
    return is_array($row) ? reset($row) : null;
316
  }
317
318
  /**
319
   * Returns iterator to iterate through mysqli_result
320
   *
321
   * @param string $query
322
   *
323
   * return DbResultIterator
324
   *
325
   * @return DbEmptyIterator|DbMysqliResultIterator
326
   */
327
  public function doSelectIterator($query) {
328
    $queryResult = $this->doSelect($query);
329
330
    if ($queryResult instanceof mysqli_result) {
331
      $result = new DbMysqliResultIterator($queryResult);
332
    } else {
333
      $result = new DbEmptyIterator();
334
    }
335
336
    return $result;
337
  }
338
339
  /**
340
   * @param DbQueryConstructor $stmt
341
   * @param bool               $skip_query_check
342
   */
343
  public function doStmtLockAll($stmt, $skip_query_check = false) {
344
    $this->doExecute(
345
      $stmt
346
        ->select()
347
        ->field(1)
348
        ->setForUpdate()
349
        ->__toString(),
350
      $skip_query_check
351
    );
352
  }
353
354
  // TODO Заменить это на новый логгер
355
  protected function security_watch_user_queries($query) {
356
    global $user;
357
358
    if (
359
      !$this->isWatching // Not already watching
360
      && !empty(classSupernova::$config->game_watchlist_array) // There is some players in watchlist
361
      && in_array($user['id'], classSupernova::$config->game_watchlist_array) // Current player is in watchlist
362
      && !preg_match('/^(select|commit|rollback|start transaction)/i', $query) // Current query should be watched
363
    ) {
364
      $this->isWatching = true;
365
      $msg = "\$query = \"{$query}\"\n\r";
366
      if (!empty($_POST)) {
367
        $msg .= "\n\r" . dump($_POST, '$_POST');
368
      }
369
      if (!empty($_GET)) {
370
        $msg .= "\n\r" . dump($_GET, '$_GET');
371
      }
372
      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...
373
      $this->isWatching = false;
374
    }
375
  }
376
377
378
  public function security_query_check_bad_words($query) {
379
    if ($this->skipQueryCheck) {
380
      return;
381
    }
382
383
    global $user, $dm_change_legit, $mm_change_legit;
384
385
    switch (true) {
386
      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...
387
      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...
388
      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...
389
      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...
390
      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...
391
      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...
392
      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...
393
      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...
394
      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...
395
      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...
396
        $report = "Hacking attempt (" . date("d.m.Y H:i:s") . " - [" . time() . "]):\n";
397
        $report .= ">Database Inforamation\n";
398
        $report .= "\tID - " . $user['id'] . "\n";
399
        $report .= "\tUser - " . $user['username'] . "\n";
400
        $report .= "\tAuth level - " . $user['authlevel'] . "\n";
401
        $report .= "\tAdmin Notes - " . $user['adminNotes'] . "\n";
402
        $report .= "\tCurrent Planet - " . $user['current_planet'] . "\n";
403
        $report .= "\tUser IP - " . $user['user_lastip'] . "\n";
404
        $report .= "\tUser IP at Reg - " . $user['ip_at_reg'] . "\n";
405
        $report .= "\tUser Agent- " . $_SERVER['HTTP_USER_AGENT'] . "\n";
406
        $report .= "\tCurrent Page - " . $user['current_page'] . "\n";
407
        $report .= "\tRegister Time - " . $user['register_time'] . "\n";
408
        $report .= "\n";
409
410
        $report .= ">Query Information\n";
411
        $report .= "\tQuery - " . $query . "\n";
412
        $report .= "\n";
413
414
        $report .= ">\$_SERVER Information\n";
415
        $report .= "\tIP - " . $_SERVER['REMOTE_ADDR'] . "\n";
416
        $report .= "\tHost Name - " . $_SERVER['HTTP_HOST'] . "\n";
417
        $report .= "\tUser Agent - " . $_SERVER['HTTP_USER_AGENT'] . "\n";
418
        $report .= "\tRequest Method - " . $_SERVER['REQUEST_METHOD'] . "\n";
419
        $report .= "\tCame From - " . $_SERVER['HTTP_REFERER'] . "\n";
420
        $report .= "\tPage is - " . $_SERVER['SCRIPT_NAME'] . "\n";
421
        $report .= "\tUses Port - " . $_SERVER['REMOTE_PORT'] . "\n";
422
        $report .= "\tServer Protocol - " . $_SERVER['SERVER_PROTOCOL'] . "\n";
423
424
        $report .= "\n--------------------------------------------------------------------------------------------------\n";
425
426
        $fp = fopen(SN_ROOT_PHYSICAL . 'badqrys.txt', 'a');
427
        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 419
  1. Fetching key HTTP_REFERER from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 419
  2. Path: Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 417
  1. Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 417
  2. $report is assigned
    in includes/classes/db_mysql.php on line 419
  3. Path: Fetching key HTTP_HOST from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 416
  1. Fetching key HTTP_HOST from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 416
  2. $report is assigned
    in includes/classes/db_mysql.php on line 417
  3. $report is assigned
    in includes/classes/db_mysql.php on line 419
  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 db_mysql::doInsert()
    in includes/classes/DBStaticFleetACS.php on line 53
  6. $query is passed to db_mysql::doExecute()
    in includes/classes/db_mysql.php on line 285
  7. $query is passed to db_mysql::doquery()
    in includes/classes/db_mysql.php on line 261
  8. $stringQuery is assigned
    in includes/classes/db_mysql.php on line 216
  9. $stringQuery is passed through trim(), and $stringQuery is assigned
    in includes/classes/db_mysql.php on line 217
  10. $stringQuery is passed to db_mysql::security_query_check_bad_words()
    in includes/classes/db_mysql.php on line 222
  11. $report is assigned
    in includes/classes/db_mysql.php on line 411
  12. $report is assigned
    in includes/classes/db_mysql.php on line 416
  13. $report is assigned
    in includes/classes/db_mysql.php on line 417
  14. $report is assigned
    in includes/classes/db_mysql.php on line 419
  5. Path: Read from $_GET in includes/classes/db_mysql.php on line 370
  1. Read from $_GET
    in includes/classes/db_mysql.php on line 370
  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 370
  4. $msg is passed to debug::warning()
    in includes/classes/db_mysql.php on line 372
  5. Data is escaped by mysqli_real_escape_string() for sql context(s)
    in vendor/includes/classes/db_mysql_v5.php on line 87
  6. $query is assigned
    in includes/classes/debug.php on line 258
  7. $query is passed to db_mysql::doExecute()
    in includes/classes/debug.php on line 263
  8. $query is passed to db_mysql::doquery()
    in includes/classes/db_mysql.php on line 261
  9. $stringQuery is assigned
    in includes/classes/db_mysql.php on line 216
  10. $stringQuery is passed through trim(), and $stringQuery is assigned
    in includes/classes/db_mysql.php on line 217
  11. $stringQuery is passed to db_mysql::security_query_check_bad_words()
    in includes/classes/db_mysql.php on line 222
  12. $report is assigned
    in includes/classes/db_mysql.php on line 411
  13. $report is assigned
    in includes/classes/db_mysql.php on line 416
  14. $report is assigned
    in includes/classes/db_mysql.php on line 417
  15. $report is assigned
    in includes/classes/db_mysql.php on line 419
  6. Path: Read from $_POST in includes/classes/db_mysql.php on line 367
  1. Read from $_POST
    in includes/classes/db_mysql.php on line 367
  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 367
  4. $msg is passed to debug::warning()
    in includes/classes/db_mysql.php on line 372
  5. Data is escaped by mysqli_real_escape_string() for sql context(s)
    in vendor/includes/classes/db_mysql_v5.php on line 87
  6. $query is assigned
    in includes/classes/debug.php on line 258
  7. $query is passed to db_mysql::doExecute()
    in includes/classes/debug.php on line 263
  8. $query is passed to db_mysql::doquery()
    in includes/classes/db_mysql.php on line 261
  9. $stringQuery is assigned
    in includes/classes/db_mysql.php on line 216
  10. $stringQuery is passed through trim(), and $stringQuery is assigned
    in includes/classes/db_mysql.php on line 217
  11. $stringQuery is passed to db_mysql::security_query_check_bad_words()
    in includes/classes/db_mysql.php on line 222
  12. $report is assigned
    in includes/classes/db_mysql.php on line 411
  13. $report is assigned
    in includes/classes/db_mysql.php on line 416
  14. $report is assigned
    in includes/classes/db_mysql.php on line 417
  15. $report is assigned
    in includes/classes/db_mysql.php on line 419
  7. Path: Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned in includes/classes/db_mysql.php on line 405
  1. Fetching key HTTP_USER_AGENT from $_SERVER, and $report is assigned
    in includes/classes/db_mysql.php on line 405
  2. $report is assigned
    in includes/classes/db_mysql.php on line 411
  3. $report is assigned
    in includes/classes/db_mysql.php on line 416
  4. $report is assigned
    in includes/classes/db_mysql.php on line 417
  5. $report is assigned
    in includes/classes/db_mysql.php on line 419

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...
428
        fclose($fp);
429
430
        $message = 'Привет, я не знаю то, что Вы пробовали сделать, но команда, которую Вы только послали базе данных, не выглядела очень дружественной и она была заблокированна.<br /><br />Ваш IP, и другие данные переданны администрации сервера. Удачи!.';
431
        die($message);
432
      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...
433
    }
434
  }
435
436
  /**
437
   * @param bool $prefixed_only
438
   *
439
   * @return array
440
   */
441
  public function db_get_table_list($prefixed_only = true) {
442
    $query = $this->mysql_get_table_list();
443
444
    $prefix_length = strlen($this->db_prefix);
445
446
    $tl = array();
447
    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 442 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...
448
      foreach ($row as $table_name) {
449
        if (strpos($table_name, $this->db_prefix) === 0) {
450
          $table_name = substr($table_name, $prefix_length);
451
        } elseif ($prefixed_only) {
452
          continue;
453
        }
454
        // $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...
455
        $tl[$table_name] = $table_name;
456
      }
457
    }
458
459
    return $tl;
460
  }
461
462
  /**
463
   * @param string $statement
464
   *
465
   * @return bool|mysqli_stmt
466
   */
467 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...
468
    $microtime = microtime(true);
469
    $result = $this->driver->mysql_prepare($statement);
470
    $this->time_mysql_total += microtime(true) - $microtime;
471
472
    return $result;
473
  }
474
475
476
  /**
477
   * L1 perform the query
478
   *
479
   * @param $query_string
480
   *
481
   * @return bool|mysqli_result
482
   */
483 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...
484
    $microtime = microtime(true);
485
    $result = $this->driver->mysql_query($query_string);
486
    $this->time_mysql_total += microtime(true) - $microtime;
487
488
    return $result;
489
  }
490
491
  /**
492
   * L1 fetch assoc array
493
   *
494
   * @param mysqli_result $query
495
   *
496
   * @return array|null
497
   */
498 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...
499
    $microtime = microtime(true);
500
    $result = $this->driver->mysql_fetch_assoc($query);
501
    $this->time_mysql_total += microtime(true) - $microtime;
502
503
    return $result;
504
  }
505
506
  public function db_fetch_row(&$query) {
507
    return $this->driver->mysql_fetch_row($query);
508
  }
509
510
  public function db_escape($unescaped_string) {
511
    return $this->driver->mysql_real_escape_string($unescaped_string);
512
  }
513
514
  public function driver_disconnect() {
515
    return $this->driver->mysql_close_link();
516
  }
517
518
  public function db_error() {
519
    return $this->driver->mysql_error();
520
  }
521
522
  public function db_insert_id() {
523
    return $this->driver->mysql_insert_id();
524
  }
525
526
  public function db_num_rows(&$result) {
527
    return $this->driver->mysql_num_rows($result);
528
  }
529
530
  public function db_affected_rows() {
531
    return $this->driver->mysql_affected_rows();
532
  }
533
534
  /**
535
   * @return string
536
   */
537
  public function db_get_client_info() {
538
    return $this->driver->mysql_get_client_info();
539
  }
540
541
  /**
542
   * @return string
543
   */
544
  public function db_get_server_info() {
545
    return $this->driver->mysql_get_server_info();
546
  }
547
548
  /**
549
   * @return string
550
   */
551
  public function db_get_host_info() {
552
    return $this->driver->mysql_get_host_info();
553
  }
554
555
  public function db_get_server_stat() {
556
    $result = array();
557
558
    $status = explode('  ', $this->driver->mysql_stat());
559
    foreach ($status as $value) {
560
      $row = explode(': ', $value);
561
      $result[$row[0]] = $row[1];
562
    }
563
564
    return $result;
565
  }
566
567
  /**
568
   * @return array
569
   * @throws Exception
570
   */
571
  public function db_core_show_status() {
572
    $result = array();
573
574
    $query = $this->db_sql_query('SHOW STATUS;');
575
    if (is_bool($query)) {
576
      throw new Exception('Result of SHOW STATUS command is boolean - which should never happen. Connection to DB is lost?');
577
    }
578
    while ($row = db_fetch($query)) {
579
      $result[$row['Variable_name']] = $row['Value'];
580
    }
581
582
    return $result;
583
  }
584
585
  public function mysql_get_table_list() {
586
    return $this->db_sql_query('SHOW TABLES;');
587
  }
588
589
  public function mysql_get_innodb_status() {
590
    return $this->db_sql_query('SHOW ENGINE INNODB STATUS;');
591
  }
592
593
  /**
594
   * @return \DBAL\DbTransaction
595
   */
596
  public function getTransaction() {
597
    return $this->transaction;
598
  }
599
600
  // Some wrappers to DbTransaction
601
  // Unused for now
602
  public function transactionCheck($status = null) {
603
    return $this->transaction->check($status);
604
  }
605
606
  public function transactionStart($level = '') {
607
    return $this->transaction->start($level);
608
  }
609
610
  public function transactionCommit() {
611
    return $this->transaction->commit();
612
  }
613
614
  public function transactionRollback() {
615
    return $this->transaction->rollback();
616
  }
617
618
}
619