ARI Adminer – WordPress Database Manager - Version 1.11.2

Version Description

Download this release

Release Info

Developer arisoft
Plugin Icon 128x128 ARI Adminer – WordPress Database Manager
Version 1.11.2
Comparing to
See all releases

Code changes from version 1.1.11 to 1.11.2

Files changed (52) hide show
  1. adminer/adminer/adminer/database.inc.php +1 -1
  2. adminer/adminer/adminer/db.inc.php +7 -7
  3. adminer/adminer/adminer/drivers/elastic.inc.php +12 -7
  4. adminer/adminer/adminer/drivers/mongo.inc.php +40 -53
  5. adminer/adminer/adminer/drivers/mssql.inc.php +10 -8
  6. adminer/adminer/adminer/drivers/mysql.inc.php +33 -12
  7. adminer/adminer/adminer/drivers/pgsql.inc.php +34 -19
  8. adminer/adminer/adminer/drivers/simpledb.inc.php +11 -0
  9. adminer/adminer/adminer/drivers/sqlite.inc.php +10 -5
  10. adminer/adminer/adminer/event.inc.php +1 -1
  11. adminer/adminer/adminer/file.inc.php +1 -9
  12. adminer/adminer/adminer/include/adminer.inc.php +35 -25
  13. adminer/adminer/adminer/include/auth.inc.php +11 -7
  14. adminer/adminer/adminer/include/bootstrap.inc.php +4 -9
  15. adminer/adminer/adminer/include/connect.inc.php +2 -2
  16. adminer/adminer/adminer/include/driver.inc.php +12 -1
  17. adminer/adminer/adminer/include/editing.inc.php +8 -10
  18. adminer/adminer/adminer/include/functions.inc.php +19 -30
  19. adminer/adminer/adminer/include/pdo.inc.php +3 -0
  20. adminer/adminer/adminer/include/version.inc.php +1 -1
  21. adminer/adminer/adminer/indexes.inc.php +1 -1
  22. adminer/adminer/adminer/lang/cs.inc.php +5 -2
  23. adminer/adminer/adminer/lang/he.inc.php +0 -1
  24. adminer/adminer/adminer/lang/ms.inc.php +0 -1
  25. adminer/adminer/adminer/lang/pl.inc.php +0 -1
  26. adminer/adminer/adminer/lang/ru.inc.php +0 -1
  27. adminer/adminer/adminer/lang/tr.inc.php +0 -1
  28. adminer/adminer/adminer/lang/xx.inc.php +4 -1
  29. adminer/adminer/adminer/privileges.inc.php +1 -1
  30. adminer/adminer/adminer/processlist.inc.php +2 -2
  31. adminer/adminer/adminer/script.inc.php +2 -2
  32. adminer/adminer/adminer/select.inc.php +4 -4
  33. adminer/adminer/adminer/sql.inc.php +5 -4
  34. adminer/adminer/adminer/sqlite.php +5 -2
  35. adminer/adminer/adminer/static/editing.js +21 -3
  36. adminer/adminer/adminer/static/functions.js +7 -12
  37. adminer/adminer/adminer/table.inc.php +3 -3
  38. adminer/adminer/adminer/user.inc.php +4 -4
  39. adminer/adminer/adminer/variables.inc.php +1 -1
  40. adminer/adminer/editor/include/adminer.inc.php +14 -13
  41. adminer/adminer/editor/include/editing.inc.php +1 -1
  42. adminer/adminer/plugins/dump-alter.php +1 -1
  43. adminer/adminer/plugins/file-upload.php +1 -1
  44. adminer/adminer/plugins/plugin.php +5 -0
  45. adminer/adminer/plugins/tables-filter.php +10 -17
  46. ari-adminer.php +1 -1
  47. assets/themes/bradezone/adminer.css +1 -1
  48. assets/themes/nette/adminer.css +1 -1
  49. assets/themes/nicu/adminer.css +1 -1
  50. assets/themes/pilot/adminer.css +10 -5
  51. includes/defines.php +1 -1
  52. readme.txt +8 -2
adminer/adminer/adminer/database.inc.php CHANGED
@@ -47,7 +47,7 @@ if ($_POST) {
47
  } elseif ($jush == "sql") {
48
  // propose database name with limited privileges
49
  foreach (get_vals("SHOW GRANTS") as $grant) {
50
- if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $grant, $match) && $match[1]) {
51
  $name = stripcslashes(idf_unescape("`$match[2]`"));
52
  break;
53
  }
47
  } elseif ($jush == "sql") {
48
  // propose database name with limited privileges
49
  foreach (get_vals("SHOW GRANTS") as $grant) {
50
+ if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~', $grant, $match) && $match[1]) {
51
  $name = stripcslashes(idf_unescape("`$match[2]`"));
52
  break;
53
  }
adminer/adminer/adminer/db.inc.php CHANGED
@@ -104,18 +104,18 @@ if ($adminer->homepage()) {
104
  echo ($link ? "<td align='right'>" . (support("table") || $key == "Rows" || (support("indexes") && $key != "Data_length")
105
  ? "<a href='" . h(ME . "$link[0]=") . urlencode($name) . "'$id title='$link[1]'>?</a>"
106
  : "<span$id>?</span>"
107
- ) : "<td id='$key-" . h($name) . "'>&nbsp;");
108
  }
109
  $tables++;
110
  }
111
- echo (support("comment") ? "<td id='Comment-" . h($name) . "'>&nbsp;" : "");
112
  }
113
 
114
- echo "<tr><td>&nbsp;<th>" . lang('%d in total', count($tables_list));
115
- echo "<td>" . nbsp($jush == "sql" ? $connection->result("SELECT @@storage_engine") : "");
116
- echo "<td>" . nbsp(db_collation(DB, collations()));
117
  foreach (array("Data_length", "Index_length", "Data_free") as $key) {
118
- echo "<td align='right' id='sum-$key'>&nbsp;";
119
  }
120
 
121
  echo "</table>\n";
@@ -159,7 +159,7 @@ if ($adminer->homepage()) {
159
  $routines = routines();
160
  if ($routines) {
161
  echo "<table cellspacing='0'>\n";
162
- echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td>&nbsp;</thead>\n";
163
  odd('');
164
  foreach ($routines as $row) {
165
  $name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"])); // not computed on the pages to be able to print the header first
104
  echo ($link ? "<td align='right'>" . (support("table") || $key == "Rows" || (support("indexes") && $key != "Data_length")
105
  ? "<a href='" . h(ME . "$link[0]=") . urlencode($name) . "'$id title='$link[1]'>?</a>"
106
  : "<span$id>?</span>"
107
+ ) : "<td id='$key-" . h($name) . "'>");
108
  }
109
  $tables++;
110
  }
111
+ echo (support("comment") ? "<td id='Comment-" . h($name) . "'>" : "");
112
  }
113
 
114
+ echo "<tr><td><th>" . lang('%d in total', count($tables_list));
115
+ echo "<td>" . h($jush == "sql" ? $connection->result("SELECT @@storage_engine") : "");
116
+ echo "<td>" . h(db_collation(DB, collations()));
117
  foreach (array("Data_length", "Index_length", "Data_free") as $key) {
118
+ echo "<td align='right' id='sum-$key'>";
119
  }
120
 
121
  echo "</table>\n";
159
  $routines = routines();
160
  if ($routines) {
161
  echo "<table cellspacing='0'>\n";
162
+ echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td></thead>\n";
163
  odd('');
164
  foreach ($routines as $row) {
165
  $name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"])); // not computed on the pages to be able to print the header first
adminer/adminer/adminer/drivers/elastic.inc.php CHANGED
@@ -2,10 +2,10 @@
2
  $drivers["elastic"] = "Elasticsearch (beta)";
3
 
4
  if (isset($_GET["elastic"])) {
5
- $possible_drivers = array("json");
6
  define("DRIVER", "elastic");
7
 
8
- if (function_exists('json_decode')) {
9
  class Min_DB {
10
  var $extension = "JSON", $server_info, $errno, $error, $_url;
11
 
@@ -129,7 +129,7 @@ if (isset($_GET["elastic"])) {
129
  }
130
  }
131
  foreach ($where as $val) {
132
- list($col,$op,$val) = explode(" ",$val,3);
133
  if ($col == "_id") {
134
  $data["query"]["ids"]["values"][] = $val;
135
  }
@@ -177,7 +177,8 @@ if (isset($_GET["elastic"])) {
177
  return new Min_Result($return);
178
  }
179
 
180
- function update($type, $record, $queryWhere) {
 
181
  $parts = preg_split('~ *= *~', $queryWhere);
182
  if (count($parts) == 2) {
183
  $id = trim($parts[1]);
@@ -195,7 +196,8 @@ if (isset($_GET["elastic"])) {
195
  return $response['created'];
196
  }
197
 
198
- function delete($type, $queryWhere) {
 
199
  $ids = array();
200
  if (is_array($_GET["where"]) && $_GET["where"]["_id"]) {
201
  $ids[] = $_GET["where"]["_id"];
@@ -225,8 +227,11 @@ if (isset($_GET["elastic"])) {
225
  function connect() {
226
  global $adminer;
227
  $connection = new Min_DB;
228
- $credentials = $adminer->credentials();
229
- if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
 
 
 
230
  return $connection;
231
  }
232
  return $connection->error;
2
  $drivers["elastic"] = "Elasticsearch (beta)";
3
 
4
  if (isset($_GET["elastic"])) {
5
+ $possible_drivers = array("json + allow_url_fopen");
6
  define("DRIVER", "elastic");
7
 
8
+ if (function_exists('json_decode') && ini_bool('allow_url_fopen')) {
9
  class Min_DB {
10
  var $extension = "JSON", $server_info, $errno, $error, $_url;
11
 
129
  }
130
  }
131
  foreach ($where as $val) {
132
+ list($col, $op, $val) = explode(" ", $val, 3);
133
  if ($col == "_id") {
134
  $data["query"]["ids"]["values"][] = $val;
135
  }
177
  return new Min_Result($return);
178
  }
179
 
180
+ function update($type, $record, $queryWhere, $limit = 0, $separator = "\n") {
181
+ //! use $limit
182
  $parts = preg_split('~ *= *~', $queryWhere);
183
  if (count($parts) == 2) {
184
  $id = trim($parts[1]);
196
  return $response['created'];
197
  }
198
 
199
+ function delete($type, $queryWhere, $limit = 0) {
200
+ //! use $limit
201
  $ids = array();
202
  if (is_array($_GET["where"]) && $_GET["where"]["_id"]) {
203
  $ids[] = $_GET["where"]["_id"];
227
  function connect() {
228
  global $adminer;
229
  $connection = new Min_DB;
230
+ list($server, $username, $password) = $adminer->credentials();
231
+ if ($password != "" && $connection->connect($server, $username, "")) {
232
+ return lang('Database does not support password.');
233
+ }
234
+ if ($connection->connect($server, $username, $password)) {
235
  return $connection;
236
  }
237
  return $connection->error;
adminer/adminer/adminer/drivers/mongo.inc.php CHANGED
@@ -7,26 +7,10 @@ if (isset($_GET["mongo"])) {
7
 
8
  if (class_exists('MongoDB')) {
9
  class Min_DB {
10
- var $extension = "Mongo", $error, $last_id, $_link, $_db;
11
-
12
- function connect($server, $username, $password) {
13
- global $adminer;
14
- $db = $adminer->database();
15
- $options = array();
16
- if ($username != "") {
17
- $options["username"] = $username;
18
- $options["password"] = $password;
19
- }
20
- if ($db != "") {
21
- $options["db"] = $db;
22
- }
23
- try {
24
- $this->_link = @new MongoClient("mongodb://$server", $options);
25
- return true;
26
- } catch (Exception $ex) {
27
- $this->error = $ex->getMessage();
28
- return false;
29
- }
30
  }
31
 
32
  function query($query) {
@@ -214,30 +198,14 @@ if (isset($_GET["mongo"])) {
214
 
215
  } elseif (class_exists('MongoDB\Driver\Manager')) {
216
  class Min_DB {
217
- var $extension = "MongoDB", $error, $last_id;
218
  /** @var MongoDB\Driver\Manager */
219
  var $_link;
220
  var $_db, $_db_name;
221
 
222
- function connect($server, $username, $password) {
223
- global $adminer;
224
- $db = $adminer->database();
225
- $options = array();
226
- if ($username != "") {
227
- $options["username"] = $username;
228
- $options["password"] = $password;
229
- }
230
- if ($db != "") {
231
- $options["db"] = $db;
232
- }
233
- try {
234
- $class = 'MongoDB\Driver\Manager';
235
- $this->_link = new $class("mongodb://$server", $options);
236
- return true;
237
- } catch (Exception $ex) {
238
- $this->error = $ex->getMessage();
239
- return false;
240
- }
241
  }
242
 
243
  function query($query) {
@@ -245,13 +213,8 @@ if (isset($_GET["mongo"])) {
245
  }
246
 
247
  function select_db($database) {
248
- try {
249
- $this->_db_name = $database;
250
- return true;
251
- } catch (Exception $ex) {
252
- $this->error = $ex->getMessage();
253
- return false;
254
- }
255
  }
256
 
257
  function quote($string) {
@@ -405,7 +368,7 @@ if (isset($_GET["mongo"])) {
405
  }
406
 
407
  function get_databases($flush) {
408
- /** @var $connection Min_DB */
409
  global $connection;
410
  $return = array();
411
  $class = 'MongoDB\Driver\Command';
@@ -516,7 +479,7 @@ if (isset($_GET["mongo"])) {
516
  }
517
 
518
  function where_to_query($whereAnd = array(), $whereOr = array()) {
519
- global $operators;
520
  $data = array();
521
  foreach (array('and' => $whereAnd, 'or' => $whereOr) as $type => $where) {
522
  if (is_array($where)) {
@@ -528,7 +491,7 @@ if (isset($_GET["mongo"])) {
528
  $class = 'MongoDB\BSON\ObjectID';
529
  $val = new $class($val);
530
  }
531
- if (!in_array($op, $operators)) {
532
  continue;
533
  }
534
  if (preg_match('~^\(f\)(.+)~', $op, $match)) {
@@ -618,6 +581,10 @@ if (isset($_GET["mongo"])) {
618
  return $return;
619
  }
620
 
 
 
 
 
621
  function last_id() {
622
  global $connection;
623
  return $connection->last_id;
@@ -641,11 +608,31 @@ if (isset($_GET["mongo"])) {
641
  function connect() {
642
  global $adminer;
643
  $connection = new Min_DB;
644
- $credentials = $adminer->credentials();
645
- if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  return $connection;
 
 
647
  }
648
- return $connection->error;
649
  }
650
 
651
  function alter_indexes($table, $alter) {
7
 
8
  if (class_exists('MongoDB')) {
9
  class Min_DB {
10
+ var $extension = "Mongo", $server_info = MongoClient::VERSION, $error, $last_id, $_link, $_db;
11
+
12
+ function connect($uri, $options) {
13
+ return @new MongoClient($uri, $options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  }
15
 
16
  function query($query) {
198
 
199
  } elseif (class_exists('MongoDB\Driver\Manager')) {
200
  class Min_DB {
201
+ var $extension = "MongoDB", $server_info = MONGODB_VERSION, $error, $last_id;
202
  /** @var MongoDB\Driver\Manager */
203
  var $_link;
204
  var $_db, $_db_name;
205
 
206
+ function connect($uri, $options) {
207
+ $class = 'MongoDB\Driver\Manager';
208
+ return new $class($uri, $options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  }
210
 
211
  function query($query) {
213
  }
214
 
215
  function select_db($database) {
216
+ $this->_db_name = $database;
217
+ return true;
 
 
 
 
 
218
  }
219
 
220
  function quote($string) {
368
  }
369
 
370
  function get_databases($flush) {
371
+ /** @var Min_DB */
372
  global $connection;
373
  $return = array();
374
  $class = 'MongoDB\Driver\Command';
479
  }
480
 
481
  function where_to_query($whereAnd = array(), $whereOr = array()) {
482
+ global $adminer;
483
  $data = array();
484
  foreach (array('and' => $whereAnd, 'or' => $whereOr) as $type => $where) {
485
  if (is_array($where)) {
491
  $class = 'MongoDB\BSON\ObjectID';
492
  $val = new $class($val);
493
  }
494
+ if (!in_array($op, $adminer->operators)) {
495
  continue;
496
  }
497
  if (preg_match('~^\(f\)(.+)~', $op, $match)) {
581
  return $return;
582
  }
583
 
584
+ function create_database($db, $collation) {
585
+ return true;
586
+ }
587
+
588
  function last_id() {
589
  global $connection;
590
  return $connection->last_id;
608
  function connect() {
609
  global $adminer;
610
  $connection = new Min_DB;
611
+ list($server, $username, $password) = $adminer->credentials();
612
+ $options = array();
613
+ if ($username . $password != "") {
614
+ $options["username"] = $username;
615
+ $options["password"] = $password;
616
+ }
617
+ $db = $adminer->database();
618
+ if ($db != "") {
619
+ $options["db"] = $db;
620
+ }
621
+ try {
622
+ $connection->_link = $connection->connect("mongodb://$server", $options);
623
+ if ($password != "") {
624
+ $options["password"] = "";
625
+ try {
626
+ $connection->connect("mongodb://$server", $options);
627
+ return lang('Database does not support password.');
628
+ } catch (Exception $ex) {
629
+ // this is what we want
630
+ }
631
+ }
632
  return $connection;
633
+ } catch (Exception $ex) {
634
+ return $ex->getMessage();
635
  }
 
636
  }
637
 
638
  function alter_indexes($table, $alter) {
adminer/adminer/adminer/drivers/mssql.inc.php CHANGED
@@ -24,7 +24,7 @@ if (isset($_GET["mssql"])) {
24
  }
25
 
26
  function connect($server, $username, $password) {
27
- $this->_link = @sqlsrv_connect($server, array("UID" => $username, "PWD" => $password, "CharacterSet" => "UTF-8"));
28
  if ($this->_link) {
29
  $info = sqlsrv_server_info($this->_link);
30
  $this->server_info = $info['SQLServerVersion'];
@@ -147,8 +147,10 @@ if (isset($_GET["mssql"])) {
147
  $this->_link = @mssql_connect($server, $username, $password);
148
  if ($this->_link) {
149
  $result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
150
- $row = $result->fetch_row();
151
- $this->server_info = $this->result("sp_server_info 2", 2) . " [$row[0]] $row[1]";
 
 
152
  } else {
153
  $this->error = mssql_get_last_message();
154
  }
@@ -239,7 +241,7 @@ if (isset($_GET["mssql"])) {
239
  var $extension = "PDO_DBLIB";
240
 
241
  function connect($server, $username, $password) {
242
- $this->dsn("dblib:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\\d)~', ';port=\\1', $server)), $username, $password);
243
  return true;
244
  }
245
 
@@ -406,7 +408,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
406
 
407
  function view($name) {
408
  global $connection;
409
- return array("select" => preg_replace('~^(?:[^[]|\\[[^]]*])*\\s+AS\\s+~isU', '', $connection->result("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q($name))));
410
  }
411
 
412
  function collations() {
@@ -423,7 +425,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
423
 
424
  function error() {
425
  global $connection;
426
- return nl_br(h(preg_replace('~^(\\[[^]]*])+~m', '', $connection->error)));
427
  }
428
 
429
  function create_database($db, $collation) {
@@ -454,7 +456,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
454
  if (!$val) {
455
  $alter["DROP"][] = " COLUMN $column";
456
  } else {
457
- $val[1] = preg_replace("~( COLLATE )'(\\w+)'~", "\\1\\2", $val[1]);
458
  if ($field[0] == "") {
459
  $alter["ADD"][] = "\n " . implode("", $val) . ($table == "" ? substr($foreign[$val[0]], 16 + strlen($val[0])) : ""); // 16 - strlen(" FOREIGN KEY ()")
460
  } else {
@@ -561,7 +563,7 @@ WHERE s.xtype = 'TR' AND s.name = " . q($name)
561
  ); // triggers are not schema-scoped
562
  $return = reset($rows);
563
  if ($return) {
564
- $return["Statement"] = preg_replace('~^.+\\s+AS\\s+~isU', '', $return["text"]); //! identifiers, comments
565
  }
566
  return $return;
567
  }
24
  }
25
 
26
  function connect($server, $username, $password) {
27
+ $this->_link = @sqlsrv_connect(preg_replace('~:~', ',', $server), array("UID" => $username, "PWD" => $password, "CharacterSet" => "UTF-8"));
28
  if ($this->_link) {
29
  $info = sqlsrv_server_info($this->_link);
30
  $this->server_info = $info['SQLServerVersion'];
147
  $this->_link = @mssql_connect($server, $username, $password);
148
  if ($this->_link) {
149
  $result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
150
+ if ($result) {
151
+ $row = $result->fetch_row();
152
+ $this->server_info = $this->result("sp_server_info 2", 2) . " [$row[0]] $row[1]";
153
+ }
154
  } else {
155
  $this->error = mssql_get_last_message();
156
  }
241
  var $extension = "PDO_DBLIB";
242
 
243
  function connect($server, $username, $password) {
244
+ $this->dsn("dblib:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)), $username, $password);
245
  return true;
246
  }
247
 
408
 
409
  function view($name) {
410
  global $connection;
411
+ return array("select" => preg_replace('~^(?:[^[]|\[[^]]*])*\s+AS\s+~isU', '', $connection->result("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q($name))));
412
  }
413
 
414
  function collations() {
425
 
426
  function error() {
427
  global $connection;
428
+ return nl_br(h(preg_replace('~^(\[[^]]*])+~m', '', $connection->error)));
429
  }
430
 
431
  function create_database($db, $collation) {
456
  if (!$val) {
457
  $alter["DROP"][] = " COLUMN $column";
458
  } else {
459
+ $val[1] = preg_replace("~( COLLATE )'(\\w+)'~", '\1\2', $val[1]);
460
  if ($field[0] == "") {
461
  $alter["ADD"][] = "\n " . implode("", $val) . ($table == "" ? substr($foreign[$val[0]], 16 + strlen($val[0])) : ""); // 16 - strlen(" FOREIGN KEY ()")
462
  } else {
563
  ); // triggers are not schema-scoped
564
  $return = reset($rows);
565
  if ($return) {
566
+ $return["Statement"] = preg_replace('~^.+\s+AS\s+~isU', '', $return["text"]); //! identifiers, comments
567
  }
568
  return $return;
569
  }
adminer/adminer/adminer/drivers/mysql.inc.php CHANGED
@@ -30,6 +30,7 @@ if (!defined("DRIVER")) {
30
  (!is_numeric($port) ? $port : $socket),
31
  ($ssl ? 64 : 0) // 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16)
32
  );
 
33
  return $return;
34
  }
35
 
@@ -56,7 +57,7 @@ if (!defined("DRIVER")) {
56
  }
57
  }
58
 
59
- } elseif (extension_loaded("mysql") && !(ini_get("sql.safe_mode") && extension_loaded("pdo_mysql"))) {
60
  class Min_DB {
61
  var
62
  $extension = "MySQL", ///< @var string extension name
@@ -74,6 +75,10 @@ if (!defined("DRIVER")) {
74
  * @return bool
75
  */
76
  function connect($server, $username, $password) {
 
 
 
 
77
  $this->_link = @mysql_connect(
78
  ($server != "" ? $server : ini_get("mysql.default_host")),
79
  ("$server$username" != "" ? $username : ini_get("mysql.default_user")),
@@ -230,17 +235,17 @@ if (!defined("DRIVER")) {
230
 
231
  function connect($server, $username, $password) {
232
  global $adminer;
233
- $options = array();
234
  $ssl = $adminer->connectSsl();
235
  if ($ssl) {
236
- $options = array(
237
  PDO::MYSQL_ATTR_SSL_KEY => $ssl['key'],
238
  PDO::MYSQL_ATTR_SSL_CERT => $ssl['cert'],
239
  PDO::MYSQL_ATTR_SSL_CA => $ssl['ca'],
240
  );
241
  }
242
  $this->dsn(
243
- "mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\\d)~', ';port=\\1', $server)),
244
  $username,
245
  $password,
246
  $options
@@ -298,8 +303,18 @@ if (!defined("DRIVER")) {
298
  return queries($prefix . implode(",\n", $values) . $suffix);
299
  }
300
 
 
 
 
 
 
 
 
 
 
 
301
  function convertSearch($idf, $val, $field) {
302
- return (preg_match('~char|text|enum|set~', $field["type"]) && !preg_match("~^utf8~", $field["collation"])
303
  ? "CONVERT($idf USING " . charset($this->_conn) . ")"
304
  : $idf
305
  );
@@ -376,7 +391,7 @@ if (!defined("DRIVER")) {
376
  $return = get_session("dbs");
377
  if ($return === null) {
378
  $query = (min_version(5)
379
- ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA"
380
  : "SHOW DATABASES"
381
  ); // SHOW DATABASES can be disabled by skip_show_database
382
  $return = ($flush ? slow_query($query) : get_vals($query));
@@ -484,7 +499,7 @@ if (!defined("DRIVER")) {
484
  ) as $row) {
485
  if ($row["Engine"] == "InnoDB") {
486
  // ignore internal comment, unnecessary since MySQL 5.1.21
487
- $row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
488
  }
489
  if (!isset($row["Engine"])) {
490
  $row["Comment"] = "";
@@ -521,7 +536,7 @@ if (!defined("DRIVER")) {
521
  function fields($table) {
522
  $return = array();
523
  foreach (get_rows("SHOW FULL COLUMNS FROM " . table($table)) as $row) {
524
- preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
525
  $return[$row["Field"]] = array(
526
  "field" => $row["Field"],
527
  "full_type" => $row["Type"],
@@ -591,7 +606,7 @@ if (!defined("DRIVER")) {
591
  */
592
  function view($name) {
593
  global $connection;
594
- return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\\s+AS\\s+~isU', '', $connection->result("SHOW CREATE VIEW " . table($name), 1)));
595
  }
596
 
597
  /** Get sorted grouped list of collations
@@ -801,6 +816,12 @@ if (!defined("DRIVER")) {
801
  ) {
802
  return false;
803
  }
 
 
 
 
 
 
804
  }
805
  foreach ($views as $table) {
806
  $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
@@ -870,7 +891,7 @@ if (!defined("DRIVER")) {
870
  "field" => $name,
871
  "type" => strtolower($param[5]),
872
  "length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]),
873
- "unsigned" => strtolower(preg_replace('~\\s+~', ' ', trim("$param[8] $param[7]"))),
874
  "null" => 1,
875
  "full_type" => $param[4],
876
  "inout" => strtoupper($param[1]),
@@ -976,7 +997,7 @@ if (!defined("DRIVER")) {
976
  global $connection;
977
  $return = $connection->result("SHOW CREATE TABLE " . table($table), 1);
978
  if (!$auto_increment) {
979
- $return = preg_replace('~ AUTO_INCREMENT=\\d+~', '', $return); //! skip comments
980
  }
981
  return $return;
982
  }
@@ -1105,7 +1126,7 @@ if (!defined("DRIVER")) {
1105
  $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select
1106
  $edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
1107
  array(
1108
- "char" => "md5/sha1/password/encrypt/uuid", //! JavaScript for disabling maxlength
1109
  "binary" => "md5/sha1",
1110
  "date|time" => "now",
1111
  ), array(
30
  (!is_numeric($port) ? $port : $socket),
31
  ($ssl ? 64 : 0) // 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16)
32
  );
33
+ $this->options(MYSQLI_OPT_LOCAL_INFILE, false);
34
  return $return;
35
  }
36
 
57
  }
58
  }
59
 
60
+ } elseif (extension_loaded("mysql") && !((ini_bool("sql.safe_mode") || ini_bool("mysql.allow_local_infile")) && extension_loaded("pdo_mysql"))) {
61
  class Min_DB {
62
  var
63
  $extension = "MySQL", ///< @var string extension name
75
  * @return bool
76
  */
77
  function connect($server, $username, $password) {
78
+ if (ini_bool("mysql.allow_local_infile")) {
79
+ $this->error = lang('Disable %s or enable %s or %s extensions.', "'mysql.allow_local_infile'", "MySQLi", "PDO_MySQL");
80
+ return false;
81
+ }
82
  $this->_link = @mysql_connect(
83
  ($server != "" ? $server : ini_get("mysql.default_host")),
84
  ("$server$username" != "" ? $username : ini_get("mysql.default_user")),
235
 
236
  function connect($server, $username, $password) {
237
  global $adminer;
238
+ $options = array(PDO::MYSQL_ATTR_LOCAL_INFILE => false);
239
  $ssl = $adminer->connectSsl();
240
  if ($ssl) {
241
+ $options += array(
242
  PDO::MYSQL_ATTR_SSL_KEY => $ssl['key'],
243
  PDO::MYSQL_ATTR_SSL_CERT => $ssl['cert'],
244
  PDO::MYSQL_ATTR_SSL_CA => $ssl['ca'],
245
  );
246
  }
247
  $this->dsn(
248
+ "mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)),
249
  $username,
250
  $password,
251
  $options
303
  return queries($prefix . implode(",\n", $values) . $suffix);
304
  }
305
 
306
+ function slowQuery($query, $timeout) {
307
+ if (min_version('5.7.8', '10.1.2')) {
308
+ if (preg_match('~MariaDB~', $this->_conn->server_info)) {
309
+ return "SET STATEMENT max_statement_time=$timeout FOR $query";
310
+ } elseif (preg_match('~^(SELECT\b)(.+)~is', $query, $match)) {
311
+ return "$match[1] /*+ MAX_EXECUTION_TIME(" . ($timeout * 1000) . ") */ $match[2]";
312
+ }
313
+ }
314
+ }
315
+
316
  function convertSearch($idf, $val, $field) {
317
+ return (preg_match('~char|text|enum|set~', $field["type"]) && !preg_match("~^utf8~", $field["collation"]) && preg_match('~[\x80-\xFF]~', $val['val'])
318
  ? "CONVERT($idf USING " . charset($this->_conn) . ")"
319
  : $idf
320
  );
391
  $return = get_session("dbs");
392
  if ($return === null) {
393
  $query = (min_version(5)
394
+ ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"
395
  : "SHOW DATABASES"
396
  ); // SHOW DATABASES can be disabled by skip_show_database
397
  $return = ($flush ? slow_query($query) : get_vals($query));
499
  ) as $row) {
500
  if ($row["Engine"] == "InnoDB") {
501
  // ignore internal comment, unnecessary since MySQL 5.1.21
502
+ $row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\1', $row["Comment"]);
503
  }
504
  if (!isset($row["Engine"])) {
505
  $row["Comment"] = "";
536
  function fields($table) {
537
  $return = array();
538
  foreach (get_rows("SHOW FULL COLUMNS FROM " . table($table)) as $row) {
539
+ preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
540
  $return[$row["Field"]] = array(
541
  "field" => $row["Field"],
542
  "full_type" => $row["Type"],
606
  */
607
  function view($name) {
608
  global $connection;
609
+ return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', $connection->result("SHOW CREATE VIEW " . table($name), 1)));
610
  }
611
 
612
  /** Get sorted grouped list of collations
816
  ) {
817
  return false;
818
  }
819
+ foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\"))) as $row) {
820
+ $trigger = $row["Trigger"];
821
+ if (!queries("CREATE TRIGGER " . ($target == DB ? idf_escape("copy_$trigger") : idf_escape($target) . "." . idf_escape($trigger)) . " $row[Timing] $row[Event] ON $name FOR EACH ROW\n$row[Statement];")) {
822
+ return false;
823
+ }
824
+ }
825
  }
826
  foreach ($views as $table) {
827
  $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
891
  "field" => $name,
892
  "type" => strtolower($param[5]),
893
  "length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]),
894
+ "unsigned" => strtolower(preg_replace('~\s+~', ' ', trim("$param[8] $param[7]"))),
895
  "null" => 1,
896
  "full_type" => $param[4],
897
  "inout" => strtoupper($param[1]),
997
  global $connection;
998
  $return = $connection->result("SHOW CREATE TABLE " . table($table), 1);
999
  if (!$auto_increment) {
1000
+ $return = preg_replace('~ AUTO_INCREMENT=\d+~', '', $return); //! skip comments
1001
  }
1002
  return $return;
1003
  }
1126
  $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select
1127
  $edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
1128
  array(
1129
+ "char" => "md5/sha1/password/encrypt/uuid",
1130
  "binary" => "md5/sha1",
1131
  "date|time" => "now",
1132
  ), array(
adminer/adminer/adminer/drivers/pgsql.inc.php CHANGED
@@ -6,7 +6,7 @@ if (isset($_GET["pgsql"])) {
6
  define("DRIVER", "pgsql");
7
  if (extension_loaded("pgsql")) {
8
  class Min_DB {
9
- var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error;
10
 
11
  function _error($errno, $error) {
12
  if (ini_bool("html_errors")) {
@@ -69,12 +69,18 @@ if (isset($_GET["pgsql"])) {
69
  $this->error = "";
70
  if (!$result) {
71
  $this->error = pg_last_error($this->_link);
72
- return false;
73
  } elseif (!pg_num_fields($result)) {
74
  $this->affected_rows = pg_affected_rows($result);
75
- return true;
 
 
76
  }
77
- return new Min_Result($result);
 
 
 
 
78
  }
79
 
80
  function multi_query($query) {
@@ -139,7 +145,7 @@ if (isset($_GET["pgsql"])) {
139
 
140
  } elseif (extension_loaded("pdo_pgsql")) {
141
  class Min_DB extends Min_PDO {
142
- var $extension = "PDO_PgSQL";
143
 
144
  function connect($server, $username, $password) {
145
  global $adminer;
@@ -155,14 +161,19 @@ if (isset($_GET["pgsql"])) {
155
  return ($adminer->database() == $database);
156
  }
157
 
158
- function value($val, $field) {
159
- return $val;
160
- }
161
-
162
  function quoteBinary($s) {
163
  return q($s);
164
  }
165
 
 
 
 
 
 
 
 
 
 
166
  function warnings() {
167
  return ''; // not implemented in PDO_PgSQL as of PHP 7.2.1
168
  }
@@ -197,17 +208,21 @@ if (isset($_GET["pgsql"])) {
197
  return true;
198
  }
199
 
 
 
 
 
 
 
200
  function convertSearch($idf, $val, $field) {
201
- return (preg_match('~char|text' . (is_numeric($val["val"]) && !preg_match('~LIKE~', $val["op"]) ? '|' . number_type() : '') . '~', $field["type"])
 
 
202
  ? $idf
203
  : "CAST($idf AS text)"
204
  );
205
  }
206
 
207
- function value($val, $field) {
208
- return $this->_conn->value($val, $field);
209
- }
210
-
211
  function quoteBinary($s) {
212
  return $this->_conn->quoteBinary($s);
213
  }
@@ -271,7 +286,7 @@ if (isset($_GET["pgsql"])) {
271
  function limit1($table, $query, $where, $separator = "\n") {
272
  return (preg_match('~^INTO~', $query)
273
  ? limit($query, $where, 1, 0, $separator)
274
- : " $query WHERE ctid = (SELECT ctid FROM " . table($table) . $where . $separator . "LIMIT 1)"
275
  );
276
  }
277
 
@@ -358,7 +373,7 @@ ORDER BY a.attnum"
358
  $row["full_type"] = $row["type"] . $length . $addon . $array;
359
  }
360
  $row["null"] = !$row["attnotnull"];
361
- $row["auto_increment"] = preg_match('~^nextval\\(~i', $row["default"]);
362
  $row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1);
363
  if (preg_match('~(.+)::[^)]+(.*)~', $row["default"], $match)) {
364
  $row["default"] = ($match[1] == "NULL" ? null : (($match[1][0] == "'" ? idf_unescape($match[1]) : $match[1]) . $match[2]));
@@ -434,8 +449,8 @@ WHERE table_schema = current_schema() AND table_name = " . q($name))));
434
  function error() {
435
  global $connection;
436
  $return = h($connection->error);
437
- if (preg_match('~^(.*\\n)?([^\\n]*)\\n( *)\\^(\\n.*)?$~s', $return, $match)) {
438
- $return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\\1<b>\\2</b>', $match[2]) . $match[4];
439
  }
440
  return nl_br($return);
441
  }
@@ -830,7 +845,7 @@ AND typelem = 0"
830
  $structured_types[$key] = array_keys($val);
831
  }
832
  $unsigned = array();
833
- $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid SQL injection
834
  $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
835
  $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
836
  $edit_functions = array(
6
  define("DRIVER", "pgsql");
7
  if (extension_loaded("pgsql")) {
8
  class Min_DB {
9
+ var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error, $timeout;
10
 
11
  function _error($errno, $error) {
12
  if (ini_bool("html_errors")) {
69
  $this->error = "";
70
  if (!$result) {
71
  $this->error = pg_last_error($this->_link);
72
+ $return = false;
73
  } elseif (!pg_num_fields($result)) {
74
  $this->affected_rows = pg_affected_rows($result);
75
+ $return = true;
76
+ } else {
77
+ $return = new Min_Result($result);
78
  }
79
+ if ($this->timeout) {
80
+ $this->timeout = 0;
81
+ $this->query("RESET statement_timeout");
82
+ }
83
+ return $return;
84
  }
85
 
86
  function multi_query($query) {
145
 
146
  } elseif (extension_loaded("pdo_pgsql")) {
147
  class Min_DB extends Min_PDO {
148
+ var $extension = "PDO_PgSQL", $timeout;
149
 
150
  function connect($server, $username, $password) {
151
  global $adminer;
161
  return ($adminer->database() == $database);
162
  }
163
 
 
 
 
 
164
  function quoteBinary($s) {
165
  return q($s);
166
  }
167
 
168
+ function query($query, $unbuffered = false) {
169
+ $return = parent::query($query, $unbuffered);
170
+ if ($this->timeout) {
171
+ $this->timeout = 0;
172
+ parent::query("RESET statement_timeout");
173
+ }
174
+ return $return;
175
+ }
176
+
177
  function warnings() {
178
  return ''; // not implemented in PDO_PgSQL as of PHP 7.2.1
179
  }
208
  return true;
209
  }
210
 
211
+ function slowQuery($query, $timeout) {
212
+ $this->_conn->query("SET statement_timeout = " . (1000 * $timeout));
213
+ $this->_conn->timeout = 1000 * $timeout;
214
+ return $query;
215
+ }
216
+
217
  function convertSearch($idf, $val, $field) {
218
+ return (preg_match('~char|text'
219
+ . (!preg_match('~LIKE~', $val["op"]) ? '|date|time(stamp)?|boolean|uuid|' . number_type() : '')
220
+ . '~', $field["type"])
221
  ? $idf
222
  : "CAST($idf AS text)"
223
  );
224
  }
225
 
 
 
 
 
226
  function quoteBinary($s) {
227
  return $this->_conn->quoteBinary($s);
228
  }
286
  function limit1($table, $query, $where, $separator = "\n") {
287
  return (preg_match('~^INTO~', $query)
288
  ? limit($query, $where, 1, 0, $separator)
289
+ : " $query" . (is_view(table_status1($table)) ? $where : " WHERE ctid = (SELECT ctid FROM " . table($table) . $where . $separator . "LIMIT 1)")
290
  );
291
  }
292
 
373
  $row["full_type"] = $row["type"] . $length . $addon . $array;
374
  }
375
  $row["null"] = !$row["attnotnull"];
376
+ $row["auto_increment"] = preg_match('~^nextval\(~i', $row["default"]);
377
  $row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1);
378
  if (preg_match('~(.+)::[^)]+(.*)~', $row["default"], $match)) {
379
  $row["default"] = ($match[1] == "NULL" ? null : (($match[1][0] == "'" ? idf_unescape($match[1]) : $match[1]) . $match[2]));
449
  function error() {
450
  global $connection;
451
  $return = h($connection->error);
452
+ if (preg_match('~^(.*\n)?([^\n]*)\n( *)\^(\n.*)?$~s', $return, $match)) {
453
+ $return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\1<b>\2</b>', $match[2]) . $match[4];
454
  }
455
  return nl_br($return);
456
  }
845
  $structured_types[$key] = array_keys($val);
846
  }
847
  $unsigned = array();
848
+ $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
849
  $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
850
  $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
851
  $edit_functions = array(
adminer/adminer/adminer/drivers/simpledb.inc.php CHANGED
@@ -19,6 +19,7 @@ if (isset($_GET["simpledb"])) {
19
  $params['NextToken'] = $this->next;
20
  }
21
  $result = sdb_request_all('Select', 'Item', $params, $this->timeout); //! respect $unbuffered
 
22
  if ($result === false) {
23
  return $result;
24
  }
@@ -236,12 +237,22 @@ if (isset($_GET["simpledb"])) {
236
  function rollback() {
237
  return false;
238
  }
 
 
 
 
 
239
 
240
  }
241
 
242
 
243
 
244
  function connect() {
 
 
 
 
 
245
  return new Min_DB;
246
  }
247
 
19
  $params['NextToken'] = $this->next;
20
  }
21
  $result = sdb_request_all('Select', 'Item', $params, $this->timeout); //! respect $unbuffered
22
+ $this->timeout = 0;
23
  if ($result === false) {
24
  return $result;
25
  }
237
  function rollback() {
238
  return false;
239
  }
240
+
241
+ function slowQuery($query, $timeout) {
242
+ $this->_conn->timeout = $timeout;
243
+ return $query;
244
+ }
245
 
246
  }
247
 
248
 
249
 
250
  function connect() {
251
+ global $adminer;
252
+ list(, , $password) = $adminer->credentials();
253
+ if ($password != "") {
254
+ return lang('Database does not support password.');
255
+ }
256
  return new Min_DB;
257
  }
258
 
adminer/adminer/adminer/drivers/sqlite.inc.php CHANGED
@@ -152,7 +152,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
152
 
153
  function fetch_field() {
154
  $name = $this->_result->fieldName($this->_offset++);
155
- $pattern = '(\\[.*]|"(?:[^"]|"")*"|(.+))';
156
  if (preg_match("~^($pattern\\.)?$pattern\$~", $name, $match)) {
157
  $table = ($match[3] != "" ? $match[3] : idf_unescape($match[2]));
158
  $name = ($match[5] != "" ? $match[5] : idf_unescape($match[4]));
@@ -240,6 +240,11 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
240
  }
241
 
242
  function connect() {
 
 
 
 
 
243
  return new Min_DB;
244
  }
245
 
@@ -273,7 +278,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
273
  }
274
 
275
  function tables_list() {
276
- return get_key_vals("SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view') ORDER BY (name = 'sqlite_sequence'), name", 1);
277
  }
278
 
279
  function count_tables($databases) {
@@ -402,7 +407,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
402
 
403
  function view($name) {
404
  global $connection;
405
- return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . q($name)))); //! identifiers may be inside []
406
  }
407
 
408
  function collations() {
@@ -649,7 +654,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
649
  if ($name == "") {
650
  return array("Statement" => "BEGIN\n\t;\nEND");
651
  }
652
- $idf = '(?:[^`"\\s]+|`[^`]*`|"[^"]*")+';
653
  $trigger_options = trigger_options();
654
  preg_match(
655
  "~^CREATE\\s+TRIGGER\\s*$idf\\s*(" . implode("|", $trigger_options["Timing"]) . ")\\s+([a-z]+)(?:\\s+OF\\s+($idf))?\\s+ON\\s*$idf\\s*(?:FOR\\s+EACH\\s+ROW\\s)?(.*)~is",
@@ -670,7 +675,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
670
  $return = array();
671
  $trigger_options = trigger_options();
672
  foreach (get_rows("SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . q($table)) as $row) {
673
- preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*(' . implode("|", $trigger_options["Timing"]) . ')\\s*(.*)\\s+ON\\b~iU', $row["sql"], $match);
674
  $return[$row["name"]] = array($match[1], $match[2]);
675
  }
676
  return $return;
152
 
153
  function fetch_field() {
154
  $name = $this->_result->fieldName($this->_offset++);
155
+ $pattern = '(\[.*]|"(?:[^"]|"")*"|(.+))';
156
  if (preg_match("~^($pattern\\.)?$pattern\$~", $name, $match)) {
157
  $table = ($match[3] != "" ? $match[3] : idf_unescape($match[2]));
158
  $name = ($match[5] != "" ? $match[5] : idf_unescape($match[4]));
240
  }
241
 
242
  function connect() {
243
+ global $adminer;
244
+ list(, , $password) = $adminer->credentials();
245
+ if ($password != "") {
246
+ return lang('Database does not support password.');
247
+ }
248
  return new Min_DB;
249
  }
250
 
278
  }
279
 
280
  function tables_list() {
281
+ return get_key_vals("SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view') ORDER BY (name = 'sqlite_sequence'), name");
282
  }
283
 
284
  function count_tables($databases) {
407
 
408
  function view($name) {
409
  global $connection;
410
+ return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . q($name)))); //! identifiers may be inside []
411
  }
412
 
413
  function collations() {
654
  if ($name == "") {
655
  return array("Statement" => "BEGIN\n\t;\nEND");
656
  }
657
+ $idf = '(?:[^`"\s]+|`[^`]*`|"[^"]*")+';
658
  $trigger_options = trigger_options();
659
  preg_match(
660
  "~^CREATE\\s+TRIGGER\\s*$idf\\s*(" . implode("|", $trigger_options["Timing"]) . ")\\s+([a-z]+)(?:\\s+OF\\s+($idf))?\\s+ON\\s*$idf\\s*(?:FOR\\s+EACH\\s+ROW\\s)?(.*)~is",
675
  $return = array();
676
  $trigger_options = trigger_options();
677
  foreach (get_rows("SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . q($table)) as $row) {
678
+ preg_match('~^CREATE\s+TRIGGER\s*(?:[^`"\s]+|`[^`]*`|"[^"]*")+\s*(' . implode("|", $trigger_options["Timing"]) . ')\s*(.*)\s+ON\b~iU', $row["sql"], $match);
679
  $return[$row["name"]] = array($match[1], $match[2]);
680
  }
681
  return $return;
adminer/adminer/adminer/event.inc.php CHANGED
@@ -42,7 +42,7 @@ if (!$row && $EVENT != "") {
42
  <tr><th><?php echo lang('Every'); ?><td><input type="number" name="INTERVAL_VALUE" value="<?php echo h($row["INTERVAL_VALUE"]); ?>" class="size"> <?php echo html_select("INTERVAL_FIELD", $intervals, $row["INTERVAL_FIELD"]); ?>
43
  <tr><th><?php echo lang('Status'); ?><td><?php echo html_select("STATUS", $statuses, $row["STATUS"]); ?>
44
  <tr><th><?php echo lang('Comment'); ?><td><input name="EVENT_COMMENT" value="<?php echo h($row["EVENT_COMMENT"]); ?>" maxlength="64">
45
- <tr><th>&nbsp;<td><?php echo checkbox("ON_COMPLETION", "PRESERVE", $row["ON_COMPLETION"] == "PRESERVE", lang('On completion preserve')); ?>
46
  </table>
47
  <p><?php textarea("EVENT_DEFINITION", $row["EVENT_DEFINITION"]); ?>
48
  <p>
42
  <tr><th><?php echo lang('Every'); ?><td><input type="number" name="INTERVAL_VALUE" value="<?php echo h($row["INTERVAL_VALUE"]); ?>" class="size"> <?php echo html_select("INTERVAL_FIELD", $intervals, $row["INTERVAL_FIELD"]); ?>
43
  <tr><th><?php echo lang('Status'); ?><td><?php echo html_select("STATUS", $statuses, $row["STATUS"]); ?>
44
  <tr><th><?php echo lang('Comment'); ?><td><input name="EVENT_COMMENT" value="<?php echo h($row["EVENT_COMMENT"]); ?>" maxlength="64">
45
+ <tr><th><td><?php echo checkbox("ON_COMPLETION", "PRESERVE", $row["ON_COMPLETION"] == "PRESERVE", lang('On completion preserve')); ?>
46
  </table>
47
  <p><?php textarea("EVENT_DEFINITION", $row["EVENT_DEFINITION"]); ?>
48
  <p>
adminer/adminer/adminer/file.inc.php CHANGED
@@ -1,13 +1,5 @@
1
  <?php
2
- //! rewrite in compile.php to cache moderately with -dev version
3
- if ($_SERVER["HTTP_IF_MODIFIED_SINCE"]) {
4
- header("HTTP/1.1 304 Not Modified");
5
- exit;
6
- }
7
-
8
- header("Expires: " . gmdate("D, d M Y H:i:s", time() + 365*24*60*60) . " GMT");
9
- header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
10
- header("Cache-Control: immutable");
11
 
12
  if ($_GET["file"] == "favicon.ico") {
13
  header("Content-Type: image/x-icon");
1
  <?php
2
+ // caching headers added in compile.php
 
 
 
 
 
 
 
 
3
 
4
  if ($_GET["file"] == "favicon.ico") {
5
  header("Content-Type: image/x-icon");
adminer/adminer/adminer/include/adminer.inc.php CHANGED
@@ -75,7 +75,7 @@ class Adminer {
75
  * @return float number of seconds
76
  */
77
  function queryTimeout() {
78
- return 5;
79
  }
80
 
81
  /** Headers to send before HTML output
@@ -118,19 +118,26 @@ class Adminer {
118
  */
119
  function loginForm() {
120
  global $drivers;
121
- ?>
122
- <table cellspacing="0">
123
- <tr><th><?php echo lang('System'); ?><td><?php echo html_select("auth[driver]", $drivers, DRIVER) . "\n"; ?>
124
- <tr><th><?php echo lang('Server'); ?><td><input name="auth[server]" value="<?php echo h(SERVER); ?>" title="hostname[:port]" placeholder="localhost" autocapitalize="off">
125
- <tr><th><?php echo lang('Username'); ?><td><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off">
126
- <tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]">
127
- <tr><th><?php echo lang('Database'); ?><td><input name="auth[db]" value="<?php echo h($_GET["db"]); ?>" autocapitalize="off">
128
- </table>
129
- <?php
130
- echo script("focus(qs('#username'));");
131
  echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
132
  echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
133
  }
 
 
 
 
 
 
 
 
 
 
134
 
135
  /** Authorize the user
136
  * @param string
@@ -138,9 +145,8 @@ class Adminer {
138
  * @return mixed true for success, string for error message, false for unknown error
139
  */
140
  function login($login, $password) {
141
- global $jush;
142
- if ($jush == "sqlite") {
143
- return lang('<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.', target_blank(), '<code>login()</code>');
144
  }
145
  return true;
146
  }
@@ -312,7 +318,7 @@ class Adminer {
312
  echo ($field["null"] ? " <i>NULL</i>" : "");
313
  echo ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : "");
314
  echo (isset($field["default"]) ? " <span title='" . lang('Default value') . "'>[<b>" . h($field["default"]) . "</b>]</span>" : "");
315
- echo (support("comment") ? "<td>" . nbsp($field["comment"]) : "");
316
  echo "\n";
317
  }
318
  echo "</table>\n";
@@ -553,7 +559,7 @@ class Adminer {
553
  // find anywhere
554
  $cols = array();
555
  foreach ($fields as $name => $field) {
556
- if ((is_numeric($val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
557
  && (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"]))
558
  ) {
559
  $cols[] = $prefix . $driver->convertSearch(idf_escape($name), $val, $field) . $cond;
@@ -575,7 +581,7 @@ class Adminer {
575
  $return = array();
576
  foreach ((array) $_GET["order"] as $key => $val) {
577
  if ($val != "") {
578
- $return[] = (preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\\)|COUNT\\(\\*\\))$~', $val) ? $val : idf_escape($val)) //! MS SQL uses []
579
  . (isset($_GET["desc"][$key]) ? " DESC" : "")
580
  ;
581
  }
@@ -718,7 +724,7 @@ class Adminer {
718
  $return = "$function()";
719
  } elseif (preg_match('~^current_(date|timestamp)$~', $function)) {
720
  $return = $function;
721
- } elseif (preg_match('~^([+-]|\\|\\|)$~', $function)) {
722
  $return = idf_escape($name) . " $function $return";
723
  } elseif (preg_match('~^[+-] interval$~', $function)) {
724
  $return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) ? $value : $return);
@@ -837,7 +843,7 @@ class Adminer {
837
  foreach ($row as $key => $val) {
838
  $field = $fields[$key];
839
  $row[$key] = ($val !== null
840
- ? unconvert_field($field, preg_match(number_type(), $field["type"]) && $val != '' ? $val : q($val))
841
  : "NULL"
842
  );
843
  }
@@ -962,7 +968,7 @@ class Adminer {
962
  }
963
  $server_info = $connection->server_info;
964
  ?>
965
- bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\\d\\.?\\d).*~s', '\\1', $server_info) : ""); ?>'<?php echo (preg_match('~MariaDB~', $server_info) ? ", true" : ""); ?>);
966
  </script>
967
  <?php
968
  }
@@ -991,6 +997,9 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\\d\\.?\\d).*~s'
991
  function databasesPrint($missing) {
992
  global $adminer, $connection;
993
  $databases = $this->databases();
 
 
 
994
  ?>
995
  <form action="">
996
  <p id="dbs">
@@ -1010,11 +1019,12 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\\d\\.?\\d).*~s'
1010
  }
1011
  }
1012
  }
1013
- echo (isset($_GET["sql"]) ? '<input type="hidden" name="sql" value="">'
1014
- : (isset($_GET["schema"]) ? '<input type="hidden" name="schema" value="">'
1015
- : (isset($_GET["dump"]) ? '<input type="hidden" name="dump" value="">'
1016
- : (isset($_GET["privileges"]) ? '<input type="hidden" name="privileges" value="">'
1017
- : ""))));
 
1018
  echo "</p></form>\n";
1019
  }
1020
 
75
  * @return float number of seconds
76
  */
77
  function queryTimeout() {
78
+ return 2;
79
  }
80
 
81
  /** Headers to send before HTML output
118
  */
119
  function loginForm() {
120
  global $drivers;
121
+ echo "<table cellspacing='0'>\n";
122
+ echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER) . "\n");
123
+ echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">' . "\n");
124
+ echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocapitalize="off">' . script("focus(qs('#username'));"));
125
+ echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]">' . "\n");
126
+ echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">' . "\n");
127
+ echo "</table>\n";
 
 
 
128
  echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
129
  echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
130
  }
131
+
132
+ /** Get login form field
133
+ * @param string
134
+ * @param string HTML
135
+ * @param string HTML
136
+ * @return string
137
+ */
138
+ function loginFormField($name, $heading, $value) {
139
+ return $heading . $value;
140
+ }
141
 
142
  /** Authorize the user
143
  * @param string
145
  * @return mixed true for success, string for error message, false for unknown error
146
  */
147
  function login($login, $password) {
148
+ if ($password == "") {
149
+ return lang('Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.', target_blank());
 
150
  }
151
  return true;
152
  }
318
  echo ($field["null"] ? " <i>NULL</i>" : "");
319
  echo ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : "");
320
  echo (isset($field["default"]) ? " <span title='" . lang('Default value') . "'>[<b>" . h($field["default"]) . "</b>]</span>" : "");
321
+ echo (support("comment") ? "<td>" . h($field["comment"]) : "");
322
  echo "\n";
323
  }
324
  echo "</table>\n";
559
  // find anywhere
560
  $cols = array();
561
  foreach ($fields as $name => $field) {
562
+ if ((preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
563
  && (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"]))
564
  ) {
565
  $cols[] = $prefix . $driver->convertSearch(idf_escape($name), $val, $field) . $cond;
581
  $return = array();
582
  foreach ((array) $_GET["order"] as $key => $val) {
583
  if ($val != "") {
584
+ $return[] = (preg_match('~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~', $val) ? $val : idf_escape($val)) //! MS SQL uses []
585
  . (isset($_GET["desc"][$key]) ? " DESC" : "")
586
  ;
587
  }
724
  $return = "$function()";
725
  } elseif (preg_match('~^current_(date|timestamp)$~', $function)) {
726
  $return = $function;
727
+ } elseif (preg_match('~^([+-]|\|\|)$~', $function)) {
728
  $return = idf_escape($name) . " $function $return";
729
  } elseif (preg_match('~^[+-] interval$~', $function)) {
730
  $return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) ? $value : $return);
843
  foreach ($row as $key => $val) {
844
  $field = $fields[$key];
845
  $row[$key] = ($val !== null
846
+ ? unconvert_field($field, preg_match(number_type(), $field["type"]) && $val != '' ? $val : q(($val === false ? 0 : $val)))
847
  : "NULL"
848
  );
849
  }
968
  }
969
  $server_info = $connection->server_info;
970
  ?>
971
+ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '\1', $server_info) : ""); ?>'<?php echo (preg_match('~MariaDB~', $server_info) ? ", true" : ""); ?>);
972
  </script>
973
  <?php
974
  }
997
  function databasesPrint($missing) {
998
  global $adminer, $connection;
999
  $databases = $this->databases();
1000
+ if ($databases && !in_array(DB, $databases)) {
1001
+ array_unshift($databases, DB);
1002
+ }
1003
  ?>
1004
  <form action="">
1005
  <p id="dbs">
1019
  }
1020
  }
1021
  }
1022
+ foreach (array("import", "sql", "schema", "dump", "privileges") as $val) {
1023
+ if (isset($_GET[$val])) {
1024
+ echo "<input type='hidden' name='$val' value=''>";
1025
+ break;
1026
+ }
1027
+ }
1028
  echo "</p></form>\n";
1029
  }
1030
 
adminer/adminer/adminer/include/auth.inc.php CHANGED
@@ -120,6 +120,7 @@ function auth_error($error) {
120
  if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$has_token) {
121
  $error = lang('Session expired, please login again.');
122
  } else {
 
123
  add_invalid_login();
124
  $password = get_password();
125
  if ($password !== null) {
@@ -149,14 +150,17 @@ function auth_error($error) {
149
  exit;
150
  }
151
 
 
 
 
 
 
 
 
 
 
 
152
  if (isset($_GET["username"])) {
153
- if (!class_exists("Min_DB")) {
154
- unset($_SESSION["pwds"][DRIVER]);
155
- unset_permanent();
156
- page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), false);
157
- page_footer("auth");
158
- exit;
159
- }
160
  list($host, $port) = explode(":", SERVER, 2);
161
  if (is_numeric($port) && $port < 1024) {
162
  auth_error(lang('Connecting to privileged ports is not allowed.'));
120
  if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$has_token) {
121
  $error = lang('Session expired, please login again.');
122
  } else {
123
+ restart_session();
124
  add_invalid_login();
125
  $password = get_password();
126
  if ($password !== null) {
150
  exit;
151
  }
152
 
153
+ if (isset($_GET["username"]) && !class_exists("Min_DB")) {
154
+ unset($_SESSION["pwds"][DRIVER]);
155
+ unset_permanent();
156
+ page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), false);
157
+ page_footer("auth");
158
+ exit;
159
+ }
160
+
161
+ stop_session(true);
162
+
163
  if (isset($_GET["username"])) {
 
 
 
 
 
 
 
164
  list($host, $port) = explode(":", SERVER, 2);
165
  if (is_numeric($port) && $port < 1024) {
166
  auth_error(lang('Connecting to privileged ports is not allowed.'));
adminer/adminer/adminer/include/bootstrap.inc.php CHANGED
@@ -33,7 +33,7 @@ if ($_GET["script"] == "version") {
33
  exit;
34
  }
35
 
36
- global $adminer, $connection, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $permanent, $structured_types, $has_token, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function
37
 
38
  if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
39
  $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
@@ -44,13 +44,13 @@ if (!strpos($_SERVER["REQUEST_URI"], '?') && $_SERVER["QUERY_STRING"] != "") { /
44
  if ($_SERVER["HTTP_X_FORWARDED_PREFIX"]) {
45
  $_SERVER["REQUEST_URI"] = $_SERVER["HTTP_X_FORWARDED_PREFIX"] . $_SERVER["REQUEST_URI"];
46
  }
47
- $HTTPS = $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off");
48
 
49
  @ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled
50
  if (!defined("SID")) {
51
  session_cache_limiter(""); // to allow restarting session
52
  session_name("adminer_sid"); // use specific session name to get own namespace
53
- $params = array(0, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS);
54
  if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
55
  $params[] = true; // HttpOnly
56
  }
@@ -83,7 +83,7 @@ include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
83
 
84
  define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost
85
  define("DB", $_GET["db"]); // for the sake of speed and size
86
- define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\\1', $_SERVER["REQUEST_URI"]) . '?'
87
  . (sid() ? SID . '&' : '')
88
  . (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
89
  . (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
@@ -95,11 +95,6 @@ include "./include/adminer.inc.php";
95
  include "../adminer/include/design.inc.php";
96
  include "../adminer/include/xxtea.inc.php";
97
  include "../adminer/include/auth.inc.php";
98
-
99
- if (!ini_bool("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled
100
- session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
101
- }
102
-
103
  include "./include/editing.inc.php";
104
  include "./include/connect.inc.php";
105
 
33
  exit;
34
  }
35
 
36
+ global $adminer, $connection, $driver, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $permanent, $structured_types, $has_token, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function
37
 
38
  if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
39
  $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
44
  if ($_SERVER["HTTP_X_FORWARDED_PREFIX"]) {
45
  $_SERVER["REQUEST_URI"] = $_SERVER["HTTP_X_FORWARDED_PREFIX"] . $_SERVER["REQUEST_URI"];
46
  }
47
+ $HTTPS = ($_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")) || ini_bool("session.cookie_secure"); // session.cookie_secure could be set on HTTP if we are behind a reverse proxy
48
 
49
  @ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled
50
  if (!defined("SID")) {
51
  session_cache_limiter(""); // to allow restarting session
52
  session_name("adminer_sid"); // use specific session name to get own namespace
53
+ $params = array(0, preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS);
54
  if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
55
  $params[] = true; // HttpOnly
56
  }
83
 
84
  define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost
85
  define("DB", $_GET["db"]); // for the sake of speed and size
86
+ define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\1', $_SERVER["REQUEST_URI"]) . '?'
87
  . (sid() ? SID . '&' : '')
88
  . (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
89
  . (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
95
  include "../adminer/include/design.inc.php";
96
  include "../adminer/include/xxtea.inc.php";
97
  include "../adminer/include/auth.inc.php";
 
 
 
 
 
98
  include "./include/editing.inc.php";
99
  include "./include/connect.inc.php";
100
 
adminer/adminer/adminer/include/connect.inc.php CHANGED
@@ -32,7 +32,7 @@ function connect_error() {
32
  echo "<table cellspacing='0' class='checkable'>\n";
33
  echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
34
  echo "<thead><tr>"
35
- . (support("database") ? "<td>&nbsp;" : "")
36
  . "<th>" . lang('Database') . " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>"
37
  . "<td>" . lang('Collation')
38
  . "<td>" . lang('Tables')
@@ -47,7 +47,7 @@ function connect_error() {
47
  $id = h("Db-" . $db);
48
  echo "<tr" . odd() . ">" . (support("database") ? "<td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : "");
49
  echo "<th><a href='$root' id='$id'>" . h($db) . "</a>";
50
- $collation = nbsp(db_collation($db, $collations));
51
  echo "<td>" . (support("database") ? "<a href='$root" . ($scheme ? "&amp;ns=" : "") . "&amp;database=' title='" . lang('Alter database') . "'>$collation</a>" : $collation);
52
  echo "<td align='right'><a href='$root&amp;schema=' id='tables-" . h($db) . "' title='" . lang('Database schema') . "'>" . ($_GET["dbsize"] ? $tables : "?") . "</a>";
53
  echo "<td align='right' id='size-" . h($db) . "'>" . ($_GET["dbsize"] ? db_size($db) : "?");
32
  echo "<table cellspacing='0' class='checkable'>\n";
33
  echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
34
  echo "<thead><tr>"
35
+ . (support("database") ? "<td>" : "")
36
  . "<th>" . lang('Database') . " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>"
37
  . "<td>" . lang('Collation')
38
  . "<td>" . lang('Tables')
47
  $id = h("Db-" . $db);
48
  echo "<tr" . odd() . ">" . (support("database") ? "<td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : "");
49
  echo "<th><a href='$root' id='$id'>" . h($db) . "</a>";
50
+ $collation = h(db_collation($db, $collations));
51
  echo "<td>" . (support("database") ? "<a href='$root" . ($scheme ? "&amp;ns=" : "") . "&amp;database=' title='" . lang('Alter database') . "'>$collation</a>" : $collation);
52
  echo "<td align='right'><a href='$root&amp;schema=' id='tables-" . h($db) . "' title='" . lang('Database schema') . "'>" . ($_GET["dbsize"] ? $tables : "?") . "</a>";
53
  echo "<td align='right' id='size-" . h($db) . "'>" . ($_GET["dbsize"] ? db_size($db) : "?");
adminer/adminer/adminer/include/driver.inc.php CHANGED
@@ -113,6 +113,14 @@
113
  return queries("ROLLBACK");
114
  }
115
 
 
 
 
 
 
 
 
 
116
  /** Convert column to be searchable
117
  * @param string escaped column name
118
  * @param array array("op" => , "val" => )
@@ -129,7 +137,10 @@
129
  * @return string
130
  */
131
  function value($val, $field) {
132
- return $val;
 
 
 
133
  }
134
 
135
  /** Quote binary string
113
  return queries("ROLLBACK");
114
  }
115
 
116
+ /** Return query with a timeout
117
+ * @param string
118
+ * @param int seconds
119
+ * @return string or null if the driver doesn't support query timeouts
120
+ */
121
+ function slowQuery($query, $timeout) {
122
+ }
123
+
124
  /** Convert column to be searchable
125
  * @param string escaped column name
126
  * @param array array("op" => , "val" => )
137
  * @return string
138
  */
139
  function value($val, $field) {
140
+ return (method_exists($this->_conn, 'value')
141
+ ? $this->_conn->value($val, $field)
142
+ : (is_resource($val) ? stream_get_contents($val) : $val)
143
+ );
144
  }
145
 
146
  /** Quote binary string
adminer/adminer/adminer/include/editing.inc.php CHANGED
@@ -64,8 +64,6 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
64
  $val = "<i>NULL</i>";
65
  } elseif ($blobs[$key] && !is_utf8($val)) {
66
  $val = "<i>" . lang('%d byte(s)', strlen($val)) . "</i>"; //! link to download
67
- } elseif (!strlen($val)) { // strlen - SQLite can return int
68
- $val = "&nbsp;"; // some content to print a border
69
  } else {
70
  $val = h($val);
71
  if ($types[$key] == 254) { // 254 - char
@@ -156,7 +154,7 @@ echo optionlist(array_merge($extra_types, $structured_types), $type);
156
  ?></select>
157
  <?php echo on_help("getTarget(event).value", 1); ?>
158
  <?php echo script("mixin(qsl('select'), {onfocus: function () { lastType = selectValue(this); }, onchange: editingTypeChange});", ""); ?>
159
- <td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); ?> aria-labelledby="label-length"><?php echo script("mixin(qsl('input'), {onfocus: editingLengthFocus, oninput: editingLengthChange});", ""); ?><td class="options"><?php //! type="number" with enabled JavaScript
160
  echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>';
161
  echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
162
  echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), $field["on_update"]) . '</select>' : '');
@@ -245,7 +243,7 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
245
  $fields = array_values($fields);
246
  ?>
247
  <thead><tr>
248
- <?php if ($type == "PROCEDURE") { ?><td>&nbsp;<?php } ?>
249
  <th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?>
250
  <td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("qs('#enum-edit').onblur = editingLengthBlur;"); ?>
251
  <td id="label-length"><?php echo lang('Length'); ?>
@@ -285,9 +283,9 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
285
  }
286
  echo "<td>";
287
  echo (support("move_col") ?
288
- "<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>&nbsp;"
289
- . "<input type='image' class='icon' name='up[$i]' src='../adminer/static/up.gif' alt='↑' title='" . lang('Move up') . "'>&nbsp;"
290
- . "<input type='image' class='icon' name='down[$i]' src='../adminer/static/down.gif' alt='↓' title='" . lang('Move down') . "'>&nbsp;"
291
  : "");
292
  echo ($orig == "" || support("drop_col") ? "<input type='image' class='icon' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "'>" : "");
293
  }
@@ -360,7 +358,7 @@ function grant($grant, $privileges, $columns, $on) {
360
  : queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on")
361
  );
362
  }
363
- return queries("$grant " . preg_replace('~(GRANT OPTION)\\([^)]*\\)~', '\\1', implode("$columns, ", $privileges) . $columns) . $on);
364
  }
365
 
366
  /** Drop old object and create a new one
@@ -443,7 +441,7 @@ function create_routine($routine, $row) {
443
  * @return string
444
  */
445
  function remove_definer($query) {
446
- return preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\\1)', logged_user()) . '`~', '\\1', $query); //! proper escaping of user
447
  }
448
 
449
  /** Format foreign key to use in SQL query
@@ -499,7 +497,7 @@ function ini_bytes($ini) {
499
  function doc_link($paths, $text = "<sup>?</sup>") {
500
  global $jush, $connection;
501
  $server_info = $connection->server_info;
502
- $version = preg_replace('~^(\\d\\.?\\d).*~s', '\\1', $server_info); // two most significant digits
503
  $urls = array(
504
  'sql' => "https://dev.mysql.com/doc/refman/$version/en/",
505
  'sqlite' => "https://www.sqlite.org/",
64
  $val = "<i>NULL</i>";
65
  } elseif ($blobs[$key] && !is_utf8($val)) {
66
  $val = "<i>" . lang('%d byte(s)', strlen($val)) . "</i>"; //! link to download
 
 
67
  } else {
68
  $val = h($val);
69
  if ($types[$key] == 254) { // 254 - char
154
  ?></select>
155
  <?php echo on_help("getTarget(event).value", 1); ?>
156
  <?php echo script("mixin(qsl('select'), {onfocus: function () { lastType = selectValue(this); }, onchange: editingTypeChange});", ""); ?>
157
+ <td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); //! type="number" with enabled JavaScript ?> aria-labelledby="label-length"><?php echo script("mixin(qsl('input'), {onfocus: editingLengthFocus, oninput: editingLengthChange});", ""); ?><td class="options"><?php
158
  echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>';
159
  echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
160
  echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), $field["on_update"]) . '</select>' : '');
243
  $fields = array_values($fields);
244
  ?>
245
  <thead><tr>
246
+ <?php if ($type == "PROCEDURE") { ?><td><?php } ?>
247
  <th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?>
248
  <td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("qs('#enum-edit').onblur = editingLengthBlur;"); ?>
249
  <td id="label-length"><?php echo lang('Length'); ?>
283
  }
284
  echo "<td>";
285
  echo (support("move_col") ?
286
+ "<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'> "
287
+ . "<input type='image' class='icon' name='up[$i]' src='../adminer/static/up.gif' alt='↑' title='" . lang('Move up') . "'> "
288
+ . "<input type='image' class='icon' name='down[$i]' src='../adminer/static/down.gif' alt='↓' title='" . lang('Move down') . "'> "
289
  : "");
290
  echo ($orig == "" || support("drop_col") ? "<input type='image' class='icon' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "'>" : "");
291
  }
358
  : queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on")
359
  );
360
  }
361
+ return queries("$grant " . preg_replace('~(GRANT OPTION)\([^)]*\)~', '\1', implode("$columns, ", $privileges) . $columns) . $on);
362
  }
363
 
364
  /** Drop old object and create a new one
441
  * @return string
442
  */
443
  function remove_definer($query) {
444
+ return preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\1)', logged_user()) . '`~', '\1', $query); //! proper escaping of user
445
  }
446
 
447
  /** Format foreign key to use in SQL query
497
  function doc_link($paths, $text = "<sup>?</sup>") {
498
  global $jush, $connection;
499
  $server_info = $connection->server_info;
500
+ $version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits
501
  $urls = array(
502
  'sql' => "https://dev.mysql.com/doc/refman/$version/en/",
503
  'sqlite' => "https://www.sqlite.org/",
adminer/adminer/adminer/include/functions.inc.php CHANGED
@@ -154,14 +154,6 @@ function h($string) {
154
  return str_replace("\0", "&#0;", htmlspecialchars($string, ENT_QUOTES, 'utf-8'));
155
  }
156
 
157
- /** Escape for TD
158
- * @param string
159
- * @return string
160
- */
161
- function nbsp($string) {
162
- return (trim($string) != "" ? h($string) : "&nbsp;");
163
- }
164
-
165
  /** Convert \n to <br>
166
  * @param string
167
  * @return string
@@ -401,19 +393,16 @@ function get_vals($query, $column = 0) {
401
  /** Get keys from first column and values from second
402
  * @param string
403
  * @param Min_DB
404
- * @param float
405
  * @param bool
406
  * @return array
407
  */
408
- function get_key_vals($query, $connection2 = null, $timeout = 0, $set_keys = true) {
409
  global $connection;
410
  if (!is_object($connection2)) {
411
  $connection2 = $connection;
412
  }
413
  $return = array();
414
- $connection2->timeout = $timeout;
415
  $result = $connection2->query($query);
416
- $connection2->timeout = 0;
417
  if (is_object($result)) {
418
  while ($row = $result->fetch_row()) {
419
  if ($set_keys) {
@@ -490,7 +479,7 @@ function where($where, $fields = array()) {
490
  $key = bracket_escape($key, 1); // 1 - back
491
  $column = escape_key($key);
492
  $return[] = $column
493
- . ($jush == "sql" && preg_match('~^[0-9]*\\.[0-9]*$~', $val) ? " LIKE " . q(addcslashes($val, "%_\\"))
494
  : ($jush == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val))
495
  : " = " . unconvert_field($fields[$key], q($val))
496
  )) // LIKE because of floats but slow with ints, in MS SQL because of text
@@ -557,7 +546,7 @@ function cookie($name, $value, $lifetime = 2592000) { // 2592000 - 30 days
557
  global $HTTPS;
558
  return header("Set-Cookie: $name=" . urlencode($value)
559
  . ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "")
560
- . "; path=" . preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"])
561
  . ($HTTPS ? "; secure" : "")
562
  . "; HttpOnly; SameSite=lax",
563
  false);
@@ -572,12 +561,13 @@ function restart_session() {
572
  }
573
  }
574
 
575
- /** Stop session if it would be possible to restart it later
 
576
  * @return null
577
  */
578
- function stop_session() {
579
- if (!ini_bool("session.use_cookies")) {
580
- session_write_close();
581
  }
582
  }
583
 
@@ -607,7 +597,7 @@ function set_session($key, $val) {
607
  */
608
  function auth_url($vendor, $server, $username, $db = null) {
609
  global $drivers;
610
- preg_match('~([^?]*)\\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . ($db !== null ? "db|" : "") . session_name()), $match);
611
  return "$match[1]?"
612
  . (sid() ? SID . "&" : "")
613
  . ($vendor != "server" || $server != "" ? urlencode($vendor) . "=" . urlencode($server) . "&" : "")
@@ -767,7 +757,7 @@ function get_file($key, $decompress = false) {
767
  }
768
  $name = $file["name"][$key];
769
  $tmp_name = $file["tmp_name"][$key];
770
- $content = file_get_contents($decompress && preg_match('~\\.gz$~', $name)
771
  ? "compress.zlib://$tmp_name"
772
  : $tmp_name
773
  ); //! may not be reachable because of open_basedir
@@ -812,7 +802,7 @@ function repeat_pattern($pattern, $length) {
812
  */
813
  function is_utf8($val) {
814
  // don't print control chars except \t\r\n
815
- return (preg_match('~~u', $val) && !preg_match('~[\\0-\\x8\\xB\\xC\\xE-\\x1F]~', $val));
816
  }
817
 
818
  /** Shorten UTF-8 string
@@ -946,14 +936,14 @@ function input($field, $value, $function) {
946
  $functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
947
  $attrs = " name='fields[$name]'";
948
  if ($field["type"] == "enum") {
949
- echo nbsp($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
950
  } else {
951
  $has_function = (in_array($function, $functions) || isset($functions[$function]));
952
  echo (count($functions) > 1
953
  ? "<select name='function[$name]'>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
954
  . on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
955
  . script("qsl('select').onchange = functionChange;", "")
956
- : nbsp(reset($functions))
957
  ) . '<td>';
958
  $input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
959
  if ($input != "") {
@@ -982,7 +972,7 @@ function input($field, $value, $function) {
982
  echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
983
  } else {
984
  // int(3) is only a display hint
985
- $maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\\d+)(,(\\d+))?$~', $field["length"], $match) ? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
986
  if ($jush == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
987
  $maxlength += 7; // microtime
988
  }
@@ -1253,9 +1243,7 @@ function select_value($val, $link, $field, $text_length) {
1253
  }
1254
  $return = $adminer->editVal($val, $field);
1255
  if ($return !== null) {
1256
- if ($return === "") { // === - may be int
1257
- $return = "&nbsp;";
1258
- } elseif (!is_utf8($return)) {
1259
  $return = "\0"; // htmlspecialchars of binary data returns an empty string
1260
  } elseif ($text_length != "" && is_shortable($field)) {
1261
  $return = shorten_utf8($return, max(0, +$text_length)); // usage of LEFT() would reduce traffic but complicate query - expected average speedup: .001 s VS .01 s on local network
@@ -1315,10 +1303,11 @@ function count_rows($table, $where, $is_group, $group) {
1315
  * @return array of strings
1316
  */
1317
  function slow_query($query) {
1318
- global $adminer, $token;
1319
  $db = $adminer->database();
1320
  $timeout = $adminer->queryTimeout();
1321
- if (support("kill") && is_object($connection2 = connect()) && ($db == "" || $connection2->select_db($db))) {
 
1322
  $kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
1323
  ?>
1324
  <script<?php echo nonce(); ?>>
@@ -1333,7 +1322,7 @@ var timeout = setTimeout(function () {
1333
  }
1334
  ob_flush();
1335
  flush();
1336
- $return = @get_key_vals($query, $connection2, $timeout, false); // @ - may be killed
1337
  if ($connection2) {
1338
  echo script("clearTimeout(timeout);");
1339
  ob_flush();
154
  return str_replace("\0", "&#0;", htmlspecialchars($string, ENT_QUOTES, 'utf-8'));
155
  }
156
 
 
 
 
 
 
 
 
 
157
  /** Convert \n to <br>
158
  * @param string
159
  * @return string
393
  /** Get keys from first column and values from second
394
  * @param string
395
  * @param Min_DB
 
396
  * @param bool
397
  * @return array
398
  */
399
+ function get_key_vals($query, $connection2 = null, $set_keys = true) {
400
  global $connection;
401
  if (!is_object($connection2)) {
402
  $connection2 = $connection;
403
  }
404
  $return = array();
 
405
  $result = $connection2->query($query);
 
406
  if (is_object($result)) {
407
  while ($row = $result->fetch_row()) {
408
  if ($set_keys) {
479
  $key = bracket_escape($key, 1); // 1 - back
480
  $column = escape_key($key);
481
  $return[] = $column
482
+ . ($jush == "sql" && preg_match('~^[0-9]*\.[0-9]*$~', $val) ? " LIKE " . q(addcslashes($val, "%_\\"))
483
  : ($jush == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val))
484
  : " = " . unconvert_field($fields[$key], q($val))
485
  )) // LIKE because of floats but slow with ints, in MS SQL because of text
546
  global $HTTPS;
547
  return header("Set-Cookie: $name=" . urlencode($value)
548
  . ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "")
549
+ . "; path=" . preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"])
550
  . ($HTTPS ? "; secure" : "")
551
  . "; HttpOnly; SameSite=lax",
552
  false);
561
  }
562
  }
563
 
564
+ /** Stop session if possible
565
+ * @param bool
566
  * @return null
567
  */
568
+ function stop_session($force = false) {
569
+ if (!ini_bool("session.use_cookies") || ($force && @ini_set("session.use_cookies", false) !== false)) { // @ - may be disabled
570
+ session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
571
  }
572
  }
573
 
597
  */
598
  function auth_url($vendor, $server, $username, $db = null) {
599
  global $drivers;
600
+ preg_match('~([^?]*)\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . ($db !== null ? "db|" : "") . session_name()), $match);
601
  return "$match[1]?"
602
  . (sid() ? SID . "&" : "")
603
  . ($vendor != "server" || $server != "" ? urlencode($vendor) . "=" . urlencode($server) . "&" : "")
757
  }
758
  $name = $file["name"][$key];
759
  $tmp_name = $file["tmp_name"][$key];
760
+ $content = file_get_contents($decompress && preg_match('~\.gz$~', $name)
761
  ? "compress.zlib://$tmp_name"
762
  : $tmp_name
763
  ); //! may not be reachable because of open_basedir
802
  */
803
  function is_utf8($val) {
804
  // don't print control chars except \t\r\n
805
+ return (preg_match('~~u', $val) && !preg_match('~[\0-\x8\xB\xC\xE-\x1F]~', $val));
806
  }
807
 
808
  /** Shorten UTF-8 string
936
  $functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
937
  $attrs = " name='fields[$name]'";
938
  if ($field["type"] == "enum") {
939
+ echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
940
  } else {
941
  $has_function = (in_array($function, $functions) || isset($functions[$function]));
942
  echo (count($functions) > 1
943
  ? "<select name='function[$name]'>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
944
  . on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
945
  . script("qsl('select').onchange = functionChange;", "")
946
+ : h(reset($functions))
947
  ) . '<td>';
948
  $input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
949
  if ($input != "") {
972
  echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
973
  } else {
974
  // int(3) is only a display hint
975
+ $maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match) ? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
976
  if ($jush == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
977
  $maxlength += 7; // microtime
978
  }
1243
  }
1244
  $return = $adminer->editVal($val, $field);
1245
  if ($return !== null) {
1246
+ if (!is_utf8($return)) {
 
 
1247
  $return = "\0"; // htmlspecialchars of binary data returns an empty string
1248
  } elseif ($text_length != "" && is_shortable($field)) {
1249
  $return = shorten_utf8($return, max(0, +$text_length)); // usage of LEFT() would reduce traffic but complicate query - expected average speedup: .001 s VS .01 s on local network
1303
  * @return array of strings
1304
  */
1305
  function slow_query($query) {
1306
+ global $adminer, $token, $driver;
1307
  $db = $adminer->database();
1308
  $timeout = $adminer->queryTimeout();
1309
+ $slow_query = $driver->slowQuery($query, $timeout);
1310
+ if (!$slow_query && support("kill") && is_object($connection2 = connect()) && ($db == "" || $connection2->select_db($db))) {
1311
  $kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
1312
  ?>
1313
  <script<?php echo nonce(); ?>>
1322
  }
1323
  ob_flush();
1324
  flush();
1325
+ $return = @get_key_vals(($slow_query ? $slow_query : $query), $connection2, false); // @ - may be killed
1326
  if ($connection2) {
1327
  echo script("clearTimeout(timeout);");
1328
  ob_flush();
adminer/adminer/adminer/include/pdo.inc.php CHANGED
@@ -29,6 +29,9 @@ if (extension_loaded('pdo')) {
29
  $this->error = "";
30
  if (!$result) {
31
  list(, $this->errno, $this->error) = $this->errorInfo();
 
 
 
32
  return false;
33
  }
34
  $this->store_result($result);
29
  $this->error = "";
30
  if (!$result) {
31
  list(, $this->errno, $this->error) = $this->errorInfo();
32
+ if (!$this->error) {
33
+ $this->error = lang('Unknown error.');
34
+ }
35
  return false;
36
  }
37
  $this->store_result($result);
adminer/adminer/adminer/include/version.inc.php CHANGED
@@ -1,2 +1,2 @@
1
  <?php
2
- $VERSION = "4.6.2";
1
  <?php
2
+ $VERSION = "4.6.3";
adminer/adminer/adminer/indexes.inc.php CHANGED
@@ -99,7 +99,7 @@ if (!$row) {
99
  <th id="label-type"><?php echo lang('Index Type'); ?>
100
  <th><input type="submit" class="wayoff"><?php echo lang('Column (length)'); ?>
101
  <th id="label-name"><?php echo lang('Name'); ?>
102
- <th><noscript><input type='image' class='icon' name='add[0]' src='../adminer/static/plus.gif' alt='+' title='<?php echo lang('Add next'); ?>'></noscript>&nbsp;
103
  </thead>
104
  <?php
105
  if ($primary) {
99
  <th id="label-type"><?php echo lang('Index Type'); ?>
100
  <th><input type="submit" class="wayoff"><?php echo lang('Column (length)'); ?>
101
  <th id="label-name"><?php echo lang('Name'); ?>
102
+ <th><noscript><?php echo "<input type='image' class='icon' name='add[0]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>"; ?></noscript>
103
  </thead>
104
  <?php
105
  if ($primary) {
adminer/adminer/adminer/lang/cs.inc.php CHANGED
@@ -10,9 +10,10 @@ $translations = array(
10
  'Logout' => 'Odhlásit',
11
  'Logged as: %s' => 'Přihlášen jako: %s',
12
  'Logout successful.' => 'Odhlášení proběhlo v pořádku.',
13
- 'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Díky za použití Admineru, zvažte <a href="%s">příspěvek</a>.',
14
  'Invalid credentials.' => 'Neplatné přihlašovací údaje.',
15
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => 'Pro přihlášení k SQLite <a href="https://www.adminer.org/cs/extension/"%s>implementujte</a> metodu %s.',
 
16
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minutu.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minuty.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minut.'),
17
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Platnost hlavního hesla vypršela. <a href="https://www.adminer.org/cs/extension/"%s>Implementujte</a> metodu %s, aby platilo stále.',
18
  'Language' => 'Jazyk',
@@ -21,6 +22,7 @@ $translations = array(
21
  'No extension' => 'Žádné rozšíření',
22
  'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).',
23
  'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
 
24
  'Session support must be enabled.' => 'Session proměnné musí být povolené.',
25
  'Session expired, please login again.' => 'Session vypršela, přihlašte se prosím znovu.',
26
  'The action will be performed after successful login with the same credentials.' => 'Akce bude provedena po úspěšném přihlášení se stejnými přihlašovacími údaji.',
@@ -53,6 +55,7 @@ $translations = array(
53
  'Query executed OK, %d row(s) affected.' => array('Příkaz proběhl v pořádku, byl změněn %d záznam.', 'Příkaz proběhl v pořádku, byly změněny %d záznamy.', 'Příkaz proběhl v pořádku, bylo změněno %d záznamů.'),
54
  'No commands to execute.' => 'Žádné příkazy k vykonání.',
55
  'Error in query' => 'Chyba v dotazu',
 
56
  'Warnings' => 'Varování',
57
  'ATTACH queries are not supported.' => 'Dotazy ATTACH nejsou podporované.',
58
  'Execute' => 'Provést',
10
  'Logout' => 'Odhlásit',
11
  'Logged as: %s' => 'Přihlášen jako: %s',
12
  'Logout successful.' => 'Odhlášení proběhlo v pořádku.',
13
+ 'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Díky za použití Admineru, <a href="%s">příspějte</a> na vývoj.',
14
  'Invalid credentials.' => 'Neplatné přihlašovací údaje.',
15
+ 'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer nepodporuje přístup k databázi bez hesla, <a href="https://www.adminer.org/cs/password/"%s>více informací</a>.',
16
+ 'Database does not support password.' => 'Databáze nepodporuje heslo.',
17
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minutu.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minuty.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minut.'),
18
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Platnost hlavního hesla vypršela. <a href="https://www.adminer.org/cs/extension/"%s>Implementujte</a> metodu %s, aby platilo stále.',
19
  'Language' => 'Jazyk',
22
  'No extension' => 'Žádné rozšíření',
23
  'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).',
24
  'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
25
+ 'Disable %s or enable %s or %s extensions.' => 'Zakažte %s nebo povolte extenze %s nebo %s.',
26
  'Session support must be enabled.' => 'Session proměnné musí být povolené.',
27
  'Session expired, please login again.' => 'Session vypršela, přihlašte se prosím znovu.',
28
  'The action will be performed after successful login with the same credentials.' => 'Akce bude provedena po úspěšném přihlášení se stejnými přihlašovacími údaji.',
55
  'Query executed OK, %d row(s) affected.' => array('Příkaz proběhl v pořádku, byl změněn %d záznam.', 'Příkaz proběhl v pořádku, byly změněny %d záznamy.', 'Příkaz proběhl v pořádku, bylo změněno %d záznamů.'),
56
  'No commands to execute.' => 'Žádné příkazy k vykonání.',
57
  'Error in query' => 'Chyba v dotazu',
58
+ 'Unknown error.' => 'Neznámá chyba.',
59
  'Warnings' => 'Varování',
60
  'ATTACH queries are not supported.' => 'Dotazy ATTACH nejsou podporované.',
61
  'Execute' => 'Provést',
adminer/adminer/adminer/lang/he.inc.php CHANGED
@@ -276,7 +276,6 @@ $translations = array(
276
  'ATTACH queries are not supported.' => 'שאילתת ATTACH אינה נתמכת',
277
  '%d / ' => '%d / ',
278
  'Limit rows' => 'הגבל שורות',
279
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/en/extension/"%s>התקן</a> את תוסף SQLite בשביל להתחבר',
280
  'Default value' => 'ערך ברירת מחדל',
281
  'Full table scan' => 'סריקה טבלה מלאה',
282
  'Too many unsuccessful logins, try again in %d minute(s).' => 'יותר מידי נסיונות כניסה נכשלו, אנא נסה עוד %d דקות',
276
  'ATTACH queries are not supported.' => 'שאילתת ATTACH אינה נתמכת',
277
  '%d / ' => '%d / ',
278
  'Limit rows' => 'הגבל שורות',
 
279
  'Default value' => 'ערך ברירת מחדל',
280
  'Full table scan' => 'סריקה טבלה מלאה',
281
  'Too many unsuccessful logins, try again in %d minute(s).' => 'יותר מידי נסיונות כניסה נכשלו, אנא נסה עוד %d דקות',
adminer/adminer/adminer/lang/ms.inc.php CHANGED
@@ -12,7 +12,6 @@ $translations = array(
12
  'Logout successful.' => 'Log keluar berjaya.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Terima kasih kerana menggunakan Adminer, pertimbangkan untuk <a href="%s">menderma</a>.',
14
  'Invalid credentials.' => 'Akses tidak sah.',
15
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/en/extension/"%s>Gunakan</a> cara %s untuk menggunakan SQLite.',
16
  'Too many unsuccessful logins, try again in %d minute(s).' => 'Terlalu banyak percubaan log masuk yang gagal, sila cuba lagi dalam masa %d minit.',
17
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Kata laluan utama telah luput. <a href="https://www.adminer.org/en/extension/"%s>Gunakan</a> cara %s untuk mengekalkannya.',
18
  'Language' => 'Bahasa',
12
  'Logout successful.' => 'Log keluar berjaya.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Terima kasih kerana menggunakan Adminer, pertimbangkan untuk <a href="%s">menderma</a>.',
14
  'Invalid credentials.' => 'Akses tidak sah.',
 
15
  'Too many unsuccessful logins, try again in %d minute(s).' => 'Terlalu banyak percubaan log masuk yang gagal, sila cuba lagi dalam masa %d minit.',
16
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Kata laluan utama telah luput. <a href="https://www.adminer.org/en/extension/"%s>Gunakan</a> cara %s untuk mengekalkannya.',
17
  'Language' => 'Bahasa',
adminer/adminer/adminer/lang/pl.inc.php CHANGED
@@ -12,7 +12,6 @@ $translations = array(
12
  'Logout successful.' => 'Wylogowano pomyślnie.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ proszę <a href="%s">dotację</a>.',
14
  'Invalid credentials.' => 'Nieprawidłowe dane logowania.',
15
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/pl/extension/"%s>Zaimplementuj</a> metodę %s aby użyć SQLite.',
16
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Za dużo nieudanych prób logowania, spróbuj ponownie za %d minutę.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minuty.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minut.'),
17
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ważność hasła głównego wygasła. <a href="https://www.adminer.org/pl/extension/"%s>Zaimplementuj</a> własną metodę %s, aby ustawić je na stałe.',
18
  'Language' => 'Język',
12
  'Logout successful.' => 'Wylogowano pomyślnie.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ proszę <a href="%s">dotację</a>.',
14
  'Invalid credentials.' => 'Nieprawidłowe dane logowania.',
 
15
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Za dużo nieudanych prób logowania, spróbuj ponownie za %d minutę.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minuty.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minut.'),
16
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ważność hasła głównego wygasła. <a href="https://www.adminer.org/pl/extension/"%s>Zaimplementuj</a> własną metodę %s, aby ustawić je na stałe.',
17
  'Language' => 'Język',
adminer/adminer/adminer/lang/ru.inc.php CHANGED
@@ -276,7 +276,6 @@ $translations = array(
276
  'ATTACH queries are not supported.' => 'ATTACH-запросы не поддерживаются.',
277
  '%d / ' => '%d / ',
278
  'Limit rows' => 'Лимит строк',
279
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/en/extension/"%s>Реализуйте</a> метод %s, чтобы использовать SQLite.',
280
  'Default value' => 'Значение по умолчанию',
281
  'Full table scan' => 'Анализ полной таблицы',
282
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Слишком много неудачных попыток входа. Попробуйте снова через %d минуту.', 'Слишком много неудачных попыток входа. Попробуйте снова через %d минуты.', 'Слишком много неудачных попыток входа. Попробуйте снова через %d минут.'),
276
  'ATTACH queries are not supported.' => 'ATTACH-запросы не поддерживаются.',
277
  '%d / ' => '%d / ',
278
  'Limit rows' => 'Лимит строк',
 
279
  'Default value' => 'Значение по умолчанию',
280
  'Full table scan' => 'Анализ полной таблицы',
281
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Слишком много неудачных попыток входа. Попробуйте снова через %d минуту.', 'Слишком много неудачных попыток входа. Попробуйте снова через %d минуты.', 'Слишком много неудачных попыток входа. Попробуйте снова через %d минут.'),
adminer/adminer/adminer/lang/tr.inc.php CHANGED
@@ -12,7 +12,6 @@ $translations = array(
12
  'Logout successful.' => 'Oturum başarıyla sonlandı.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Adminer kullandığınız için teşekkür ederiz <a href="%s">bağış yapmayı düşünün</a>.',
14
  'Invalid credentials.' => 'Geçersiz kimlik bilgileri.',
15
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => 'SQLite kullanmak için <a href="https://www.adminer.org/en/extension/"%s>%s metodunu</a> kullanın.',
16
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Çok fazla oturum açma denemesi yapıldı.', '%d Dakika sonra tekrar deneyiniz.'),
17
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ana şifrenin süresi doldu. Kalıcı olması için <a href="https://www.adminer.org/en/extension/"%s>%s medodunu</a> kullanın.',
18
  'Language' => 'Dil',
12
  'Logout successful.' => 'Oturum başarıyla sonlandı.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Adminer kullandığınız için teşekkür ederiz <a href="%s">bağış yapmayı düşünün</a>.',
14
  'Invalid credentials.' => 'Geçersiz kimlik bilgileri.',
 
15
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Çok fazla oturum açma denemesi yapıldı.', '%d Dakika sonra tekrar deneyiniz.'),
16
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ana şifrenin süresi doldu. Kalıcı olması için <a href="https://www.adminer.org/en/extension/"%s>%s medodunu</a> kullanın.',
17
  'Language' => 'Dil',
adminer/adminer/adminer/lang/xx.inc.php CHANGED
@@ -12,7 +12,8 @@ $translations = array(
12
  'Logout successful.' => 'Xx.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Xx <a href="%s">xx</a>.',
14
  'Invalid credentials.' => 'Xx.',
15
- '<a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
 
16
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Xx %d.', 'Xx %d.'),
17
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '<a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
18
  'Language' => 'Xx',
@@ -21,6 +22,7 @@ $translations = array(
21
  'No extension' => 'Xx',
22
  'None of the supported PHP extensions (%s) are available.' => 'Xx (%s).',
23
  'Connecting to privileged ports is not allowed.' => 'Xx.',
 
24
  'Session support must be enabled.' => 'Xx.',
25
  'Session expired, please login again.' => 'Xx.',
26
  'The action will be performed after successful login with the same credentials.' => 'Xx.',
@@ -53,6 +55,7 @@ $translations = array(
53
  'Query executed OK, %d row(s) affected.' => array('Xx, %d.', 'Xx, %d.'),
54
  'No commands to execute.' => 'Xx.',
55
  'Error in query' => 'Xx',
 
56
  'Warnings' => 'Xx',
57
  'ATTACH queries are not supported.' => 'Xx.',
58
  'Execute' => 'Xx',
12
  'Logout successful.' => 'Xx.',
13
  'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Xx <a href="%s">xx</a>.',
14
  'Invalid credentials.' => 'Xx.',
15
+ 'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Xx, <a href="https://www.adminer.org/en/password/"%s>xx</a>.',
16
+ 'Database does not support password.' => 'Xx.',
17
  'Too many unsuccessful logins, try again in %d minute(s).' => array('Xx %d.', 'Xx %d.'),
18
  'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '<a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
19
  'Language' => 'Xx',
22
  'No extension' => 'Xx',
23
  'None of the supported PHP extensions (%s) are available.' => 'Xx (%s).',
24
  'Connecting to privileged ports is not allowed.' => 'Xx.',
25
+ 'Disable %s or enable %s or %s extensions.' => 'Xx %s xx %s xx %s xx.',
26
  'Session support must be enabled.' => 'Xx.',
27
  'Session expired, please login again.' => 'Xx.',
28
  'The action will be performed after successful login with the same credentials.' => 'Xx.',
55
  'Query executed OK, %d row(s) affected.' => array('Xx, %d.', 'Xx, %d.'),
56
  'No commands to execute.' => 'Xx.',
57
  'Error in query' => 'Xx',
58
+ 'Unknown error.' => 'Xx.',
59
  'Warnings' => 'Xx',
60
  'ATTACH queries are not supported.' => 'Xx.',
61
  'Execute' => 'Xx',
adminer/adminer/adminer/privileges.inc.php CHANGED
@@ -15,7 +15,7 @@ hidden_fields_get();
15
  echo "<input type='hidden' name='db' value='" . h(DB) . "'>\n";
16
  echo ($grant ? "" : "<input type='hidden' name='grant' value=''>\n");
17
  echo "<table cellspacing='0'>\n";
18
- echo "<thead><tr><th>" . lang('Username') . "<th>" . lang('Server') . "<th>&nbsp;</thead>\n";
19
 
20
  while ($row = $result->fetch_assoc()) {
21
  echo '<tr' . odd() . '><td>' . h($row["User"]) . "<td>" . h($row["Host"]) . '<td><a href="' . h(ME . 'user=' . urlencode($row["User"]) . '&host=' . urlencode($row["Host"])) . '">' . lang('Edit') . "</a>\n";
15
  echo "<input type='hidden' name='db' value='" . h(DB) . "'>\n";
16
  echo ($grant ? "" : "<input type='hidden' name='grant' value=''>\n");
17
  echo "<table cellspacing='0'>\n";
18
+ echo "<thead><tr><th>" . lang('Username') . "<th>" . lang('Server') . "<th></thead>\n";
19
 
20
  while ($row = $result->fetch_assoc()) {
21
  echo '<tr' . odd() . '><td>' . h($row["User"]) . "<td>" . h($row["Host"]) . '<td><a href="' . h(ME . 'user=' . urlencode($row["User"]) . '&host=' . urlencode($row["Host"])) . '">' . lang('Edit') . "</a>\n";
adminer/adminer/adminer/processlist.inc.php CHANGED
@@ -21,7 +21,7 @@ $i = -1;
21
  foreach (process_list() as $i => $row) {
22
 
23
  if (!$i) {
24
- echo "<thead><tr lang='en'>" . (support("kill") ? "<th>&nbsp;" : "");
25
  foreach ($row as $key => $val) {
26
  echo "<th>$key" . doc_link(array(
27
  'sql' => "show-processlist.html#processlist_" . strtolower($key),
@@ -38,7 +38,7 @@ foreach (process_list() as $i => $row) {
38
  ($jush == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
39
  ($jush == "oracle" && $key == "sql_text" && $val != "")
40
  ? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Clone') . '</a>'
41
- : nbsp($val)
42
  );
43
  }
44
  echo "\n";
21
  foreach (process_list() as $i => $row) {
22
 
23
  if (!$i) {
24
+ echo "<thead><tr lang='en'>" . (support("kill") ? "<th>" : "");
25
  foreach ($row as $key => $val) {
26
  echo "<th>$key" . doc_link(array(
27
  'sql' => "show-processlist.html#processlist_" . strtolower($key),
38
  ($jush == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
39
  ($jush == "oracle" && $key == "sql_text" && $val != "")
40
  ? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Clone') . '</a>'
41
+ : h($val)
42
  );
43
  }
44
  echo "\n";
adminer/adminer/adminer/script.inc.php CHANGED
@@ -4,10 +4,10 @@ header("Content-Type: text/javascript; charset=utf-8");
4
  if ($_GET["script"] == "db") {
5
  $sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
6
  foreach (table_status() as $name => $table_status) {
7
- json_row("Comment-$name", nbsp($table_status["Comment"]));
8
  if (!is_view($table_status)) {
9
  foreach (array("Engine", "Collation") as $key) {
10
- json_row("$key-$name", nbsp($table_status[$key]));
11
  }
12
  foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
13
  if ($table_status[$key] != "") {
4
  if ($_GET["script"] == "db") {
5
  $sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
6
  foreach (table_status() as $name => $table_status) {
7
+ json_row("Comment-$name", h($table_status["Comment"]));
8
  if (!is_view($table_status)) {
9
  foreach (array("Engine", "Collation") as $key) {
10
+ json_row("$key-$name", h($table_status[$key]));
11
  }
12
  foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
13
  if ($table_status[$key] != "") {
adminer/adminer/adminer/select.inc.php CHANGED
@@ -184,7 +184,7 @@ if ($_POST && !$error) {
184
  cookie("adminer_import", "output=" . urlencode($adminer_import["output"]) . "&format=" . urlencode($_POST["separator"]));
185
  $result = true;
186
  $cols = array_keys($fields);
187
- preg_match_all('~(?>"[^"]*"|[^"\\r\\n]+)+~', $file, $matches);
188
  $affected = count($matches[0]);
189
  $driver->begin();
190
  $separator = ($_POST["separator"] == "csv" ? "," : ($_POST["separator"] == "tsv" ? "\t" : ";"));
@@ -369,7 +369,7 @@ if (!$columns && support("table")) {
369
  if (!$unique_array) {
370
  $unique_array = array();
371
  foreach ($rows[$n] as $key => $val) {
372
- if (!preg_match('~^(COUNT\\((\\*|(DISTINCT )?`(?:[^`]|``)+`)\\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\\(`(?:[^`]|``)+`\\))$~', $key)) { //! columns looking like functions
373
  $unique_array[$key] = $val;
374
  }
375
  }
@@ -407,9 +407,9 @@ if (!$columns && support("table")) {
407
  foreach ($foreign_key["source"] as $i => $source) {
408
  $link .= where_link($i, $foreign_key["target"][$i], $rows[$n][$source]);
409
  }
410
- $link = ($foreign_key["db"] != "" ? preg_replace('~([?&]db=)[^&]+~', '\\1' . urlencode($foreign_key["db"]), ME) : ME) . 'select=' . urlencode($foreign_key["table"]) . $link; // InnoDB supports non-UNIQUE keys
411
  if ($foreign_key["ns"]) {
412
- $link = preg_replace('~([?&]ns=)[^&]+~', '\\1' . urlencode($foreign_key["ns"]), $link);
413
  }
414
  if (count($foreign_key["source"]) == 1) {
415
  break;
184
  cookie("adminer_import", "output=" . urlencode($adminer_import["output"]) . "&format=" . urlencode($_POST["separator"]));
185
  $result = true;
186
  $cols = array_keys($fields);
187
+ preg_match_all('~(?>"[^"]*"|[^"\r\n]+)+~', $file, $matches);
188
  $affected = count($matches[0]);
189
  $driver->begin();
190
  $separator = ($_POST["separator"] == "csv" ? "," : ($_POST["separator"] == "tsv" ? "\t" : ";"));
369
  if (!$unique_array) {
370
  $unique_array = array();
371
  foreach ($rows[$n] as $key => $val) {
372
+ if (!preg_match('~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~', $key)) { //! columns looking like functions
373
  $unique_array[$key] = $val;
374
  }
375
  }
407
  foreach ($foreign_key["source"] as $i => $source) {
408
  $link .= where_link($i, $foreign_key["target"][$i], $rows[$n][$source]);
409
  }
410
+ $link = ($foreign_key["db"] != "" ? preg_replace('~([?&]db=)[^&]+~', '\1' . urlencode($foreign_key["db"]), ME) : ME) . 'select=' . urlencode($foreign_key["table"]) . $link; // InnoDB supports non-UNIQUE keys
411
  if ($foreign_key["ns"]) {
412
+ $link = preg_replace('~([?&]ns=)[^&]+~', '\1' . urlencode($foreign_key["ns"]), $link);
413
  }
414
  if (count($foreign_key["source"]) == 1) {
415
  break;
adminer/adminer/adminer/sql.inc.php CHANGED
@@ -56,7 +56,7 @@ if (!$error && $_POST) {
56
  }
57
  $commands = 0;
58
  $errors = array();
59
- $parse = '[\'"' . ($jush == "sql" ? '`#' : ($jush == "sqlite" ? '`[' : ($jush == "mssql" ? '[' : ''))) . ']|/\\*|-- |$' . ($jush == "pgsql" ? '|\\$[^$]*\\$' : '');
60
  $total_start = microtime(true);
61
  parse_str($_COOKIE["adminer_export"], $adminer_export);
62
  $dump_format = $adminer->dumpFormat();
@@ -78,7 +78,7 @@ if (!$error && $_POST) {
78
  $offset = $pos + strlen($found);
79
 
80
  if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end
81
- while (preg_match('(' . ($found == '/*' ? '\\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset)) { //! respect sql_mode NO_BACKSLASH_ESCAPES
82
  $s = $match[0][0];
83
  if (!$s && $fp && !feof($fp)) {
84
  $query .= fread($fp, 1e5);
@@ -225,13 +225,14 @@ if (!isset($_GET["import"])) {
225
 
226
  } else {
227
  echo "<fieldset><legend>" . lang('File upload') . "</legend><div>";
 
228
  echo (ini_bool("file_uploads")
229
- ? "SQL (&lt; " . ini_get("upload_max_filesize") . "B): <input type='file' name='sql_file[]' multiple>\n$execute" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary
230
  : lang('File uploads are disabled.')
231
  );
232
  echo "</div></fieldset>\n";
233
  echo "<fieldset><legend>" . lang('From server') . "</legend><div>";
234
- echo lang('Webserver file %s', "<code>" . h($adminer->importServerPath()) . (extension_loaded("zlib") ? "[.gz]" : "") . "</code>");
235
  echo ' <input type="submit" name="webfile" value="' . lang('Run file') . '">';
236
  echo "</div></fieldset>\n";
237
  echo "<p>";
56
  }
57
  $commands = 0;
58
  $errors = array();
59
+ $parse = '[\'"' . ($jush == "sql" ? '`#' : ($jush == "sqlite" ? '`[' : ($jush == "mssql" ? '[' : ''))) . ']|/\*|-- |$' . ($jush == "pgsql" ? '|\$[^$]*\$' : '');
60
  $total_start = microtime(true);
61
  parse_str($_COOKIE["adminer_export"], $adminer_export);
62
  $dump_format = $adminer->dumpFormat();
78
  $offset = $pos + strlen($found);
79
 
80
  if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end
81
+ while (preg_match('(' . ($found == '/*' ? '\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset)) { //! respect sql_mode NO_BACKSLASH_ESCAPES
82
  $s = $match[0][0];
83
  if (!$s && $fp && !feof($fp)) {
84
  $query .= fread($fp, 1e5);
225
 
226
  } else {
227
  echo "<fieldset><legend>" . lang('File upload') . "</legend><div>";
228
+ $gz = (extension_loaded("zlib") ? "[.gz]" : "");
229
  echo (ini_bool("file_uploads")
230
+ ? "SQL$gz (&lt; " . ini_get("upload_max_filesize") . "B): <input type='file' name='sql_file[]' multiple>\n$execute" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary
231
  : lang('File uploads are disabled.')
232
  );
233
  echo "</div></fieldset>\n";
234
  echo "<fieldset><legend>" . lang('From server') . "</legend><div>";
235
+ echo lang('Webserver file %s', "<code>" . h($adminer->importServerPath()) . "$gz</code>");
236
  echo ' <input type="submit" name="webfile" value="' . lang('Run file') . '">';
237
  echo "</div></fieldset>\n";
238
  echo "<p>";
adminer/adminer/adminer/sqlite.php CHANGED
@@ -1,8 +1,11 @@
1
  <?php
2
  function adminer_object() {
3
  include_once "../plugins/plugin.php";
4
- include_once "../plugins/login-sqlite.php";
5
- return new AdminerPlugin(array(new AdminerLoginSqlite("admin", password_hash("", PASSWORD_DEFAULT))));
 
 
 
6
  }
7
 
8
  include "./index.php";
1
  <?php
2
  function adminer_object() {
3
  include_once "../plugins/plugin.php";
4
+ include_once "../plugins/login-password-less.php";
5
+ return new AdminerPlugin(array(
6
+ // TODO: inline the result of password_hash() so that the password is not visible in source codes
7
+ new AdminerLoginPasswordLess(password_hash("YOUR_PASSWORD_HERE", PASSWORD_DEFAULT)),
8
+ ));
9
  }
10
 
11
  include "./index.php";
adminer/adminer/adminer/static/editing.js CHANGED
@@ -395,8 +395,7 @@ function editingLengthFocus() {
395
  var td = this.parentNode;
396
  if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) {
397
  var edit = qs('#enum-edit');
398
- var val = this.value;
399
- edit.value = (/^'.+'$/.test(val) ? val.substr(1, val.length - 2).replace(/','/g, "\n").replace(/''/g, "'") : val); //! doesn't handle 'a'',''b' correctly
400
  td.appendChild(edit);
401
  this.style.display = 'none';
402
  edit.style.display = 'inline';
@@ -404,13 +403,32 @@ function editingLengthFocus() {
404
  }
405
  }
406
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  /** Finish editing of enum or set
408
  * @this HTMLTextAreaElement
409
  */
410
  function editingLengthBlur() {
411
  var field = this.parentNode.firstChild;
412
  var val = this.value;
413
- field.value = (/^'[^\n]+'$/.test(val) ? val : val && "'" + val.replace(/\n+$/, '').replace(/'/g, "''").replace(/\n/g, "','") + "'");
414
  field.style.display = 'inline';
415
  this.style.display = 'none';
416
  }
395
  var td = this.parentNode;
396
  if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) {
397
  var edit = qs('#enum-edit');
398
+ edit.value = enumValues(this.value);
 
399
  td.appendChild(edit);
400
  this.style.display = 'none';
401
  edit.style.display = 'inline';
403
  }
404
  }
405
 
406
+ /** Get enum values
407
+ * @param string
408
+ * @return string values separated by newlines
409
+ */
410
+ function enumValues(s) {
411
+ var re = /(^|,)\s*'(([^\\']|\\.|'')*)'\s*/g;
412
+ var result = [];
413
+ var offset = 0;
414
+ var match;
415
+ while (match = re.exec(s)) {
416
+ if (offset != match.index) {
417
+ break;
418
+ }
419
+ result.push(match[2].replace(/'(')|\\(.)/g, '$1$2'));
420
+ offset += match[0].length;
421
+ }
422
+ return (offset == s.length ? result.join('\n') : s);
423
+ }
424
+
425
  /** Finish editing of enum or set
426
  * @this HTMLTextAreaElement
427
  */
428
  function editingLengthBlur() {
429
  var field = this.parentNode.firstChild;
430
  var val = this.value;
431
+ field.value = (/^'[^\n]+'$/.test(val) ? val : val && "'" + val.replace(/\n+$/, '').replace(/'/g, "''").replace(/\\/g, '\\\\').replace(/\n/g, "','") + "'");
432
  field.style.display = 'inline';
433
  this.style.display = 'none';
434
  }
adminer/adminer/adminer/static/functions.js CHANGED
@@ -205,14 +205,9 @@ function formCheck(name) {
205
  /** Check all rows in <table class="checkable">
206
  */
207
  function tableCheck() {
208
- var tables = qsa('table', document);
209
- for (var i=0; i < tables.length; i++) {
210
- if (/(^|\s)checkable(\s|$)/.test(tables[i].className)) {
211
- var trs = qsa('tr', tables[i]);
212
- for (var j=0; j < trs.length; j++) {
213
- trCheck(trs[j].firstChild.firstChild);
214
- }
215
- }
216
  }
217
  }
218
 
@@ -319,13 +314,13 @@ function checkboxClick(event) {
319
 
320
  /** Set HTML code of an element
321
  * @param string
322
- * @param string undefined to set parentNode to &nbsp;
323
  */
324
  function setHtml(id, html) {
325
- var el = qs('#' + id);
326
  if (el) {
327
  if (html == null) {
328
- el.parentNode.innerHTML = '&nbsp;';
329
  } else {
330
  el.innerHTML = html;
331
  }
@@ -716,7 +711,7 @@ function selectClick(event, text, warning) {
716
  });
717
  input.rows = rows;
718
  }
719
- if (value == '\u00A0' || qsa('i', td).length) { // &nbsp; or i - NULL
720
  value = '';
721
  }
722
  if (document.selection) {
205
  /** Check all rows in <table class="checkable">
206
  */
207
  function tableCheck() {
208
+ var inputs = qsa('table.checkable td:first-child input', document);
209
+ for (var i=0; i < inputs.length; i++) {
210
+ trCheck(inputs[i]);
 
 
 
 
 
211
  }
212
  }
213
 
314
 
315
  /** Set HTML code of an element
316
  * @param string
317
+ * @param string undefined to set parentNode to empty string
318
  */
319
  function setHtml(id, html) {
320
+ var el = qs('[id="' + id.replace(/[\\"]/g, '\\$&') + '"]'); // database name is used as ID
321
  if (el) {
322
  if (html == null) {
323
+ el.parentNode.innerHTML = '';
324
  } else {
325
  el.innerHTML = html;
326
  }
711
  });
712
  input.rows = rows;
713
  }
714
+ if (qsa('i', td).length) { // <i> - NULL
715
  value = '';
716
  }
717
  if (document.selection) {
adminer/adminer/adminer/table.inc.php CHANGED
@@ -34,7 +34,7 @@ if (!is_view($table_status)) {
34
  $foreign_keys = foreign_keys($TABLE);
35
  if ($foreign_keys) {
36
  echo "<table cellspacing='0'>\n";
37
- echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . "<td>&nbsp;</thead>\n";
38
  foreach ($foreign_keys as $name => $foreign_key) {
39
  echo "<tr title='" . h($name) . "'>";
40
  echo "<th><i>" . implode("</i>, <i>", array_map('h', $foreign_key["source"])) . "</i>";
@@ -43,8 +43,8 @@ if (!is_view($table_status)) {
43
  . "</a>"
44
  ;
45
  echo "(<i>" . implode("</i>, <i>", array_map('h', $foreign_key["target"])) . "</i>)";
46
- echo "<td>" . nbsp($foreign_key["on_delete"]) . "\n";
47
- echo "<td>" . nbsp($foreign_key["on_update"]) . "\n";
48
  echo '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>';
49
  }
50
  echo "</table>\n";
34
  $foreign_keys = foreign_keys($TABLE);
35
  if ($foreign_keys) {
36
  echo "<table cellspacing='0'>\n";
37
+ echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . "<td></thead>\n";
38
  foreach ($foreign_keys as $name => $foreign_key) {
39
  echo "<tr title='" . h($name) . "'>";
40
  echo "<th><i>" . implode("</i>, <i>", array_map('h', $foreign_key["source"])) . "</i>";
43
  . "</a>"
44
  ;
45
  echo "(<i>" . implode("</i>, <i>", array_map('h', $foreign_key["target"])) . "</i>)";
46
+ echo "<td>" . h($foreign_key["on_delete"]) . "\n";
47
+ echo "<td>" . h($foreign_key["on_update"]) . "\n";
48
  echo '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>';
49
  }
50
  echo "</table>\n";