Compare commits

..

115 Commits

Author SHA1 Message Date
Jakub Vrana
967647759e Release 5.0.5 2025-03-13 18:28:43 +01:00
Jakub Vrana
e4323ced55 Tests: Fix CockroachDB after 48308f3 2025-03-13 18:22:06 +01:00
Jakub Vrana
85c6af6f87 Compile: strip space after CSS comment 2025-03-13 18:00:54 +01:00
Jakub Vrana
9226804aa2 CSS: Move media selector to <link> 2025-03-13 17:55:42 +01:00
Jakub Vrana
041e7064ca php_shrink: Simplify test 2025-03-13 17:45:16 +01:00
Jakub Vrana
4c2a8b0050 Compile: Move ?><? removal to php_shrink 2025-03-13 17:43:20 +01:00
Jakub Vrana
9afbf1a465 Compile: dark.css 2025-03-13 17:33:19 +01:00
Jakub Vrana
352ef9c778 CSS: Don't use dark theme with adminer.css 2025-03-13 17:11:40 +01:00
Jakub Vrana
45107dc46e Don't highlight NULL as JSON 2025-03-13 16:55:17 +01:00
Jakub Vrana
21f3426adb Design: Update dark mode (by rmsoft) 2025-03-13 16:48:56 +01:00
Jakub Vrana
95dccfe9fb MongoDB: Rename file 2025-03-13 15:21:19 +01:00
Jakub Vrana
fe88f83c95 Elastic: Fix number of rows in group queries 2025-03-13 14:34:26 +01:00
Jakub Vrana
078957fe32 MongoDB: Move to plugin 2025-03-13 14:27:54 +01:00
Jakub Vrana
61f07867f9 Update readme 2025-03-13 14:09:45 +01:00
Jakub Vrana
0135dd5b81 Tests: Add tests for MS SQL 2025-03-13 14:07:31 +01:00
Jakub Vrana
773a2253d3 Export: Display unknown number of rows as ? 2025-03-13 13:29:10 +01:00
Jakub Vrana
272042a30e Fix skipOriginal after unconvertFunction 2025-03-13 13:13:06 +01:00
Jakub Vrana
48308f3357 CockroachDB: Recognize unique_rowid() as auto_increment 2025-03-13 13:09:05 +01:00
Jakub Vrana
c90033a962 Test PostgreSQL: SQL command 2025-03-13 13:03:24 +01:00
Jakub Vrana
8bd022f974 CockroachDB: Fix test 2025-03-13 13:02:53 +01:00
Jakub Vrana
b1550b052d MySQL: Simplify checking for MariaDB 2025-03-13 12:24:35 +01:00
Jakub Vrana
9862846a7c CockroachDB: Declare support 2025-03-13 12:15:37 +01:00
Jakub Vrana
f14e3e38f6 CockroachDB: Disable processlist 2025-03-13 12:12:44 +01:00
Jakub Vrana
95262c4215 CSS: Fix style 2025-03-13 12:08:01 +01:00
Jakub Vrana
dacfdc4608 Tests: Work with JUSH textarea 2025-03-13 12:07:49 +01:00
Jakub Vrana
7636c253fb CockroachDB: Display version 2025-03-13 11:51:03 +01:00
Jakub Vrana
44d26a9dd3 Tests: Add tests for CockroachDB 2025-03-13 11:08:42 +01:00
Jakub Vrana
b229e7b583 Tests: Add tests for MariaDB and PostgreSQL 2025-03-13 10:45:53 +01:00
Jakub Vrana
8e91417be1 MySQL: Display converting function for binary, bit or geometry fields 2025-03-13 07:50:20 +01:00
Peter Knut
db7202fcf0 MySQL: Fix saving string default value of json field 2025-03-13 07:19:27 +01:00
Jakub Vrana
260487fbc2 Designs: Update rmsoft (fix #911) 2025-03-13 07:10:23 +01:00
Jakub Vrana
3ae964c915 Designs: Fix price 2025-03-13 07:06:43 +01:00
Jakub Vrana
d56c8cbaae CSS: Simplify .odds 2025-03-13 07:03:42 +01:00
Jakub Vrana
d347f88c54 Design: Update rmsoft (fix #911) 2025-03-13 06:38:32 +01:00
Jakub Vrana
b9b4db0c8e Compile: Add more php_shrink tests 2025-03-13 06:10:58 +01:00
Jakub Vrana
818b9ad903 Compile: Strip public 2025-03-12 23:15:24 +01:00
Jakub Vrana
4a6436773f Compile: Add tests for php_shrink 2025-03-12 23:15:22 +01:00
Jakub Vrana
81594e4a2d Issues: Prefer MySQLi 2025-03-12 18:28:56 +01:00
Jakub Vrana
f0bdb0e6ca Designs: Update .odds 2025-03-12 17:50:24 +01:00
Jakub Vrana
b9e4806d3c CSS: lowercase color names 2025-03-12 17:43:58 +01:00
Jakub Vrana
7e708dae57 CSS: Add dark theme 2025-03-12 17:42:53 +01:00
Jakub Vrana
a0fe44ec18 CSS: Expand <code> in <pre> 2025-03-12 17:35:44 +01:00
Jakub Vrana
eb0f280776 CSS: Fix highlighting checked odd rows 2025-03-12 17:35:34 +01:00
Jakub Vrana
3b1189cd3c MySQL: Allow setting default values of json column 2025-03-12 14:25:19 +01:00
Jakub Vrana
434a8f7705 CSS: Disable odd on hover 2025-03-12 13:58:20 +01:00
Jakub Vrana
f9478c67d2 CSS: Merge rules 2025-03-12 12:57:59 +01:00
Jakub Vrana
f2ce6c0a71 Wrap long lines 2025-03-12 11:43:21 +01:00
Jakub Vrana
a50b3d6385 MS SQL: Fix editing rows with datetime column in primary key
Inspired by adminneo-org@b4afc08.
This fixes https://sourceforge.net/p/adminer/discussion/960418/thread/a547e79622/.
2025-03-12 09:28:22 +01:00
Jakub Vrana
e39deca4f1 Wrap Schema: in navigation to <span> (fix #907) 2025-03-12 09:26:04 +01:00
Jakub Vrana
ce69970f54 Update German translation (by @wintstar) 2025-03-12 09:09:09 +01:00
Jakub Vrana
51ac1312a1 MariaDB: Don't display NULL as default value 2025-03-12 08:51:25 +01:00
Jakub Vrana
4505544953 Code style: exclude removed extensions 2025-03-12 08:12:28 +01:00
Jakub Vrana
fa75213ff6 Coverage: Fix newlines 2025-03-12 06:15:47 +01:00
Jakub Vrana
63acb37ea6 Coverage: Display drivers 2025-03-12 06:09:18 +01:00
Jakub Vrana
3ad6c16f59 Coverage: Modernize HTML 2025-03-12 06:06:28 +01:00
Jakub Vrana
22d08b4a50 Add comment 2025-03-12 06:01:29 +01:00
Jakub Vrana
dd3cc4e683 Add plugin AdminerEditorViews (fix #905) 2025-03-12 05:22:57 +01:00
Jakub Vrana
5504a617d0 Compile: Support private static 2025-03-12 05:03:42 +01:00
Jakub Vrana
2fdebfda29 Ensure PHP 5.3 compatibility 2025-03-11 21:43:59 +01:00
Jakub Vrana
dc2e945aef MySQL: Convert binary default value to hex when editing 2025-03-11 20:25:52 +01:00
Jakub Vrana
43d86287c4 Fix focusing first field 2025-03-11 20:16:49 +01:00
Jakub Vrana
a94a727af7 PostgreSQL PDO: Escape bytea values (bug #218) 2025-03-11 19:42:10 +01:00
Jakub Vrana
c2d29a6937 MySQL: Display default values of binary columns 2025-03-11 19:25:42 +01:00
Jakub Vrana
c082136558 Rename variable 2025-03-11 18:40:34 +01:00
Jakub Vrana
7b1ea5fa2c AdminerDumpAlter: Use dumpFooter 2025-03-11 18:20:11 +01:00
Jakub Vrana
156839142e Fix plugin AdminerPrettyJsonColumn 2025-03-11 18:16:44 +01:00
Jakub Vrana
2ee4e3b2e1 Compile: Fix shortening in protected functions 2025-03-11 17:56:21 +01:00
Jakub Vrana
8b4c8b0156 Fix coverage 2025-03-11 14:37:08 +01:00
Jakub Vrana
9702878297 Develop 2025-03-11 14:00:37 +01:00
Jakub Vrana
4a54648995 Release 5.0.4 2025-03-11 13:52:53 +01:00
Jakub Vrana
2e5027a1aa Compile: Fix shortening in private methods 2025-03-11 13:50:36 +01:00
Jakub Vrana
5a4c4dd892 Release 5.0.3 2025-03-11 13:16:35 +01:00
Jakub Vrana
7ef009336f PostgreSQL: Fix where and order privileges (fix #902) 2025-03-11 13:07:50 +01:00
Jakub Vrana
1defc94d12 Fix $result visibility 2025-03-11 12:53:35 +01:00
Jakub Vrana
5d3376e620 Check more style 2025-03-11 12:21:07 +01:00
Jakub Vrana
d410cdc5be Mongo: Add helper method 2025-03-11 11:13:40 +01:00
Jakub Vrana
a44e625882 Set visibility to protected 2025-03-11 11:05:39 +01:00
Jakub Vrana
ae57d42105 SQLite: Fix calling private property 2025-03-11 11:05:10 +01:00
Jakub Vrana
199edfe11f Plugins: Add method dumpFooter() 2025-03-11 08:59:38 +01:00
Jakub Vrana
b02c3e1f7f Use private visibility 2025-03-11 08:36:35 +01:00
Jakub Vrana
98cb9b9aca Add comment 2025-03-11 08:29:01 +01:00
Jakub Vrana
514d64048d Disallow var 2025-03-11 08:17:02 +01:00
Jakub Vrana
1e963cf90f Change var to public 2025-03-11 08:17:00 +01:00
Jakub Vrana
0c15a9f42d Use private visibility on methods 2025-03-11 08:16:41 +01:00
Jakub Vrana
c454ea8430 Use protected visibility 2025-03-11 08:16:41 +01:00
Jakub Vrana
607febea8e Use private visibility 2025-03-11 08:16:39 +01:00
Jakub Vrana
ebd5f19dd4 Use protected visibility 2025-03-11 08:12:09 +01:00
Jakub Vrana
1b0984ff31 Compile: Change public to var 2025-03-11 07:16:20 +01:00
Jakub Vrana
b017928256 Revert accidental revert 2025-03-11 07:05:16 +01:00
Jakub Vrana
526077535e Update changes 2025-03-11 07:00:21 +01:00
Jakub Vrana
8274b2e0e8 Update bug template 2025-03-11 06:50:04 +01:00
Jakub Vrana
8f7d456887 Update changes 2025-03-11 06:45:38 +01:00
Jakub Vrana
91b735c576 Compile: Support \r\n line ends 2025-03-11 06:30:31 +01:00
Jakub Vrana
916b9e62de Fix double unescaping 2025-03-11 06:24:21 +01:00
Jakub Vrana
f25c65837f Add comment 2025-03-11 06:24:21 +01:00
Jakub Vrana
b0182834bf Fix typo 2025-03-11 06:24:21 +01:00
David Grudl
6bf0b85919 Compile: supports visibility modifiers 2025-03-11 06:24:07 +01:00
Jakub Vrana
37e63dd82f MySQL: Stop treating enum as set as numbers (bug #475) 2025-03-10 23:40:07 +01:00
Jakub Vrana
6fdde32f86 Remove check for PHP version 2025-03-10 23:03:20 +01:00
Jakub Vrana
aeac0a3329 MySQL: Allow setting default values of text column 2025-03-10 21:15:01 +01:00
Christian Weiske
fde7d7dde2 Elastic: Properly display sparse result rows
Result records in Elasticsearch do not always have all columns
that are defined in an index.
This often happens when multiple document types are stored in the same index.

The first row has columns ["_id", "html", "url"], while the second
misses the "html" column: ["_id", "url"].

Adminer expects that all result rows include all columns.
This leads to the problem that the "url" value in the 2nd example row
was rendered in the "html" column.

This patch fixes this problem by fetching the actual column list first
when all fields are to be shown, and using that field list
as base for all rows.
2025-03-10 21:14:54 +01:00
Christian Weiske
e993462412 Elastic: Fix record insertion on Elasticsearch 7
1. Make values NULLable by default, so that empty values do not
get submitted to the Elasticsearch server.
This helps e.g. with empty date fields - Elasticsearch would try to
convert the field type to string when the value is an empty string,
but that fails when there are documents with properly filled date fields

2. Remove _id from the POST array because this is not allowed.
The server fails if it is included with
> mapper_parsing_exception:
> Field [_id] is a metadata field and cannot be added inside a document.
> Use the index API request parameters.

3. Use the correct URL to create a document: "$index/_doc/"
and "$index/_doc/$id". This is the same for ES 7 and 8:
- https://www.elastic.co/guide/en/elasticsearch/reference/8.17/docs-index_.html#docs-index-api-request
- https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docs-index_.html#docs-index-api-request

4. Handle failed creations by checking for false

5. Return the "result" property string instead of the non-existing
"created" property.
2025-03-10 21:13:16 +01:00
Jakub Vrana
31f8f61d0e MySQL, MariaDB: Fix default values with ' (fix #895) 2025-03-10 21:01:21 +01:00
Jakub Vrana
e589ee3fde MariaDB: Fix creating and altering generated columns (fixes #897) 2025-03-10 19:18:14 +01:00
Jakub Vrána
35274f18bb Update issue templates 2025-03-10 19:09:56 +01:00
Jakub Vrana
f8b2640156 Fix gzip export (fixes #896) 2025-03-10 18:51:28 +01:00
Jakub Vrana
bb23546478 Use <datalist> for altering collations 2025-03-10 14:13:34 +01:00
Jakub Vrana
dddfc190a5 Split helper html_radios 2025-03-10 11:31:43 +01:00
Jakub Vrana
40760d153c Update changes 2025-03-10 09:09:09 +01:00
Peter Knut
4fe3d17255 Update Slovak translation 2025-03-10 09:09:09 +01:00
Jakub Vrana
6dcc5081e1 Fix importing multiple SQL files not terminated by semicolon
Inspired by adminneo-org/adminneo#1c08e86.
2025-03-10 09:09:09 +01:00
Jakub Vrana
df6fe6b108 Fix link 2025-03-10 09:09:09 +01:00
Jakub Vrana
e6339046ff Remove unused variable 2025-03-10 09:09:09 +01:00
Jakub Vrana
2c0cfbdd3f Develop 2025-03-10 09:09:09 +01:00
Christian Weiske
f13770c664 Make login to Elasticsearch work again
By partially reverting the changes made by
commit 2c9f380c64
> Elastic: Remove plugin for version 5
which removed the passwordless login plugin from adminer/elastic.php
2025-03-10 08:53:19 +01:00
106 changed files with 2617 additions and 958 deletions

14
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,14 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Adminer version:** please use latest published or Git
**Driver:** e.g. MySQLi
**Database version:** e.g. 10.2.12-MariaDB
Please provide reproducible steps including a SQL dump (with no personal information) if applicable.

View File

@@ -73,11 +73,8 @@ if ($in) {
echo "<tr><th>" . $adminer->fieldName($field);
$value = $_POST["fields"][$name];
if ($value != "") {
if ($field["type"] == "enum") {
$value = +$value;
}
if ($field["type"] == "set") {
$value = array_sum($value);
$value = implode(",", $value);
}
}
input($field, $value, (string) $_POST["function"][$name]); // param name can be empty

View File

@@ -83,17 +83,18 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
$partitioning = "";
if (support("partitioning")) {
if (isset($partition_by[$row["partition_by"]])) {
$params = array_filter($row, function ($key) {
return preg_match('~^partition~', $key);
}, ARRAY_FILTER_USE_KEY);
$params = array();
foreach ($row as $key => $val) {
if (preg_match('~^partition~', $key)) {
$params[$key] = $val;
}
}
foreach ($params["partition_names"] as $key => $name) {
if ($name == "") {
unset($params["partition_names"][$key]);
unset($params["partition_values"][$key]);
}
}
if ($params != get_partitions_info($TABLE)) {
$partitions = array();
if ($params["partition_by"] == 'RANGE' || $params["partition_by"] == 'LIST') {
@@ -102,7 +103,6 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
$partitions[] = "\n PARTITION " . idf_escape($name) . " VALUES " . ($params["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
}
}
// $params["partition"] can be expression, not only column
$partitioning .= "\nPARTITION BY $params[partition_by]($params[partition])";
if ($partitions) {
@@ -183,7 +183,12 @@ foreach ($engines as $engine) {
<?php if (support("columns") || $TABLE == "") { ?>
<?php echo lang('Table name'); ?>: <input name="name"<?php echo ($TABLE == "" && !$_POST ? " autofocus" : ""); ?> data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?>
<?php echo ($collations && !preg_match("~sqlite|mssql~", JUSH) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
<?php
if ($collations) {
echo "<datalist id='collations'>" . optionlist($collations) . "</datalist>";
echo (preg_match("~sqlite|mssql~", JUSH) ? "" : "<input list='collations' name='Collation' value='" . h($row["Collation"]) . "' placeholder='(" . lang('collation') . ")'>");
}
?>
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php } ?>

View File

@@ -13,9 +13,10 @@ if (isset($_GET["mssql"])) {
define('Adminer\DRIVER', "mssql");
if (extension_loaded("sqlsrv")) {
class Db {
var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $errno, $error;
public $extension = "sqlsrv", $server_info, $affected_rows, $errno, $error;
private $link, $result;
function _get_error() {
private function get_error() {
$this->error = "";
foreach (sqlsrv_errors() as $error) {
$this->errno = $error["code"];
@@ -38,14 +39,14 @@ if (isset($_GET["mssql"])) {
if ($db != "") {
$connection_info["Database"] = $db;
}
$this->_link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info);
if ($this->_link) {
$info = sqlsrv_server_info($this->_link);
$this->link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info);
if ($this->link) {
$info = sqlsrv_server_info($this->link);
$this->server_info = $info['SQLServerVersion'];
} else {
$this->_get_error();
$this->get_error();
}
return (bool) $this->_link;
return (bool) $this->link;
}
function quote($string) {
@@ -58,20 +59,20 @@ if (isset($_GET["mssql"])) {
}
function query($query, $unbuffered = false) {
$result = sqlsrv_query($this->_link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
$result = sqlsrv_query($this->link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
$this->error = "";
if (!$result) {
$this->_get_error();
$this->get_error();
return false;
}
return $this->store_result($result);
}
function multi_query($query) {
$this->_result = sqlsrv_query($this->_link, $query);
$this->result = sqlsrv_query($this->link, $query);
$this->error = "";
if (!$this->_result) {
$this->_get_error();
if (!$this->result) {
$this->get_error();
return false;
}
return true;
@@ -79,7 +80,7 @@ if (isset($_GET["mssql"])) {
function store_result($result = null) {
if (!$result) {
$result = $this->_result;
$result = $this->result;
}
if (!$result) {
return false;
@@ -92,7 +93,7 @@ if (isset($_GET["mssql"])) {
}
function next_result() {
return $this->_result ? sqlsrv_next_result($this->_result) : null;
return $this->result ? sqlsrv_next_result($this->result) : null;
}
function result($query, $field = 0) {
@@ -106,14 +107,15 @@ if (isset($_GET["mssql"])) {
}
class Result {
var $_result, $_offset = 0, $_fields, $num_rows;
public $num_rows;
private $result, $offset = 0, $fields;
function __construct($result) {
$this->_result = $result;
$this->result = $result;
// $this->num_rows = sqlsrv_num_rows($result); // available only in scrollable results
}
function _convert($row) {
private function convert($row) {
foreach ((array) $row as $key => $val) {
if (is_a($val, 'DateTime')) {
$row[$key] = $val->format("Y-m-d H:i:s");
@@ -124,18 +126,18 @@ if (isset($_GET["mssql"])) {
}
function fetch_assoc() {
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_ASSOC));
return $this->convert(sqlsrv_fetch_array($this->result, SQLSRV_FETCH_ASSOC));
}
function fetch_row() {
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_NUMERIC));
return $this->convert(sqlsrv_fetch_array($this->result, SQLSRV_FETCH_NUMERIC));
}
function fetch_field() {
if (!$this->_fields) {
$this->_fields = sqlsrv_field_metadata($this->_result);
if (!$this->fields) {
$this->fields = sqlsrv_field_metadata($this->result);
}
$field = $this->_fields[$this->_offset++];
$field = $this->fields[$this->offset++];
$return = new \stdClass;
$return->name = $field["Name"];
$return->orgname = $field["Name"];
@@ -145,18 +147,18 @@ if (isset($_GET["mssql"])) {
function seek($offset) {
for ($i=0; $i < $offset; $i++) {
sqlsrv_fetch($this->_result); // SQLSRV_SCROLL_ABSOLUTE added in sqlsrv 1.1
sqlsrv_fetch($this->result); // SQLSRV_SCROLL_ABSOLUTE added in sqlsrv 1.1
}
}
function __destruct() {
sqlsrv_free_stmt($this->_result);
sqlsrv_free_stmt($this->result);
}
}
} elseif (extension_loaded("pdo_sqlsrv")) {
class Db extends PdoDb {
var $extension = "PDO_SQLSRV";
public $extension = "PDO_SQLSRV";
function connect($server, $username, $password) {
$this->dsn("sqlsrv:Server=" . str_replace(":", ",", $server), $username, $password);
@@ -171,7 +173,7 @@ if (isset($_GET["mssql"])) {
} elseif (extension_loaded("pdo_dblib")) {
class Db extends PdoDb {
var $extension = "PDO_DBLIB";
public $extension = "PDO_DBLIB";
function connect($server, $username, $password) {
$this->dsn("dblib:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)), $username, $password);
@@ -189,7 +191,7 @@ if (isset($_GET["mssql"])) {
static $possibleDrivers = array("SQLSRV", "PDO_SQLSRV", "PDO_DBLIB");
static $jush = "mssql";
var $editFunctions = array(
public $editFunctions = array(
array(
"date|time" => "getdate",
), array(
@@ -198,11 +200,11 @@ if (isset($_GET["mssql"])) {
)
);
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
var $functions = array("len", "lower", "round", "upper");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
var $onActions = "NO ACTION|CASCADE|SET NULL|SET DEFAULT";
var $generated = array("PERSISTED", "VIRTUAL");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
public $functions = array("len", "lower", "round", "upper");
public $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
public $onActions = "NO ACTION|CASCADE|SET NULL|SET DEFAULT";
public $generated = array("PERSISTED", "VIRTUAL");
function __construct($connection) {
parent::__construct($connection);
@@ -507,7 +509,16 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table), $connection2) as $row
foreach ($comments as $key => $val) {
$comment = substr($val, 9); // 9 - strlen(" COMMENT ")
queries("EXEC sp_dropextendedproperty @name = N'MS_Description', @level0type = N'Schema', @level0name = " . q(get_schema()) . ", @level1type = N'Table', @level1name = " . q($name) . ", @level2type = N'Column', @level2name = " . q($key));
queries("EXEC sp_addextendedproperty @name = N'MS_Description', @value = " . $comment . ", @level0type = N'Schema', @level0name = " . q(get_schema()) . ", @level1type = N'Table', @level1name = " . q($name) . ", @level2type = N'Column', @level2name = " . q($key));
queries("EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = $comment,
@level0type = N'Schema',
@level0name = " . q(get_schema()) . ",
@level1type = N'Table',
@level1name = " . q($name) . ",
@level2type = N'Column',
@level2name = " . q($key))
;
}
return true;
}

View File

@@ -8,7 +8,7 @@ if (!defined('Adminer\DRIVER')) {
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
if (extension_loaded("mysqli")) {
class Db extends \MySQLi {
var $extension = "MySQLi";
public $extension = "MySQLi";
function __construct() {
parent::init();
@@ -60,14 +60,14 @@ if (!defined('Adminer\DRIVER')) {
} elseif (extension_loaded("mysql") && !((ini_bool("sql.safe_mode") || ini_bool("mysql.allow_local_infile")) && extension_loaded("pdo_mysql"))) {
class Db {
var
public
$extension = "MySQL", ///< @var string extension name
$server_info, ///< @var string server version
$affected_rows, ///< @var int number of affected rows
$errno, ///< @var int last error code
$error, ///< @var string last error message
$_link, $_result ///< @access private
$error ///< @var string last error message
;
private $link, $result;
/** Connect to server
* @param string
@@ -80,19 +80,19 @@ if (!defined('Adminer\DRIVER')) {
$this->error = lang('Disable %s or enable %s or %s extensions.', "'mysql.allow_local_infile'", "MySQLi", "PDO_MySQL");
return false;
}
$this->_link = @mysql_connect(
$this->link = @mysql_connect(
($server != "" ? $server : ini_get("mysql.default_host")),
("$server$username" != "" ? $username : ini_get("mysql.default_user")),
("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
true,
131072 // CLIENT_MULTI_RESULTS for CALL
);
if ($this->_link) {
$this->server_info = mysql_get_server_info($this->_link);
if ($this->link) {
$this->server_info = mysql_get_server_info($this->link);
} else {
$this->error = mysql_error();
}
return (bool) $this->_link;
return (bool) $this->link;
}
/** Sets the client character set
@@ -101,11 +101,11 @@ if (!defined('Adminer\DRIVER')) {
*/
function set_charset($charset) {
if (function_exists('mysql_set_charset')) {
if (mysql_set_charset($charset, $this->_link)) {
if (mysql_set_charset($charset, $this->link)) {
return true;
}
// the client library may not support utf8mb4
mysql_set_charset('utf8', $this->_link);
mysql_set_charset('utf8', $this->link);
}
return $this->query("SET NAMES $charset");
}
@@ -115,7 +115,7 @@ if (!defined('Adminer\DRIVER')) {
* @return string escaped string enclosed in '
*/
function quote($string) {
return "'" . mysql_real_escape_string($string, $this->_link) . "'";
return "'" . mysql_real_escape_string($string, $this->link) . "'";
}
/** Select database
@@ -123,7 +123,7 @@ if (!defined('Adminer\DRIVER')) {
* @return bool
*/
function select_db($database) {
return mysql_select_db($database, $this->_link);
return mysql_select_db($database, $this->link);
}
/** Send query
@@ -132,16 +132,16 @@ if (!defined('Adminer\DRIVER')) {
* @return mixed bool or Result
*/
function query($query, $unbuffered = false) {
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->link) : mysql_query($query, $this->link)); // @ - mute mysql.trace_mode
$this->error = "";
if (!$result) {
$this->errno = mysql_errno($this->_link);
$this->error = mysql_error($this->_link);
$this->errno = mysql_errno($this->link);
$this->error = mysql_error($this->link);
return false;
}
if ($result === true) {
$this->affected_rows = mysql_affected_rows($this->_link);
$this->info = mysql_info($this->_link);
$this->affected_rows = mysql_affected_rows($this->link);
$this->info = mysql_info($this->link);
return true;
}
return new Result($result);
@@ -152,14 +152,14 @@ if (!defined('Adminer\DRIVER')) {
* @return bool
*/
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
/** Get current resultset
* @return Result
*/
function store_result() {
return $this->_result;
return $this->result;
}
/** Fetch next resultset
@@ -177,24 +177,19 @@ if (!defined('Adminer\DRIVER')) {
*/
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result || !$result->num_rows) {
return false;
}
return mysql_result($result->_result, 0, $field);
return ($result ? $result->fetch_column($field) : false);
}
}
class Result {
var
$num_rows, ///< @var int number of rows in the result
$_result, $_offset = 0 ///< @access private
;
public $num_rows; ///< @var int number of rows in the result
private $result, $offset = 0;
/** Constructor
* @param resource
*/
function __construct($result) {
$this->_result = $result;
$this->result = $result;
$this->num_rows = mysql_num_rows($result);
}
@@ -202,21 +197,29 @@ if (!defined('Adminer\DRIVER')) {
* @return array
*/
function fetch_assoc() {
return mysql_fetch_assoc($this->_result);
return mysql_fetch_assoc($this->result);
}
/** Fetch next row as numbered array
* @return array
*/
function fetch_row() {
return mysql_fetch_row($this->_result);
return mysql_fetch_row($this->result);
}
/** Fetch a single column
* @param int
* @return string or false if there are no rows
*/
function fetch_column($field) {
return ($this->num_rows ? mysql_result($this->result, 0, $field) : false);
}
/** Fetch next field
* @return object properties: name, type, orgtable, orgname, charsetnr
*/
function fetch_field() {
$return = mysql_fetch_field($this->_result, $this->_offset++); // offset required under certain conditions
$return = mysql_fetch_field($this->result, $this->offset++); // offset required under certain conditions
$return->orgtable = $return->table;
$return->orgname = $return->name;
$return->charsetnr = ($return->blob ? 63 : 0);
@@ -226,13 +229,13 @@ if (!defined('Adminer\DRIVER')) {
/** Free result set
*/
function __destruct() {
mysql_free_result($this->_result);
mysql_free_result($this->result);
}
}
} elseif (extension_loaded("pdo_mysql")) {
class Db extends PdoDb {
var $extension = "PDO_MySQL";
public $extension = "PDO_MySQL";
function connect($server, $username, $password) {
global $adminer;
@@ -284,10 +287,10 @@ if (!defined('Adminer\DRIVER')) {
static $possibleDrivers = array("MySQLi", "MySQL", "PDO_MySQL");
static $jush = "sql"; ///< @var string JUSH identifier
var $unsigned = array("unsigned", "zerofill", "unsigned zerofill");
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL");
var $functions = array("char_length", "date", "from_unixtime", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper");
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
public $unsigned = array("unsigned", "zerofill", "unsigned zerofill");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL");
public $functions = array("char_length", "date", "from_unixtime", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper");
public $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
@@ -327,6 +330,13 @@ if (!defined('Adminer\DRIVER')) {
}
}
function unconvertFunction($field) {
return (preg_match("~binary~", $field["type"]) ? "<code class='jush-sql'>UNHEX</code>"
: ($field["type"] == "bit" ? doc_link(array('sql' => 'bit-value-literals.html'), "<code>b''</code>")
: (preg_match("~geometry|point|linestring|polygon~", $field["type"]) ? "<code class='jush-sql'>GeomFromText</code>"
: "")));
}
function insert($table, $set) {
return ($set ? parent::insert($table, $set) : queries("INSERT INTO " . table($table) . " ()\nVALUES ()"));
}
@@ -358,7 +368,7 @@ if (!defined('Adminer\DRIVER')) {
function slowQuery($query, $timeout) {
if (min_version('5.7.8', '10.1.2')) {
if (preg_match('~MariaDB~', $this->_conn->server_info)) {
if ($this->conn->maria) {
return "SET STATEMENT max_statement_time=$timeout FOR $query";
} elseif (preg_match('~^(SELECT\b)(.+)~is', $query, $match)) {
return "$match[1] /*+ MAX_EXECUTION_TIME(" . ($timeout * 1000) . ") */ $match[2]";
@@ -368,13 +378,13 @@ if (!defined('Adminer\DRIVER')) {
function convertSearch($idf, $val, $field) {
return (preg_match('~char|text|enum|set~', $field["type"]) && !preg_match("~^utf8~", $field["collation"]) && preg_match('~[\x80-\xFF]~', $val['val'])
? "CONVERT($idf USING " . charset($this->_conn) . ")"
? "CONVERT($idf USING " . charset($this->conn) . ")"
: $idf
);
}
function warnings() {
$result = $this->_conn->query("SHOW WARNINGS");
$result = $this->conn->query("SHOW WARNINGS");
if ($result && $result->num_rows) {
ob_start();
select($result); // select() usually needs to print a big table progressively
@@ -383,7 +393,7 @@ if (!defined('Adminer\DRIVER')) {
}
function tableHelp($name, $is_view = false) {
$maria = preg_match('~MariaDB~', $this->_conn->server_info);
$maria = $this->conn->maria;
if (information_schema(DB)) {
return strtolower("information-schema-" . ($maria ? "$name-table/" : str_replace("_", "-", $name) . "-table.html"));
}
@@ -395,7 +405,7 @@ if (!defined('Adminer\DRIVER')) {
function hasCStyleEscapes() {
static $c_style;
if ($c_style === null) {
$sql_mode = $this->_conn->result("SHOW VARIABLES LIKE 'sql_mode'", 1);
$sql_mode = $this->conn->result("SHOW VARIABLES LIKE 'sql_mode'", 1);
$c_style = (strpos($sql_mode, 'NO_BACKSLASH_ESCAPES') === false);
}
return $c_style;
@@ -429,6 +439,7 @@ if (!defined('Adminer\DRIVER')) {
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
$connection->set_charset(charset($connection)); // available in MySQLi since PHP 5.0.5
$connection->query("SET sql_quote_show_create = 1, autocommit = 1");
$connection->maria = preg_match('~MariaDB~', $connection->server_info);
return $connection;
}
$return = $connection->error;
@@ -584,30 +595,45 @@ if (!defined('Adminer\DRIVER')) {
/** Get information about fields
* @param string
* @return array [$name => ["field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => , "generated" => ]]
* @return array [$name => ["field" =>, "full_type" =>, "type" =>, "length" =>, "unsigned" =>, "default" =>, "null" =>, "auto_increment" =>, "on_update" =>, "collation" =>, "privileges" =>, "comment" =>, "primary" =>, "generated" =>]]
*/
function fields($table) {
global $connection;
$maria = $connection->maria;
$return = array();
foreach (get_rows("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . q($table) . " ORDER BY ORDINAL_POSITION") as $row) {
$field = $row["COLUMN_NAME"];
$default = $row["COLUMN_DEFAULT"];
$type = $row["COLUMN_TYPE"];
$generation = $row["GENERATION_EXPRESSION"];
$extra = $row["EXTRA"];
// https://mariadb.com/kb/en/library/show-columns/, https://github.com/vrana/adminer/pull/359#pullrequestreview-276677186
preg_match('~^(VIRTUAL|PERSISTENT|STORED)~', $extra, $generated);
preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $type, $match);
preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $type, $match_type);
$default = $row["COLUMN_DEFAULT"];
if ($default != "") {
$is_text = preg_match('~text|json~', $match_type[1]);
if (!$maria && $is_text) {
// default value a'b of text column is stored as _utf8mb4\'a\\\'b\' in MySQL
$default = preg_replace("~^(_\w+)?('.*')$~", '\2', stripslashes($default));
}
if ($maria || $is_text) {
$default = ($default == "NULL" ? null : preg_replace_callback("~^'(.*)'$~", function ($match) {
return stripslashes(str_replace("''", "'", $match[1]));
}, $default));
}
if (!$maria && preg_match('~binary~', $match_type[1]) && preg_match('~^0x(\w*)$~', $default, $match)) {
$default = pack("H*", $match[1]);
}
}
$return[$field] = array(
"field" => $field,
"full_type" => $type,
"type" => $match[1],
"length" => $match[2],
"unsigned" => ltrim($match[3] . $match[4]),
"type" => $match_type[1],
"length" => $match_type[2],
"unsigned" => ltrim($match_type[3] . $match_type[4]),
"default" => ($generated
? $row["GENERATION_EXPRESSION"]
: ($default != "" || preg_match("~char|set~", $match[1])
? (preg_match('~text~', $match[1]) ? stripslashes(preg_replace("~^'(.*)'\$~", '\1', $default)) : $default)
: null
)
? ($maria ? $generation : stripslashes($generation))
: $default
),
"null" => ($row["IS_NULLABLE"] == "YES"),
"auto_increment" => ($extra == "auto_increment"),
@@ -649,7 +675,12 @@ if (!defined('Adminer\DRIVER')) {
$return = array();
$create_table = get_val("SHOW CREATE TABLE " . table($table), 1);
if ($create_table) {
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($driver->onActions))?(?: ON UPDATE ($driver->onActions))?~", $create_table, $matches, PREG_SET_ORDER);
preg_match_all(
"~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($driver->onActions))?(?: ON UPDATE ($driver->onActions))?~",
$create_table,
$matches,
PREG_SET_ORDER
);
foreach ($matches as $match) {
preg_match_all("~$pattern~", $match[2], $source);
preg_match_all("~$pattern~", $match[5], $target);
@@ -786,12 +817,14 @@ if (!defined('Adminer\DRIVER')) {
* @return bool
*/
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
global $connection;
$alter = array();
foreach ($fields as $field) {
if ($field[1]) {
$default = $field[1][3];
if (preg_match('~ GENERATED~', $default)) {
$field[1][3] = $field[1][2];
// swap default and null
$field[1][3] = ($connection->maria ? "" : $field[1][2]); // MariaDB doesn't support NULL on virtual columns
$field[1][2] = $default;
}
$alter[] = ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "");
@@ -967,7 +1000,9 @@ if (!defined('Adminer\DRIVER')) {
global $driver;
$aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar");
$space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
$type_pattern = "((" . implode("|", array_merge(array_keys($driver->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$driver->enumLength)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
$enum = $driver->enumLength;
$type_pattern = "((" . implode("|", array_merge(array_keys($driver->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum)++)\\))?"
. "\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : $driver->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
$create = get_val("SHOW CREATE $type " . idf_escape($name), 2);
preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match);
@@ -977,7 +1012,7 @@ if (!defined('Adminer\DRIVER')) {
$fields[] = array(
"field" => str_replace("``", "`", $param[2]) . $param[3],
"type" => strtolower($param[5]),
"length" => preg_replace_callback("~$driver->enumLength~s", 'Adminer\normalize_enum', $param[6]),
"length" => preg_replace_callback("~$enum~s", 'Adminer\normalize_enum', $param[6]),
"unsigned" => strtolower(preg_replace('~\s+~', ' ', trim("$param[8] $param[7]"))),
"null" => 1,
"full_type" => $param[4],
@@ -1177,7 +1212,7 @@ if (!defined('Adminer\DRIVER')) {
}
/** Check whether a feature is supported
* @param string "check", "comment", "copy", "database", "descidx", "drop_col", "dump", "event", "indexes", "kill", "materializedview", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "table", "trigger", "type", "variables", "view", "view_trigger"
* @param string "check|comment|copy|database|descidx|drop_col|dump|event|indexes|kill|materializedview|partitioning|privileges|procedure|processlist|routine|scheme|sequence|status|table|trigger|type|variables|view|view_trigger"
* @return bool
*/
function support($feature) {

View File

@@ -7,8 +7,9 @@ if (isset($_GET["oracle"])) {
define('Adminer\DRIVER', "oracle");
if (extension_loaded("oci8")) {
class Db {
var $extension = "oci8", $_link, $_result, $server_info, $affected_rows, $errno, $error;
var $_current_db;
public $extension = "oci8", $server_info, $affected_rows, $errno, $error;
public $_current_db;
private $link, $result;
function _error($errno, $error) {
if (ini_bool("html_errors")) {
@@ -19,9 +20,9 @@ if (isset($_GET["oracle"])) {
}
function connect($server, $username, $password) {
$this->_link = @oci_new_connect($username, $password, $server, "AL32UTF8");
if ($this->_link) {
$this->server_info = oci_server_version($this->_link);
$this->link = @oci_new_connect($username, $password, $server, "AL32UTF8");
if ($this->link) {
$this->server_info = oci_server_version($this->link);
return true;
}
$error = oci_error();
@@ -39,10 +40,10 @@ if (isset($_GET["oracle"])) {
}
function query($query, $unbuffered = false) {
$result = oci_parse($this->_link, $query);
$result = oci_parse($this->link, $query);
$this->error = "";
if (!$result) {
$error = oci_error($this->_link);
$error = oci_error($this->link);
$this->errno = $error["code"];
$this->error = $error["message"];
return false;
@@ -61,11 +62,11 @@ if (isset($_GET["oracle"])) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function store_result() {
return $this->_result;
return $this->result;
}
function next_result() {
@@ -74,21 +75,19 @@ if (isset($_GET["oracle"])) {
function result($query, $field = 0) {
$result = $this->query($query);
if (!is_object($result) || !oci_fetch($result->_result)) {
return false;
}
return oci_result($result->_result, $field + 1);
return (is_object($result) ? $result->fetch_column($field) : false);
}
}
class Result {
var $_result, $_offset = 1, $num_rows;
public $num_rows;
private $result, $offset = 1;
function __construct($result) {
$this->_result = $result;
$this->result = $result;
}
function _convert($row) {
private function convert($row) {
foreach ((array) $row as $key => $val) {
if (is_a($val, 'OCI-Lob')) {
$row[$key] = $val->load();
@@ -98,32 +97,36 @@ if (isset($_GET["oracle"])) {
}
function fetch_assoc() {
return $this->_convert(oci_fetch_assoc($this->_result));
return $this->convert(oci_fetch_assoc($this->result));
}
function fetch_row() {
return $this->_convert(oci_fetch_row($this->_result));
return $this->convert(oci_fetch_row($this->result));
}
function fetch_column($field) {
return (oci_fetch($this->result) ? oci_result($this->result, $field + 1) : false);
}
function fetch_field() {
$column = $this->_offset++;
$column = $this->offset++;
$return = new \stdClass;
$return->name = oci_field_name($this->_result, $column);
$return->name = oci_field_name($this->result, $column);
$return->orgname = $return->name;
$return->type = oci_field_type($this->_result, $column);
$return->type = oci_field_type($this->result, $column);
$return->charsetnr = (preg_match("~raw|blob|bfile~", $return->type) ? 63 : 0); // 63 - binary
return $return;
}
function __destruct() {
oci_free_statement($this->_result);
oci_free_statement($this->result);
}
}
} elseif (extension_loaded("pdo_oci")) {
class Db extends PdoDb {
var $extension = "PDO_OCI";
var $_current_db;
public $extension = "PDO_OCI";
public $_current_db;
function connect($server, $username, $password) {
$this->dsn("oci:dbname=//$server;charset=AL32UTF8", $username, $password);
@@ -144,7 +147,7 @@ if (isset($_GET["oracle"])) {
static $possibleDrivers = array("OCI8", "PDO_OCI");
static $jush = "oracle";
var $editFunctions = array(
public $editFunctions = array(
array( //! no parentheses
"date" => "current_date",
"timestamp" => "current_timestamp",
@@ -155,9 +158,9 @@ if (isset($_GET["oracle"])) {
)
);
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL");
var $functions = array("length", "lower", "round", "upper");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL");
public $functions = array("length", "lower", "round", "upper");
public $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
@@ -518,7 +521,16 @@ AND c_src.TABLE_NAME = " . q($table);
}
function process_list() {
return get_rows('SELECT sess.process AS "process", sess.username AS "user", sess.schemaname AS "schema", sess.status AS "status", sess.wait_class AS "wait_class", sess.seconds_in_wait AS "seconds_in_wait", sql.sql_text AS "sql_text", sess.machine AS "machine", sess.port AS "port"
return get_rows('SELECT
sess.process AS "process",
sess.username AS "user",
sess.schemaname AS "schema",
sess.status AS "status",
sess.wait_class AS "wait_class",
sess.seconds_in_wait AS "seconds_in_wait",
sql.sql_text AS "sql_text",
sess.machine AS "machine",
sess.port AS "port"
FROM v$session sess LEFT OUTER JOIN v$sql sql
ON sql.sql_id = sess.sql_id
WHERE sess.type = \'USER\'

View File

@@ -7,7 +7,8 @@ if (isset($_GET["pgsql"])) {
define('Adminer\DRIVER', "pgsql");
if (extension_loaded("pgsql")) {
class Db {
var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error, $timeout;
public $extension = "PgSQL", $server_info, $affected_rows, $error, $timeout;
private $link, $result, $string, $database = true;
function _error($errno, $error) {
if (ini_bool("html_errors")) {
@@ -21,59 +22,58 @@ if (isset($_GET["pgsql"])) {
global $adminer;
$db = $adminer->database();
set_error_handler(array($this, '_error'));
$this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
$this->string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
$ssl = $adminer->connectSsl();
if (isset($ssl["mode"])) {
$this->_string .= " sslmode='" . $ssl["mode"] . "'";
$this->string .= " sslmode='" . $ssl["mode"] . "'";
}
$this->_link = @pg_connect("$this->_string dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'", PGSQL_CONNECT_FORCE_NEW);
if (!$this->_link && $db != "") {
$this->link = @pg_connect("$this->string dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'", PGSQL_CONNECT_FORCE_NEW);
if (!$this->link && $db != "") {
// try to connect directly with database for performance
$this->_database = false;
$this->_link = @pg_connect("$this->_string dbname='postgres'", PGSQL_CONNECT_FORCE_NEW);
$this->database = false;
$this->link = @pg_connect("$this->string dbname='postgres'", PGSQL_CONNECT_FORCE_NEW);
}
restore_error_handler();
if ($this->_link) {
$version = pg_version($this->_link);
if ($this->link) {
$version = pg_version($this->link);
$this->server_info = $version["server"];
pg_set_client_encoding($this->_link, "UTF8");
pg_set_client_encoding($this->link, "UTF8");
}
return (bool) $this->_link;
return (bool) $this->link;
}
function quote($string) {
return pg_escape_literal($this->_link, $string);
return (function_exists('pg_escape_literal')
? pg_escape_literal($this->link, $string) // available since PHP 5.4.4
: "'" . pg_escape_string($this->link, $string) . "'"
);
}
function value($val, $field) {
return ($field["type"] == "bytea" && $val !== null ? pg_unescape_bytea($val) : $val);
}
function quoteBinary($string) {
return "'" . pg_escape_bytea($this->_link, $string) . "'";
}
function select_db($database) {
global $adminer;
if ($database == $adminer->database()) {
return $this->_database;
return $this->database;
}
$return = @pg_connect("$this->_string dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
$return = @pg_connect("$this->string dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
if ($return) {
$this->_link = $return;
$this->link = $return;
}
return $return;
}
function close() {
$this->_link = @pg_connect("$this->_string dbname='postgres'");
$this->link = @pg_connect("$this->string dbname='postgres'");
}
function query($query, $unbuffered = false) {
$result = @pg_query($this->_link, $query);
$result = @pg_query($this->link, $query);
$this->error = "";
if (!$result) {
$this->error = pg_last_error($this->_link);
$this->error = pg_last_error($this->link);
$return = false;
} elseif (!pg_num_fields($result)) {
$this->affected_rows = pg_affected_rows($result);
@@ -89,11 +89,11 @@ if (isset($_GET["pgsql"])) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function store_result() {
return $this->_result;
return $this->result;
}
function next_result() {
@@ -103,54 +103,56 @@ if (isset($_GET["pgsql"])) {
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result || !$result->num_rows) {
return false;
}
return pg_fetch_result($result->_result, 0, $field);
return ($result ? $result->fetch_column($field) : false);
}
function warnings() {
return h(pg_last_notice($this->_link)); // second parameter is available since PHP 7.1.0
return h(pg_last_notice($this->link)); // second parameter is available since PHP 7.1.0
}
}
class Result {
var $_result, $_offset = 0, $num_rows;
public $num_rows;
private $result, $offset = 0;
function __construct($result) {
$this->_result = $result;
$this->result = $result;
$this->num_rows = pg_num_rows($result);
}
function fetch_assoc() {
return pg_fetch_assoc($this->_result);
return pg_fetch_assoc($this->result);
}
function fetch_row() {
return pg_fetch_row($this->_result);
return pg_fetch_row($this->result);
}
function fetch_column($field) {
return ($this->num_rows ? pg_fetch_result($this->result, 0, $field) : false);
}
function fetch_field() {
$column = $this->_offset++;
$column = $this->offset++;
$return = new \stdClass;
if (function_exists('pg_field_table')) {
$return->orgtable = pg_field_table($this->_result, $column);
$return->orgtable = pg_field_table($this->result, $column);
}
$return->name = pg_field_name($this->_result, $column);
$return->name = pg_field_name($this->result, $column);
$return->orgname = $return->name;
$return->type = pg_field_type($this->_result, $column);
$return->type = pg_field_type($this->result, $column);
$return->charsetnr = ($return->type == "bytea" ? 63 : 0); // 63 - binary
return $return;
}
function __destruct() {
pg_free_result($this->_result);
pg_free_result($this->result);
}
}
} elseif (extension_loaded("pdo_pgsql")) {
class Db extends PdoDb {
var $extension = "PDO_PgSQL", $timeout;
public $extension = "PDO_PgSQL", $timeout;
function connect($server, $username, $password) {
global $adminer;
@@ -170,10 +172,6 @@ if (isset($_GET["pgsql"])) {
return ($adminer->database() == $database);
}
function quoteBinary($s) {
return q($s);
}
function query($query, $unbuffered = false) {
$return = parent::query($query, $unbuffered);
if ($this->timeout) {
@@ -199,9 +197,9 @@ if (isset($_GET["pgsql"])) {
static $possibleDrivers = array("PgSQL", "PDO_PgSQL");
static $jush = "pgsql";
var $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
var $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
public $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
public $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
@@ -265,8 +263,8 @@ if (isset($_GET["pgsql"])) {
}
function slowQuery($query, $timeout) {
$this->_conn->query("SET statement_timeout = " . (1000 * $timeout));
$this->_conn->timeout = 1000 * $timeout;
$this->conn->query("SET statement_timeout = " . (1000 * $timeout));
$this->conn->timeout = 1000 * $timeout;
return $query;
}
@@ -280,11 +278,11 @@ if (isset($_GET["pgsql"])) {
}
function quoteBinary($s) {
return $this->_conn->quoteBinary($s);
return "'\\x" . bin2hex($s) . "'"; // available since PostgreSQL 8.1
}
function warnings() {
return $this->_conn->warnings();
return $this->conn->warnings();
}
function tableHelp($name, $is_view = false) {
@@ -299,13 +297,14 @@ if (isset($_GET["pgsql"])) {
}
function supportsIndex($table_status) {
// returns true for "materialized view"
return $table_status["Engine"] != "view";
}
function hasCStyleEscapes() {
static $c_style;
if ($c_style === null) {
$c_style = ($this->_conn->result("SHOW standard_conforming_strings") == "off");
$c_style = ($this->conn->result("SHOW standard_conforming_strings") == "off");
}
return $c_style;
}
@@ -327,6 +326,8 @@ if (isset($_GET["pgsql"])) {
if (min_version(9, 0, $connection)) {
$connection->query("SET application_name = 'Adminer'");
}
$crdb_version = $connection->result("SHOW crdb_version");
$connection->server_info .= ($crdb_version ? "-" . preg_replace('~ \(.*~', '', $crdb_version) : "");
return $connection;
}
return $connection->error;
@@ -428,7 +429,14 @@ WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
'timestamp with time zone' => 'timestamptz',
);
foreach (
get_rows("SELECT a.attname AS field, format_type(a.atttypid, a.atttypmod) AS full_type, pg_get_expr(d.adbin, d.adrelid) AS default, a.attnotnull::int, col_description(c.oid, a.attnum) AS comment" . (min_version(10) ? ", a.attidentity" . (min_version(12) ? ", a.attgenerated" : "") : "") . "
get_rows("SELECT
a.attname AS field,
format_type(a.atttypid, a.atttypmod) AS full_type,
pg_get_expr(d.adbin, d.adrelid) AS default,
a.attnotnull::int,
col_description(c.oid, a.attnum) AS comment" . (min_version(10) ? ",
a.attidentity" . (min_version(12) ? ",
a.attgenerated" : "") : "") . "
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
JOIN pg_attribute a ON c.oid = a.attrelid
@@ -456,8 +464,9 @@ ORDER BY a.attnum") as $row
}
$row["generated"] = ($row["attgenerated"] == "s" ? "STORED" : "");
$row["null"] = !$row["attnotnull"];
$row["auto_increment"] = $row['attidentity'] || preg_match('~^nextval\(~i', $row["default"]);
$row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1);
$row["auto_increment"] = $row['attidentity'] || preg_match('~^nextval\(~i', $row["default"])
|| preg_match('~^unique_rowid\(~', $row["default"]); // CockroachDB
$row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1, "where" => 1, "order" => 1);
if (preg_match('~(.+)::[^,)]+(.*)~', $row["default"], $match)) {
$row["default"] = ($match[1] == "NULL" ? null : idf_unescape($match[1]) . $match[2]);
}
@@ -474,7 +483,12 @@ ORDER BY a.attnum") as $row
$return = array();
$table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($table));
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
foreach (get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row) {
foreach (
get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial
FROM pg_index i, pg_class ci
WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid
ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row
) {
$relname = $row["relname"];
$return[$relname]["type"] = ($row["indispartial"] ? "INDEX" : ($row["indisprimary"] ? "PRIMARY" : ($row["indisunique"] ? "UNIQUE" : "INDEX")));
$return[$relname]["columns"] = array();
@@ -658,7 +672,6 @@ ORDER BY conkey, conname") as $row
function truncate_tables($tables) {
return queries("TRUNCATE " . implode(", ", array_map('Adminer\table', $tables)));
return true;
}
function drop_views($views) {
@@ -695,7 +708,12 @@ ORDER BY conkey, conname") as $row
$columns[] = $row["event_object_column"];
}
$return = array();
foreach (get_rows('SELECT trigger_name AS "Trigger", action_timing AS "Timing", event_manipulation AS "Event", \'FOR EACH \' || action_orientation AS "Type", action_statement AS "Statement" FROM information_schema.triggers ' . "$where ORDER BY event_manipulation DESC") as $row) {
foreach (
get_rows('SELECT trigger_name AS "Trigger", action_timing AS "Timing", event_manipulation AS "Event", \'FOR EACH \' || action_orientation AS "Type", action_statement AS "Statement"
FROM information_schema.triggers' . "
$where
ORDER BY event_manipulation DESC") as $row
) {
if ($columns && $row["Event"] == "UPDATE") {
$row["Event"] .= " OF";
}
@@ -935,7 +953,11 @@ AND typelem = 0"
}
function support($feature) {
return preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature);
global $connection;
return ($feature == "processlist"
? !preg_match('~CockroachDB~', $connection->server_info) // https://github.com/cockroachdb/cockroach/issues/24745
: preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature)
);
}
function kill_process($val) {

View File

@@ -8,37 +8,38 @@ if (isset($_GET["sqlite"])) {
if (class_exists("SQLite3")) {
class SqliteDb {
var $extension = "SQLite3", $server_info, $affected_rows, $errno, $error, $_link;
public $extension = "SQLite3", $server_info, $affected_rows, $errno, $error;
private $link;
function __construct($filename) {
$this->_link = new \SQLite3($filename);
$version = $this->_link->version();
$this->link = new \SQLite3($filename);
$version = $this->link->version();
$this->server_info = $version["versionString"];
}
function query($query) {
$result = @$this->_link->query($query);
$result = @$this->link->query($query);
$this->error = "";
if (!$result) {
$this->errno = $this->_link->lastErrorCode();
$this->error = $this->_link->lastErrorMsg();
$this->errno = $this->link->lastErrorCode();
$this->error = $this->link->lastErrorMsg();
return false;
} elseif ($result->numColumns()) {
return new Result($result);
}
$this->affected_rows = $this->_link->changes();
$this->affected_rows = $this->link->changes();
return true;
}
function quote($string) {
return (is_utf8($string)
? "'" . $this->_link->escapeString($string) . "'"
? "'" . $this->link->escapeString($string) . "'"
: "x'" . reset(unpack('H*', $string)) . "'"
);
}
function store_result() {
return $this->_result;
return $this->result;
}
function result($query, $field = 0) {
@@ -46,44 +47,45 @@ if (isset($_GET["sqlite"])) {
if (!is_object($result)) {
return false;
}
$row = $result->_result->fetchArray();
$row = $result->fetch_row();
return $row ? $row[$field] : false;
}
}
class Result {
var $_result, $_offset = 0, $num_rows;
public $num_rows;
private $result, $offset = 0;
function __construct($result) {
$this->_result = $result;
$this->result = $result;
}
function fetch_assoc() {
return $this->_result->fetchArray(SQLITE3_ASSOC);
return $this->result->fetchArray(SQLITE3_ASSOC);
}
function fetch_row() {
return $this->_result->fetchArray(SQLITE3_NUM);
return $this->result->fetchArray(SQLITE3_NUM);
}
function fetch_field() {
$column = $this->_offset++;
$type = $this->_result->columnType($column);
$column = $this->offset++;
$type = $this->result->columnType($column);
return (object) array(
"name" => $this->_result->columnName($column),
"name" => $this->result->columnName($column),
"type" => $type,
"charsetnr" => ($type == SQLITE3_BLOB ? 63 : 0), // 63 - binary
);
}
function __desctruct() {
return $this->_result->finalize();
function __destruct() {
return $this->result->finalize();
}
}
} elseif (extension_loaded("pdo_sqlite")) {
class SqliteDb extends PdoDb {
var $extension = "PDO_SQLite";
public $extension = "PDO_SQLite";
function __construct($filename) {
$this->dsn(DRIVER . ":$filename", "", "");
@@ -115,7 +117,7 @@ if (isset($_GET["sqlite"])) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function next_result() {
@@ -132,7 +134,7 @@ if (isset($_GET["sqlite"])) {
protected $types = array(array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0));
var $editFunctions = array(
public $editFunctions = array(
array(
// "text" => "date('now')/time('now')/datetime('now')",
), array(
@@ -142,9 +144,9 @@ if (isset($_GET["sqlite"])) {
)
);
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"); // REGEXP can be user defined function
var $functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"); // REGEXP can be user defined function
public $functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
public $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
@@ -175,7 +177,7 @@ if (isset($_GET["sqlite"])) {
}
function checkConstraints($table) {
preg_match_all('~ CHECK *(\( *(((?>[^()]*[^() ])|(?1))*) *\))~', $this->_conn->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table)), $matches); //! could be inside a comment
preg_match_all('~ CHECK *(\( *(((?>[^()]*[^() ])|(?1))*) *\))~', $this->conn->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table)), $matches); //! could be inside a comment
return array_combine($matches[2], $matches[2]);
}
}

View File

@@ -140,9 +140,7 @@ SET foreign_key_checks = 0;
}
}
if ($is_sql) {
echo "-- " . gmdate("Y-m-d H:i:s e") . "\n";
}
$adminer->dumpFooter();
exit;
}
@@ -167,9 +165,9 @@ if (!isset($row["events"])) { // backwards compatibility
$row["triggers"] = $row["table_style"];
}
echo "<tr><th>" . lang('Output') . "<td>" . html_select("output", $adminer->dumpOutput(), $row["output"], 0) . "\n"; // 0 - radio
echo "<tr><th>" . lang('Output') . "<td>" . html_radios("output", $adminer->dumpOutput(), $row["output"]) . "\n";
echo "<tr><th>" . lang('Format') . "<td>" . html_select("format", $adminer->dumpFormat(), $row["format"], 0) . "\n"; // 0 - radio
echo "<tr><th>" . lang('Format') . "<td>" . html_radios("format", $adminer->dumpFormat(), $row["format"]) . "\n";
echo (JUSH == "sqlite" ? "" : "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"])
. (support("type") ? checkbox("types", 1, $row["types"], lang('User types')) : "")

View File

@@ -68,13 +68,7 @@ if ($_POST["save"]) {
$select = array();
foreach ($fields as $name => $field) {
if (isset($field["privileges"]["select"])) {
$as = convert_field($field);
if ($_POST["clone"] && $field["auto_increment"]) {
$as = "''";
}
if (JUSH == "sql" && preg_match("~enum|set~", $field["type"])) {
$as = "1*" . idf_escape($name);
}
$as = ($_POST["clone"] && $field["auto_increment"] ? "''" : convert_field($field));
$select[] = ($as ? "$as AS " : "") . idf_escape($name);
}
}

View File

@@ -2,8 +2,13 @@
// To create Adminer just for Elasticsearch, run `../compile.php elastic`.
function adminer_object() {
include_once "../plugins/plugin.php";
include_once "../plugins/login-password-less.php";
include_once "../plugins/drivers/elastic.php";
return new Adminer\Adminer;
return new AdminerPlugin(array(
// TODO: inline the result of password_hash() so that the password is not visible in source codes
new AdminerLoginPasswordLess(password_hash("YOUR_PASSWORD_HERE", PASSWORD_DEFAULT)),
));
}
include "./index.php";

View File

@@ -9,6 +9,9 @@ if ($_GET["file"] == "favicon.ico") {
} elseif ($_GET["file"] == "default.css") {
header("Content-Type: text/css; charset=utf-8");
echo lzw_decompress(compile_file('../adminer/static/default.css;../externals/jush/jush.css', 'minify_css'));
} elseif ($_GET["file"] == "dark.css") {
header("Content-Type: text/css; charset=utf-8");
echo lzw_decompress(compile_file('../adminer/static/dark.css', 'minify_css'));
} elseif ($_GET["file"] == "functions.js") {
header("Content-Type: text/javascript; charset=utf-8");
echo lzw_decompress(compile_file('../adminer/static/functions.js;static/editing.js', 'minify_js'));

View File

@@ -94,8 +94,8 @@ if (support("scheme")) {
$j = 0;
foreach ($row["source"] as $key => $val) {
echo "<tr>";
echo "<td>" . html_select("source[" . (+$key) . "]", array(-1 => "") + $source, $val, ($j == count($row["source"]) - 1 ? "foreignAddRow.call(this);" : 1), "label-source");
echo "<td>" . html_select("target[" . (+$key) . "]", $target, $row["target"][$key], 1, "label-target");
echo "<td>" . html_select("source[" . (+$key) . "]", array(-1 => "") + $source, $val, ($j == count($row["source"]) - 1 ? "foreignAddRow.call(this);" : ""), "label-source");
echo "<td>" . html_select("target[" . (+$key) . "]", $target, $row["target"][$key], "", "label-target");
$j++;
}
?>

View File

@@ -5,7 +5,7 @@ namespace Adminer;
class Adminer {
/** @var array operators used in select, null for all operators */
var $operators;
public $operators;
/** Name in title and navigation
* @return string HTML code
@@ -98,7 +98,7 @@ class Adminer {
*/
function head() {
?>
<link rel="stylesheet" type="text/css" href="../externals/jush/jush.css">
<link rel="stylesheet" href="../externals/jush/jush.css">
<?php
return true;
}
@@ -289,13 +289,14 @@ class Adminer {
* @return string
*/
function selectVal($val, $link, $field, $original) {
$return = ($val === null ? "<i>NULL</i>" : (preg_match("~char|binary|boolean~", $field["type"]) && !preg_match("~var~", $field["type"]) ? "<code>$val</code>" : $val));
$return = ($val === null ? "<i>NULL</i>"
: (preg_match("~char|binary|boolean~", $field["type"]) && !preg_match("~var~", $field["type"]) ? "<code>$val</code>"
: (preg_match('~json~', $field["type"]) ? "<code class='jush-js'>$val</code>"
: $val)
));
if (preg_match('~blob|bytea|raw|file~', $field["type"]) && !is_utf8($val)) {
$return = "<i>" . lang('%d byte(s)', strlen($original)) . "</i>";
}
if (preg_match('~json~', $field["type"])) {
$return = "<code class='jush-js'>$return</code>";
}
return ($link ? "<a href='" . h($link) . "'" . (is_url($link) ? target_blank() : "") . ">$return</a>" : $return);
}
@@ -937,11 +938,23 @@ class Adminer {
($ext == "sql" || $output != "file" ? "text/plain" : "text/csv") . "; charset=utf-8"
)));
if ($output == "gz") {
ob_start('ob_gzencode', 1e6);
ob_start(function ($string) {
// ob_start() callback receives an optional parameter $phase but gzencode() accepts optional parameter $level
return gzencode($string);
}, 1e6);
}
return $ext;
}
/** Print text after export
* @return null prints data
*/
function dumpFooter() {
if ($_POST["format"] == "sql") {
echo "-- " . gmdate("Y-m-d H:i:s e") . "\n";
}
}
/** Set the path of the file for webserver load
* @return string path of the sql dump file
*/
@@ -1018,9 +1031,8 @@ class Adminer {
echo "jushLinks.$val = jushLinks." . JUSH . ";\n";
}
}
$server_info = $connection->server_info;
?>
bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '\1', $server_info) : ""); ?>'<?php echo (preg_match('~MariaDB~', $server_info) ? ", true" : ""); ?>);
bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '\1', $connection->server_info) : ""); ?>'<?php echo ($connection->maria ? ", true" : ""); ?>);
</script>
<?php
}
@@ -1064,14 +1076,14 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
<?php
hidden_fields_get();
$db_events = script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");
echo "<span title='" . lang('Database') . "'>" . lang('DB') . "</span>: " . ($databases
echo "<span title='" . lang('Database') . "'>" . lang('DB') . ":</span> " . ($databases
? html_select("db", array("" => "") + $databases, DB) . $db_events
: "<input name='db' value='" . h(DB) . "' autocapitalize='off' size='19'>\n"
);
echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n";
if (support("scheme")) {
if ($missing != "db" && DB != "" && $connection->select_db(DB)) {
echo "<br>" . lang('Schema') . ": " . html_select("ns", array("" => "") + $adminer->schemas(), $_GET["ns"]) . $db_events;
echo "<br><span>" . lang('Schema') . ":</span> " . html_select("ns", array("" => "") + $adminer->schemas(), $_GET["ns"]) . $db_events;
if ($_GET["ns"] != "") {
set_schema($_GET["ns"]);
}

View File

@@ -62,7 +62,6 @@ if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) {
set_magic_quotes_runtime(false);
}
@set_time_limit(0); // @ - can be disabled
@ini_set("zend.ze1_compatibility_mode", false); // @ - deprecated
@ini_set("precision", 15); // @ - can be disabled, 15 - internal PHP precision
include "../adminer/include/lang.inc.php";
@@ -73,7 +72,6 @@ include "../adminer/drivers/sqlite.inc.php";
include "../adminer/drivers/pgsql.inc.php";
include "../adminer/drivers/oracle.inc.php";
include "../adminer/drivers/mssql.inc.php";
include "../adminer/drivers/mongo.inc.php";
include "./include/adminer.inc.php";
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver

View File

@@ -8,7 +8,13 @@ if (isset($_GET["import"])) {
$_GET["sql"] = $_GET["import"];
}
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
if (
!(DB != ""
? $connection->select_db(DB)
: isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"])
|| $_GET["script"] == "connect" || $_GET["script"] == "kill"
)
) {
if (DB != "" || $_GET["refresh"]) {
restart_session();
set_session("dbs", null);

View File

@@ -28,15 +28,22 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
<meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width">
<title><?php echo $title_page; ?></title>
<link rel="stylesheet" type="text/css" href="../adminer/static/default.css">
<?php echo script_src("../adminer/static/functions.js"); ?>
<?php echo script_src("static/editing.js"); ?>
<link rel="stylesheet" href="../adminer/static/default.css">
<?php
$css = $adminer->css();
if ($css) {
foreach ($css as $val) {
echo "<link rel='stylesheet' href='" . h($val) . "'>\n";
}
} else {
echo "<link rel='stylesheet' media='(prefers-color-scheme: dark)' href='../adminer/static/dark.css'>\n";
}
echo script_src("../adminer/static/functions.js");
echo script_src("static/editing.js");
?>
<?php if ($adminer->head()) { ?>
<link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico">
<link rel="apple-touch-icon" href="../adminer/static/favicon.ico">
<?php foreach ($adminer->css() as $css) { ?>
<link rel="stylesheet" type="text/css" href="<?php echo h($css); ?>">
<?php } ?>
<?php } ?>
<body class="<?php echo lang('ltr'); ?> nojs">

View File

@@ -13,36 +13,35 @@ function add_driver($id, $name) {
$drivers[$id] = $name;
}
/** Get driver name
* @param string
* @return string
/** Get driver
* @return Driver
*/
function get_driver($id) {
global $drivers;
return $drivers[$id];
function get_driver() {
global $driver;
return $driver;
}
abstract class SqlDriver {
static $possibleDrivers = array();
static $jush; ///< @var string JUSH identifier
var $_conn;
protected $conn;
protected $types = array(); ///< @var array [$description => [$type => $maximum_unsigned_length, ...], ...]
var $editFunctions = array(); ///< @var array of ["$type|$type2" => "$function/$function2"] functions used in editing, [0] - edit and insert, [1] - edit only
var $unsigned = array(); ///< @var array number variants
var $operators = array(); ///< @var array operators used in select
var $functions = array(); ///< @var array functions used in select
var $grouping = array(); ///< @var array grouping functions used in select
var $onActions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()
var $inout = "IN|OUT|INOUT";
var $enumLength = "'(?:''|[^'\\\\]|\\\\.)*'";
var $generated = array();
public $editFunctions = array(); ///< @var array of ["$type|$type2" => "$function/$function2"] functions used in editing, [0] - edit and insert, [1] - edit only
public $unsigned = array(); ///< @var array number variants
public $operators = array(); ///< @var array operators used in select
public $functions = array(); ///< @var array functions used in select
public $grouping = array(); ///< @var array grouping functions used in select
public $onActions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()
public $inout = "IN|OUT|INOUT"; ///< @var string used in routines
public $enumLength = "'(?:''|[^'\\\\]|\\\\.)*'"; ///< @var string regular expression for parsing enum lengths
public $generated = array(); ///< @var array allowed types of generated columns
/** Create object for performing database operations
* @param Db
*/
function __construct($connection) {
$this->_conn = $connection;
$this->conn = $connection;
}
/** Get all types
@@ -66,6 +65,13 @@ abstract class SqlDriver {
function enumLength($field) {
}
/** Function used to convert the value inputted by user
* @param array
* @return string or null
*/
function unconvertFunction($field) {
}
/** Select data from table
* @param string
* @param array result of $adminer->selectColumnsProcess()[0]
@@ -91,7 +97,7 @@ abstract class SqlDriver {
);
}
$start = microtime(true);
$return = $this->_conn->query($query);
$return = $this->conn->query($query);
if ($print) {
echo $adminer->selectQuery($query, $start, !$return);
}
@@ -201,8 +207,8 @@ abstract class SqlDriver {
* @return string
*/
function value($val, $field) {
return (method_exists($this->_conn, 'value')
? $this->_conn->value($val, $field)
return (method_exists($this->conn, 'value')
? $this->conn->value($val, $field)
: (is_resource($val) ? stream_get_contents($val) : $val)
);
}

View File

@@ -224,13 +224,19 @@ function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_ty
size="3"
<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); //! type="number" with enabled JavaScript ?>
aria-labelledby="label-length"><td class="options"><?php
echo ($collations ? "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>' : '');
echo ($collations
? "<input list='collations' name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . " value='" . h($field["collation"]) . "' placeholder='(" . lang('collation') . ")'>"
: ''
);
echo ($driver->unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($driver->unsigned, $field["unsigned"]) . '</select>' : '');
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"), (preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"]) ? "CURRENT_TIMESTAMP" : $field["on_update"]))
. '</select>' : ''
);
echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $driver->onActions), $field["on_delete"]) . "</select> " : " "); // space for IE
echo ($foreign_keys
? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $driver->onActions), $field["on_delete"]) . "</select> "
: " " // space for IE
);
}
/** Get partition info
@@ -307,8 +313,8 @@ function default_value($field) {
$generated = $field["generated"];
return ($default === null ? "" : (in_array($generated, $driver->generated)
? (JUSH == "mssql" ? " AS ($default)" . ($generated == "VIRTUAL" ? "" : " $generated") . "" : " GENERATED ALWAYS AS ($default) $generated")
: " DEFAULT " . (!preg_match('~^GENERATED ~i', $default) && (preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default))
? q($default)
: " DEFAULT " . (!preg_match('~^GENERATED ~i', $default) && (preg_match('~char|binary|text|json|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default))
? (JUSH == "sql" && preg_match('~text|json~', $field["type"]) ? "(" . q($default) . ")" : q($default)) // MySQL requires () around default value of text column
: str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", (JUSH == "sqlite" ? "($default)" : $default))
)
));
@@ -624,22 +630,13 @@ function doc_link($paths, $text = "<sup>?</sup>") {
'mssql' => "https://learn.microsoft.com/en-us/sql/",
'oracle' => "https://www.oracle.com/pls/topic/lookup?ctx=db" . preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s', '\1\2', $server_info) . "&id=",
);
if (preg_match('~MariaDB~', $server_info)) {
if ($connection->maria) {
$urls['sql'] = "https://mariadb.com/kb/en/";
$paths['sql'] = (isset($paths['mariadb']) ? $paths['mariadb'] : str_replace(".html", "/", $paths['sql']));
}
return ($paths[JUSH] ? "<a href='" . h($urls[JUSH] . $paths[JUSH] . (JUSH == 'mssql' ? "?view=sql-server-ver$version" : "")) . "'" . target_blank() . ">$text</a>" : "");
}
/** Wrap gzencode() for usage in ob_start()
* @param string
* @return string
*/
function ob_gzencode($string) {
// ob_start() callback receives an optional parameter $phase but gzencode() accepts optional parameter $level
return gzencode($string);
}
/** Compute size of database
* @param string
* @return string formatted

View File

@@ -217,22 +217,29 @@ function optionlist($options, $selected = null, $use_keys = false) {
return $return;
}
/** Generate HTML <select>
* @param string
* @param array
* @param string
* @param string
* @param string
* @return string
*/
function html_select($name, $options, $value = "", $onchange = "", $labelled_by = "") {
return "<select name='" . h($name) . "'"
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
. ">" . optionlist($options, $value) . "</select>"
. ($onchange ? script("qsl('select').onchange = function () { $onchange };", "") : "")
;
}
/** Generate HTML radio list
* @param string
* @param array
* @param string
* @param string true for no onchange, false for radio
* @param string
* @return string
*/
function html_select($name, $options, $value = "", $onchange = true, $labelled_by = "") {
if ($onchange) {
return "<select name='" . h($name) . "'"
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
. ">" . optionlist($options, $value) . "</select>"
. (is_string($onchange) ? script("qsl('select').onchange = function () { $onchange };", "") : "")
;
}
function html_radios($name, $options, $value = "") {
$return = "";
foreach ($options as $key => $val) {
$return .= "<label><input type='radio' name='" . h($name) . "' value='" . h($key) . "'" . ($key == $value ? " checked" : "") . ">" . h($val) . "</label>";
@@ -452,14 +459,15 @@ function where($where, $fields = array()) {
foreach ((array) $where["where"] as $key => $val) {
$key = bracket_escape($key, 1); // 1 - back
$column = escape_key($key);
$field_type = $fields[$key]["type"];
$return[] = $column
. (JUSH == "sql" && $fields[$key]["type"] == "json" ? " = CAST(" . q($val) . " AS JSON)"
. (JUSH == "sql" && $field_type == "json" ? " = CAST(" . q($val) . " AS JSON)"
: (JUSH == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
: (JUSH == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text
: (JUSH == "mssql" && strpos($field_type, "datetime") === false ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text but it does not work with datetime
: " = " . unconvert_field($fields[$key], q($val))
)))
; //! enum and set
if (JUSH == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
if (JUSH == "sql" && preg_match('~char|text~', $field_type) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
$return[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin";
}
}
@@ -728,9 +736,10 @@ function pagination($page, $current) {
/** Get file contents from $_FILES
* @param string
* @param bool
* @param string
* @return mixed int for error, string otherwise
*/
function get_file($key, $decompress = false) {
function get_file($key, $decompress = false, $delimiter = "") {
$file = $_FILES[$key];
if (!$file) {
return null;
@@ -752,17 +761,17 @@ function get_file($key, $decompress = false) {
); //! may not be reachable because of open_basedir
if ($decompress) {
$start = substr($content, 0, 3);
if (function_exists("iconv") && preg_match("~^\xFE\xFF|^\xFF\xFE~", $start, $regs)) { // not ternary operator to save memory
if (function_exists("iconv") && preg_match("~^\xFE\xFF|^\xFF\xFE~", $start)) { // not ternary operator to save memory
$content = iconv("utf-16", "utf-8", $content);
} elseif ($start == "\xEF\xBB\xBF") { // UTF-8 BOM
$content = substr($content, 3);
}
$return .= $content . "\n\n";
} else {
$return .= $content;
}
$return .= $content;
if ($delimiter) {
$return .= (preg_match("($delimiter\\s*\$)", $content) ? "" : $delimiter) . "\n\n";
}
}
//! support SQL files not ending with semicolon
return $return;
}
@@ -883,18 +892,18 @@ function column_foreign_keys($table) {
* @param string "radio"|"checkbox"
* @param string
* @param array
* @param mixed int|string|array
* @param mixed string|array
* @param string
* @return null
*/
function enum_input($type, $attrs, $field, $value, $empty = null) {
global $adminer;
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
$return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === 0) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
$return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === $empty) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_int($value) ? $value == $i+1 : (is_array($value) ? in_array($i+1, $value) : $value === $val));
$return .= " <label><input type='$type'$attrs value='" . (JUSH == "sql" ? $i+1 : h($val)) . "'" . ($checked ? ' checked' : '') . '>' . h($adminer->editVal($val, $field)) . '</label>';
$checked = (is_array($value) ? in_array($val, $value) : $value === $val);
$return .= " <label><input type='$type'$attrs value='" . h($val) . "'" . ($checked ? ' checked' : '') . '>' . h($adminer->editVal($val, $field)) . '</label>';
}
return $return;
}
@@ -910,11 +919,7 @@ function input($field, $value, $function) {
$name = h(bracket_escape($field["field"]));
echo "<td class='function'>";
if (is_array($value) && !$function) {
$args = array($value);
if (version_compare(PHP_VERSION, 5.4) >= 0) {
$args[] = JSON_PRETTY_PRINT;
}
$value = call_user_func_array('json_encode', $args); //! requires PHP 5.2
$value = json_encode($value, 128); // 128 - JSON_PRETTY_PRINT available since PHP 5.4
$function = "json";
}
$reset = (JUSH == "mssql" && $field["auto_increment"]);
@@ -929,6 +934,7 @@ function input($field, $value, $function) {
$field["type"] = "enum";
$field["length"] = $enums;
}
echo $driver->unconvertFunction($field) . " ";
if ($field["type"] == "enum") {
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
} else {
@@ -945,12 +951,12 @@ function input($field, $value, $function) {
} elseif (preg_match('~bool~', $field["type"])) {
echo "<input type='hidden'$attrs value='0'>"
. "<input type='checkbox'" . (preg_match('~^(1|t|true|y|yes|on)$~i', $value) ? " checked='checked'" : "") . "$attrs value='1'>";
} elseif ($field["type"] == "set") { //! 64 bits
} elseif ($field["type"] == "set") {
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_int($value) ? ($value >> $i) & 1 : in_array($val, explode(",", $value), true));
echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . (1 << $i) . "'" . ($checked ? ' checked' : '') . ">" . h($adminer->editVal($val, $field)) . '</label>';
$checked = in_array($val, explode(",", $value), true);
echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . h($val) . "'" . ($checked ? ' checked' : '') . ">" . h($adminer->editVal($val, $field)) . '</label>';
}
} elseif (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
echo "<input type='file' name='fields-$name'>";
@@ -1019,9 +1025,6 @@ function process_input($field) {
return "NULL";
}
}
if ($field["type"] == "enum") {
return +$value;
}
if ($field["auto_increment"] && $value == "") {
return null;
}
@@ -1032,7 +1035,7 @@ function process_input($field) {
return "NULL";
}
if ($field["type"] == "set") {
return array_sum((array) $value);
$value = implode(",", (array) $value);
}
if ($function == "json") {
$function = "";
@@ -1422,6 +1425,7 @@ function edit_form($table, $fields, $row, $update) {
<form action="" method="post" enctype="multipart/form-data" id="form">
<?php
$first = 0;
$is_first = true;
if (!$fields) {
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
} else {
@@ -1434,10 +1438,13 @@ function edit_form($table, $fields, $row, $update) {
if ($field["type"] == "bit" && preg_match("~^b'([01]*)'\$~", $default, $regs)) {
$default = $regs[1];
}
if (JUSH == "sql" && preg_match('~binary~', $field["type"])) {
$default = bin2hex($default); // same as UNHEX
}
}
$value = ($row !== null
? ($row[$name] != "" && JUSH == "sql" && preg_match("~enum|set~", $field["type"])
? (is_array($row[$name]) ? array_sum($row[$name]) : +$row[$name])
? ($row[$name] != "" && JUSH == "sql" && preg_match("~enum|set~", $field["type"]) && is_array($row[$name])
? implode(",", $row[$name])
: (is_bool($row[$name]) ? +$row[$name] : $row[$name])
)
: (!$update && $field["auto_increment"]
@@ -1466,8 +1473,10 @@ function edit_form($table, $fields, $row, $update) {
$value = "";
$function = "uuid";
}
if ($field["auto_increment"] || $function == "now" || $function == "uuid") {
if ($is_first && ($field["auto_increment"] || $function == "now" || $function == "uuid")) {
$first++;
} else {
$is_first = false;
}
input($field, $value, $function);
echo "\n";

View File

@@ -74,7 +74,7 @@ function lang($idf, $number = null) {
: ($LANG == 'sl' ? ($number % 100 == 1 ? 0 : ($number % 100 == 2 ? 1 : ($number % 100 == 3 || $number % 100 == 4 ? 2 : 3))) // different forms for 1, 2, 3-4, other
: ($LANG == 'lt' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1, 12-19, other
: ($LANG == 'lv' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number ? 1 : 2)) // different forms for 1 except 11, other, 0
: ($LANG == 'bs' || $LANG == 'ru' || $LANG == 'sr' || $LANG == 'uk' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1 except 11, 2-4 except 12-14, other
: (in_array($LANG, array('bs', 'ru', 'sr', 'uk')) ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1 except 11, 2-4 except 12-14, other
: 1 // different forms for 1, other
)))))))); // http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
$translation = $translation[$pos];

View File

@@ -4,7 +4,9 @@ namespace Adminer;
// PDO can be used in several database drivers
if (extension_loaded('pdo')) {
abstract class PdoDb {
var $_result, $server_info, $affected_rows, $errno, $error, $pdo;
public $server_info, $affected_rows, $errno, $error;
protected $pdo;
private $result;
function dsn($dsn, $username, $password, $options = array()) {
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT;
@@ -38,12 +40,12 @@ if (extension_loaded('pdo')) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function store_result($result = null) {
if (!$result) {
$result = $this->_result;
$result = $this->result;
if (!$result) {
return false;
}
@@ -57,11 +59,11 @@ if (extension_loaded('pdo')) {
}
function next_result() {
if (!$this->_result) {
if (!$this->result) {
return false;
}
$this->_result->_offset = 0;
return @$this->_result->nextRowset(); // @ - PDO_PgSQL doesn't support it
$this->result->_offset = 0;
return @$this->result->nextRowset(); // @ - PDO_PgSQL doesn't support it
}
function result($query, $field = 0) {
@@ -75,7 +77,7 @@ if (extension_loaded('pdo')) {
}
class PdoDbStatement extends \PDOStatement {
var $_offset = 0, $num_rows;
public $_offset = 0, $num_rows;
function fetch_assoc() {
return $this->fetch(\PDO::FETCH_ASSOC);

View File

@@ -2,8 +2,7 @@
namespace Adminer;
class TmpFile {
var $handler;
var $size;
private $handler, $size;
function __construct() {
$this->handler = tmpfile();

View File

@@ -1,4 +1,4 @@
<?php
namespace Adminer;
$VERSION = "5.0.2";
$VERSION = "5.0.5";

View File

@@ -126,7 +126,7 @@ if ($primary) {
$j = 1;
foreach ($row["indexes"] as $index) {
if (!$_POST["drop_col"] || $j != key($_POST["drop_col"])) {
echo "<tr><td>" . html_select("indexes[$j][type]", array(-1 => "") + $index_types, $index["type"], ($j == count($row["indexes"]) ? "indexesAddRow.call(this);" : 1), "label-type");
echo "<tr><td>" . html_select("indexes[$j][type]", array(-1 => "") + $index_types, $index["type"], ($j == count($row["indexes"]) ? "indexesAddRow.call(this);" : ""), "label-type");
echo "<td>";
ksort($index["columns"]);

View File

@@ -302,4 +302,10 @@ $translations = array(
'Unknown error.' => 'Unbekannter Fehler.',
'Database does not support password.' => 'Die Datenbank unterstützt kein Passwort.',
'Disable %s or enable %s or %s extensions.' => 'Deaktivieren Sie %s oder aktivieren Sie die Erweiterungen %s oder %s.',
'Check has been dropped.' => 'Check wurde abgebrochen.',
'Check has been altered.' => 'Check wurde geändert.',
'Check has been created.' => 'Check wurde erstellt.',
'Alter check' => 'Check ändern',
'Create check' => 'Check erstellen',
'Checks' => 'Checks',
);

View File

@@ -285,7 +285,7 @@ $translations = array(
'Default value' => 'Predvolená hodnota',
'Full table scan' => 'Prechod celej tabuľky',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Príliš veľa pokusov o prihlásenie, skúste to znova za %d minutu.', 'Príliš veľa pokusov o prihlásenie, skúste to znova za %d minuty.', 'Príliš veľa pokusov o prihlásenie, skúste to znova za %d minút.'),
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Vďaka za používanie Admineru, <a href="https://www.adminer.org/cs/donation/">prispejte</a> na vývoj.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Vďaka za používanie Admineru, <a href="https://www.adminer.org/sk/donation/">prispejte</a> na vývoj.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Platnosť hlavného hesla vypršala. <a href="https://www.adminer.org/cs/extension/"%s>Implementujte</a> metodu %s, aby platilo natrvalo.',
'The action will be performed after successful login with the same credentials.' => 'Akcia sa vykoná po úspešnom prihlásení s rovnakými prihlasovacími údajmi.',
'Connecting to privileged ports is not allowed.' => 'Pripojenie k privilegovaným portom nie je povolené.',
@@ -302,4 +302,10 @@ $translations = array(
'Disable %s or enable %s or %s extensions.' => 'Zakážte %s alebo povoľte rozšírenie %s alebo %s.',
'yes' => 'áno',
'no' => 'nie',
'Checks' => 'Kontroly',
'Create check' => 'Vytvoriť kontrolu',
'Alter check' => 'Zmeniť kontrolu',
'Check has been created.' => 'Kontrola bola vytvorená.',
'Check has been altered.' => 'Kontrola bola zmenená.',
'Check has been dropped.' => 'Kontrola bola odstránená.',
);

View File

@@ -34,6 +34,7 @@ if (!$_POST && $PROCEDURE != "") {
$collations = get_vals("SHOW CHARACTER SET");
sort($collations);
$routine_languages = routine_languages();
echo ($collations ? "<datalist id='collations'>" . optionlist($collations) . "</datalist>" : "");
?>
<form action="" method="post" id="form">

View File

@@ -74,7 +74,9 @@ foreach ($schema as $name => $table) {
$left1 = $left - $table_pos[$name][1];
$i = 0;
foreach ($ref[0] as $source) {
echo "\n<div class='references' title='" . h($target_name) . "' id='refs$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$source]["pos"] . "em; padding-top: .5em;'><div style='border-top: 1px solid Gray; width: " . (-$left1) . "em;'></div></div>";
echo "\n<div class='references' title='" . h($target_name) . "' id='refs$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$source]["pos"] . "em; padding-top: .5em;'>"
. "<div style='border-top: 1px solid gray; width: " . (-$left1) . "em;'></div></div>"
;
}
}
}
@@ -84,8 +86,9 @@ foreach ($schema as $name => $table) {
$left1 = $left - $table_pos[$name][1];
$i = 0;
foreach ($columns as $target) {
echo "\n<div class='references' title='" . h($target_name) . "' id='refd$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$target]["pos"] . "em; height: 1.25em; background: url(../adminer/static/arrow.gif) no-repeat right center;'>"
. "<div style='height: .5em; border-bottom: 1px solid Gray; width: " . (-$left1) . "em;'></div>"
echo "\n<div class='references' title='" . h($target_name) . "' id='refd$left-" . ($i++) . "'"
. " style='left: $left1" . "em; top: " . $table["fields"][$target]["pos"] . "em; height: 1.25em; background: url(../adminer/static/arrow.gif) no-repeat right center;'>"
. "<div style='height: .5em; border-bottom: 1px solid gray; width: " . (-$left1) . "em;'></div>"
. "</div>"
;
}
@@ -106,7 +109,7 @@ foreach ($schema as $name => $table) {
$min_pos = min($min_pos, $pos1, $pos2);
$max_pos = max($max_pos, $pos1, $pos2);
}
echo "<div class='references' id='refl$left' style='left: $left" . "em; top: $min_pos" . "em; padding: .5em 0;'><div style='border-right: 1px solid Gray; margin-top: 1px; height: " . ($max_pos - $min_pos) . "em;'></div></div>\n";
echo "<div class='references' id='refl$left' style='left: $left" . "em; top: $min_pos" . "em; padding: .5em 0;'><div style='border-right: 1px solid gray; margin-top: 1px; height: " . ($max_pos - $min_pos) . "em;'></div></div>\n";
}
}
}

View File

@@ -25,7 +25,7 @@ if ($_GET["script"] == "db") {
$sums[$key] += ($table_status["Engine"] != "InnoDB" || $key != "Data_free" ? $table_status[$key] : 0);
}
} elseif (array_key_exists($key, $table_status)) {
json_row("$key-$name");
json_row("$key-$name", "?");
}
}
}

View File

@@ -100,6 +100,7 @@ if ($_POST && !$error) {
$query = implode(" UNION ALL ", $union);
}
$adminer->dumpData($TABLE, "table", $query);
$adminer->dumpFooter();
exit;
}
@@ -451,7 +452,7 @@ if (!$columns && support("table")) {
$id = h("val[$unique_idf][" . bracket_escape($key) . "]");
$value = $_POST["val"][$unique_idf][bracket_escape($key)];
$editable = !is_array($row[$key]) && is_utf8($val) && $rows[$n][$key] == $row[$key] && !$functions[$key] && !$field["generated"];
$text = preg_match('~text|lob~', $field["type"]);
$text = preg_match('~text|json|lob~', $field["type"]);
echo "<td id='$id'";
if (($_GET["modify"] && $editable) || $value !== null) {
$h_value = h($value !== null ? $value : $row[$key]);
@@ -587,7 +588,7 @@ if (!$columns && support("table")) {
echo script("qsl('a').onclick = partial(toggle, 'import');", "");
echo "<span id='import'" . ($_POST["import"] ? "" : " class='hidden'") . ">: ";
echo "<input type='file' name='csv_file'> ";
echo html_select("separator", array("csv" => "CSV,", "csv;" => "CSV;", "tsv" => "TSV"), $adminer_import["format"], 1); // 1 - select
echo html_select("separator", array("csv" => "CSV,", "csv;" => "CSV;", "tsv" => "TSV"), $adminer_import["format"]);
echo " <input type='submit' name='import' value='" . lang('Import') . "'>";
echo "</span>";
echo "</div>";

View File

@@ -5,6 +5,7 @@ if (!$error && $_POST["export"]) {
dump_headers("sql");
$adminer->dumpTable("", "");
$adminer->dumpData("", "table", $_POST["query"]);
$adminer->dumpFooter();
exit;
}
@@ -30,7 +31,7 @@ if (!$error && $_POST) {
), "rb");
$query = ($fp ? fread($fp, 1e6) : false);
} else {
$query = get_file("sql_file", true);
$query = get_file("sql_file", true, ";");
}
if (is_string($query)) { // get_file() returns error as number, fread() as false

47
adminer/static/dark.css Normal file
View File

@@ -0,0 +1,47 @@
/** @author Robert Mesaros, https://www.rmsoft.sk */
body { color: #829bb0; background: #002240; }
a { color: #517fa8; }
a:visited { color: #517fa8; }
a:link:hover, a:visited:hover { color: #9bc0e1; }
h1 { border-color: #5e94c1; color: #ffddbf; background: #154269; }
h2 { border-color: #a3bdd3; color: #000; background: #3c678d; }
td, th { border-color: #0e416d; }
th { background: #11385a; }
thead td, thead th { color: #a8b05f; background: #011d35; }
thead th a { color: #a8b05f; }
fieldset { border-color: #16548a; }
code { background: #11385a; }
code[class^="jush-"] { color: #002240; background: #81a0bc; padding: .2em .5em; }
tbody tr:hover td, tbody tr:hover th { background: #133553; }
pre.jush { background: #a7c3dc; }
input.default { box-shadow: 1px 1px 1px #888; }
input.required, input.maxlength { box-shadow: 1px 1px 1px red; }
.version { color: #888; }
.js .column { background: #011d35; }
.error { color: red; background: #efdada; border: 1px solid #e76f6f; }
.error b { background: #002240; }
.message { color: #0b860b; background: #efe; border: 1px solid #7fbd7f; }
.message table { color: #829bb0; background: #002240; }
.char { color: #a949a9; }
.date { color: #59c159; }
.enum { color: #d55c5c; }
.binary { color: #9bc0e1; }
.odds tbody tr:nth-child(2n) { background: #042541; }
.js .checkable .checked td, .js .checkable .checked th { background: #10395c; color: #67a4a5; }
.js .checkable .checked:hover td, .js .checkable .checked:hover th { background: #133553; }
.js .checkable .checked a { color: #67a4a5; }
.icon { background-color: #062642; }
.icon:hover { background-color: #d1394e; }
.footer { border-top-color: rgba(0, 34, 64, .7); border-image-source: linear-gradient(rgba(0, 34, 64, 0.2), #002240); }
.footer > div { background: #002240; }
#menu p, #logins, #tables { border-color: #326b9c; }
#logins a, #tables a, #tables span { background: #002240; }
#breadcrumb { background: #154269; }
#h1 { color: #ffddbf; }
#version { color: #d2b397; }
#schema .table { border-color: #093459; }
#help { border-color: #666; background: #c7e4fe; }
#schema div.table a { color: #3c7bb3; }
#menu .active { color: #398c8d; }
#edit-fields tbody tr:hover td, #edit-fields tbody tr:hover th { background: #3b6f9d; }

View File

@@ -1,4 +1,5 @@
/** @author Ondrej Valka, http://valka.info */
body { color: #000; background: #fff; font: 90%/1.25 Verdana, Arial, Helvetica, sans-serif; margin: 0; min-width: fit-content; }
a { color: blue; text-decoration: none; }
a:visited { color: navy; }
@@ -25,12 +26,12 @@ pre { margin: 1em 0 0; }
td pre { margin: 0; }
pre, textarea { font: 100%/1.25 monospace; }
pre.jush { background: #fff; }
pre code { display: block; }
input, textarea { box-sizing: border-box; }
input, select { vertical-align: middle; }
input[type="radio"] { vertical-align: text-bottom; }
input.default { box-shadow: 1px 1px 1px #777; }
input.required { box-shadow: 1px 1px 1px red; }
input.maxlength { box-shadow: 1px 1px 1px red; }
input.required, input.maxlength { box-shadow: 1px 1px 1px red; }
input.wayoff { left: -1000px; position: absolute; }
.block { display: block; }
.version { color: #777; font-size: 62%; }
@@ -47,14 +48,12 @@ input.wayoff { left: -1000px; position: absolute; }
.date { color: #7F007F; }
.enum { color: #007F7F; }
.binary { color: red; }
.odds tbody tr:nth-child(2n) td { background: #F5F5F5; }
.odds tbody tr:nth-child(2n) { background: #F5F5F5; }
.js .checkable .checked td, .js .checkable .checked th { background: #ddf; }
.time { color: silver; font-size: 70%; }
.function { text-align: right; }
.number { text-align: right; }
.datetime { text-align: right; }
.type { width: 15ex; width: auto\9; }
.options select { width: 20ex; width: auto\9; }
.function, .number, .datetime { text-align: right; }
.type { width: 15ex; }
.options select, .options input { width: 20ex; }
.view { font-style: italic; }
.active { font-weight: bold; }
.sqlarea { width: 98%; }

View File

@@ -568,7 +568,7 @@ function functionChange() {
* @this HTMLTableCellElement
*/
function skipOriginal(first) {
var fnSelect = this.previousSibling.firstChild;
var fnSelect = qs('select', this.previousSibling);
if (fnSelect.selectedIndex < first) {
fnSelect.selectedIndex = first;
}

View File

@@ -45,7 +45,11 @@ if (!is_view($table_status)) {
foreach ($foreign_keys as $name => $foreign_key) {
echo "<tr title='" . h($name) . "'>";
echo "<th><i>" . implode("</i>, <i>", array_map('Adminer\h', $foreign_key["source"])) . "</i>";
echo "<td><a href='" . h($foreign_key["db"] != "" ? preg_replace('~db=[^&]*~', "db=" . urlencode($foreign_key["db"]), ME) : ($foreign_key["ns"] != "" ? preg_replace('~ns=[^&]*~', "ns=" . urlencode($foreign_key["ns"]), ME) : ME)) . "table=" . urlencode($foreign_key["table"]) . "'>"
$link = ($foreign_key["db"] != ""
? preg_replace('~db=[^&]*~', "db=" . urlencode($foreign_key["db"]), ME)
: ($foreign_key["ns"] != "" ? preg_replace('~ns=[^&]*~', "ns=" . urlencode($foreign_key["ns"]), ME) : ME)
);
echo "<td><a href='" . h($link . "table=" . urlencode($foreign_key["table"])) . "'>"
. ($foreign_key["db"] != "" && $foreign_key["db"] != DB ? "<b>" . h($foreign_key["db"]) . "</b>." : "")
. ($foreign_key["ns"] != "" && $foreign_key["ns"] != $_GET["ns"] ? "<b>" . h($foreign_key["ns"]) . "</b>." : "")
. h($foreign_key["table"])

View File

@@ -148,7 +148,10 @@ echo "<table class='odds'>\n";
echo "<thead><tr><th colspan='2'>" . lang('Privileges') . doc_link(array('sql' => "grant.html#priv_level"));
$i = 0;
foreach ($grants as $object => $grant) {
echo '<th>' . ($object != "*.*" ? "<input name='objects[$i]' value='" . h($object) . "' size='10' autocapitalize='off'>" : "<input type='hidden' name='objects[$i]' value='*.*' size='10'>*.*"); //! separate db, table, columns, PROCEDURE|FUNCTION, routine
echo '<th>' . ($object != "*.*"
? "<input name='objects[$i]' value='" . h($object) . "' size='10' autocapitalize='off'>"
: "<input type='hidden' name='objects[$i]' value='*.*' size='10'>*.*"
); //! separate db, table, columns, PROCEDURE|FUNCTION, routine
$i++;
}
echo "</thead>\n";

View File

@@ -1,3 +1,32 @@
Adminer 5.0.5 (released 2025-03-13):
MySQL: Display converting function for binary, bit or geometry fields
MySQL: Display default values of binary columns
MySQL: Allow setting default values of json column
MariaDB: Don't display NULL as default value (regression from 5.0.0)
PostgreSQL PDO: Escape bytea values (bug #218)
CockroachDB: Display version
CockroachDB: Recognize unique_rowid() as auto_increment
MS SQL: Fix editing rows with datetime column in primary key
MongoDB: Move to plugin
CSS: Add dark theme
Adminer 5.0.4 (released 2025-03-11):
Compile: Fix shortening in private methods (regression from 5.0.3)
Adminer 5.0.3 (released 2025-03-11):
Fix gzip export (bug #896, regression from 5.0.0)
Fix importing multiple SQL files not terminated by semicolon
Use <datalist> for altering collations
MySQL: Allow setting default values of text column
MySQL: Stop treating enum and set as numbers (bug #475)
MySQL, MariaDB: Fix default values with ' (bug #895)
MariaDB: Fix creating and altering generated columns (bug #897)
PostgreSQL: Fix "where" and "order" privileges (bug #902, regression from 5.0.2)
SQLite: Fix creating table in compiled version (bug #901, regression from 5.0.0)
Elastic: Do not pass null values on insert (PR #892)
Elastic: Fix displaying sparse rows (PR #893)
Plugins: Add method dumpFooter()
Adminer 5.0.2 (released 2025-03-10):
PostgreSQL: Fix setting NULL and original value on enum (bug #884)
CockroachDB: Add support via PostgreSQL driver
@@ -64,7 +93,7 @@ SQLite: Show all supported pragmas in Variables
MS SQL: Allow altering table in non-default schema (bug #405)
MS SQL: Fix default values (bug #732, bug #733)
MS SQL: Fix length of nvarchar columns
Editor: PDO: Select value of foreign key in edit (bug #847)
Editor PDO: Select value of foreign key in edit (bug #847)
Mobile devices: Use device width
Adminer 4.16.0 (released 2025-02-20):
@@ -83,6 +112,7 @@ Escape unknown field in select
HTTP drivers: Don't allow path in server name
HTTP drivers: Hide connection error message
SimpleDB: Disable XML entity loader
Latvian translation
Adminer 4.14.0:
Use autofocus HTML attribute
@@ -546,7 +576,7 @@ MySQL: Speed up updating rows without numeric or UTF-8 primary key
Non-MySQL: Descending indexes
PostgreSQL: Fix detecting oid column in PDO
PostgreSQL: Handle timestamp types (bug #324)
Add Korean translation
Korean translation
Adminer 3.7.0 (released 2013-05-19):
Allow more SQL files to be uploaded at the same time

View File

@@ -2,12 +2,9 @@
<?php
include __DIR__ . "/adminer/include/version.inc.php";
include __DIR__ . "/adminer/include/errors.inc.php";
include __DIR__ . "/php_shrink.inc.php";
include __DIR__ . "/externals/JsShrink/jsShrink.php";
function add_apo_slashes($s) {
return addcslashes($s, "\\'");
}
function add_quo_slashes($s) {
$return = $s;
$return = addcslashes($return, "\n\r\$\"\\");
@@ -41,7 +38,7 @@ function put_file($match) {
return $match[0]; // processed later
}
$return = file_get_contents(__DIR__ . "/$project/$match[2]");
$return = str_replace("namespace Adminer;\n", "", $return);
$return = preg_replace('~namespace Adminer;\s*~', '', $return);
if (basename($match[2]) == "file.inc.php") {
$return = str_replace("\n// caching headers added in compile.php", (preg_match('~-dev$~', $VERSION) ? '' : '
if ($_SERVER["HTTP_IF_MODIFIED_SINCE"]) {
@@ -212,126 +209,8 @@ if (!$translations) {
';
}
function short_identifier($number, $chars) {
$return = '';
while ($number >= 0) {
$return .= $chars[$number % strlen($chars)];
$number = floor($number / strlen($chars)) - 1;
}
return $return;
}
// based on http://latrine.dgx.cz/jak-zredukovat-php-skripty
function php_shrink($input) {
global $VERSION;
$special_variables = array_flip(array('$this', '$GLOBALS', '$_GET', '$_POST', '$_FILES', '$_COOKIE', '$_SESSION', '$_SERVER', '$http_response_header', '$php_errormsg'));
$short_variables = array();
$shortening = true;
$tokens = token_get_all($input);
// remove unnecessary { }
//! change also `while () { if () {;} }` to `while () if () ;` but be careful about `if () { if () { } } else { }
$shorten = 0;
$opening = -1;
foreach ($tokens as $i => $token) {
if (in_array($token[0], array(T_IF, T_ELSE, T_ELSEIF, T_WHILE, T_DO, T_FOR, T_FOREACH), true)) {
$shorten = ($token[0] == T_FOR ? 4 : 2);
$opening = -1;
} elseif (in_array($token[0], array(T_SWITCH, T_FUNCTION, T_CLASS, T_CLOSE_TAG), true)) {
$shorten = 0;
} elseif ($token === ';') {
$shorten--;
} elseif ($token === '{') {
if ($opening < 0) {
$opening = $i;
} elseif ($shorten > 1) {
$shorten = 0;
}
} elseif ($token === '}' && $opening >= 0 && $shorten == 1) {
unset($tokens[$opening]);
unset($tokens[$i]);
$shorten = 0;
$opening = -1;
}
}
$tokens = array_values($tokens);
foreach ($tokens as $i => $token) {
if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$short_variables[$token[1]]++;
}
}
arsort($short_variables);
$chars = implode(range('a', 'z')) . '_' . implode(range('A', 'Z'));
// preserve variable names between versions if possible
$short_variables2 = array_splice($short_variables, strlen($chars));
ksort($short_variables);
ksort($short_variables2);
$short_variables += $short_variables2;
foreach (array_keys($short_variables) as $number => $key) {
$short_variables[$key] = short_identifier($number, $chars); // could use also numbers and \x7f-\xff
}
$set = array_flip(preg_split('//', '!"#$%&\'()*+,-./:;<=>?@[]^`{|}'));
$space = '';
$output = '';
$in_echo = false;
$doc_comment = false; // include only first /**
for (reset($tokens); list($i, $token) = each($tokens);) {
if (!is_array($token)) {
$token = array(0, $token);
}
if (
$tokens[$i+2][0] === T_CLOSE_TAG && $tokens[$i+3][0] === T_INLINE_HTML && $tokens[$i+4][0] === T_OPEN_TAG
&& strlen(add_apo_slashes($tokens[$i+3][1])) < strlen($tokens[$i+3][1]) + 3
) {
$tokens[$i+2] = array(T_ECHO, 'echo');
$tokens[$i+3] = array(T_CONSTANT_ENCAPSED_STRING, "'" . add_apo_slashes($tokens[$i+3][1]) . "'");
$tokens[$i+4] = array(0, ';');
}
if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) {
$space = "\n";
} else {
if ($token[0] == T_DOC_COMMENT) {
$doc_comment = true;
$token[1] = substr_replace($token[1], "* @version $VERSION\n", -2, 0);
}
if ($token[0] == T_VAR) {
$shortening = false;
} elseif (!$shortening) {
if ($token[1] == ';') {
$shortening = true;
}
} elseif ($token[0] == T_ECHO) {
$in_echo = true;
} elseif ($token[1] == ';' && $in_echo) {
if ($tokens[$i+1][0] === T_WHITESPACE && $tokens[$i+2][0] === T_ECHO) {
next($tokens);
$i++;
}
if ($tokens[$i+1][0] === T_ECHO) {
// join two consecutive echos
next($tokens);
$token[1] = ','; // '.' would conflict with "a".1+2 and would use more memory //! remove ',' and "," but not $var","
} else {
$in_echo = false;
}
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$token[1] = '$' . $short_variables[$token[1]];
}
if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
$space = '';
}
$output .= $space . $token[1];
$space = '';
}
}
return $output;
}
function minify_css($file) {
return lzw_compress(preg_replace('~\s*([:;{},])\s*~', '\1', preg_replace('~/\*.*\*/~sU', '', $file)));
return lzw_compress(preg_replace('~\s*([:;{},])\s*~', '\1', preg_replace('~/\*.*?\*/\s*~s', '', $file)));
}
function minify_js($file) {
@@ -356,14 +235,6 @@ function compile_file($match) {
return '"' . add_quo_slashes($file) . '"';
}
if (!function_exists("each")) {
function each(&$arr) {
$key = key($arr);
next($arr);
return $key === null ? false : array($key, $arr[$key]);
}
}
function min_version() {
return true;
}
@@ -411,6 +282,7 @@ include __DIR__ . "/adminer/include/driver.inc.php";
$features = array("check", "call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view");
$lang_ids = array(); // global variable simplifies usage in a callback function
$file = file_get_contents(__DIR__ . "/$project/index.php");
$file = preg_replace('~\*/~', "* @version $VERSION\n*/", $file, 1);
if ($driver) {
$_GET[$driver] = true; // to load the driver
include_once __DIR__ . $driver_path;
@@ -443,7 +315,7 @@ if ($driver) {
}
if (count($drivers) == 1) {
$file = str_replace('html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);")', "\"<input type='hidden' name='auth[driver]' value='" . ($driver == "mysql" ? "server" : $driver) . "'>" . reset($drivers) . "\"", $file, $count);
if (!$count) {
if (!$count && $project != "editor") {
echo "auth[driver] form field not found\n";
}
$file = str_replace(" . script(\"qs('#username').form['auth[driver]'].onchange();\")", "", $file);
@@ -469,16 +341,15 @@ if ($_SESSION["lang"]) {
$file = str_replace("switch_lang();", "", $file);
$file = str_replace('<?php echo $LANG; ?>', $_SESSION["lang"], $file);
}
$file = str_replace('<?php echo script_src("static/editing.js"); ?>' . "\n", "", $file);
$file = preg_replace('~\s+echo script_src\("\.\./externals/jush/modules/jush-(textarea|txt|js|" \. JUSH \. ")\.js"\);~', '', $file);
$file = str_replace('<link rel="stylesheet" type="text/css" href="../externals/jush/jush.css">' . "\n", "", $file);
$file = str_replace('echo script_src("static/editing.js");' . "\n", "", $file); // merged into functions.js
$file = preg_replace('~\s+echo script_src\("\.\./externals/jush/modules/jush-(textarea|txt|js|" \. JUSH \. ")\.js"\);~', '', $file); // merged into jush.js
$file = str_replace('<link rel="stylesheet" href="../externals/jush/jush.css">' . "\n", "", $file); // merged into default.css
$file = preg_replace_callback("~compile_file\\('([^']+)'(?:, '([^']*)')?\\)~", 'compile_file', $file); // integrate static files
$replace = 'preg_replace("~\\\\\\\\?.*~", "", ME) . "?file=\1&version=' . $VERSION . '"';
$file = preg_replace('~\.\./adminer/static/(default\.css|favicon\.ico)~', '<?php echo h(' . $replace . '); ?>', $file);
$file = preg_replace('~"\.\./adminer/static/(functions\.js)"~', $replace, $file);
$file = preg_replace('~\.\./adminer/static/([^\'"]*)~', '" . h(' . $replace . ') . "', $file);
$file = preg_replace('~"\.\./externals/jush/modules/(jush\.js)"~', $replace, $file);
$file = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $file);
$file = php_shrink($file);
$filename = $project . (preg_match('~-dev$~', $VERSION) ? "" : "-$VERSION") . ($driver ? "-$driver" : "") . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php";

View File

@@ -1,13 +1,14 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="cs">
<!DOCTYPE html>
<html lang="cs">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Coverage</title>
</head>
<body>
<?php
include "./adminer/include/errors.inc.php";
function xhtml_open_tags($s) {
// returns array of opened tags in $s
$return = array();
@@ -24,17 +25,18 @@ function xhtml_open_tags($s) {
$coverage_filename = sys_get_temp_dir() . "/adminer_coverage.ser";
if (!extension_loaded("xdebug")) {
echo "<p class='error'>Xdebug has to be enabled.</p>\n";
echo "<p class='error'>Xdebug has to be enabled.\n";
} elseif ($_GET["coverage"] === "0") {
file_put_contents($coverage_filename, serialize(array()));
echo "<p class='message'>Coverage started.</p>\n";
} elseif (preg_match('~^(adminer|editor)/(include/)?[-_.a-z0-9]+$~i', $_GET["coverage"])) {
echo "<p class='message'>Coverage started.\n";
} elseif (preg_match('~^(adminer|editor)/(include/|drivers/)?[-_.a-z0-9]+$~i', $_GET["coverage"])) {
// highlight single file
$filename = $_GET["coverage"];
$coverage = (file_exists($coverage_filename) ? unserialize(file_get_contents($coverage_filename)) : array());
$file = explode("<br />", highlight_file($filename, true));
$file = explode("\n", substr(highlight_file($filename, true), 5, -6)); // unwrap <pre></pre>
$prev_color = null;
$s = "";
echo "<pre>";
for ($l=0; $l <= count($file); $l++) {
$line = $file[$l];
$color = "#C0FFC0"; // tested
@@ -58,31 +60,28 @@ if (!extension_loaded("xdebug")) {
foreach (array_reverse($open_tags) as $tag) {
echo "</" . preg_replace('~ .*~', '', $tag) . ">";
}
echo "</div>\n";
echo "</div>";
$s = ($open_tags ? "<" . implode("><", $open_tags) . ">" : "");
$prev_color = $color;
}
$s .= "$line<br />\n";
$s .= "$line\n";
}
echo "</pre>";
} else {
if (file_exists($coverage_filename)) {
// display list of files
$coverage = unserialize(file_get_contents($coverage_filename));
echo "<table border='1' cellspacing='0'>\n";
foreach (array_merge(glob("adminer/*.php"), glob("adminer/include/*.php"), glob("editor/*.php"), glob("editor/include/*.php")) as $filename) {
foreach (array_merge(glob("adminer/*.php"), glob("adminer/drivers/*.php"), glob("adminer/include/*.php"), glob("editor/*.php"), glob("editor/include/*.php")) as $filename) {
$cov = $coverage[realpath($filename)];
$ratio = 0;
if (is_array($cov)) {
$values = array_count_values($cov);
$ratio = round(100 - 100 * $values[-1] / (count($cov) - $values[-2]));
}
echo "<tr><td align='right' style='background-color: " . ($ratio < 50 ? "Red" : ($ratio < 75 ? "#FFEA20" : "#A7FC9D")) . ";'>$ratio%</td><td><a href='coverage.php?coverage=$filename'>$filename</a></td></tr>\n";
echo "<tr><td align='right' style='background-color: " . ($ratio < 50 ? "Red" : ($ratio < 75 ? "#FFEA20" : "#A7FC9D")) . ";'>$ratio%<td><a href='coverage.php?coverage=$filename'>$filename</a>\n";
}
echo "</table>\n";
}
echo "<p><a href='coverage.php?coverage=0'>Start new coverage</a></p>\n";
echo "<p><a href='coverage.php?coverage=0'>Start new coverage</a>\n";
}
?>
</body>
</html>

View File

@@ -198,7 +198,7 @@ table label.block{padding:0}
tr{border-bottom:1px dotted rgba(255,255,255,0.1)}
th,td{padding:4px 10px}
th[style="text-align: right;"] input[type="checkbox"],td[align="right"] input[type="checkbox"],th[style="text-align: right;"] input[type="radio"],td[align="right"] input[type="radio"]{margin-right:0;margin-left:5px}
thead td,thead th,.odds tbody tr:nth-child(2n) td,tbody tr:hover td,tbody tr:hover th,.js .checkable .checked td,.js .checkable .checked th{background:transparent}
thead td,thead th,.odds tbody tr:nth-child(2n),tbody tr:hover td,tbody tr:hover th,.js .checkable .checked td,.js .checkable .checked th{background:transparent}
thead tr{background:#282b2f;border-bottom:1px solid rgba(255,255,255,0.1)}
thead td,thead th{padding:7px 10px;background:transparent;text-align:left}
tbody th,tbody td{vertical-align:top}

View File

@@ -112,7 +112,7 @@ border-bottom: 1px #BBB solid;
thead tr:hover td, thead tr:hover th {
background-color: #DDD !important;
}
tr:nth-child(2n) td, tr:nth-child(2n) th, .odd td, .odd th, tr.odd {
tr:nth-child(2n) td, tr:nth-child(2n) th {
background-color: #F1F1F1;
}
tr:hover td, tr:hover th {

View File

@@ -175,8 +175,7 @@
background: var(--color-darkPurple);
}
.odds tbody tr:nth-child(2n) th,
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background: var(--color-darkDraculaVSCode);
}

View File

@@ -133,7 +133,7 @@ th {
background:white;
}
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background:#fcfaf5;
}

View File

@@ -72,7 +72,7 @@ tr:first-child th {padding-right: 30px;}
td:first-child, th:first-child {border-left-width: 0;}
thead td, thead th {background-color: #DFDFDF; border: none; border-bottom: 1px #BBB solid;}
thead tr:hover td, thead tr:hover th {background-color: #DDD !important;}
tr:nth-child(2n) td, tr:nth-child(2n) th, .odds tbody tr:nth-child(2n) td, .odds tbody tr:nth-child(2n) th, .odds tbody tr:nth-child(2n) {background-color: #F1F1F1;}
tr:nth-child(2n) td, tr:nth-child(2n) th, .odds tbody tr:nth-child(2n), .odds tbody tr:nth-child(2n):not(.checked, :hover) {background-color: #F1F1F1;}
tr:hover td, tr:hover th {background-color: #BCD;}
fieldset {display: inline; vertical-align: top; padding: 2px 12px; margin: 25px 12px 12px 0; border: none; background-color: #F1F1F1; border: 1px solid #E3E3E3; position: relative;}
fieldset, x:-moz-any-link {padding-top: 4px;}

View File

@@ -378,7 +378,7 @@ thead td abbr, thead td sup, thead th acronym, thead th sup {
color: #cdf
}
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background: #fcfaf5
}

View File

@@ -153,7 +153,7 @@ th, td {
vertical-align: top;
}
.odds tbody tr:nth-child(2n) th, .odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background: #FCFAF5;
}

View File

@@ -132,7 +132,7 @@ th {
background:white;
}
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background:#fcfaf5;
}

View File

@@ -187,7 +187,7 @@ td.nowrap {
.binary {
color: red;
}
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background: transparent;
}
.js .checkable .checked td,

View File

@@ -169,7 +169,7 @@ th {
background:white;
}
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background:#fcfaf5;
}
@@ -181,7 +181,7 @@ th {
background: #f2f2f2;
}
#content tbody tr.checked td, .odds tbody tr:nth-child(2n).checked td {
#content tbody tr.checked td {
background:#fbe2e2;
color:red;
}

View File

@@ -65,7 +65,7 @@ thead td, thead th {
border-bottom: 1px #DDD solid; }
.nowrap tr:nth-child(2n) td, .nowrap tr:nth-child(2n) th {
background-color: #DEF; }
.odds tbody tr:nth-child(2n) td, .odds tbody tr:nth-child(2n) th {
.odds tbody tr:nth-child(2n) {
background-color: #DEF; } /* IEx */
tr.selected td, tr.selected th {
background-color: #ABC !important; }
@@ -234,7 +234,7 @@ legend a:hover {
select[name^="columns"] optgroup:last-child option:nth-child(3)::before {
content: "count "; }
select[name$="[collation]"] {
input[name$="[collation]"] {
max-width: 120px; }
.logout a:first-child, p a {

View File

@@ -136,8 +136,7 @@ table.checkable tbody tr:hover th {
background: #bfb008;
}
.odds tbody tr:nth-child(2n) th,
.odds tbody tr:nth-child(2n) td {
.odds tbody tr:nth-child(2n) {
background: #f5f5f5;
}

View File

@@ -58,7 +58,7 @@ table{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-ri
td,th{-moz-border-bottom-colors:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;border-color:-moz-use-text-color #999 #999 -moz-use-text-color;border-image:none;border-style:none solid solid none;border-width:0 1px 1px 0;padding:.2em .3em}
thead td,thead th{background:#eee;background:-moz-linear-gradient(top,#eee 0,#ccc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#eee),color-stop(100%,#ccc));background:-webkit-linear-gradient(top,#eee 0,#ccc 100%);background:-o-linear-gradient(top,#eee 0,#ccc 100%);background:-ms-linear-gradient(top,#eee 0,#ccc 100%);background:linear-gradient(to bottom,#eee 0,#ccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee',endColorstr='#cccccc',GradientType=0)}
td{background-color:#f4f8ff}
.odds tbody tr:nth-child(2n) td{background-color:#fff}
.odds tbody tr:nth-child(2n){background-color:#fff}
tbody tr:hover td,tbody tr:hover th{background-color:#FFE}
p.tabs{margin:0 20px 0 0}
.jush-sql{background:0}
@@ -70,6 +70,7 @@ a:hover{color:#28c}
#logout:hover,#logins a:hover,#tables a:hover,#breadcrumb a:hover,.logout a:hover,.tabs a:hover{color:#fff;text-decoration:none;background:#93c9ff;background:-moz-linear-gradient(top,#93c9ff 0,#79b8f7 44%,#57a2ed 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#93c9ff),color-stop(44%,#79b8f7),color-stop(100%,#57a2ed));background:-webkit-linear-gradient(top,#93c9ff 0,#79b8f7 44%,#57a2ed 100%);background:-o-linear-gradient(top,#93c9ff 0,#79b8f7 44%,#57a2ed 100%);background:-ms-linear-gradient(top,#93c9ff 0,#79b8f7 44%,#57a2ed 100%);background:linear-gradient(to bottom,#93c9ff 0,#79b8f7 44%,#57a2ed 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#93c9ff',endColorstr='#57a2ed',GradientType=0)}
#breadcrumb a,#breadcrumb a:link{border:1px solid #246;padding:2px 6px;margin:1px auto;line-height:1.6em}
#logins a,#tables a{background:none repeat scroll 0 0 #fff;padding:2px 6px;margin:1px 0;font-size:.8em}
#lang{top:-4.5em;}
a[title='Show structure'],#tables a[title='Show structure']{border:0;background:0;color:#369}
.jush a{border:0;background:0;margin:0;padding:0}
a.active,a.active:link,a.active:hover{text-decoration:underline}

View File

@@ -2,8 +2,8 @@
* @package Adminer.css - Theme CSS for Adminer --- [theme light] gray - orange B (with icons)
*
*//*!
* @version 4.17.1.2
* @date Thu, 27 Feb 2025 09:28:32 +0100
* @version 5.0.4.1
* @date Wed, 12 Mar 2025 21:35:32 +0100
* @author Robert Mesaros
* @copyright Copyright 2025 Robert Mesaros, rmSOFT, Slovakia
* @web https://www.rmsoft.sk
@@ -35,10 +35,6 @@
* Modified icons by Robert Mesaros
*
*/
#menu{padding:0 0 30px 0}
.ltr .logout{right:0;left:auto;margin-top:.5em}
.rtl .logout{left:0;right:auto;margin-top:.5em}
.rtl table.layout tbody{direction:ltr}
html{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
*,*:before,*:after{box-sizing:inherit}
body{color:#000;background:#f0f0f0;font-family:Verdana,Arial,Helvetica,sans-serif;font-weight:normal;cursor:default;margin:0}
@@ -49,6 +45,9 @@ img{width:100%;max-width:100%}
#menu #h1{margin-left:10px}
#menu h1{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozNDA3NDEwQ0Y0MkQxMUVGODA4RUNENTRFQzJENUU4RCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozNDA3NDEwQkY0MkQxMUVGODA4RUNENTRFQzJENUU4RCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph59M4AAAAPFSURBVHja7JZrSFNRHMDvvVvq1mNlucBK0g/lh+Us6oPrU0ERRFgRUqYUVEb2qTJ0vko0ZbMHiBT0sizSXEUfJGzN1CjBQLPCR/RwSYKp23RO3e527/r/57mxxpblhCD8w59z7t2553f+zx36Ulk5FYxkZpyiijVahUgkqnc62cu5arUGXrMl2tIkhmGuu91uGp4HXre0qB490A3C3IXfMVSQojl/QQYAHUzlNtvYPBhl2Xn5672gqBFxSmXF0WPpCTCfg+/EwUDBwkixeM4TmqZjzSbTFU1J8W00RiaTtUxMTJSfzctFd4Yq49eGJ6ekNETHxGyG50jQkWDAcoA+BqjSbDaXA/QqvBtFBWg6QGuJtSaapr7jB7AWrV0C6pguWAZurIeNFCaTqUxbUnwd3lkRAjoO0JswStApEGs1jJs4jusw9vTcEcI7LTBA3wA02mI2X/WFgvIIxCQC6EmIdQ7P898qb1Xs7O7qGiVrWWaa4C5PZopEy6RSKQfTYS8oRUYO1i3Hh4e6mlSA2sjhLHgwMdkoA04lI1noV8BVn/Nzsu/iFHTP2cIiHSTR9tNZaqYgP28/iecv4nA4ajmXi7NYLKPkcFbiDYomdcxNVVoul6s9JytzC/mYWxEVtfDQkbQKiUSyw26368/k5iTBexvZSxA0bD4Zx0An0E4B3Nfz5cu+zs4OJ+tgQwOBlfHxcSujo7MHBwfTLpZq69Cdq2NjFyWnpFaGhYVtA3hdU2PD4ecGQ78AhxjnQi6o29va1lVX3TNibAUwniSyq7PT+qKxcQjmduEHX0lQqSIgUZaOj4+FwyM2ipEP3d1msHRvQdG5GoQnqDYWAviEYDmErw/G1t7e3hAYQwiY+tm5Pn36aCdusATS+QsWDOBa8ArWInqGga6FltnQzcPDlrKvRmMTKSMRroXQ3AXd3fzq5ZCvQZ7kOnb8ONQXbYd+6/pNmBd70pXnfHPBAy8pKsojUNYruzmSEwzp0e5fwNCBFIFc7CXMZHbzIn9JT9wrJA/nVVasv8084PvVVVvftLbavIPvK6kHDqoUa9Zc+03J8V6WTike8FzpXJ4UtzUQOEIux98oCAdHzYCIJzsQw5M6s0LC+D01NIPxmQQz1D+SWfAs+D8FO1mn6w9uHUJ90zPSQOAvcdWOxERD4q5dSwjA/0KxuNmg1294/+7tGLlFuIOy+NbNG0b4s3YSSwIqyzr4Z/qnlv7+/iE/N42/FjokJBQ3lmI7JteUQK5E0Ajp6fZgLUaw0LNDp7juuomL2WCtRfkhwACjULOQ0RiwkAAAAABJRU5ErkJggg==");background-repeat:no-repeat}
#menu h1:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQUNCOTdFQkY0MkQxMUVGOUM0OUMyQTRDNjAyNzhENiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQUNCOTdFQUY0MkQxMUVGOUM0OUMyQTRDNjAyNzhENiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pq1mg9cAAAQtSURBVHja7JZdTFxFFIDP3J9dCgqUQimQIlBSWNoCNfVBYmo0jX9Jg014aYrWFzWGRl9MTHzpiy8k2kbrm9qUWtMaY9S2RqV9ADQm9o/+pHsvhW5Lw8/iLu6PC9yfvTOeWWbbC9ktlPWRk5ydvWfmzjfnzJkzlxz+7HNYSpIeD1QEAtB2+kew8vKgwdXn9Wsw1uR7tQTg+zhjfRs0fTeazWCT71ARwLt8jANgn0nMNO+9d+82nw6VSZCj3PE1VhcDnJIBpDnG8tC0TmvYvC8N5YJ9yq6C/L4/6je9jo8eVJITOMjY9lJCdBUdn6D0Sq0+9B6alTpZ7okwNrjGrzWjPnkwHO4oJKR8h8fzJfaXcLiUA3TLWkJ+x+WvQeglhL6N5jhqZIqxbyo1vQP/z6GOW5QN8nfI/KtrOVhZLogwllIuE4xVo6eXEJo3TumFOn2oS0D/Rv23WtPfxPYxVCvU5DuL41pMAOOWbf+ENu4sWR4YgUlVBUdRQHIcKJPlEQyvGqT02mLofC6BhRrFBPuhEOAZG20HJoOvHItEJtEeQ7WXFWrFtmGq+gm4+NLL6DUF23Ei3O4hpLRKVXkY/nFBRSKDjUlVxR8+Coc7BTSEGuZZr8w7xN6nlBZhS7LBqWHc3n/kyAkxaV2osWG4RJKqrtRvOluu6S0PtvCBxCg9iZtsBSwrJBYXEdFgKTAhpFuW5aW8v4p6RoTV7Bwb23F848aLxYRUhn2NN0o13Sf6kukX6vWhT7E5zoMm+mwOTTGxgIzfCQT2+v03bcu0vNmoLa2tzTW1tR+GpsNvHeru/pVP0FlcXHG4YsMFflSweEwdjUaf/2AyeEtEhWFincMM2/XzzOxzHaOjf6HNSIP5Sio1vz8+0NcXdncslqfb2sokSSqfTSRKRMbGTkSjE6hb0GM/h+8rKvoOwTtFAiUtxkYNQqI3TYNHkztlusEwMjJsiDMXzQZ+vLCQZy1gVFQxiWQ+u9P29g/EMMxNdxsbfhm2rH4+FHWWg6s0/QC2B0W1WjBvCvxOV9fXGHUD9zn5kD1el0oy6tzPhdM1tQD9A/ydWI0+9KKA8uShYogtkkpKJ9UCsKKoW7N56pIU0HGonDaMtG4H6OkBkVBxETUmgOljNZfxiPKfb0+dfGHw8uXE4lW55bX9b7Rt3bbtC/eR4wXFJY7rHC9dG/hPQX4BD820WHVGcNn69fHUTSPL9ydXDWPFF0wKLMkSB89wcPfHn9BMA03TnF0MxgKwYnDO9/EqeBW8Cl4Ati07ufTXD0ufb/J/gBW8Ejfvbm8/375nT6kAZB6oKH+e7+196sb1azPuC33FHh87+tVd/AKxhSdZ1bJMeq73t0gwGOT3duJR6nLGr1aPx8snzuflWFxr2ULpiAt++mEfDI8CTtdsb7p2Z9tmEWIrV2+5/CfAAOVxxSK4gGWJAAAAAElFTkSuQmCC")}
.rtl table.layout tbody td{display:flex}
.rtl table.layout~table thead th:first-child,.rtl table.layout~table tbody td:first-child{text-align:right !important}
.rtl table.layout~table thead th:last-child,.rtl table.layout~table tbody td:last-child{text-align:left !important}
h1{padding:.6em .4em;background:#c60;border:1px solid #894501;text-align:left}
#h1{color:#fff}
.version{color:#ddd;margin-left:8px}
@@ -99,7 +98,7 @@ code{background:#f0d6d6;padding:.2em .5em}
table code{font-size:130%;background:#f5e8ce;padding:.1em .3em}
code.jush-sql{background:#f0e8d6}
.rtl p code.jush-sql{background-position:right;clear:right;float:right}
pre.sqlarea{background:#e0e0e0;padding:5px}
pre{background:#e0e0e0 !important;padding:5px}
textarea{font-size:120%}
.ltr p.count{font-size:90%;margin:.8em 20px 8px 0}
.rtl p.count{font-size:90%;margin:.8em 0 8px 20px}
@@ -119,12 +118,12 @@ table{border-spacing:0}
table,td,th{border:0;border-collapse:separate}
.ltr table{margin:1.9em 0 0 0}
.rtl table{margin:1.9em 0 0 0}
.rtl table tbody td,.rtl table tbody th{text-align:right}
.rtl table tbody td,.rtl table tbody th{text-align:right !important}
.ltr table thead td:first-child,.ltr table thead th:first-child{border-left:1px solid #999}
.rtl table thead td:first-child,.rtl table thead th:first-child{border-right:1px solid #999}
table thead td,table thead th{height:1.6em;border-top:1px solid #999;border-bottom:1px solid #999}
.ltr table thead td,.ltr table thead th{border-right:1px solid #999}
.rtl table thead td,.rtl table thead th{border-left:1px solid #999;text-align:right !important}
.rtl table thead td,.rtl table thead th{border-left:1px solid #999}
table tbody tr:first-child td,table tbody tr:first-child th{border-top:1px solid #999}
.ltr table tbody td:first-child,.ltr table tbody th:first-child{border-left:1px solid #999}
.rtl table tbody td:first-child,.rtl table tbody th:first-child{border-right:1px solid #999}
@@ -421,9 +420,12 @@ input[type=radio]{margin-bottom:5px}
.rtl input[type=checkbox],.rtl input[type=radio],.rtl input[type=range],.rtl progress{margin-left:5px}
.ltr input[type=submit]{margin-right:10px}
.rtl input[type=submit]{margin-left:10px}
.ltr table.layout label,.ltr label.jsonly{margin-left:8px}
.rtl table.layout label,.rtl label.jsonly{margin-right:8px}
input,button,select,.sqlarea{border-radius:3px}
.sqlarea{background:#e0e0e0;font-size:105%}
fieldset a{line-height:unset}
input[type=submit]{padding:2px 6px}
.ltr table.layout label,.ltr label.jsonly{margin-left:8px}
.rtl table.layout label,.rtl label.jsonly{margin-right:8px}
#menu{padding:0 0 30px 0}
.ltr .logout{right:0;left:auto;margin-top:.5em}
.rtl .logout{left:0;right:auto;margin-top:.5em}

View File

@@ -2,8 +2,8 @@
* @package Adminer.css - Theme CSS for Adminer --- [theme dark] blue B (with icons)
*
*//*!
* @version 4.17.1.2
* @date Thu, 27 Feb 2025 09:28:32 +0100
* @version 5.0.4.1
* @date Wed, 12 Mar 2025 21:35:32 +0100
* @author Robert Mesaros
* @copyright Copyright 2025 Robert Mesaros, rmSOFT, Slovakia
* @web https://www.rmsoft.sk
@@ -35,10 +35,6 @@
* Modified icons by Robert Mesaros
*
*/
#menu{padding:0 0 30px 0}
.ltr .logout{right:0;left:auto;margin-top:.5em}
.rtl .logout{left:0;right:auto;margin-top:.5em}
.rtl table.layout tbody{direction:ltr}
html{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
*,*:before,*:after{box-sizing:inherit}
body{color:#829bb0;background:#002240;font-family:Verdana,Arial,Helvetica,sans-serif;font-weight:normal;cursor:default;margin:0}
@@ -50,6 +46,9 @@ img{width:100%;max-width:100%}
#menu h1{background-color:#1d4e78}
#menu h1{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozNDA3NDEwQ0Y0MkQxMUVGODA4RUNENTRFQzJENUU4RCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozNDA3NDEwQkY0MkQxMUVGODA4RUNENTRFQzJENUU4RCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph59M4AAAAPFSURBVHja7JZrSFNRHMDvvVvq1mNlucBK0g/lh+Us6oPrU0ERRFgRUqYUVEb2qTJ0vko0ZbMHiBT0sizSXEUfJGzN1CjBQLPCR/RwSYKp23RO3e527/r/57mxxpblhCD8w59z7t2553f+zx36Ulk5FYxkZpyiijVahUgkqnc62cu5arUGXrMl2tIkhmGuu91uGp4HXre0qB490A3C3IXfMVSQojl/QQYAHUzlNtvYPBhl2Xn5672gqBFxSmXF0WPpCTCfg+/EwUDBwkixeM4TmqZjzSbTFU1J8W00RiaTtUxMTJSfzctFd4Yq49eGJ6ekNETHxGyG50jQkWDAcoA+BqjSbDaXA/QqvBtFBWg6QGuJtSaapr7jB7AWrV0C6pguWAZurIeNFCaTqUxbUnwd3lkRAjoO0JswStApEGs1jJs4jusw9vTcEcI7LTBA3wA02mI2X/WFgvIIxCQC6EmIdQ7P898qb1Xs7O7qGiVrWWaa4C5PZopEy6RSKQfTYS8oRUYO1i3Hh4e6mlSA2sjhLHgwMdkoA04lI1noV8BVn/Nzsu/iFHTP2cIiHSTR9tNZaqYgP28/iecv4nA4ajmXi7NYLKPkcFbiDYomdcxNVVoul6s9JytzC/mYWxEVtfDQkbQKiUSyw26368/k5iTBexvZSxA0bD4Zx0An0E4B3Nfz5cu+zs4OJ+tgQwOBlfHxcSujo7MHBwfTLpZq69Cdq2NjFyWnpFaGhYVtA3hdU2PD4ecGQ78AhxjnQi6o29va1lVX3TNibAUwniSyq7PT+qKxcQjmduEHX0lQqSIgUZaOj4+FwyM2ipEP3d1msHRvQdG5GoQnqDYWAviEYDmErw/G1t7e3hAYQwiY+tm5Pn36aCdusATS+QsWDOBa8ArWInqGga6FltnQzcPDlrKvRmMTKSMRroXQ3AXd3fzq5ZCvQZ7kOnb8ONQXbYd+6/pNmBd70pXnfHPBAy8pKsojUNYruzmSEwzp0e5fwNCBFIFc7CXMZHbzIn9JT9wrJA/nVVasv8084PvVVVvftLbavIPvK6kHDqoUa9Zc+03J8V6WTike8FzpXJ4UtzUQOEIux98oCAdHzYCIJzsQw5M6s0LC+D01NIPxmQQz1D+SWfAs+D8FO1mn6w9uHUJ90zPSQOAvcdWOxERD4q5dSwjA/0KxuNmg1294/+7tGLlFuIOy+NbNG0b4s3YSSwIqyzr4Z/qnlv7+/iE/N42/FjokJBQ3lmI7JteUQK5E0Ajp6fZgLUaw0LNDp7juuomL2WCtRfkhwACjULOQ0RiwkAAAAABJRU5ErkJggg==");background-repeat:no-repeat;mix-blend-mode:difference}
#menu h1:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQUNCOTdFQkY0MkQxMUVGOUM0OUMyQTRDNjAyNzhENiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQUNCOTdFQUY0MkQxMUVGOUM0OUMyQTRDNjAyNzhENiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pq1mg9cAAAQtSURBVHja7JZdTFxFFIDP3J9dCgqUQimQIlBSWNoCNfVBYmo0jX9Jg014aYrWFzWGRl9MTHzpiy8k2kbrm9qUWtMaY9S2RqV9ADQm9o/+pHsvhW5Lw8/iLu6PC9yfvTOeWWbbC9ktlPWRk5ydvWfmzjfnzJkzlxz+7HNYSpIeD1QEAtB2+kew8vKgwdXn9Wsw1uR7tQTg+zhjfRs0fTeazWCT71ARwLt8jANgn0nMNO+9d+82nw6VSZCj3PE1VhcDnJIBpDnG8tC0TmvYvC8N5YJ9yq6C/L4/6je9jo8eVJITOMjY9lJCdBUdn6D0Sq0+9B6alTpZ7okwNrjGrzWjPnkwHO4oJKR8h8fzJfaXcLiUA3TLWkJ+x+WvQeglhL6N5jhqZIqxbyo1vQP/z6GOW5QN8nfI/KtrOVhZLogwllIuE4xVo6eXEJo3TumFOn2oS0D/Rv23WtPfxPYxVCvU5DuL41pMAOOWbf+ENu4sWR4YgUlVBUdRQHIcKJPlEQyvGqT02mLofC6BhRrFBPuhEOAZG20HJoOvHItEJtEeQ7WXFWrFtmGq+gm4+NLL6DUF23Ei3O4hpLRKVXkY/nFBRSKDjUlVxR8+Coc7BTSEGuZZr8w7xN6nlBZhS7LBqWHc3n/kyAkxaV2osWG4RJKqrtRvOluu6S0PtvCBxCg9iZtsBSwrJBYXEdFgKTAhpFuW5aW8v4p6RoTV7Bwb23F848aLxYRUhn2NN0o13Sf6kukX6vWhT7E5zoMm+mwOTTGxgIzfCQT2+v03bcu0vNmoLa2tzTW1tR+GpsNvHeru/pVP0FlcXHG4YsMFflSweEwdjUaf/2AyeEtEhWFincMM2/XzzOxzHaOjf6HNSIP5Sio1vz8+0NcXdncslqfb2sokSSqfTSRKRMbGTkSjE6hb0GM/h+8rKvoOwTtFAiUtxkYNQqI3TYNHkztlusEwMjJsiDMXzQZ+vLCQZy1gVFQxiWQ+u9P29g/EMMxNdxsbfhm2rH4+FHWWg6s0/QC2B0W1WjBvCvxOV9fXGHUD9zn5kD1el0oy6tzPhdM1tQD9A/ydWI0+9KKA8uShYogtkkpKJ9UCsKKoW7N56pIU0HGonDaMtG4H6OkBkVBxETUmgOljNZfxiPKfb0+dfGHw8uXE4lW55bX9b7Rt3bbtC/eR4wXFJY7rHC9dG/hPQX4BD820WHVGcNn69fHUTSPL9ydXDWPFF0wKLMkSB89wcPfHn9BMA03TnF0MxgKwYnDO9/EqeBW8Cl4Ati07ufTXD0ufb/J/gBW8Ejfvbm8/375nT6kAZB6oKH+e7+196sb1azPuC33FHh87+tVd/AKxhSdZ1bJMeq73t0gwGOT3duJR6nLGr1aPx8snzuflWFxr2ULpiAt++mEfDI8CTtdsb7p2Z9tmEWIrV2+5/CfAAOVxxSK4gGWJAAAAAElFTkSuQmCC");mask-image:linear-gradient(black, transparent);-webkit-mask-image:linear-gradient(black, transparent);mix-blend-mode:unset;background-color:unset}
.rtl table.layout tbody td{display:flex}
.rtl table.layout~table thead th:first-child,.rtl table.layout~table tbody td:first-child{text-align:right !important}
.rtl table.layout~table thead th:last-child,.rtl table.layout~table tbody td:last-child{text-align:left !important}
h1{padding:.6em .4em;background:#1d4e78;border:1px solid #f2ddaf;text-align:left}
#h1{color:#fff}
.version{color:#ddd;margin-left:8px}
@@ -100,7 +99,7 @@ code{background:#81a0bc;padding:.2em .5em}
table code{font-size:130%;background:#154167;padding:.1em .3em}
code.jush-sql{background:#c5d8e9}
.rtl p code.jush-sql{background-position:right;clear:right;float:right}
pre.sqlarea{background:#a7c3dc;padding:5px}
pre{background:#a7c3dc !important;padding:5px}
textarea{font-size:120%}
.ltr p.count{font-size:90%;margin:.8em 20px 8px 0}
.rtl p.count{font-size:90%;margin:.8em 0 8px 20px}
@@ -120,12 +119,12 @@ table{border-spacing:0}
table,td,th{border:0;border-collapse:separate}
.ltr table{margin:1.9em 0 0 0}
.rtl table{margin:1.9em 0 0 0}
.rtl table tbody td,.rtl table tbody th{text-align:right}
.rtl table tbody td,.rtl table tbody th{text-align:right !important}
.ltr table thead td:first-child,.ltr table thead th:first-child{border-left:1px solid #1e5687}
.rtl table thead td:first-child,.rtl table thead th:first-child{border-right:1px solid #1e5687}
table thead td,table thead th{height:1.6em;border-top:1px solid #1e5687;border-bottom:1px solid #1e5687}
.ltr table thead td,.ltr table thead th{border-right:1px solid #1e5687}
.rtl table thead td,.rtl table thead th{border-left:1px solid #1e5687;text-align:right !important}
.rtl table thead td,.rtl table thead th{border-left:1px solid #1e5687}
table tbody tr:first-child td,table tbody tr:first-child th{border-top:1px solid #1e5687}
.ltr table tbody td:first-child,.ltr table tbody th:first-child{border-left:1px solid #1e5687}
.rtl table tbody td:first-child,.rtl table tbody th:first-child{border-right:1px solid #1e5687}
@@ -422,9 +421,12 @@ input[type=radio]{margin-bottom:5px}
.rtl input[type=checkbox],.rtl input[type=radio],.rtl input[type=range],.rtl progress{margin-left:5px}
.ltr input[type=submit]{margin-right:10px}
.rtl input[type=submit]{margin-left:10px}
.ltr table.layout label,.ltr label.jsonly{margin-left:8px}
.rtl table.layout label,.rtl label.jsonly{margin-right:8px}
input,button,select,.sqlarea{border-radius:3px}
.sqlarea{background:#a7c3dc;font-size:105%}
fieldset a{line-height:unset}
input[type=submit]{padding:2px 6px}
.ltr table.layout label,.ltr label.jsonly{margin-left:8px}
.rtl table.layout label,.rtl label.jsonly{margin-right:8px}
#menu{padding:0 0 30px 0}
.ltr .logout{right:0;left:auto;margin-top:.5em}
.rtl .logout{left:0;right:auto;margin-top:.5em}

View File

@@ -2,8 +2,8 @@
* @package Adminer.css - Theme CSS for Adminer --- [theme light] blue B (with icons)
*
*//*!
* @version 4.17.1.2
* @date Thu, 27 Feb 2025 09:28:32 +0100
* @version 5.0.4.1
* @date Wed, 12 Mar 2025 21:35:32 +0100
* @author Robert Mesaros
* @copyright Copyright 2025 Robert Mesaros, rmSOFT, Slovakia
* @web https://www.rmsoft.sk
@@ -35,10 +35,6 @@
* Modified icons by Robert Mesaros
*
*/
#menu{padding:0 0 30px 0}
.ltr .logout{right:0;left:auto;margin-top:.5em}
.rtl .logout{left:0;right:auto;margin-top:.5em}
.rtl table.layout tbody{direction:ltr}
html{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
*,*:before,*:after{box-sizing:inherit}
body{color:#000;background:#82a7c0;font-family:Verdana,Arial,Helvetica,sans-serif;font-weight:normal;cursor:default;margin:0}
@@ -49,6 +45,9 @@ img{width:100%;max-width:100%}
#menu #h1{margin-left:10px}
#menu h1{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozNDA3NDEwQ0Y0MkQxMUVGODA4RUNENTRFQzJENUU4RCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozNDA3NDEwQkY0MkQxMUVGODA4RUNENTRFQzJENUU4RCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph59M4AAAAPFSURBVHja7JZrSFNRHMDvvVvq1mNlucBK0g/lh+Us6oPrU0ERRFgRUqYUVEb2qTJ0vko0ZbMHiBT0sizSXEUfJGzN1CjBQLPCR/RwSYKp23RO3e527/r/57mxxpblhCD8w59z7t2553f+zx36Ulk5FYxkZpyiijVahUgkqnc62cu5arUGXrMl2tIkhmGuu91uGp4HXre0qB490A3C3IXfMVSQojl/QQYAHUzlNtvYPBhl2Xn5672gqBFxSmXF0WPpCTCfg+/EwUDBwkixeM4TmqZjzSbTFU1J8W00RiaTtUxMTJSfzctFd4Yq49eGJ6ekNETHxGyG50jQkWDAcoA+BqjSbDaXA/QqvBtFBWg6QGuJtSaapr7jB7AWrV0C6pguWAZurIeNFCaTqUxbUnwd3lkRAjoO0JswStApEGs1jJs4jusw9vTcEcI7LTBA3wA02mI2X/WFgvIIxCQC6EmIdQ7P898qb1Xs7O7qGiVrWWaa4C5PZopEy6RSKQfTYS8oRUYO1i3Hh4e6mlSA2sjhLHgwMdkoA04lI1noV8BVn/Nzsu/iFHTP2cIiHSTR9tNZaqYgP28/iecv4nA4ajmXi7NYLKPkcFbiDYomdcxNVVoul6s9JytzC/mYWxEVtfDQkbQKiUSyw26368/k5iTBexvZSxA0bD4Zx0An0E4B3Nfz5cu+zs4OJ+tgQwOBlfHxcSujo7MHBwfTLpZq69Cdq2NjFyWnpFaGhYVtA3hdU2PD4ecGQ78AhxjnQi6o29va1lVX3TNibAUwniSyq7PT+qKxcQjmduEHX0lQqSIgUZaOj4+FwyM2ipEP3d1msHRvQdG5GoQnqDYWAviEYDmErw/G1t7e3hAYQwiY+tm5Pn36aCdusATS+QsWDOBa8ArWInqGga6FltnQzcPDlrKvRmMTKSMRroXQ3AXd3fzq5ZCvQZ7kOnb8ONQXbYd+6/pNmBd70pXnfHPBAy8pKsojUNYruzmSEwzp0e5fwNCBFIFc7CXMZHbzIn9JT9wrJA/nVVasv8084PvVVVvftLbavIPvK6kHDqoUa9Zc+03J8V6WTike8FzpXJ4UtzUQOEIux98oCAdHzYCIJzsQw5M6s0LC+D01NIPxmQQz1D+SWfAs+D8FO1mn6w9uHUJ90zPSQOAvcdWOxERD4q5dSwjA/0KxuNmg1294/+7tGLlFuIOy+NbNG0b4s3YSSwIqyzr4Z/qnlv7+/iE/N42/FjokJBQ3lmI7JteUQK5E0Ajp6fZgLUaw0LNDp7juuomL2WCtRfkhwACjULOQ0RiwkAAAAABJRU5ErkJggg==");background-repeat:no-repeat}
#menu h1:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQUNCOTdFQkY0MkQxMUVGOUM0OUMyQTRDNjAyNzhENiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQUNCOTdFQUY0MkQxMUVGOUM0OUMyQTRDNjAyNzhENiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFODREQjFFMzE2RjRFRjExOTIyNkVEQzE2RkYzQkNDRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pq1mg9cAAAQtSURBVHja7JZdTFxFFIDP3J9dCgqUQimQIlBSWNoCNfVBYmo0jX9Jg014aYrWFzWGRl9MTHzpiy8k2kbrm9qUWtMaY9S2RqV9ADQm9o/+pHsvhW5Lw8/iLu6PC9yfvTOeWWbbC9ktlPWRk5ydvWfmzjfnzJkzlxz+7HNYSpIeD1QEAtB2+kew8vKgwdXn9Wsw1uR7tQTg+zhjfRs0fTeazWCT71ARwLt8jANgn0nMNO+9d+82nw6VSZCj3PE1VhcDnJIBpDnG8tC0TmvYvC8N5YJ9yq6C/L4/6je9jo8eVJITOMjY9lJCdBUdn6D0Sq0+9B6alTpZ7okwNrjGrzWjPnkwHO4oJKR8h8fzJfaXcLiUA3TLWkJ+x+WvQeglhL6N5jhqZIqxbyo1vQP/z6GOW5QN8nfI/KtrOVhZLogwllIuE4xVo6eXEJo3TumFOn2oS0D/Rv23WtPfxPYxVCvU5DuL41pMAOOWbf+ENu4sWR4YgUlVBUdRQHIcKJPlEQyvGqT02mLofC6BhRrFBPuhEOAZG20HJoOvHItEJtEeQ7WXFWrFtmGq+gm4+NLL6DUF23Ei3O4hpLRKVXkY/nFBRSKDjUlVxR8+Coc7BTSEGuZZr8w7xN6nlBZhS7LBqWHc3n/kyAkxaV2osWG4RJKqrtRvOluu6S0PtvCBxCg9iZtsBSwrJBYXEdFgKTAhpFuW5aW8v4p6RoTV7Bwb23F848aLxYRUhn2NN0o13Sf6kukX6vWhT7E5zoMm+mwOTTGxgIzfCQT2+v03bcu0vNmoLa2tzTW1tR+GpsNvHeru/pVP0FlcXHG4YsMFflSweEwdjUaf/2AyeEtEhWFincMM2/XzzOxzHaOjf6HNSIP5Sio1vz8+0NcXdncslqfb2sokSSqfTSRKRMbGTkSjE6hb0GM/h+8rKvoOwTtFAiUtxkYNQqI3TYNHkztlusEwMjJsiDMXzQZ+vLCQZy1gVFQxiWQ+u9P29g/EMMxNdxsbfhm2rH4+FHWWg6s0/QC2B0W1WjBvCvxOV9fXGHUD9zn5kD1el0oy6tzPhdM1tQD9A/ydWI0+9KKA8uShYogtkkpKJ9UCsKKoW7N56pIU0HGonDaMtG4H6OkBkVBxETUmgOljNZfxiPKfb0+dfGHw8uXE4lW55bX9b7Rt3bbtC/eR4wXFJY7rHC9dG/hPQX4BD820WHVGcNn69fHUTSPL9ydXDWPFF0wKLMkSB89wcPfHn9BMA03TnF0MxgKwYnDO9/EqeBW8Cl4Ati07ufTXD0ufb/J/gBW8Ejfvbm8/375nT6kAZB6oKH+e7+196sb1azPuC33FHh87+tVd/AKxhSdZ1bJMeq73t0gwGOT3duJR6nLGr1aPx8snzuflWFxr2ULpiAt++mEfDI8CTtdsb7p2Z9tmEWIrV2+5/CfAAOVxxSK4gGWJAAAAAElFTkSuQmCC")}
.rtl table.layout tbody td{display:flex}
.rtl table.layout~table thead th:first-child,.rtl table.layout~table tbody td:first-child{text-align:right !important}
.rtl table.layout~table thead th:last-child,.rtl table.layout~table tbody td:last-child{text-align:left !important}
h1{padding:.6em .4em;background:#1d5377;border:1px solid #f2ddaf;text-align:left}
#h1{color:#fff}
.version{color:#ddd;margin-left:8px}
@@ -99,7 +98,7 @@ code{background:#93b3c8;padding:.2em .5em}
table code{font-size:130%;background:#bfd9eb;padding:.1em .3em}
code.jush-sql{background:#d8e9f4}
.rtl p code.jush-sql{background-position:right;clear:right;float:right}
pre.sqlarea{background:#aac6d8;padding:5px}
pre{background:#aac6d8 !important;padding:5px}
textarea{font-size:120%}
.ltr p.count{font-size:90%;margin:.8em 20px 8px 0}
.rtl p.count{font-size:90%;margin:.8em 0 8px 20px}
@@ -119,12 +118,12 @@ table{border-spacing:0}
table,td,th{border:0;border-collapse:separate}
.ltr table{margin:1.9em 0 0 0}
.rtl table{margin:1.9em 0 0 0}
.rtl table tbody td,.rtl table tbody th{text-align:right}
.rtl table tbody td,.rtl table tbody th{text-align:right !important}
.ltr table thead td:first-child,.ltr table thead th:first-child{border-left:1px solid #0e344e}
.rtl table thead td:first-child,.rtl table thead th:first-child{border-right:1px solid #0e344e}
table thead td,table thead th{height:1.6em;border-top:1px solid #0e344e;border-bottom:1px solid #0e344e}
.ltr table thead td,.ltr table thead th{border-right:1px solid #0e344e}
.rtl table thead td,.rtl table thead th{border-left:1px solid #0e344e;text-align:right !important}
.rtl table thead td,.rtl table thead th{border-left:1px solid #0e344e}
table tbody tr:first-child td,table tbody tr:first-child th{border-top:1px solid #527d9a}
.ltr table tbody td:first-child,.ltr table tbody th:first-child{border-left:1px solid #527d9a}
.rtl table tbody td:first-child,.rtl table tbody th:first-child{border-right:1px solid #527d9a}
@@ -421,9 +420,12 @@ input[type=radio]{margin-bottom:5px}
.rtl input[type=checkbox],.rtl input[type=radio],.rtl input[type=range],.rtl progress{margin-left:5px}
.ltr input[type=submit]{margin-right:10px}
.rtl input[type=submit]{margin-left:10px}
.ltr table.layout label,.ltr label.jsonly{margin-left:8px}
.rtl table.layout label,.rtl label.jsonly{margin-right:8px}
input,button,select,.sqlarea{border-radius:3px}
.sqlarea{background:#aac6d8;font-size:105%}
fieldset a{line-height:unset}
input[type=submit]{padding:2px 6px}
.ltr table.layout label,.ltr label.jsonly{margin-left:8px}
.rtl table.layout label,.rtl label.jsonly{margin-right:8px}
#menu{padding:0 0 30px 0}
.ltr .logout{right:0;left:auto;margin-top:.5em}
.rtl .logout{left:0;right:auto;margin-top:.5em}

View File

@@ -20,7 +20,7 @@ if ($adminer->homepage()) {
foreach (table_status() as $table => $row) {
$name = $adminer->tableName($row);
if (isset($row["Engine"]) && $name != "") {
if ($name != "") {
echo '<tr><td>' . checkbox("tables[]", $table, in_array($table, (array) $_POST["tables"], true));
echo "<th><a href='" . h(ME) . 'select=' . urlencode($table) . "'>$name</a>";
$val = format_number($row["Rows"]);

View File

@@ -1,6 +1,5 @@
<?php
function adminer_object() {
class AdminerCds extends Adminer\Adminer {
function name() {

View File

@@ -2,8 +2,8 @@
namespace Adminer;
class Adminer {
var $operators = array("<=", ">=");
var $_values = array();
public $operators = array("<=", ">=");
private $values = array();
function name() {
return "<a href='https://www.adminer.org/editor/'" . target_blank() . " id='h1'>" . lang('Editor') . "</a>";
@@ -90,7 +90,10 @@ class Adminer {
}
function tableName($tableStatus) {
return h($tableStatus["Comment"] != "" ? $tableStatus["Comment"] : $tableStatus["Name"]);
return h(isset($tableStatus["Engine"])
? ($tableStatus["Comment"] != "" ? $tableStatus["Comment"] : $tableStatus["Name"])
: "" // ignore views
);
}
function fieldName($field, $order = 0) {
@@ -175,7 +178,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row //! requires MySQL 5
$ids[$row[$key]] = q($row[$key]);
}
// uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow
$descriptions = $this->_values[$table];
$descriptions = $this->values[$table];
if (!$descriptions) {
$descriptions = get_key_vals("SELECT $id, $name FROM " . table($table) . " WHERE $id IN (" . implode(", ", $ids) . ")");
}
@@ -248,7 +251,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row //! requires MySQL 5
);
echo "</div>\n";
unset($columns[$name]);
} elseif (is_array($options = $this->_foreignKeyOptions($_GET["select"], $name))) {
} elseif (is_array($options = $this->foreignKeyOptions($_GET["select"], $name))) {
if ($fields[$name]["null"]) {
$options[0] = '(' . lang('empty') . ')';
}
@@ -482,7 +485,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row //! requires MySQL 5
. enum_input("radio", $attrs, $field, ($value || isset($_GET["select"]) ? $value : 0), ($field["null"] ? "" : null))
;
}
$options = $this->_foreignKeyOptions($table, $field["field"], $value);
$options = $this->foreignKeyOptions($table, $field["field"], $value);
if ($options !== null) {
return (is_array($options)
? "<select$attrs>" . optionlist($options, $value, true) . "</select>"
@@ -574,6 +577,9 @@ qsl('div').onclick = whisperClick;", "")
return $ext;
}
function dumpFooter() {
}
function importServerPath() {
}
@@ -629,7 +635,7 @@ qsl('div').onclick = whisperClick;", "")
foreach ($tables as $row) {
echo '<li>';
$name = $this->tableName($row);
if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name
if ($name != "") { // ignore tables without name
echo "<a href='" . h(ME) . 'select=' . urlencode($row["Name"]) . "'"
. bold($_GET["select"] == $row["Name"] || $_GET["edit"] == $row["Name"], "select")
. " title='" . lang('Select data') . "'>$name</a>\n"
@@ -651,9 +657,9 @@ qsl('div').onclick = whisperClick;", "")
}
}
function _foreignKeyOptions($table, $column, $value = null) {
private function foreignKeyOptions($table, $column, $value = null) {
if (list($target, $id, $name) = $this->_foreignColumn(column_foreign_keys($table), $column)) {
$return = &$this->_values[$target];
$return = &$this->values[$target];
if ($return === null) {
$table_status = table_status($target);
$return = ($table_status["Rows"] > 1000 ? "" : array("" => "") + get_key_vals("SELECT $id, $name FROM " . table($target) . " ORDER BY 2"));

2
externals/jush vendored

View File

@@ -44,7 +44,7 @@ foreach (glob(__DIR__ . "/adminer/lang/" . ($_SESSION["lang"] ?: "*") . ".inc.ph
unset($messages[$en]);
$en_fullstop = (substr($en, -2, 1) == ".");
//! check in array
if ($en != "','" && ($en_fullstop xor preg_match("~($fullstop)'\)?\$~", $line, $match))) {
if ($en != "','" && ($en_fullstop xor preg_match("~$fullstop'\)?\$~", $line))) {
if ($lang != ($en_fullstop ? "ja" : "he")) { // fullstop is optional in 'ja', forbidden in 'he'
echo "$filename:" . (substr_count($file, "\n", 0, $offset) + 1) . ":Not matching fullstop: $line\n";
}

144
php_shrink.inc.php Normal file
View File

@@ -0,0 +1,144 @@
<?php
/** Minify PHP code with these operations:
* remove extra {}
* minify variables
* strip comments, preserve only the first doc-comment
* join consecutive echo
* change ?>HTML<?php to echo 'HTML' if it saves space
* strip public visibility or change it to var
*
* @param string PHP code including <?php
* @return string
*/
function php_shrink($input) {
// based on http://latrine.dgx.cz/jak-zredukovat-php-skripty
$input = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $input);
$special_variables = array_flip(array('$this', '$GLOBALS', '$_GET', '$_POST', '$_FILES', '$_COOKIE', '$_SESSION', '$_SERVER', '$http_response_header', '$php_errormsg'));
$short_variables = array();
$shortening = true;
$tokens = token_get_all($input);
// remove unnecessary { }
//! change also `while () { if () {;} }` to `while () if () ;` but be careful about `if () { if () { } } else { }
$shorten = 0;
$opening = -1;
foreach ($tokens as $i => $token) {
if (in_array($token[0], array(T_IF, T_ELSE, T_ELSEIF, T_WHILE, T_DO, T_FOR, T_FOREACH), true)) {
$shorten = ($token[0] == T_FOR ? 4 : 2);
$opening = -1;
} elseif (in_array($token[0], array(T_SWITCH, T_FUNCTION, T_CLASS, T_CLOSE_TAG), true)) {
$shorten = 0;
} elseif ($token === ';') {
$shorten--;
} elseif ($token === '{') {
if ($opening < 0) {
$opening = $i;
} elseif ($shorten > 1) {
$shorten = 0;
}
} elseif ($token === '}' && $opening >= 0 && $shorten == 1) {
unset($tokens[$opening]);
unset($tokens[$i]);
$shorten = 0;
$opening = -1;
}
}
$tokens = array_values($tokens);
foreach ($tokens as $i => $token) {
if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$short_variables[$token[1]]++;
}
}
arsort($short_variables);
$chars = implode(range('a', 'z')) . '_' . implode(range('A', 'Z'));
//! preserve variable names between versions if possible
$short_variables2 = array_splice($short_variables, strlen($chars));
ksort($short_variables);
ksort($short_variables2);
$short_variables += $short_variables2;
foreach (array_keys($short_variables) as $number => $key) {
$short_variables[$key] = short_identifier($number, $chars); // could use also numbers and \x7f-\xff
}
$set = array_flip(preg_split('//', '!"#$%&\'()*+,-./:;<=>?@[]^`{|}'));
$space = '';
$output = '';
$in_echo = false;
$doc_comment = false; // include only first /**
for (reset($tokens); list($i, $token) = each($tokens);) {
if (!is_array($token)) {
$token = array(0, $token);
}
if (
$tokens[$i+2][0] === T_CLOSE_TAG && $tokens[$i+3][0] === T_INLINE_HTML && $tokens[$i+4][0] === T_OPEN_TAG
&& strlen(add_apo_slashes($tokens[$i+3][1])) < strlen($tokens[$i+3][1]) + 3
) {
$tokens[$i+2] = array(T_ECHO, 'echo');
$tokens[$i+3] = array(T_CONSTANT_ENCAPSED_STRING, "'" . add_apo_slashes($tokens[$i+3][1]) . "'");
$tokens[$i+4] = array(0, ';');
}
if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) {
$space = "\n";
} else {
if ($token[0] == T_DOC_COMMENT) {
$doc_comment = true;
}
if ($token[0] == T_VAR || $token[0] == T_PUBLIC || $token[0] == T_PROTECTED || $token[0] == T_PRIVATE) {
if ($token[0] == T_PUBLIC) {
$token[1] = ($tokens[$i+2][1][0] == '$' ? 'var' : '');
}
$shortening = false;
} elseif (!$shortening) {
if ($token[1] == ';' || $token[0] == T_FUNCTION) {
$shortening = true;
}
} elseif ($token[0] == T_ECHO) {
$in_echo = true;
} elseif ($token[1] == ';' && $in_echo) {
if ($tokens[$i+1][0] === T_WHITESPACE && $tokens[$i+2][0] === T_ECHO) {
next($tokens);
$i++;
}
if ($tokens[$i+1][0] === T_ECHO) {
// join two consecutive echos
next($tokens);
$token[1] = ','; // '.' would conflict with "a".1+2 and would use more memory //! remove ',' and "," but not $var","
} else {
$in_echo = false;
}
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$token[1] = '$' . $short_variables[$token[1]];
}
if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
$space = '';
}
$output .= $space . $token[1];
$space = '';
}
}
return $output;
}
function short_identifier($number, $chars) {
$return = '';
while ($number >= 0) {
$return .= $chars[$number % strlen($chars)];
$number = floor($number / strlen($chars)) - 1;
}
return $return;
}
function add_apo_slashes($s) {
return addcslashes($s, "\\'");
}
if (!function_exists("each")) {
function each(&$arr) {
$key = key($arr);
next($arr);
return $key === null ? false : array($key, $arr[$key]);
}
}

View File

@@ -12,8 +12,6 @@
<rule ref="PSR12">
<exclude name="Generic.Whitespace.DisallowTabIndent"/><!-- Replaced by: Generic.Whitespace.DisallowSpaceIndent -->
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
<exclude name="PSR12.Operators.OperatorSpacing.NoSpaceBefore"/>
<exclude name="PSR12.Operators.OperatorSpacing.NoSpaceAfter"/>
<exclude name="PSR1.Classes.ClassDeclaration.MultipleClasses"/>
<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine"/><!-- Replaced by: Generic.Classes.OpeningBraceSameLine -->
<exclude name="PSR2.Classes.PropertyDeclaration.Underscore"/>
@@ -24,11 +22,12 @@
<!-- More readable. -->
<exclude name="PSR12.Files.FileHeader.SpacingAfterBlock"/>
<exclude name="PSR12.Classes.OpeningBraceSpace.Found"/>
<exclude name="PSR12.Operators.OperatorSpacing.NoSpaceBefore"/>
<exclude name="PSR12.Operators.OperatorSpacing.NoSpaceAfter"/>
<exclude name="Squiz.WhiteSpace.ControlStructureSpacing.SpacingBeforeClose"/>
<!-- Saves bytes. -->
<exclude name="PSR2.Classes.PropertyDeclaration.Multiple"/>
<exclude name="PSR2.Classes.PropertyDeclaration.VarUsed"/>
<exclude name="PSR2.Classes.PropertyDeclaration.ScopeMissing"/>
<exclude name="PSR12.Classes.ClassInstantiation.MissingParentheses"/>
<exclude name="Squiz.Scope.MethodScope.Missing"/>
@@ -46,7 +45,7 @@
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="310"/>
<property name="lineLimit" value="250"/>
</properties>
<exclude-pattern>adminer/lang/</exclude-pattern>
</rule>
@@ -79,4 +78,51 @@
<rule ref="Generic.VersionControl.GitMergeConflict"/>
<rule ref="Generic.Whitespace.DisallowSpaceIndent"/>
<rule ref="Generic.WhiteSpace.LanguageConstructSpacing"/>
<rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
<rule ref="Squiz.Classes.LowercaseClassKeywords"/>
<rule ref="Squiz.Classes.SelfMemberReference"/>
<rule ref="Squiz.CSS.ClassDefinitionNameSpacing"/>
<rule ref="Squiz.CSS.ColonSpacing"/>
<rule ref="Squiz.CSS.DuplicateClassDefinition"/>
<rule ref="Squiz.CSS.DuplicateStyleDefinition"/>
<rule ref="Squiz.CSS.EmptyClassDefinition"/>
<rule ref="Squiz.CSS.EmptyStyleDefinition"/>
<rule ref="Squiz.CSS.ForbiddenStyles"/>
<rule ref="Squiz.CSS.Indentation"/>
<rule ref="Squiz.CSS.MissingColon"/>
<rule ref="Squiz.CSS.Opacity"/>
<rule ref="Squiz.CSS.SemicolonSpacing"/>
<rule ref="Squiz.Functions.FunctionDuplicateArgument"/>
<rule ref="Squiz.Objects.ObjectMemberComma"/>
<rule ref="Squiz.Operators.IncrementDecrementUsage"/>
<rule ref="Squiz.Operators.ValidLogicalOperators"/>
<rule ref="Squiz.PHP.DiscouragedFunctions"/>
<rule ref="Squiz.PHP.Eval"/>
<rule ref="Squiz.PHP.Heredoc"/>
<rule ref="Squiz.PHP.InnerFunctions"/>
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
<rule ref="Squiz.PHP.NonExecutableCode"/>
<rule ref="Squiz.Scope.StaticThisUsage"/>
<rule ref="Squiz.WhiteSpace.FunctionOpeningBraceSpace"/>
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
<rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing"/>
<!--
This is slow and has false positives but it's useful occasionally.
https://github.com/PHPCompatibility/PHPCompatibility
<rule ref="PHPCompatibility"/>
<config name="testVersion" value="5.3-"/>
<rule ref="PHPCompatibility.Extensions.RemovedExtensions">
<exclude name="PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved"/>
<exclude name="PHPCompatibility.Extensions.RemovedExtensions.ibaseRemoved"/>
</rule>
<rule ref="PHPCompatibility.Constants.RemovedConstants">
<exclude-pattern>adminer/plugins/drivers/firebird.php</exclude-pattern>
</rule>
<rule ref="PHPCompatibility.FunctionUse.RemovedFunctions">
<exclude-pattern>adminer/plugins/drivers/firebird.php</exclude-pattern>
</rule>
-->
</ruleset>

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDesigns {
/** @access protected */
var $designs;
protected $designs;
/**
* @param array URL in key, name in value

View File

@@ -8,11 +8,12 @@ if (isset($_GET["clickhouse"])) {
if (ini_bool('allow_url_fopen')) {
class Db {
var $extension = "JSON", $server_info, $errno, $_result, $error, $_url;
var $_db = 'default';
public $extension = "JSON", $server_info, $errno, $error;
public $_db = 'default';
private $result, $url;
function rootQuery($db, $query) {
$file = @file_get_contents("$this->_url/?database=$db", false, stream_context_create(array('http' => array(
$file = @file_get_contents("$this->url/?database=$db", false, stream_context_create(array('http' => array(
'method' => 'POST',
'content' => $this->isQuerySelectLike($query) ? "$query FORMAT JSONCompact" : $query,
'header' => 'Content-type: application/x-www-form-urlencoded',
@@ -57,7 +58,7 @@ if (isset($_GET["clickhouse"])) {
function connect($server, $username, $password) {
preg_match('~^(https?://)?(.*)~', $server, $match);
$this->_url = ($match[1] ?: "http://") . urlencode($username) . ":" . urlencode($password) . "@$match[2]";
$this->url = ($match[1] ?: "http://") . urlencode($username) . ":" . urlencode($password) . "@$match[2]";
$return = $this->query('SELECT 1');
return (bool) $return;
}
@@ -72,11 +73,11 @@ if (isset($_GET["clickhouse"])) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function store_result() {
return $this->_result;
return $this->result;
}
function next_result() {
@@ -90,7 +91,8 @@ if (isset($_GET["clickhouse"])) {
}
class Result {
var $num_rows, $_rows, $columns, $meta, $_offset = 0;
public $num_rows, $columns, $meta;
private $rows, $offset = 0;
function __construct($result) {
foreach ($result['data'] as $item) {
@@ -98,28 +100,28 @@ if (isset($_GET["clickhouse"])) {
foreach ($item as $key => $val) {
$row[$key] = is_scalar($val) ? $val : json_encode($val, 256); // 256 - JSON_UNESCAPED_UNICODE
}
$this->_rows[] = $row;
$this->rows[] = $row;
}
$this->num_rows = $result['rows'];
$this->meta = $result['meta'];
$this->columns = array_column($this->meta, 'name');
reset($this->_rows);
reset($this->rows);
}
function fetch_assoc() {
$row = current($this->_rows);
next($this->_rows);
$row = current($this->rows);
next($this->rows);
return $row === false ? false : array_combine($this->columns, $row);
}
function fetch_row() {
$row = current($this->_rows);
next($this->_rows);
$row = current($this->rows);
next($this->rows);
return $row;
}
function fetch_field() {
$column = $this->_offset++;
$column = $this->offset++;
$return = new \stdClass;
if ($column < count($this->columns)) {
$return->name = $this->meta[$column]['name'];
@@ -135,13 +137,18 @@ if (isset($_GET["clickhouse"])) {
static $possibleDrivers = array("allow_url_fopen");
static $jush = "clickhouse";
var $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL");
public $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
$this->types = array( //! arrays
lang('Numbers') => array("Int8" => 3, "Int16" => 5, "Int32" => 10, "Int64" => 19, "UInt8" => 3, "UInt16" => 5, "UInt32" => 10, "UInt64" => 20, "Float32" => 7, "Float64" => 16, 'Decimal' => 38, 'Decimal32' => 9, 'Decimal64' => 18, 'Decimal128' => 38),
lang('Numbers') => array(
"Int8" => 3, "Int16" => 5, "Int32" => 10, "Int64" => 19,
"UInt8" => 3, "UInt16" => 5, "UInt32" => 10, "UInt64" => 20,
"Float32" => 7, "Float64" => 16,
'Decimal' => 38, 'Decimal32' => 9, 'Decimal64' => 18, 'Decimal128' => 38,
),
lang('Date and time') => array("Date" => 13, "DateTime" => 20),
lang('Strings') => array("String" => 0),
lang('Binary') => array("FixedString" => 0),

View File

@@ -9,7 +9,8 @@ if (isset($_GET["elastic"])) {
if (ini_bool('allow_url_fopen')) {
class Db {
var $extension = "JSON", $server_info, $errno, $error, $_url;
public $extension = "JSON", $server_info, $errno, $error;
private $url;
/**
* @param string $path
@@ -18,7 +19,7 @@ if (isset($_GET["elastic"])) {
* @return array|false
*/
function rootQuery($path, array $content = null, $method = 'GET') {
$file = @file_get_contents("$this->_url/" . ltrim($path, '/'), false, stream_context_create(array('http' => array(
$file = @file_get_contents("$this->url/" . ltrim($path, '/'), false, stream_context_create(array('http' => array(
'method' => $method,
'content' => $content !== null ? json_encode($content) : null,
'header' => $content !== null ? 'Content-Type: application/json' : array(),
@@ -78,7 +79,7 @@ if (isset($_GET["elastic"])) {
*/
function connect($server, $username, $password) {
preg_match('~^(https?://)?(.*)~', $server, $match);
$this->_url = ($match[1] ?: "http://") . urlencode($username) . ":" . urlencode($password) . "@$match[2]";
$this->url = ($match[1] ?: "http://") . urlencode($username) . ":" . urlencode($password) . "@$match[2]";
$return = $this->query('');
if ($return) {
$this->server_info = $return['version']['number'];
@@ -96,18 +97,19 @@ if (isset($_GET["elastic"])) {
}
class Result {
var $num_rows, $_rows;
public $num_rows;
private $rows;
function __construct($rows) {
$this->num_rows = count($rows);
$this->_rows = $rows;
$this->rows = $rows;
reset($this->_rows);
reset($this->rows);
}
function fetch_assoc() {
$return = current($this->_rows);
next($this->_rows);
$return = current($this->rows);
next($this->rows);
return $return;
}
@@ -124,8 +126,8 @@ if (isset($_GET["elastic"])) {
static $possibleDrivers = array("json + allow_url_fopen");
static $jush = "elastic";
var $editFunctions = array(array("json"));
var $operators = array("=", "must", "should", "must_not");
public $editFunctions = array(array("json"));
public $operators = array("=", "must", "should", "must_not");
function __construct($connection) {
parent::__construct($connection);
@@ -197,7 +199,7 @@ if (isset($_GET["elastic"])) {
$query = "$table/_search";
$start = microtime(true);
$search = $this->_conn->rootQuery($query, $data);
$search = $this->conn->rootQuery($query, $data);
if ($print) {
echo adminer()->selectQuery("$query: " . json_encode($data), $start, !$search);
@@ -205,6 +207,9 @@ if (isset($_GET["elastic"])) {
if (empty($search)) {
return false;
}
if ($select == array("*")) {
$tableFields = array_keys(fields($table));
}
$return = array();
foreach ($search["hits"]["hits"] as $hit) {
@@ -219,7 +224,9 @@ if (isset($_GET["elastic"])) {
$fields[$key] = $key == "_id" ? $hit["_id"] : $hit["_source"][$key];
}
} else {
$fields = $hit["_source"];
foreach ($tableFields as $key) {
$fields[$key] = $key == "_id" ? $hit["_id"] : $hit["_source"][$key];
}
}
foreach ($fields as $key => $val) {
$row[$key] = (is_array($val) ? json_encode($val) : $val);
@@ -238,19 +245,30 @@ if (isset($_GET["elastic"])) {
$id = trim($parts[1]);
$query = "$type/$id";
return $this->_conn->query($query, $record, 'POST');
return $this->conn->query($query, $record, 'POST');
}
return false;
}
function insert($type, $record) {
$id = ""; //! user should be able to inform _id
$query = "$type/$id";
$response = $this->_conn->query($query, $record, 'POST');
$this->_conn->last_id = $response['_id'];
$query = "$type/_doc/";
if (isset($record["_id"]) && $record["_id"] != "NULL") {
$query .= $record["_id"];
unset($record["_id"]);
}
foreach ($record as $key => $value) {
if ($value == "NULL") {
unset($record[$key]);
}
}
$response = $this->conn->query($query, $record, 'POST');
if ($response == false) {
return false;
}
$this->conn->last_id = $response['_id'];
return $response['created'];
return $response['result'];
}
function delete($table, $queryWhere, $limit = 0) {
@@ -268,17 +286,17 @@ if (isset($_GET["elastic"])) {
}
}
$this->_conn->affected_rows = 0;
$this->conn->affected_rows = 0;
foreach ($ids as $id) {
$query = "$table/_doc/$id";
$response = $this->_conn->query($query, null, 'DELETE');
$response = $this->conn->query($query, null, 'DELETE');
if (isset($response['result']) && $response['result'] == 'deleted') {
$this->_conn->affected_rows++;
$this->conn->affected_rows++;
}
}
return $this->_conn->affected_rows;
return $this->conn->affected_rows;
}
function convertOperator($operator) {
@@ -466,6 +484,7 @@ if (isset($_GET["elastic"])) {
"field" => "_id",
"full_type" => "text",
"type" => "text",
"null" => true,
"privileges" => array("insert" => 1, "select" => 1, "where" => 1, "order" => 1),
)
);
@@ -475,6 +494,7 @@ if (isset($_GET["elastic"])) {
"field" => $name,
"full_type" => $field["type"],
"type" => $field["type"],
"null" => true,
"privileges" => array(
"insert" => 1,
"select" => 1,

View File

@@ -12,14 +12,15 @@ if (isset($_GET["firebird"])) {
if (extension_loaded("interbase")) {
class Db {
var
public
$extension = "Firebird",
$server_info,
$affected_rows,
$errno,
$error,
$_link, $_result
$_link
;
private $result;
function connect($server, $username, $password) {
$this->_link = ibase_connect($server, $username, $password);
@@ -58,11 +59,11 @@ if (isset($_GET["firebird"])) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function store_result() {
return $this->_result;
return $this->result;
}
function next_result() {
@@ -80,23 +81,24 @@ if (isset($_GET["firebird"])) {
}
class Result {
var $num_rows, $_result, $_offset = 0;
public $num_rows;
private $result, $offset = 0;
function __construct($result) {
$this->_result = $result;
$this->result = $result;
// $this->num_rows = ibase_num_rows($result);
}
function fetch_assoc() {
return ibase_fetch_assoc($this->_result);
return ibase_fetch_assoc($this->result);
}
function fetch_row() {
return ibase_fetch_row($this->_result);
return ibase_fetch_row($this->result);
}
function fetch_field() {
$field = ibase_field_info($this->_result, $this->_offset++);
$field = ibase_field_info($this->result, $this->offset++);
return (object) array(
'name' => $field['name'],
'orgname' => $field['name'],
@@ -106,7 +108,7 @@ if (isset($_GET["firebird"])) {
}
function __destruct() {
ibase_free_result($this->_result);
ibase_free_result($this->result);
}
}
@@ -118,7 +120,7 @@ if (isset($_GET["firebird"])) {
static $possibleDrivers = array("interbase");
static $jush = "firebird";
var $operators = array("=");
public $operators = array("=");
}

View File

@@ -1,24 +1,28 @@
<?php
namespace Adminer;
$drivers["mongo"] = "MongoDB (alpha)";
add_driver("mongo", "MongoDB (alpha)");
if (isset($_GET["mongo"])) {
define('Adminer\DRIVER', "mongo");
if (class_exists('MongoDB\Driver\Manager')) {
class Db {
var $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id;
public $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id;
/** @var MongoDB\Driver\Manager */
var $_link;
var $_db, $_db_name;
public $_link;
public $_db, $_db_name;
function connect($uri, $options) {
$this->_link = new \MongoDB\Driver\Manager($uri, $options);
$this->executeCommand($options["db"], array('ping' => 1));
$this->executeDbCommand($options["db"], array('ping' => 1));
}
function executeCommand($db, $command) {
function executeCommand($command) {
return $this->executeDbCommand($this->_db_name);
}
function executeDbCommand($db, $command) {
try {
return $this->_link->executeCommand($db, new \MongoDB\Driver\Command($command));
} catch (Exception $e) {
@@ -53,14 +57,15 @@ if (isset($_GET["mongo"])) {
}
class Result {
var $num_rows, $_rows = array(), $_offset = 0, $_charset = array();
public $num_rows;
private $rows = array(), $offset = 0, $charset = array();
function __construct($result) {
foreach ($result as $item) {
$row = array();
foreach ($item as $key => $val) {
if (is_a($val, 'MongoDB\BSON\Binary')) {
$this->_charset[$key] = 63;
$this->charset[$key] = 63;
}
$row[$key] =
(is_a($val, 'MongoDB\BSON\ObjectID') ? 'MongoDB\BSON\ObjectID("' . "$val\")" :
@@ -71,26 +76,26 @@ if (isset($_GET["mongo"])) {
$val // MongoMinKey, MongoMaxKey
)))));
}
$this->_rows[] = $row;
$this->rows[] = $row;
foreach ($row as $key => $val) {
if (!isset($this->_rows[0][$key])) {
$this->_rows[0][$key] = null;
if (!isset($this->rows[0][$key])) {
$this->rows[0][$key] = null;
}
}
}
$this->num_rows = count($this->_rows);
$this->num_rows = count($this->rows);
}
function fetch_assoc() {
$row = current($this->_rows);
$row = current($this->rows);
if (!$row) {
return $row;
}
$return = array();
foreach ($this->_rows[0] as $key => $val) {
foreach ($this->rows[0] as $key => $val) {
$return[$key] = $row[$key];
}
next($this->_rows);
next($this->rows);
return $return;
}
@@ -103,11 +108,11 @@ if (isset($_GET["mongo"])) {
}
function fetch_field() {
$keys = array_keys($this->_rows[0]);
$name = $keys[$this->_offset++];
$keys = array_keys($this->rows[0]);
$name = $keys[$this->offset++];
return (object) array(
'name' => $name,
'charsetnr' => $this->_charset[$name],
'charsetnr' => $this->charset[$name],
);
}
}
@@ -115,9 +120,8 @@ if (isset($_GET["mongo"])) {
function get_databases($flush) {
global $connection;
$return = array();
foreach ($connection->executeCommand($connection->_db_name, array('listDatabases' => 1)) as $dbs) {
foreach (connection()->executeCommand(array('listDatabases' => 1)) as $dbs) {
foreach ($dbs->databases as $db) {
$return[] = $db->name;
}
@@ -131,9 +135,8 @@ if (isset($_GET["mongo"])) {
}
function tables_list() {
global $connection;
$collections = array();
foreach ($connection->executeCommand($connection->_db_name, array('listCollections' => 1)) as $result) {
foreach (connection()->executeCommand(array('listCollections' => 1)) as $result) {
$collections[$result->name] = 'table';
}
return $collections;
@@ -144,9 +147,8 @@ if (isset($_GET["mongo"])) {
}
function indexes($table, $connection2 = null) {
global $connection;
$return = array();
foreach ($connection->executeCommand($connection->_db_name, array('listIndexes' => $table)) as $index) {
foreach (connection()->executeCommand(array('listIndexes' => $table)) as $index) {
$descs = array();
$columns = array();
foreach (get_object_vars($index->key) as $column => $type) {
@@ -164,7 +166,7 @@ if (isset($_GET["mongo"])) {
}
function fields($table) {
global $driver;
$driver = get_driver();
$fields = fields_from_edit();
if (!$fields) {
$result = $driver->select($table, array("*"), null, null, array(), 10);
@@ -193,9 +195,8 @@ if (isset($_GET["mongo"])) {
}
function found_rows($table_status, $where) {
global $connection;
$where = where_to_query($where);
$toArray = $connection->executeCommand($connection->_db_name, array('count' => $table_status['Name'], 'query' => $where))->toArray();
$toArray = connection()->executeCommand(array('count' => $table_status['Name'], 'query' => $where))->toArray();
return $toArray[0]->n;
}
@@ -220,7 +221,6 @@ if (isset($_GET["mongo"])) {
}
function where_to_query($whereAnd = array(), $whereOr = array()) {
global $adminer;
$data = array();
foreach (array('and' => $whereAnd, 'or' => $whereOr) as $type => $where) {
if (is_array($where)) {
@@ -230,7 +230,7 @@ if (isset($_GET["mongo"])) {
list(, $class, $val) = $match;
$val = new $class($val);
}
if (!in_array($op, $adminer->operators)) {
if (!in_array($op, adminer()->operators)) {
continue;
}
if (preg_match('~^\(f\)(.+)~', $op, $match)) {
@@ -284,9 +284,9 @@ if (isset($_GET["mongo"])) {
static $possibleDrivers = array("mongodb");
static $jush = "mongo";
var $editFunctions = array(array("json"));
public $editFunctions = array(array("json"));
var $operators = array(
public $operators = array(
"=",
"!=",
">",
@@ -330,15 +330,15 @@ if (isset($_GET["mongo"])) {
$limit = min(200, max(1, (int) $limit));
$skip = $page * $limit;
try {
return new Result($this->_conn->_link->executeQuery($this->_conn->_db_name . ".$table", new \MongoDB\Driver\Query($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort))));
return new Result($this->conn->_link->executeQuery($this->conn->_db_name . ".$table", new \MongoDB\Driver\Query($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort))));
} catch (Exception $e) {
$this->_conn->error = $e->getMessage();
$this->conn->error = $e->getMessage();
return false;
}
}
function update($table, $set, $queryWhere, $limit = 0, $separator = "\n") {
$db = $this->_conn->_db_name;
$db = $this->conn->_db_name;
$where = sql_query_where_parser($queryWhere);
$bulk = new \MongoDB\Driver\BulkWrite(array());
if (isset($set['_id'])) {
@@ -356,25 +356,25 @@ if (isset($_GET["mongo"])) {
$update['$unset'] = $removeFields;
}
$bulk->update($where, $update, array('upsert' => false));
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getModifiedCount');
return $this->conn->executeBulkWrite("$db.$table", $bulk, 'getModifiedCount');
}
function delete($table, $queryWhere, $limit = 0) {
$db = $this->_conn->_db_name;
$db = $this->conn->_db_name;
$where = sql_query_where_parser($queryWhere);
$bulk = new \MongoDB\Driver\BulkWrite(array());
$bulk->delete($where, array('limit' => $limit));
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
return $this->conn->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
}
function insert($table, $set) {
$db = $this->_conn->_db_name;
$db = $this->conn->_db_name;
$bulk = new \MongoDB\Driver\BulkWrite(array());
if ($set['_id'] == '') {
unset($set['_id']);
}
$bulk->insert($set);
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getInsertedCount');
return $this->conn->executeBulkWrite("$db.$table", $bulk, 'getInsertedCount');
}
}
@@ -404,13 +404,11 @@ if (isset($_GET["mongo"])) {
}
function last_id() {
global $connection;
return $connection->last_id;
return connection()->last_id;
}
function error() {
global $connection;
return h($connection->error);
return h(connection()->error);
}
function collations() {
@@ -418,13 +416,11 @@ if (isset($_GET["mongo"])) {
}
function logged_user() {
global $adminer;
$credentials = $adminer->credentials();
$credentials = adminer()->credentials();
return $credentials[1];
}
function connect($credentials) {
global $adminer;
$connection = new Db;
list($server, $username, $password) = $credentials;
@@ -437,7 +433,7 @@ if (isset($_GET["mongo"])) {
$options["username"] = $username;
$options["password"] = $password;
}
$db = $adminer->database();
$db = adminer()->database();
if ($db != "") {
$options["db"] = $db;
}
@@ -452,7 +448,7 @@ if (isset($_GET["mongo"])) {
}
function alter_indexes($table, $alter) {
global $connection;
$connection = connection();
foreach ($alter as $val) {
list($type, $name, $set) = $val;
if ($set == "DROP") {
@@ -509,17 +505,15 @@ if (isset($_GET["mongo"])) {
}
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
global $connection;
if ($table == "") {
$connection->_db->createCollection($name);
connection()->_db->createCollection($name);
return true;
}
}
function drop_tables($tables) {
global $connection;
foreach ($tables as $table) {
$response = $connection->_db->selectCollection($table)->drop();
$response = connection()->_db->selectCollection($table)->drop();
if (!$response['ok']) {
return false;
}
@@ -528,9 +522,8 @@ if (isset($_GET["mongo"])) {
}
function truncate_tables($tables) {
global $connection;
foreach ($tables as $table) {
$response = $connection->_db->selectCollection($table)->remove();
$response = connection()->_db->selectCollection($table)->remove();
if (!$response['ok']) {
return false;
}

View File

@@ -8,7 +8,8 @@ if (isset($_GET["simpledb"])) {
if (class_exists('SimpleXMLElement') && ini_bool('allow_url_fopen')) {
class Db {
var $extension = "SimpleXML", $server_info = '2009-04-15', $error, $timeout, $next, $affected_rows, $_result;
public $extension = "SimpleXML", $server_info = '2009-04-15', $error, $timeout, $next, $affected_rows;
private $result;
function select_db($database) {
return ($database == "domain");
@@ -38,11 +39,11 @@ if (isset($_GET["simpledb"])) {
}
function multi_query($query) {
return $this->_result = $this->query($query);
return $this->result = $this->query($query);
}
function store_result() {
return $this->_result;
return $this->result;
}
function next_result() {
@@ -55,7 +56,8 @@ if (isset($_GET["simpledb"])) {
}
class Result {
var $num_rows, $_rows = array(), $_offset = 0;
public $num_rows;
private $rows = array(), $offset = 0;
function __construct($result) {
foreach ($result as $item) {
@@ -64,8 +66,8 @@ if (isset($_GET["simpledb"])) {
$row['itemName()'] = (string) $item->Name;
}
foreach ($item->Attribute as $attribute) {
$name = $this->_processValue($attribute->Name);
$value = $this->_processValue($attribute->Value);
$name = $this->processValue($attribute->Name);
$value = $this->processValue($attribute->Value);
if (isset($row[$name])) {
$row[$name] = (array) $row[$name];
$row[$name][] = $value;
@@ -73,30 +75,30 @@ if (isset($_GET["simpledb"])) {
$row[$name] = $value;
}
}
$this->_rows[] = $row;
$this->rows[] = $row;
foreach ($row as $key => $val) {
if (!isset($this->_rows[0][$key])) {
$this->_rows[0][$key] = null;
if (!isset($this->rows[0][$key])) {
$this->rows[0][$key] = null;
}
}
}
$this->num_rows = count($this->_rows);
$this->num_rows = count($this->rows);
}
function _processValue($element) {
private function processValue($element) {
return (is_object($element) && $element['encoding'] == 'base64' ? base64_decode($element) : (string) $element);
}
function fetch_assoc() {
$row = current($this->_rows);
$row = current($this->rows);
if (!$row) {
return $row;
}
$return = array();
foreach ($this->_rows[0] as $key => $val) {
foreach ($this->rows[0] as $key => $val) {
$return[$key] = $row[$key];
}
next($this->_rows);
next($this->rows);
return $return;
}
@@ -109,8 +111,8 @@ if (isset($_GET["simpledb"])) {
}
function fetch_field() {
$keys = array_keys($this->_rows[0]);
return (object) array('name' => $keys[$this->_offset++]);
$keys = array_keys($this->rows[0]);
return (object) array('name' => $keys[$this->offset++]);
}
}
}
@@ -121,12 +123,12 @@ if (isset($_GET["simpledb"])) {
static $possibleDrivers = array("SimpleXML + allow_url_fopen");
static $jush = "simpledb";
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "IS NOT NULL");
var $grouping = array("count");
public $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "IS NOT NULL");
public $grouping = array("count");
public $primary = "itemName()";
function _chunkRequest($ids, $action, $params, $expand = array()) {
private function chunkRequest($ids, $action, $params, $expand = array()) {
$connection = connection();
foreach (array_chunk($ids, 25) as $chunk) {
$params2 = $params;
@@ -144,7 +146,7 @@ if (isset($_GET["simpledb"])) {
return true;
}
function _extractIds($table, $queryWhere, $limit) {
private function extractIds($table, $queryWhere, $limit) {
$return = array();
if (preg_match_all("~itemName\(\) = (('[^']*+')+)~", $queryWhere, $matches)) {
$return = array_map('Adminer\idf_unescape', $matches[1]);
@@ -165,8 +167,8 @@ if (isset($_GET["simpledb"])) {
}
function delete($table, $queryWhere, $limit = 0) {
return $this->_chunkRequest(
$this->_extractIds($table, $queryWhere, $limit),
return $this->chunkRequest(
$this->extractIds($table, $queryWhere, $limit),
'BatchDeleteAttributes',
array('DomainName' => $table)
);
@@ -176,7 +178,7 @@ if (isset($_GET["simpledb"])) {
$delete = array();
$insert = array();
$i = 0;
$ids = $this->_extractIds($table, $queryWhere, $limit);
$ids = $this->extractIds($table, $queryWhere, $limit);
$id = idf_unescape($set["`itemName()`"]);
unset($set["`itemName()`"]);
foreach ($set as $key => $val) {
@@ -196,8 +198,8 @@ if (isset($_GET["simpledb"])) {
}
}
$params = array('DomainName' => $table);
return (!$insert || $this->_chunkRequest(($id != "" ? array($id) : $ids), 'BatchPutAttributes', $params, $insert))
&& (!$delete || $this->_chunkRequest($ids, 'BatchDeleteAttributes', $params, $delete))
return (!$insert || $this->chunkRequest(($id != "" ? array($id) : $ids), 'BatchPutAttributes', $params, $insert))
&& (!$delete || $this->chunkRequest($ids, 'BatchDeleteAttributes', $params, $delete))
;
}
@@ -244,7 +246,7 @@ if (isset($_GET["simpledb"])) {
}
function slowQuery($query, $timeout) {
$this->_conn->timeout = $timeout;
$this->conn->timeout = $timeout;
return $query;
}
}
@@ -420,7 +422,7 @@ if (isset($_GET["simpledb"])) {
'max_redirects' => 0,
))));
if (!$file) {
$this->error = lang('Invalid credentials.');
$connection->error = lang('Invalid credentials.');
return false;
}
libxml_use_internal_errors(true);

View File

@@ -14,7 +14,7 @@ class AdminerDumpAlter {
}
}
function _database() {
private function database() {
// drop old tables
$query = "SELECT TABLE_NAME, ENGINE, TABLE_COLLATION, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()";
echo "DELIMITER ;;
@@ -59,9 +59,8 @@ SELECT @adminer_alter;
if ($first) {
$first = false;
echo "SET @adminer_alter = '';\n\n";
register_shutdown_function(array($this, '_database'));
} else {
$this->_database();
$this->database();
}
return true;
}
@@ -75,7 +74,10 @@ SELECT @adminer_alter;
} else {
echo substr_replace($create, " IF NOT EXISTS", 12, 0) . ";\n\n";
// create procedure which iterates over original columns and adds new and removes old
$query = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLLATION_NAME, COLUMN_TYPE, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . Adminer\q($table) . " ORDER BY ORDINAL_POSITION";
$query = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLLATION_NAME, COLUMN_TYPE, EXTRA, COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . Adminer\q($table) . "
ORDER BY ORDINAL_POSITION";
echo "DELIMITER ;;
CREATE PROCEDURE adminer_alter (INOUT alter_command text) BEGIN
DECLARE _column_name, _collation_name, after varchar(64) DEFAULT '';
@@ -159,4 +161,10 @@ DROP PROCEDURE adminer_alter;
return true;
}
}
function dumpFooter() {
if ($_POST["format"] == "sql_alter") {
$this->database();
}
}
}

View File

@@ -8,8 +8,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDumpBz2 {
/** @access protected */
var $filename, $fp;
protected $filename, $fp;
function dumpOutput() {
if (!function_exists('bzopen')) {

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDumpJson {
/** @access protected */
var $database = false;
protected $database = false;
function dumpFormat() {
return array('json' => 'JSON');
@@ -20,10 +19,6 @@ class AdminerDumpJson {
}
}
function _database() {
echo "}\n";
}
function dumpData($table, $style, $query) {
if ($_POST["format"] == "json") {
if ($this->database) {
@@ -31,7 +26,6 @@ class AdminerDumpJson {
} else {
$this->database = true;
echo "{\n";
register_shutdown_function(array($this, '_database'));
}
$connection = Adminer\connection();
$result = $connection->query($query, 1);
@@ -58,4 +52,10 @@ class AdminerDumpJson {
return "json";
}
}
function dumpFooter() {
if ($_POST["format"] == "json" && $this->database) {
echo "}\n";
}
}
}

View File

@@ -6,8 +6,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDumpPhp {
var $output = array();
var $shutdown_callback = false;
protected $output = array();
function dumpFormat() {
return array('php' => 'PHP');
@@ -23,10 +22,6 @@ class AdminerDumpPhp {
function dumpTable($table, $style, $is_view = 0) {
if ($_POST['format'] == 'php') {
$this->output[$table] = array();
if (!$this->shutdown_callback) {
$this->shutdown_callback = true;
register_shutdown_function(array($this, '_export'));
}
return true;
}
}
@@ -44,8 +39,11 @@ class AdminerDumpPhp {
}
}
function _export() {
echo "<?php\n";
var_export($this->output);
function dumpFooter() {
if ($_POST['format'] == 'php') {
echo "<?php\n";
var_export($this->output);
echo ";\n";
}
}
}

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDumpXml {
/** @access protected */
var $database = false;
protected $database = false;
function dumpFormat() {
return array('xml' => 'XML');
@@ -20,16 +19,11 @@ class AdminerDumpXml {
}
}
function _database() {
echo "</database>\n";
}
function dumpData($table, $style, $query) {
if ($_POST["format"] == "xml") {
if (!$this->database) {
$this->database = true;
echo "<database name='" . Adminer\h(Adminer\DB) . "'>\n";
register_shutdown_function(array($this, '_database'));
}
$connection = Adminer\connection();
$result = $connection->query($query, 1);
@@ -52,4 +46,10 @@ class AdminerDumpXml {
return "xml";
}
}
function dumpFooter() {
if ($_POST["format"] == "xml" && $this->database) {
echo "</database>\n";
}
}
}

View File

@@ -8,8 +8,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDumpZip {
/** @access protected */
var $filename, $data;
protected $filename, $data;
function dumpOutput() {
if (!class_exists('ZipArchive')) {

View File

@@ -9,8 +9,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerEditCalendar {
/** @access protected */
var $prepend, $langPath;
protected $prepend, $langPath;
/**
* @param string text to append before first calendar usage

View File

@@ -7,10 +7,10 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerEditForeign {
var $_limit;
protected $limit;
function __construct($limit = 0) {
$this->_limit = $limit;
$this->limit = $limit;
}
function editInput($table, $field, $attrs, $value) {
@@ -30,8 +30,8 @@ class AdminerEditForeign {
if (preg_match('~binary~', $field["type"])) {
$column = "HEX($column)";
}
$options = array("" => "") + Adminer\get_vals("SELECT $column FROM " . Adminer\table($target) . " ORDER BY 1" . ($this->_limit ? " LIMIT " . ($this->_limit + 1) : ""));
if ($this->_limit && count($options) - 1 > $this->_limit) {
$options = array("" => "") + Adminer\get_vals("SELECT $column FROM " . Adminer\table($target) . " ORDER BY 1" . ($this->limit ? " LIMIT " . ($this->limit + 1) : ""));
if ($this->limit && count($options) - 1 > $this->limit) {
return;
}
}

14
plugins/editor-views.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
/** Display views in Adminer Editor
* @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerEditorViews {
function tableName($tableStatus) {
return Adminer\h($tableStatus["Comment"] != "" ? $tableStatus["Comment"] : $tableStatus["Name"]);
}
}

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerEmailTable {
/** @access protected */
var $table, $id, $title, $subject, $message;
protected $table, $id, $title, $subject, $message;
/**
* @param string quoted table name

View File

@@ -20,20 +20,16 @@ class AdminerEnumOption {
}
if ($field["null"]) {
$options[""] = "NULL";
if ($value === null && !isset($_GET["select"])) {
if ($selected === null) {
$selected = "";
}
}
$options[0] = Adminer\lang('empty');
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) {
foreach ($matches[1] as $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$options[$i + 1] = $val;
if ($value === $val) {
$selected = $i + 1;
}
$options[$val] = $val;
}
return "<select$attrs>" . Adminer\optionlist($options, (string) $selected, 1) . "</select>"; // 1 - use keys
return "<select$attrs>" . Adminer\optionlist($options, $selected, 1) . "</select>"; // 1 - use keys
}
}
}

View File

@@ -8,8 +8,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerFileUpload {
/** @access protected */
var $uploadPath, $displayPath, $extensions;
protected $uploadPath, $displayPath, $extensions;
/**
* @param string prefix for uploading data (create writable subdirectory for each table containing uploadable fields)

View File

@@ -14,12 +14,18 @@ class AdminerForeignSystem {
"columns_priv" => array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))),
"db" => array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))),
"help_category" => array(array("table" => "help_category", "source" => array("parent_category_id"), "target" => array("help_category_id"))),
"help_relation" => array(array("table" => "help_topic", "source" => array("help_topic_id"), "target" => array("help_topic_id")), array("table" => "help_keyword", "source" => array("help_keyword_id"), "target" => array("help_keyword_id"))),
"help_relation" => array(
array("table" => "help_topic", "source" => array("help_topic_id"), "target" => array("help_topic_id")),
array("table" => "help_keyword", "source" => array("help_keyword_id"), "target" => array("help_keyword_id")),
),
"help_topic" => array(array("table" => "help_category", "source" => array("help_category_id"), "target" => array("help_category_id"))),
"procs_priv" => array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User")), array("table" => "proc", "source" => array("Db", "Routine_name"), "target" => array("db", "name"))),
"tables_priv" => array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))),
"time_zone_name" => array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id"))),
"time_zone_transition" => array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id")), array("table" => "time_zone_transition_type", "source" => array("Time_zone_id", "Transition_type_id"), "target" => array("Time_zone_id", "Transition_type_id"))),
"time_zone_transition" => array(
array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id")),
array("table" => "time_zone_transition_type", "source" => array("Time_zone_id", "Transition_type_id"), "target" => array("Time_zone_id", "Transition_type_id")),
),
"time_zone_transition_type" => array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id"))),
);
return $return[$table];

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerFrames {
/** @access protected */
var $sameOrigin;
protected $sameOrigin;
/**
* @param bool allow running from the same origin only

View File

@@ -8,14 +8,14 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerJsonColumn {
private function _testJson($value) {
private function testJson($value) {
if ((substr($value, 0, 1) == '{' || substr($value, 0, 1) == '[') && ($json = json_decode($value, true))) {
return $json;
}
return $value;
}
private function _buildTable($json) {
private function buildTable($json) {
echo '<table style="margin:2px; font-size:100%;">';
foreach ($json as $key => $val) {
echo '<tr>';
@@ -31,7 +31,7 @@ class AdminerJsonColumn {
}
echo '<code class="jush-js">' . $val . '</code>';
} else {
$this->_buildTable($val);
$this->buildTable($val);
}
echo '</td>';
echo '</tr>';
@@ -40,9 +40,9 @@ class AdminerJsonColumn {
}
function editInput($table, $field, $attrs, $value) {
$json = $this->_testJson($value);
$json = $this->testJson($value);
if ($json !== $value) {
$this->_buildTable($json);
$this->buildTable($json);
}
}
}

View File

@@ -7,10 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginIp {
/** @access protected */
var $ips;
/** @access protected */
var $forwarded_for;
protected $ips, $forwarded_for;
/** Set allowed IP addresses
* @param array IP address prefixes

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginOtp {
/** @access protected */
var $secret;
protected $secret;
/**
* @param string decoded secret, e.g. base64_decode("SECRET")

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginPasswordLess {
/** @access protected */
var $password_hash;
protected $password_hash;
/** Set allowed password
* @param string result of password_hash

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginServers {
/** @access protected */
var $servers;
protected $servers;
/** Set supported servers
* @param array [$description => ["server" => , "driver" => "server|pgsql|sqlite|..."]]

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginSsl {
/** @access protected */
var $ssl;
protected $ssl;
/**
* @param array

View File

@@ -16,8 +16,7 @@ CREATE TABLE login (
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginTable {
/** @access protected */
var $database;
protected $database;
/** Set database of login table
* @param string

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerPlugin extends Adminer\Adminer {
/** @access protected */
var $plugins;
protected $plugins;
/** Register plugins
* @param array object instances or null to register all classes starting by 'Adminer'
@@ -26,11 +25,11 @@ class AdminerPlugin extends Adminer\Adminer {
//! it is possible to use ReflectionObject to find out which plugins defines which methods at once
}
function _callParent($function, $args) {
private function callParent($function, $args) {
return call_user_func_array(array('parent', $function), $args);
}
function _applyPlugin($function, $args) {
private function applyPlugin($function, $args) {
foreach ($this->plugins as $plugin) {
if (method_exists($plugin, $function)) {
switch (count($args)) { // call_user_func_array() doesn't work well with references
@@ -63,11 +62,11 @@ class AdminerPlugin extends Adminer\Adminer {
}
}
}
return $this->_callParent($function, $args);
return $this->callParent($function, $args);
}
function _appendPlugin($function, $args) {
$return = $this->_callParent($function, $args);
private function appendPlugin($function, $args) {
$return = $this->callParent($function, $args);
foreach ($this->plugins as $plugin) {
if (method_exists($plugin, $function)) {
$value = call_user_func_array(array($plugin, $function), $args);
@@ -83,333 +82,338 @@ class AdminerPlugin extends Adminer\Adminer {
function dumpFormat() {
$args = func_get_args();
return $this->_appendPlugin(__FUNCTION__, $args);
return $this->appendPlugin(__FUNCTION__, $args);
}
function dumpOutput() {
$args = func_get_args();
return $this->_appendPlugin(__FUNCTION__, $args);
return $this->appendPlugin(__FUNCTION__, $args);
}
function editRowPrint($table, $fields, $row, $update) {
$args = func_get_args();
return $this->_appendPlugin(__FUNCTION__, $args);
return $this->appendPlugin(__FUNCTION__, $args);
}
function editFunctions($field) {
$args = func_get_args();
return $this->_appendPlugin(__FUNCTION__, $args);
return $this->appendPlugin(__FUNCTION__, $args);
}
// applyPlugin
function name() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function credentials() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function connectSsl() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function permanentLogin($create = false) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function bruteForceKey() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function serverName($server) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function database() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function schemas() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function databases($flush = true) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function queryTimeout() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function headers() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function csp() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function head() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function css() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function loginForm() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function loginFormField($name, $heading, $value) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function login($login, $password) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function tableName($tableStatus) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function fieldName($field, $order = 0) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectLinks($tableStatus, $set = "") {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function foreignKeys($table) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function backwardKeys($table, $tableName) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function backwardKeysPrint($backwardKeys, $row) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectQuery($query, $start, $failed = false) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function sqlCommandQuery($query) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function rowDescription($table) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function rowDescriptions($rows, $foreignKeys) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectLink($val, $field) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectVal($val, $link, $field, $original) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function editVal($val, $field) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function tableStructurePrint($fields) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function tableIndexesPrint($indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectColumnsPrint($select, $columns) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectSearchPrint($where, $columns, $indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectOrderPrint($order, $columns, $indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectLimitPrint($limit) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectLengthPrint($text_length) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectActionPrint($indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectCommandPrint() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectImportPrint() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectEmailPrint($emailFields, $columns) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectColumnsProcess($columns, $indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectSearchProcess($fields, $indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectOrderProcess($fields, $indexes) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectLimitProcess() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectLengthProcess() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectEmailProcess($where, $foreignKeys) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function selectQueryBuild($select, $where, $group, $order, $limit, $page) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function messageQuery($query, $time, $failed = false) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function editInput($table, $field, $attrs, $value) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function editHint($table, $field, $value) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function processInput($field, $value, $function = "") {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function dumpDatabase($db) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function dumpTable($table, $style, $is_view = 0) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function dumpData($table, $style, $query) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function dumpFilename($identifier) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function dumpHeaders($identifier, $multi_table = false) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function dumpFooter() {
$args = func_get_args();
return $this->applyPlugin(__FUNCTION__, $args);
}
function importServerPath() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function homepage() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function navigation($missing) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function databasesPrint($missing) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
function tablesPrint($tables) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
return $this->applyPlugin(__FUNCTION__, $args);
}
}

View File

@@ -1,16 +1,13 @@
<?php
/** Pretty print JSON values in edit
* @link https://www.adminer.org/plugins/#use
* @author Christopher Chen
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerPrettyJsonColumn {
/** @var AdminerPlugin */
protected $adminer;
public function __construct($adminer) {
$this->adminer = $adminer;
}
private function _testJson($value) {
private function testJson($value) {
if ((substr($value, 0, 1) == '{' || substr($value, 0, 1) == '[') && ($json = json_decode($value, true))) {
return $json;
}
@@ -18,23 +15,20 @@ class AdminerPrettyJsonColumn {
}
function editInput($table, $field, $attrs, $value) {
$json = $this->_testJson($value);
$json = $this->testJson($value);
if ($json !== $value) {
$jsonText = json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return <<<HTML
<textarea $attrs cols="50" rows="20">$jsonText</textarea>
HTML;
return "<textarea$attrs cols='50' rows='20'>" . h($jsonText) . "</textarea>";
}
return '';
}
function processInput($field, $value, $function = '') {
if ($function === '') {
$json = $this->_testJson($value);
$json = $this->testJson($value);
if ($json !== $value) {
$value = json_encode($json);
}
}
return $this->adminer->_callParent('processInput', array($field, $value, $function));
}
}

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerSlugify {
/** @access protected */
var $from, $to;
protected $from, $to;
/**
* @param string find these characters ...

View File

@@ -7,8 +7,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerSqlLog {
/** @access protected */
var $filename;
protected $filename;
/**
* @param string defaults to "$database.sql"
@@ -18,14 +17,14 @@ class AdminerSqlLog {
}
function messageQuery($query, $time, $failed = false) {
$this->_log($query);
$this->log($query);
}
function sqlCommandQuery($query) {
$this->_log($query);
$this->log($query);
}
function _log($query) {
private function log($query) {
if ($this->filename == "") {
$adminer = Adminer\adminer();
$this->filename = $adminer->database() . ".sql"; // no database goes to ".sql" to avoid collisions

View File

@@ -15,7 +15,15 @@ class AdminerTableStructure {
function tableStructurePrint($fields) {
echo "<div class='scrollable'>\n";
echo "<table class='nowrap odds'>\n";
echo "<thead><tr><th>" . Adminer\lang('Column') . "<th>" . Adminer\lang('Type') . "<th>" . Adminer\lang('Collation') . "<th>" . Adminer\lang('Nullable') . "<th>" . Adminer\lang('Default') . (Adminer\support("comment") ? "<th>" . Adminer\lang('Comment') : "") . "</thead>\n";
echo "<thead><tr>"
. "<th>" . Adminer\lang('Column')
. "<th>" . Adminer\lang('Type')
. "<th>" . Adminer\lang('Collation')
. "<th>" . Adminer\lang('Nullable')
. "<th>" . Adminer\lang('Default')
. (Adminer\support("comment") ? "<th>" . Adminer\lang('Comment') : "")
. "</thead>\n"
;
foreach ($fields as $field) {
echo "<tr><th>" . Adminer\h($field["field"]) . ($field["primary"] ? " (PRIMARY)" : "");
echo "<td><span>" . Adminer\h($field["full_type"]) . "</span>";

View File

@@ -8,8 +8,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerTinymce {
/** @access protected */
var $path;
protected $path;
/**
* @param string

View File

@@ -18,7 +18,7 @@ CREATE TABLE translation (
*/
class AdminerTranslation {
function _translate($idf) {
private function translate($idf) {
static $translations, $lang;
if ($lang === null) {
$lang = Adminer\get_lang();
@@ -39,16 +39,16 @@ class AdminerTranslation {
}
function tableName(&$tableStatus) {
$tableStatus["Comment"] = $this->_translate($tableStatus["Comment"]);
$tableStatus["Comment"] = $this->translate($tableStatus["Comment"]);
}
function fieldName(&$field, $order = 0) {
$field["comment"] = $this->_translate($field["comment"]);
$field["comment"] = $this->translate($field["comment"]);
}
function editVal(&$val, $field) {
if ($field["type"] == "enum") {
$val = $this->_translate($val);
$val = $this->translate($val);
}
}
}

View File

@@ -8,8 +8,7 @@
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerWymeditor {
/** @access protected */
var $scripts, $options;
protected $scripts, $options;
/**
* @param array

View File

@@ -2,7 +2,9 @@ Adminer - Database management in a single PHP file
Adminer Editor - Data manipulation for end-users
https://www.adminer.org/
Supports: MySQL, MariaDB, PostgreSQL, SQLite, MS SQL, Oracle, MongoDB, Elasticsearch (plugin), SimpleDB (plugin), Firebird (plugin), ClickHouse (plugin)
Supports: MySQL, MariaDB, PostgreSQL, CockroachDB, SQLite, MS SQL, Oracle
Plugins for: Elasticsearch, SimpleDB, MongoDB, Firebird, ClickHouse
Requirements: PHP 5.3+
adminer/index.php - Run development version of Adminer
@@ -15,6 +17,6 @@ editor/sqlite.php - Development version of Editor with SQLite allowed
adminer/designs.php - Development version of Adminer with adminer.css switcher
compile.php - Create a single file version
lang.php - Update translations
tests/katalon.html - Katalon Automation Recorder test suite
tests/*.html - Katalon Recorder test suites
If downloaded from Git then run: git submodule update --init

307
tests/cocroachdb.html Normal file
View File

@@ -0,0 +1,307 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<title>Katalon CockroachDB</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Login</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/</td><td></td></tr>
<tr><td>select</td><td>name=lang</td><td>label=English</td></tr>
<tr><td>clickAndWait</td><td>css=#lang &gt; input[type="submit"]</td><td></td></tr>
<tr><td>select</td><td>name=auth[driver]</td><td>label=PostgreSQL</td></tr>
<tr><td>type</td><td>name=auth[server]</td><td>localhost:26257</td></tr>
<tr><td>type</td><td>id=username</td><td>ODBC</td></tr>
<tr><td>type</td><td>name=auth[password]</td><td>ODBC</td></tr>
<tr><td>clickAndWait</td><td>xpath=//input[@value='Login']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>CockroachDB</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Create table</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Create table</td><td></td></tr>
<tr><td>type</td><td>name</td><td>interprets</td></tr>
<tr><td>type</td><td>fields[1][field]</td><td>id</td></tr>
<tr><td>select</td><td>fields[1][type]</td><td>label=integer</td></tr>
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
<tr><td>type</td><td>fields[1.1][field]</td><td>name</td></tr>
<tr><td>select</td><td>fields[1.1][type]</td><td>label=character varying</td></tr>
<tr><td>type</td><td>fields[1.1][length]</td><td>50</td></tr>
<tr><td>uncheck</td><td>name=comments</td><td></td></tr>
<tr><td>clickAndWait</td><td>name=comments</td><td></td></tr>
<tr><td>type</td><td>fields[1.1][comment]</td><td>Interpret</td></tr>
<tr><td>type</td><td>Comment</td><td>Interprets</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Table has been created.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Create index</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;table=interprets</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Alter indexes</td><td></td></tr>
<tr><td>select</td><td>indexes[2][type]</td><td>label=PRIMARY</td></tr>
<tr><td>select</td><td>indexes[2][columns][1]</td><td>label=name</td></tr>
<tr><td>verifyValue</td><td>name=indexes[2][name]</td><td>interprets_name</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>multiple primary keys for table "interprets" are not allowed</td><td></td></tr>
<tr><td>select</td><td>indexes[2][type]</td><td>label=INDEX</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Indexes have been altered.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Create table 2</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;table=interprets</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Create table</td><td></td></tr>
<tr><td>type</td><td>name</td><td>albums</td></tr>
<tr><td>click</td><td>//input[@name='auto_increment_col' and @value='1']</td><td></td></tr>
<tr><td>type</td><td>fields[1.1][field]</td><td>interpret</td></tr>
<tr><td>select</td><td>fields[1.1][type]</td><td>label=integer</td></tr>
<tr><td>type</td><td>fields[1.11][field]</td><td>title</td></tr>
<tr><td>select</td><td>fields[1.11][type]</td><td>label=character varying</td></tr>
<tr><td>type</td><td>fields[1.11][length]</td><td>50</td></tr>
<tr><td>check</td><td>name=comments</td><td></td></tr>
<tr><td>type</td><td>fields[1.1][comment]</td><td>Interpret</td></tr>
<tr><td>type</td><td>fields[1.11][comment]</td><td>Album</td></tr>
<tr><td>type</td><td>Comment</td><td>Albums</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Table has been created.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Foreign key</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;table=albums</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Add foreign key</td><td></td></tr>
<tr><td>selectAndWait</td><td>table</td><td>label=interprets</td></tr>
<tr><td>select</td><td>source[0]</td><td>label=interpret</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Foreign key has been created.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Alter table</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;table=interprets</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Alter table</td><td></td></tr>
<tr><td>click</td><td>add[2]</td><td></td></tr>
<tr><td>type</td><td>fields[3][field]</td><td>albums</td></tr>
<tr><td>select</td><td>fields[3][type]</td><td>label=integer</td></tr>
<tr><td>type</td><td>fields[3][length]</td><td></td></tr>
<tr><td>uncheck</td><td>name=defaults</td><td></td></tr>
<tr><td>clickAndWait</td><td>name=defaults</td><td></td></tr>
<tr><td>type</td><td>name=fields[3][default]</td><td>0</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Table has been altered.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Check constraints</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;table=albums</td><td></td></tr>
<tr><td>click</td><td>link=Create check</td><td></td></tr>
<tr><td>type</td><td>name=name</td><td>albums_interpret_check</td></tr>
<tr><td>runScript</td><td>document.querySelector('[name="clause"]').value = 'interpret > 0'</td><td></td></tr>
<tr><td>click</td><td>xpath=//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Check has been created.</td><td></td></tr>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;check=albums&amp;name=albums_interpret_check</td><td></td></tr>
<tr><td>verifyTextPresent<td>((interpret > 0:::INT8))</td><td></td></tr>
<tr><td>chooseOkOnNextConfirmation</td><td>Drop albums_interpret_check?</td><td></td></tr>
<tr><td>click</td><td>name=drop</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Check has been dropped.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Create view</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;view=</td><td></td></tr>
<tr><td>runScript</td><td>document.querySelector('[name="select"]').value = 'SELECT albums.id, albums.title, interprets.name FROM albums LEFT JOIN interprets ON albums.interpret = interprets.id'</td><td></td></tr>
<tr><td>type</td><td>name</td><td>albums_interprets</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>View has been created.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Insert</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;edit=interprets</td><td></td></tr>
<tr><td>type</td><td>fields[id]</td><td>1</td></tr>
<tr><td>type</td><td>fields[name]</td><td>Michael Jackson</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Item has been inserted.</td><td></td></tr>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;edit=albums</td><td></td></tr>
<tr><td>type</td><td>fields[interpret]</td><td>1</td></tr>
<tr><td>type</td><td>fields[title]</td><td>Dangerous</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Item has been inserted.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Clone</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;select=albums</td><td></td></tr>
<tr><td>click</td><td>check[]</td><td></td></tr>
<tr><td>clickAndWait</td><td>clone</td><td></td></tr>
<tr><td>type</td><td>fields[id]</td><td>2</td></tr>
<tr><td>type</td><td>fields[title]</td><td>Black and White</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>1 item has been affected.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Explain</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;select=albums</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Edit</td><td></td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Execute']</td><td></td></tr>
<tr><td>click</td><td>link=Explain</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>LIMITED SCAN</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Reference</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;select=albums</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=1</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Michael Jackson</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Update</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;edit=albums&amp;where%5Bid%5D=2</td><td></td></tr>
<tr><td>type</td><td>fields[title]</td><td>Black or White</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Item has been updated.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Delete</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;select=albums</td><td></td></tr>
<tr><td>click</td><td>//input[@name='check[]' and @value='where%5Bid%5D=2']</td><td></td></tr>
<tr><td>waitForChecked</td><td>//input[@name='check[]' and @value='where%5Bid%5D=2']</td><td></td></tr>
<tr><td>chooseOkOnNextConfirmation</td><td>Are you sure?</td><td></td></tr>
<tr><td>click</td><td>delete</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>1 item has been affected.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Truncate</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;select=albums</td><td></td></tr>
<tr><td>click</td><td>all</td><td></td></tr>
<tr><td>waitForChecked</td><td>all</td><td></td></tr>
<tr><td>chooseOkOnNextConfirmation</td><td>Are you sure?</td><td></td></tr>
<tr><td>click</td><td>delete</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>No rows.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Export</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;dump=</td><td></td></tr>
<tr><td>click</td><td>output</td><td></td></tr>
<tr><td>click</td><td>format</td><td></td></tr>
<tr><td>select</td><td>table_style</td><td>label=DROP+CREATE</td></tr>
<tr><td>select</td><td>data_style</td><td>label=INSERT</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Export']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>CREATE TABLE "public"."interprets"</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>INSERT INTO "interprets"</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>VIEW "albums_interprets"</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Procedures</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;procedure=</td><td></td></tr>
<tr><td>clickAndWait</td><td>add[0]</td><td></td></tr>
<tr><td>type</td><td>fields[1][field]</td><td>interpret_name</td></tr>
<tr><td>select</td><td>fields[1][type]</td><td>label=character varying</td></tr>
<tr><td>type</td><td>fields[1][length]</td><td>50</td></tr>
<tr><td>type</td><td>fields[1.1][field]</td><td>album_title</td></tr>
<tr><td>select</td><td>fields[1.1][type]</td><td>label=character varying</td></tr>
<tr><td>type</td><td>fields[1.1][length]</td><td>50</td></tr>
<tr><td>runScript</td><td>document.querySelector('[name="definition"]').value = 'SELECT id FROM interprets;'</td><td></td></tr>
<tr><td>type</td><td>name</td><td>insert_album</td></tr>
<tr><td>select</td><td>name=language</td><td>label=sql</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Routine has been created.</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=insert_album</td><td></td></tr>
<tr><td>type</td><td>fields[interpret_name]</td><td>Michael Jackson</td></tr>
<tr><td>type</td><td>fields[album_title]</td><td>Dangerous</td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Call']</td><td></td></tr>
<tr><td>assertTextPresent</td><td>Routine has been called,</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=public</td><td></td></tr>
<tr><td>clickAndWait</td><td>link=Alter</td><td></td></tr>
<tr><td>chooseOkOnNextConfirmation</td><td>Drop insert_album?</td><td></td></tr>
<tr><td>click</td><td>drop</td><td></td></tr>
<!-- This looks like a bug in CockroachDB, not Adminer. <tr><td>verifyTextPresent</td><td>Routine has been dropped.</td><td></td></tr> -->
<tr><td>open</td><td>/adminer/?pgsql=localhost%3A26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public&amp;sql=DROP+PROCEDURE+%22insert_album%22</td><td></td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Execute']</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Drop</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;db=adminer_test&amp;ns=public</td><td></td></tr>
<tr><td>click</td><td>id=check-all</td><td></td></tr>
<tr><td>chooseOkOnNextConfirmation</td><td>Are you sure?</td><td></td></tr>
<tr><td>click</td><td>name=drop</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>No tables.</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Variables</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;variables=</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>crdb_version</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">SQL command</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC&amp;sql=SELECT+122%2B1</td><td></td></tr>
<tr><td>clickAndWait</td><td>//input[@value='Execute']</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>123</td><td></td></tr>
</tbody></table>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Logout</td></tr>
</thead>
<tbody>
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&amp;username=ODBC</td><td></td></tr>
<tr><td>clickAndWait</td><td>logout</td><td></td></tr>
<tr><td>verifyTextPresent</td><td>Logout successful.</td><td></td></tr>
<tr><td>open</td><td>/coverage.php</td><td></td></tr>
</tbody></table>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More