mirror of
https://github.com/vrana/adminer.git
synced 2025-09-02 10:53:09 +02:00
Compare commits
200 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b7679701ce | ||
|
b7258d2e95 | ||
|
c51d9919fe | ||
|
78c431ab20 | ||
|
916889bb8e | ||
|
e8b15c99f4 | ||
|
a460019535 | ||
|
ea5a7453fb | ||
|
587f6a5375 | ||
|
2bb74e7467 | ||
|
a684044bb3 | ||
|
36a3465a64 | ||
|
223aee70d5 | ||
|
c02a7d6abe | ||
|
22a3efe4ed | ||
|
dd47df9b9c | ||
|
0b0e8940e0 | ||
|
fa8339c8c2 | ||
|
f0ee812b29 | ||
|
f093cb6db2 | ||
|
68d4a5a650 | ||
|
6576fa6a73 | ||
|
28535bf384 | ||
|
43e3fe375d | ||
|
d8a9a3db8d | ||
|
777d5dca0e | ||
|
6d71cd678e | ||
|
30714d98f9 | ||
|
8353bd48de | ||
|
0762c761ac | ||
|
529197f403 | ||
|
d20cbf14e7 | ||
|
517f63835d | ||
|
4fee062b73 | ||
|
26769b2357 | ||
|
42bf7b9ca0 | ||
|
d8755c903d | ||
|
a391fcb6c4 | ||
|
c99ca863ce | ||
|
e0283543f3 | ||
|
a72e053520 | ||
|
de654712d5 | ||
|
9c1d5484a2 | ||
|
1fd8aa885b | ||
|
08882c6a8e | ||
|
fd199ec156 | ||
|
e3515fd63f | ||
|
be0a485b14 | ||
|
94c04712d6 | ||
|
caea0b7f68 | ||
|
134301b3ff | ||
|
d14f3dd2d8 | ||
|
67c313c86d | ||
|
5eaa73583a | ||
|
68b6af6fce | ||
|
e65fdba5d1 | ||
|
8f336cd0b3 | ||
|
5f3bfe8451 | ||
|
1a3d58e74e | ||
|
af9a851c5e | ||
|
3a40a855ea | ||
|
967647759e | ||
|
e4323ced55 | ||
|
85c6af6f87 | ||
|
9226804aa2 | ||
|
041e7064ca | ||
|
4c2a8b0050 | ||
|
9afbf1a465 | ||
|
352ef9c778 | ||
|
45107dc46e | ||
|
21f3426adb | ||
|
95dccfe9fb | ||
|
fe88f83c95 | ||
|
078957fe32 | ||
|
61f07867f9 | ||
|
0135dd5b81 | ||
|
773a2253d3 | ||
|
272042a30e | ||
|
48308f3357 | ||
|
c90033a962 | ||
|
8bd022f974 | ||
|
b1550b052d | ||
|
9862846a7c | ||
|
f14e3e38f6 | ||
|
95262c4215 | ||
|
dacfdc4608 | ||
|
7636c253fb | ||
|
44d26a9dd3 | ||
|
b229e7b583 | ||
|
8e91417be1 | ||
|
db7202fcf0 | ||
|
260487fbc2 | ||
|
3ae964c915 | ||
|
d56c8cbaae | ||
|
d347f88c54 | ||
|
b9b4db0c8e | ||
|
818b9ad903 | ||
|
4a6436773f | ||
|
81594e4a2d | ||
|
f0bdb0e6ca | ||
|
b9e4806d3c | ||
|
7e708dae57 | ||
|
a0fe44ec18 | ||
|
eb0f280776 | ||
|
3b1189cd3c | ||
|
434a8f7705 | ||
|
f9478c67d2 | ||
|
f2ce6c0a71 | ||
|
a50b3d6385 | ||
|
e39deca4f1 | ||
|
ce69970f54 | ||
|
51ac1312a1 | ||
|
4505544953 | ||
|
fa75213ff6 | ||
|
63acb37ea6 | ||
|
3ad6c16f59 | ||
|
22d08b4a50 | ||
|
dd3cc4e683 | ||
|
5504a617d0 | ||
|
2fdebfda29 | ||
|
dc2e945aef | ||
|
43d86287c4 | ||
|
a94a727af7 | ||
|
c2d29a6937 | ||
|
c082136558 | ||
|
7b1ea5fa2c | ||
|
156839142e | ||
|
2ee4e3b2e1 | ||
|
8b4c8b0156 | ||
|
9702878297 | ||
|
4a54648995 | ||
|
2e5027a1aa | ||
|
5a4c4dd892 | ||
|
7ef009336f | ||
|
1defc94d12 | ||
|
5d3376e620 | ||
|
d410cdc5be | ||
|
a44e625882 | ||
|
ae57d42105 | ||
|
199edfe11f | ||
|
b02c3e1f7f | ||
|
98cb9b9aca | ||
|
514d64048d | ||
|
1e963cf90f | ||
|
0c15a9f42d | ||
|
c454ea8430 | ||
|
607febea8e | ||
|
ebd5f19dd4 | ||
|
1b0984ff31 | ||
|
b017928256 | ||
|
526077535e | ||
|
8274b2e0e8 | ||
|
8f7d456887 | ||
|
91b735c576 | ||
|
916b9e62de | ||
|
f25c65837f | ||
|
b0182834bf | ||
|
6bf0b85919 | ||
|
37e63dd82f | ||
|
6fdde32f86 | ||
|
aeac0a3329 | ||
|
fde7d7dde2 | ||
|
e993462412 | ||
|
31f8f61d0e | ||
|
e589ee3fde | ||
|
35274f18bb | ||
|
f8b2640156 | ||
|
bb23546478 | ||
|
dddfc190a5 | ||
|
40760d153c | ||
|
4fe3d17255 | ||
|
6dcc5081e1 | ||
|
df6fe6b108 | ||
|
e6339046ff | ||
|
2c0cfbdd3f | ||
|
f13770c664 | ||
|
100a1f49bc | ||
|
47ccd9b44d | ||
|
7512bc2d51 | ||
|
4991817b0d | ||
|
e883ad428e | ||
|
87d87248c1 | ||
|
862e5b4aa4 | ||
|
ad2cbbf26e | ||
|
afe7dd9ad9 | ||
|
3b2ef32349 | ||
|
47b64f4752 | ||
|
a1c3e34e04 | ||
|
608eec89dd | ||
|
cfe39e48ca | ||
|
900a3c0d6a | ||
|
ead6a9a36f | ||
|
d05a758a88 | ||
|
b0450d0d2a | ||
|
e7c3a046a7 | ||
|
d35c896b92 | ||
|
4b71549ca0 | ||
|
ab0f07dd81 | ||
|
c19e6f27f1 | ||
|
14b257784b |
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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.
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -4,3 +4,6 @@
|
||||
[submodule "JsShrink"]
|
||||
path = externals/JsShrink
|
||||
url = https://github.com/vrana/JsShrink
|
||||
[submodule "PhpShrink"]
|
||||
path = externals/PhpShrink
|
||||
url = https://github.com/vrana/PhpShrink
|
||||
|
@@ -6,6 +6,6 @@ I support only the last published version and the last development version (last
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report a vulnerability, create a private bug at https://sourceforge.net/p/adminer/bugs-and-features/new/?private=1.
|
||||
To report a vulnerability, add a new draft security advisory at https://github.com/vrana/adminer/security/advisories/new.
|
||||
|
||||
I handle security issues with top priority. If you don't hear from me in a week then please ping the bug. Once I accept the bug, the fix should be available and new version released within days. I will mark the bug as public after releasing a new version or declining the bug.
|
||||
|
@@ -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
|
||||
|
@@ -30,7 +30,7 @@ if ($row["auto_increment_col"]) {
|
||||
}
|
||||
|
||||
if ($_POST) {
|
||||
set_adminer_settings(array("comments" => $_POST["comments"], "defaults" => $_POST["defaults"]));
|
||||
save_settings(array("comments" => $_POST["comments"], "defaults" => $_POST["defaults"]));
|
||||
}
|
||||
|
||||
if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
@@ -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) {
|
||||
@@ -180,27 +180,27 @@ foreach ($engines as $engine) {
|
||||
|
||||
<form action="" method="post" id="form">
|
||||
<p>
|
||||
<?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 ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . 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"]) : ""); ?>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php } ?>
|
||||
<?php
|
||||
if (support("columns") || $TABLE == "") {
|
||||
echo lang('Table name') . "<input name='name'" . ($TABLE == "" && !$_POST ? " autofocus" : "") . " data-maxlength='64' value='" . h($row["name"]) . "' autocapitalize='off'>\n";
|
||||
echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") . "\n" : "");
|
||||
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') . ")'>");
|
||||
}
|
||||
echo "<input type='submit' value='" . lang('Save') . "'>\n";
|
||||
}
|
||||
|
||||
<?php if (support("columns")) { ?>
|
||||
<div class="scrollable">
|
||||
<table id="edit-fields" class="nowrap">
|
||||
<?php
|
||||
if (support("columns")) {
|
||||
echo "<div class='scrollable'>\n";
|
||||
echo "<table id='edit-fields' class='nowrap'>\n";
|
||||
edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
|
||||
?>
|
||||
</table>
|
||||
<?php echo script("editFields();"); ?>
|
||||
</div>
|
||||
<p>
|
||||
<?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" class="size" value="<?php echo h($row["Auto_increment"]); ?>">
|
||||
<?php echo checkbox("defaults", 1, ($_POST ? $_POST["defaults"] : adminer_setting("defaults")), lang('Default values'), "columnShow(this.checked, 5)", "jsonly"); ?>
|
||||
<?php
|
||||
$comments = ($_POST ? $_POST["comments"] : adminer_setting("comments"));
|
||||
echo "</table>\n";
|
||||
echo script("editFields();");
|
||||
echo "</div>\n<p>\n";
|
||||
echo lang('Auto Increment') . ": <input type='number' name='Auto_increment' class='size' value='" . h($row["Auto_increment"]) . "'>\n";
|
||||
echo checkbox("defaults", 1, ($_POST ? $_POST["defaults"] : get_setting("defaults")), lang('Default values'), "columnShow(this.checked, 5)", "jsonly");
|
||||
$comments = ($_POST ? $_POST["comments"] : get_setting("comments"));
|
||||
echo (support("comment")
|
||||
? checkbox("comments", 1, $comments, lang('Comment'), "editingCommentsClick(this, true);", "jsonly")
|
||||
. ' ' . (preg_match('~\n~', $row["Comment"])
|
||||
@@ -221,24 +221,18 @@ foreach ($engines as $engine) {
|
||||
if (support("partitioning")) {
|
||||
$partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]);
|
||||
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
|
||||
?>
|
||||
<p>
|
||||
<?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?>
|
||||
(<input name="partition" value="<?php echo h($row["partition"]); ?>">)
|
||||
<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>">
|
||||
<table id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
|
||||
<thead><tr><th><?php echo lang('Partition name'); ?><th><?php echo lang('Values'); ?></thead>
|
||||
<?php
|
||||
echo "<p>" . html_select("partition_by", array("" => "") + $partition_by, $row["partition_by"]) . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;");
|
||||
echo "(<input name='partition' value='" . h($row["partition"]) . "'>)\n";
|
||||
echo lang('Partitions') . ": <input type='number' name='partitions' class='size" . ($partition_table || !$row["partition_by"] ? " hidden" : "") . "' value='" . h($row["partitions"]) . "'>\n";
|
||||
echo "<table id='partition-table'" . ($partition_table ? "" : " class='hidden'") . ">\n";
|
||||
echo "<thead><tr><th>" . lang('Partition name') . "<th>" . lang('Values') . "</thead>\n";
|
||||
foreach ($row["partition_names"] as $key => $val) {
|
||||
echo '<tr>';
|
||||
echo '<td><input name="partition_names[]" value="' . h($val) . '" autocapitalize="off">';
|
||||
echo ($key == count($row["partition_names"]) - 1 ? script("qsl('input').oninput = partitionNameChange;") : '');
|
||||
echo '<td><input name="partition_values[]" value="' . h($row["partition_values"][$key]) . '">';
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div></fieldset>
|
||||
<?php
|
||||
echo "</table>\n</div></fieldset>\n";
|
||||
}
|
||||
?>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
|
@@ -123,7 +123,7 @@ if ($adminer->homepage()) {
|
||||
}
|
||||
|
||||
echo "<tr><td><th>" . lang('%d in total', count($tables_list));
|
||||
echo "<td>" . h(JUSH == "sql" ? $connection->result("SELECT @@default_storage_engine") : "");
|
||||
echo "<td>" . h(JUSH == "sql" ? get_val("SELECT @@default_storage_engine") : "");
|
||||
echo "<td>" . h(db_collation(DB, collations()));
|
||||
foreach (array("Data_length", "Index_length", "Data_free") as $key) {
|
||||
echo "<td align='right' id='sum-$key'>";
|
||||
@@ -232,7 +232,7 @@ if ($adminer->homepage()) {
|
||||
echo '<td><a href="' . h(ME) . 'event=' . urlencode($row["Name"]) . '">' . lang('Alter') . '</a>';
|
||||
}
|
||||
echo "</table>\n";
|
||||
$event_scheduler = $connection->result("SELECT @@event_scheduler");
|
||||
$event_scheduler = get_val("SELECT @@event_scheduler");
|
||||
if ($event_scheduler && $event_scheduler != "ON") {
|
||||
echo "<p class='error'><code class='jush-sqlset'>event_scheduler</code>: " . h($event_scheduler) . "\n";
|
||||
}
|
||||
|
@@ -3,8 +3,13 @@ function adminer_object() {
|
||||
include_once "../plugins/plugin.php";
|
||||
include_once "../plugins/designs.php";
|
||||
$designs = array();
|
||||
foreach (glob("../designs/*", GLOB_ONLYDIR) as $filename) {
|
||||
$designs["$filename/adminer.css"] = basename($filename);
|
||||
foreach (glob("../designs/*", GLOB_ONLYDIR) as $dirname) {
|
||||
foreach (array("", "-dark") as $mode) {
|
||||
$filename = "$dirname/adminer$mode.css";
|
||||
if (file_exists($filename)) {
|
||||
$designs[$filename] = basename($dirname);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new AdminerPlugin(array(
|
||||
new AdminerDesigns($designs),
|
||||
|
@@ -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);
|
||||
@@ -304,8 +306,7 @@ if (isset($_GET["mssql"])) {
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT collation_name FROM sys.databases WHERE name = " . q($db));
|
||||
return get_val("SELECT collation_name FROM sys.databases WHERE name = " . q($db));
|
||||
}
|
||||
|
||||
function engines() {
|
||||
@@ -313,8 +314,7 @@ if (isset($_GET["mssql"])) {
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT SUSER_NAME()");
|
||||
return get_val("SELECT SUSER_NAME()");
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
@@ -326,7 +326,7 @@ if (isset($_GET["mssql"])) {
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
$connection->select_db($db);
|
||||
$return[$db] = $connection->result("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES");
|
||||
$return[$db] = get_val("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -355,10 +355,9 @@ WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V')
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$comments = get_key_vals("SELECT objname, cast(value as varchar(max)) FROM fn_listextendedproperty('MS_DESCRIPTION', 'schema', " . q(get_schema()) . ", 'table', " . q($table) . ", 'column', NULL)");
|
||||
$return = array();
|
||||
$table_id = $connection->result("SELECT object_id FROM sys.all_objects WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') AND name = " . q($table));
|
||||
$table_id = get_val("SELECT object_id FROM sys.all_objects WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') AND name = " . q($table));
|
||||
foreach (
|
||||
get_rows("SELECT c.max_length, c.precision, c.scale, c.name, c.is_nullable, c.is_identity, c.collation_name, t.name type, CAST(d.definition as text) [default], d.name default_constraint, i.is_primary_key
|
||||
FROM sys.all_columns c
|
||||
@@ -383,7 +382,7 @@ WHERE c.object_id = " . q($table_id)) as $row
|
||||
"null" => $row["is_nullable"],
|
||||
"auto_increment" => $row["is_identity"],
|
||||
"collation" => $row["collation_name"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1),
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1, "where" => 1, "order" => 1),
|
||||
"primary" => $row["is_primary_key"],
|
||||
"comment" => $comments[$row["name"]],
|
||||
);
|
||||
@@ -415,8 +414,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table), $connection2) as $row
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^[]|\[[^]]*])*\s+AS\s+~isU', '', $connection->result("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q($name))));
|
||||
return array("select" => preg_replace('~^(?:[^[]|\[[^]]*])*\s+AS\s+~isU', '', get_val("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q($name))));
|
||||
}
|
||||
|
||||
function collations() {
|
||||
@@ -511,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;
|
||||
}
|
||||
@@ -541,8 +548,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table), $connection2) as $row
|
||||
}
|
||||
|
||||
function last_id() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT SCOPE_IDENTITY()"); // @@IDENTITY can return trigger INSERT
|
||||
return get_val("SELECT SCOPE_IDENTITY()"); // @@IDENTITY can return trigger INSERT
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
@@ -635,11 +641,10 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)) as $row
|
||||
}
|
||||
|
||||
function get_schema() {
|
||||
global $connection;
|
||||
if ($_GET["ns"] != "") {
|
||||
return $_GET["ns"];
|
||||
}
|
||||
return $connection->result("SELECT SCHEMA_NAME()");
|
||||
return get_val("SELECT SCHEMA_NAME()");
|
||||
}
|
||||
|
||||
function set_schema($schema) {
|
||||
|
@@ -1,14 +1,14 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$drivers = array("server" => "MySQL") + $drivers;
|
||||
$drivers = array("server" => "MySQL / MariaDB") + $drivers;
|
||||
|
||||
if (!defined('Adminer\DRIVER')) {
|
||||
define('Adminer\DRIVER', "server"); // server - backwards compatibility
|
||||
// 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;
|
||||
@@ -425,10 +435,13 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return mixed Db or string for error
|
||||
*/
|
||||
function connect($credentials) {
|
||||
global $drivers;
|
||||
$connection = new Db;
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
$connection->set_charset(charset($connection)); // available in MySQLi since PHP 5.0.5
|
||||
$connection->set_charset(charset($connection));
|
||||
$connection->query("SET sql_quote_show_create = 1, autocommit = 1");
|
||||
$connection->maria = preg_match('~MariaDB~', $connection->server_info);
|
||||
$drivers[DRIVER] = ($connection->maria ? "MariaDB" : "MySQL");
|
||||
return $connection;
|
||||
}
|
||||
$return = $connection->error;
|
||||
@@ -484,9 +497,8 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return string
|
||||
*/
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
$return = null;
|
||||
$create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1);
|
||||
$create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1);
|
||||
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
|
||||
$return = $match[1];
|
||||
} elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
|
||||
@@ -513,8 +525,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return string
|
||||
*/
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT USER()");
|
||||
return get_val("SELECT USER()");
|
||||
}
|
||||
|
||||
/** Get tables list
|
||||
@@ -586,36 +597,51 @@ 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"),
|
||||
"on_update" => (preg_match('~\bon update (\w+)~i', $extra, $match) ? $match[1] : ""), //! available since MySQL 5.1.23
|
||||
"collation" => $row["COLLATION_NAME"],
|
||||
"privileges" => array_flip(explode(",", $row["PRIVILEGES"])),
|
||||
"privileges" => array_flip(explode(",", "$row[PRIVILEGES],where,order")),
|
||||
"comment" => $row["COLUMN_COMMENT"],
|
||||
"primary" => ($row["COLUMN_KEY"] == "PRI"),
|
||||
"generated" => ($generated[1] == "PERSISTENT" ? "STORED" : $generated[1]),
|
||||
@@ -646,12 +672,17 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return array [$name => ["db" => , "ns" => , "table" => , "source" => [], "target" => [], "on_delete" => , "on_update" => ]]
|
||||
*/
|
||||
function foreign_keys($table) {
|
||||
global $connection, $driver;
|
||||
global $driver;
|
||||
static $pattern = '(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")';
|
||||
$return = array();
|
||||
$create_table = $connection->result("SHOW CREATE TABLE " . table($table), 1);
|
||||
$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);
|
||||
@@ -673,8 +704,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return array ["select" => ]
|
||||
*/
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', $connection->result("SHOW CREATE VIEW " . table($name), 1)));
|
||||
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', get_val("SHOW CREATE VIEW " . table($name), 1)));
|
||||
}
|
||||
|
||||
/** Get sorted grouped list of collations
|
||||
@@ -789,12 +819,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,12 +999,14 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return array ["fields" => ["field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ], "returns" => , "definition" => , "language" => ]
|
||||
*/
|
||||
function routine($name, $type) {
|
||||
global $connection, $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 = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
|
||||
$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);
|
||||
$fields = array();
|
||||
preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER);
|
||||
@@ -980,7 +1014,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],
|
||||
@@ -990,7 +1024,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
}
|
||||
return array(
|
||||
"fields" => $fields,
|
||||
"comment" => $connection->result("SELECT ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE() AND ROUTINE_NAME = " . q($name)),
|
||||
"comment" => get_val("SELECT ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE() AND ROUTINE_NAME = " . q($name)),
|
||||
) + ($type != "FUNCTION" ? array("definition" => $match[11]) : array(
|
||||
"returns" => array("type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]),
|
||||
"definition" => $match[17],
|
||||
@@ -1025,8 +1059,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return string
|
||||
*/
|
||||
function last_id() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint
|
||||
return get_val("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint
|
||||
}
|
||||
|
||||
/** Explain select
|
||||
@@ -1089,8 +1122,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return string
|
||||
*/
|
||||
function create_sql($table, $auto_increment, $style) {
|
||||
global $connection;
|
||||
$return = $connection->result("SHOW CREATE TABLE " . table($table), 1);
|
||||
$return = get_val("SHOW CREATE TABLE " . table($table), 1);
|
||||
if (!$auto_increment) {
|
||||
$return = preg_replace('~ AUTO_INCREMENT=\d+~', '', $return); //! skip comments
|
||||
}
|
||||
@@ -1164,7 +1196,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
|
||||
/** Convert value in edit after applying functions back
|
||||
* @param array one element from fields()
|
||||
* @param string
|
||||
* @param string SQL expression
|
||||
* @return string
|
||||
*/
|
||||
function unconvert_field($field, $return) {
|
||||
@@ -1182,7 +1214,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) {
|
||||
@@ -1208,7 +1240,6 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return int
|
||||
*/
|
||||
function max_connections() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT @@max_connections");
|
||||
return get_val("SELECT @@max_connections");
|
||||
}
|
||||
}
|
||||
|
@@ -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,34 +62,32 @@ 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() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function result($query, $field = 1) {
|
||||
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);
|
||||
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);
|
||||
@@ -241,8 +244,7 @@ ORDER BY 1"
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'"); //! respect $db
|
||||
return get_val("SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'"); //! respect $db
|
||||
}
|
||||
|
||||
function engines() {
|
||||
@@ -250,8 +252,7 @@ ORDER BY 1"
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT USER FROM DUAL");
|
||||
return get_val("SELECT USER FROM DUAL");
|
||||
}
|
||||
|
||||
function get_current_db() {
|
||||
@@ -284,10 +285,9 @@ ORDER BY 1"
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
$return[$db] = $connection->result("SELECT COUNT(*) FROM all_tables WHERE tablespace_name = " . q($db));
|
||||
$return[$db] = get_val("SELECT COUNT(*) FROM all_tables WHERE tablespace_name = " . q($db));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -337,7 +337,7 @@ ORDER BY 1") as $row
|
||||
"null" => ($row["NULLABLE"] == "Y"),
|
||||
//! "auto_increment" => false,
|
||||
//! "collation" => $row["CHARACTER_SET_NAME"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1),
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1, "where" => 1, "order" => 1),
|
||||
//! "comment" => $row["Comment"],
|
||||
//! "primary" => ($row["Key"] == "PRI"),
|
||||
);
|
||||
@@ -505,8 +505,7 @@ AND c_src.TABLE_NAME = " . q($table);
|
||||
}
|
||||
|
||||
function get_schema() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT sys_context('USERENV', 'SESSION_USER') FROM dual");
|
||||
return get_val("SELECT sys_context('USERENV', 'SESSION_USER') FROM dual");
|
||||
}
|
||||
|
||||
function set_schema($scheme, $connection2 = null) {
|
||||
@@ -522,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\'
|
||||
|
@@ -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);
|
||||
@@ -234,6 +232,11 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
}
|
||||
|
||||
function enumLength($field) {
|
||||
$enum = $this->types[lang('User types')][$field["type"]];
|
||||
return ($enum ? type_values($enum) : "");
|
||||
}
|
||||
|
||||
function setUserTypes($types) {
|
||||
$this->types[lang('User types')] = array_flip($types);
|
||||
}
|
||||
@@ -260,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;
|
||||
}
|
||||
|
||||
@@ -275,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) {
|
||||
@@ -294,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;
|
||||
}
|
||||
@@ -317,11 +321,18 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
|
||||
function connect($credentials) {
|
||||
global $drivers;
|
||||
$connection = new Db;
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
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) : "");
|
||||
$connection->cockroach = preg_match('~CockroachDB~', $connection->server_info);
|
||||
if ($connection->cockroach) { // we don't use "PostgreSQL / CockroachDB" by default because it's too long
|
||||
$drivers[DRIVER] = "CockroachDB";
|
||||
}
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
@@ -345,8 +356,7 @@ ORDER BY datname");
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT datcollate FROM pg_database WHERE datname = " . q($db));
|
||||
return get_val("SELECT datcollate FROM pg_database WHERE datname = " . q($db));
|
||||
}
|
||||
|
||||
function engines() {
|
||||
@@ -354,8 +364,7 @@ ORDER BY datname");
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT user");
|
||||
return get_val("SELECT user");
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
@@ -384,13 +393,18 @@ ORDER BY 1";
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
static $has_size;
|
||||
if ($has_size === null) {
|
||||
// https://github.com/cockroachdb/cockroach/issues/40391
|
||||
$has_size = get_val("SELECT 'pg_table_size'::regproc");
|
||||
}
|
||||
$return = array();
|
||||
foreach (
|
||||
get_rows("SELECT
|
||||
c.relname AS \"Name\",
|
||||
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\",
|
||||
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\"" . ($has_size ? ",
|
||||
pg_table_size(c.oid) AS \"Data_length\",
|
||||
pg_indexes_size(c.oid) AS \"Index_length\",
|
||||
pg_indexes_size(c.oid) AS \"Index_length\"" : "") . ",
|
||||
obj_description(c.oid, 'pg_class') AS \"Comment\",
|
||||
" . (min_version(12) ? "''" : "CASE WHEN c.relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\",
|
||||
c.reltuples as \"Rows\",
|
||||
@@ -420,7 +434,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
|
||||
@@ -448,8 +469,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]);
|
||||
}
|
||||
@@ -466,7 +488,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();
|
||||
@@ -510,8 +537,7 @@ ORDER BY conkey, conname") as $row
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => trim($connection->result("SELECT pg_get_viewdef(" . $connection->result("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($name)) . ")")));
|
||||
return array("select" => trim(get_val("SELECT pg_get_viewdef(" . get_val("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($name)) . ")")));
|
||||
}
|
||||
|
||||
function collations() {
|
||||
@@ -651,7 +677,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) {
|
||||
@@ -688,7 +713,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";
|
||||
}
|
||||
@@ -759,8 +789,7 @@ ORDER BY SPECIFIC_NAME');
|
||||
}
|
||||
|
||||
function found_rows($table_status, $where) {
|
||||
global $connection;
|
||||
if (preg_match("~ rows=([0-9]+)~", $connection->result("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")), $regs)) {
|
||||
if (preg_match("~ rows=([0-9]+)~", get_val("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")), $regs)) {
|
||||
return $regs[1];
|
||||
}
|
||||
return false;
|
||||
@@ -787,8 +816,7 @@ AND typelem = 0"
|
||||
}
|
||||
|
||||
function get_schema() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT current_schema()");
|
||||
return get_val("SELECT current_schema()");
|
||||
}
|
||||
|
||||
function set_schema($schema, $connection2 = null) {
|
||||
@@ -930,7 +958,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 preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|sequence|trigger|type|variables|drop_col'
|
||||
. ($connection->cockroach ? '' : '|processlist') // https://github.com/cockroachdb/cockroach/issues/24745
|
||||
. '|kill|dump)$~', $feature)
|
||||
;
|
||||
}
|
||||
|
||||
function kill_process($val) {
|
||||
@@ -942,7 +974,6 @@ AND typelem = 0"
|
||||
}
|
||||
|
||||
function max_connections() {
|
||||
global $connection;
|
||||
return $connection->result("SHOW max_connections");
|
||||
return get_val("SHOW max_connections");
|
||||
}
|
||||
}
|
||||
|
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -207,16 +209,14 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function limit1($table, $query, $where, $separator = "\n") {
|
||||
global $connection;
|
||||
return (preg_match('~^INTO~', $query) || $connection->result("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')")
|
||||
return (preg_match('~^INTO~', $query) || get_val("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')")
|
||||
? limit($query, $where, 1, 0, $separator)
|
||||
: " $query WHERE rowid = (SELECT rowid FROM " . table($table) . $where . $separator . "LIMIT 1)" //! use primary key in tables with WITHOUT rowid
|
||||
);
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("PRAGMA encoding"); // there is no database list so $db == DB
|
||||
return get_val("PRAGMA encoding"); // there is no database list so $db == DB
|
||||
}
|
||||
|
||||
function engines() {
|
||||
@@ -236,10 +236,9 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach (get_rows("SELECT name AS Name, type AS Engine, 'rowid' AS Oid, '' AS Auto_increment FROM sqlite_master WHERE type IN ('table', 'view') " . ($name != "" ? "AND name = " . q($name) : "ORDER BY name")) as $row) {
|
||||
$row["Rows"] = $connection->result("SELECT COUNT(*) FROM " . idf_escape($row["Name"]));
|
||||
$row["Rows"] = get_val("SELECT COUNT(*) FROM " . idf_escape($row["Name"]));
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
foreach (get_rows("SELECT * FROM sqlite_sequence", null, "") as $row) {
|
||||
@@ -253,12 +252,10 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
global $connection;
|
||||
return !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
|
||||
return !get_val("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$primary = "";
|
||||
foreach (get_rows("PRAGMA table_" . (min_version(3.31) ? "x" : "") . "info(" . table($table) . ")") as $row) {
|
||||
@@ -271,7 +268,7 @@ if (isset($_GET["sqlite"])) {
|
||||
"full_type" => $type,
|
||||
"default" => (preg_match("~^'(.*)'$~", $default, $match) ? str_replace("''", "'", $match[1]) : ($default == "NULL" ? null : $default)),
|
||||
"null" => !$row["notnull"],
|
||||
"privileges" => array("select" => 1, "insert" => 1, "update" => 1),
|
||||
"privileges" => array("select" => 1, "insert" => 1, "update" => 1, "where" => 1, "order" => 1),
|
||||
"primary" => $row["pk"],
|
||||
);
|
||||
if ($row["pk"]) {
|
||||
@@ -283,7 +280,7 @@ if (isset($_GET["sqlite"])) {
|
||||
$primary = $name;
|
||||
}
|
||||
}
|
||||
$sql = $connection->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table));
|
||||
$sql = get_val("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table));
|
||||
$idf = '(("[^"]*+")+|[a-z0-9_]+)';
|
||||
preg_match_all('~' . $idf . '\s+text\s+COLLATE\s+(\'[^\']+\'|\S+)~i', $sql, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
@@ -362,8 +359,7 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE type = 'view' AND name = " . q($name)))); //! identifiers may be inside []
|
||||
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', get_val("SELECT sql FROM sqlite_master WHERE type = 'view' AND name = " . q($name)))); //! identifiers may be inside []
|
||||
}
|
||||
|
||||
function collations() {
|
||||
@@ -492,7 +488,7 @@ if (isset($_GET["sqlite"])) {
|
||||
* @return bool
|
||||
*/
|
||||
function recreate_table($table, $name, $fields, $originals, $foreign, $auto_increment = 0, $indexes = array(), $drop_check = "", $add_check = "") {
|
||||
global $connection, $driver;
|
||||
global $driver;
|
||||
if ($table != "") {
|
||||
if (!$fields) {
|
||||
foreach (fields($table) as $key => $field) {
|
||||
@@ -578,7 +574,7 @@ if (isset($_GET["sqlite"])) {
|
||||
$trigger = trigger($trigger_name);
|
||||
$triggers[] = "CREATE TRIGGER " . idf_escape($trigger_name) . " " . implode(" ", $timing_event) . " ON " . table($name) . "\n$trigger[Statement]";
|
||||
}
|
||||
$auto_increment = $auto_increment ? 0 : $connection->result("SELECT seq FROM sqlite_sequence WHERE name = " . q($table)); // if $auto_increment is set then it will be updated later
|
||||
$auto_increment = $auto_increment ? 0 : get_val("SELECT seq FROM sqlite_sequence WHERE name = " . q($table)); // if $auto_increment is set then it will be updated later
|
||||
if (
|
||||
!queries("DROP TABLE " . table($table)) // drop before creating indexes and triggers to allow using old names
|
||||
|| ($table == $name && !queries("ALTER TABLE " . table($temp_name) . " RENAME TO " . table($name)))
|
||||
@@ -642,7 +638,6 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
if ($name == "") {
|
||||
return array("Statement" => "BEGIN\n\t;\nEND");
|
||||
}
|
||||
@@ -650,7 +645,7 @@ if (isset($_GET["sqlite"])) {
|
||||
$trigger_options = trigger_options();
|
||||
preg_match(
|
||||
"~^CREATE\\s+TRIGGER\\s*$idf\\s*(" . implode("|", $trigger_options["Timing"]) . ")\\s+([a-z]+)(?:\\s+OF\\s+($idf))?\\s+ON\\s*$idf\\s*(?:FOR\\s+EACH\\s+ROW\\s)?(.*)~is",
|
||||
$connection->result("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = " . q($name)),
|
||||
get_val("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = " . q($name)),
|
||||
$match
|
||||
);
|
||||
$of = $match[3];
|
||||
@@ -686,8 +681,7 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function last_id() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT LAST_INSERT_ROWID()");
|
||||
return get_val("SELECT LAST_INSERT_ROWID()");
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
@@ -702,8 +696,7 @@ if (isset($_GET["sqlite"])) {
|
||||
}
|
||||
|
||||
function create_sql($table, $auto_increment, $style) {
|
||||
global $connection;
|
||||
$return = $connection->result("SELECT sql FROM sqlite_master WHERE type IN ('table', 'view') AND name = " . q($table));
|
||||
$return = get_val("SELECT sql FROM sqlite_master WHERE type IN ('table', 'view') AND name = " . q($table));
|
||||
foreach (indexes($table) as $name => $index) {
|
||||
if ($name == '') {
|
||||
continue;
|
||||
|
@@ -4,11 +4,10 @@ namespace Adminer;
|
||||
$TABLE = $_GET["dump"];
|
||||
|
||||
if ($_POST && !$error) {
|
||||
$cookie = "";
|
||||
foreach (array("output", "format", "db_style", "types", "routines", "events", "table_style", "auto_increment", "triggers", "data_style") as $key) {
|
||||
$cookie .= "&$key=" . urlencode($_POST[$key]);
|
||||
}
|
||||
cookie("adminer_export", substr($cookie, 1));
|
||||
save_settings(
|
||||
array_intersect_key($_POST, array_flip(array("output", "format", "db_style", "types", "routines", "events", "table_style", "auto_increment", "triggers", "data_style"))),
|
||||
"adminer_export"
|
||||
);
|
||||
$tables = array_flip((array) $_POST["tables"]) + array_flip((array) $_POST["data"]);
|
||||
$ext = dump_headers(
|
||||
(count($tables) == 1 ? key($tables) : DB),
|
||||
@@ -42,7 +41,7 @@ SET foreign_key_checks = 0;
|
||||
foreach ((array) $databases as $db) {
|
||||
$adminer->dumpDatabase($db);
|
||||
if ($connection->select_db($db)) {
|
||||
if ($is_sql && preg_match('~CREATE~', $style) && ($create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1))) {
|
||||
if ($is_sql && preg_match('~CREATE~', $style) && ($create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1))) {
|
||||
set_utf8mb4($create);
|
||||
if ($style == "DROP+CREATE") {
|
||||
echo "DROP DATABASE IF EXISTS " . idf_escape($db) . ";\n";
|
||||
@@ -79,7 +78,7 @@ SET foreign_key_checks = 0;
|
||||
|
||||
if ($_POST["events"]) {
|
||||
foreach (get_rows("SHOW EVENTS", null, "-- ") as $row) {
|
||||
$create = remove_definer($connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3));
|
||||
$create = remove_definer(get_val("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3));
|
||||
set_utf8mb4($create);
|
||||
$out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") . "$create;;\n\n";
|
||||
}
|
||||
@@ -140,9 +139,7 @@ SET foreign_key_checks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_sql) {
|
||||
echo "-- " . gmdate("Y-m-d H:i:s e") . "\n";
|
||||
}
|
||||
$adminer->dumpFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -158,7 +155,7 @@ $data_style = array('', 'TRUNCATE+INSERT', 'INSERT');
|
||||
if (JUSH == "sql") { //! use insertUpdate() in all drivers
|
||||
$data_style[] = 'INSERT+UPDATE';
|
||||
}
|
||||
parse_str($_COOKIE["adminer_export"], $row);
|
||||
$row = get_settings("adminer_export");
|
||||
if (!$row) {
|
||||
$row = array("output" => "text", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT");
|
||||
}
|
||||
@@ -167,9 +164,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')) : "")
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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";
|
||||
|
@@ -1,7 +1,15 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
// caching headers added in compile.php
|
||||
if (substr($VERSION, -4) != '-dev') {
|
||||
if ($_SERVER["HTTP_IF_MODIFIED_SINCE"]) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
exit;
|
||||
}
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 365*24*60*60) . " GMT");
|
||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
||||
header("Cache-Control: immutable");
|
||||
}
|
||||
|
||||
if ($_GET["file"] == "favicon.ico") {
|
||||
header("Content-Type: image/x-icon");
|
||||
@@ -9,6 +17,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;../externals/jush/jush-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'));
|
||||
|
@@ -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++;
|
||||
}
|
||||
?>
|
||||
|
@@ -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
|
||||
@@ -94,12 +94,13 @@ class Adminer {
|
||||
}
|
||||
|
||||
/** Print HTML code inside <head>
|
||||
* @return bool true to link favicon.ico and adminer.css if exists
|
||||
* @param bool dark CSS: false to disable, true to force, null to base on user preferences
|
||||
* @return bool true to link favicon.ico
|
||||
*/
|
||||
function head() {
|
||||
?>
|
||||
<link rel="stylesheet" type="text/css" href="../externals/jush/jush.css">
|
||||
<?php
|
||||
function head($dark = null) {
|
||||
// this is matched by compile.php
|
||||
echo "<link rel='stylesheet' href='../externals/jush/jush.css'>\n";
|
||||
echo ($dark !== false ? "<link rel='stylesheet'" . ($dark ? "" : " media='(prefers-color-scheme: dark)'") . " href='../externals/jush/jush-dark.css'>\n" : "");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -108,9 +109,11 @@ class Adminer {
|
||||
*/
|
||||
function css() {
|
||||
$return = array();
|
||||
$filename = "adminer.css";
|
||||
if (file_exists($filename)) {
|
||||
$return[] = "$filename?v=" . crc32(file_get_contents($filename));
|
||||
foreach (array("", "-dark") as $mode) {
|
||||
$filename = "adminer$mode.css";
|
||||
if (file_exists($filename)) {
|
||||
$return[] = "$filename?v=" . crc32(file_get_contents($filename));
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -121,8 +124,10 @@ class Adminer {
|
||||
function loginForm() {
|
||||
global $drivers;
|
||||
echo "<table class='layout'>\n";
|
||||
// this is matched by compile.php
|
||||
echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);"));
|
||||
echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">');
|
||||
// this is matched by compile.php
|
||||
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" autofocus value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("qs('#username').form['auth[driver]'].onchange();"));
|
||||
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">');
|
||||
echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">');
|
||||
@@ -167,7 +172,7 @@ class Adminer {
|
||||
* @return string HTML code, "" to ignore field
|
||||
*/
|
||||
function fieldName($field, $order = 0) {
|
||||
return '<span title="' . h($field["full_type"]) . '">' . h($field["field"]) . '</span>';
|
||||
return '<span title="' . h($field["full_type"] . ($field["comment"] != "" ? " : $field[comment]" : '')) . '">' . h($field["field"]) . '</span>';
|
||||
}
|
||||
|
||||
/** Print links after select heading
|
||||
@@ -289,13 +294,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);
|
||||
}
|
||||
|
||||
@@ -374,8 +380,7 @@ class Adminer {
|
||||
$val["col"],
|
||||
($key !== "" ? "selectFieldChange" : "selectAddRow")
|
||||
);
|
||||
echo "<div>" . ($driver->functions || $driver->grouping ? "<select name='columns[$i][fun]'>"
|
||||
. optionlist(array(-1 => "") + array_filter(array(lang('Functions') => $driver->functions, lang('Aggregation') => $driver->grouping)), $val["fun"]) . "</select>"
|
||||
echo "<div>" . ($driver->functions || $driver->grouping ? html_select("columns[$i][fun]", array(-1 => "") + array_filter(array(lang('Functions') => $driver->functions, lang('Aggregation') => $driver->grouping)), $val["fun"])
|
||||
. on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1)
|
||||
. script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "")
|
||||
. "($column)" : $column) . "</div>\n";
|
||||
@@ -572,7 +577,8 @@ class Adminer {
|
||||
$cols = array();
|
||||
foreach ($fields as $name => $field) {
|
||||
if (
|
||||
(preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
|
||||
isset($field["privileges"]["where"])
|
||||
&& (preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
|
||||
&& (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"]))
|
||||
&& (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val["val"]))
|
||||
) {
|
||||
@@ -937,11 +943,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
|
||||
*/
|
||||
@@ -975,16 +993,18 @@ class Adminer {
|
||||
</span>
|
||||
</h1>
|
||||
<?php
|
||||
// this is matched by compile.php
|
||||
switch_lang();
|
||||
if ($missing == "auth") {
|
||||
$output = "";
|
||||
foreach ((array) $_SESSION["pwds"] as $vendor => $servers) {
|
||||
foreach ($servers as $server => $usernames) {
|
||||
$name = h(get_setting("vendor-$server") ?: $drivers[$vendor]);
|
||||
foreach ($usernames as $username => $password) {
|
||||
if ($password !== null) {
|
||||
$dbs = $_SESSION["db"][$vendor][$server][$username];
|
||||
foreach (($dbs ? array_keys($dbs) : array("")) as $db) {
|
||||
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($drivers[$vendor]) " . h($username . ($server != "" ? "@" . $this->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
|
||||
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($name) " . h($username . ($server != "" ? "@" . $this->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -999,31 +1019,7 @@ class Adminer {
|
||||
$connection->select_db(DB);
|
||||
$tables = table_status('', true);
|
||||
}
|
||||
echo script_src("../externals/jush/modules/jush.js");
|
||||
echo script_src("../externals/jush/modules/jush-textarea.js");
|
||||
echo script_src("../externals/jush/modules/jush-txt.js");
|
||||
echo script_src("../externals/jush/modules/jush-js.js");
|
||||
if (support("sql")) {
|
||||
echo script_src("../externals/jush/modules/jush-" . JUSH . ".js");
|
||||
?>
|
||||
<script<?php echo nonce(); ?>>
|
||||
<?php
|
||||
if ($tables) {
|
||||
$links = array();
|
||||
foreach ($tables as $table => $type) {
|
||||
$links[] = preg_quote($table, '/');
|
||||
}
|
||||
echo "var jushLinks = { " . JUSH . ": [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
|
||||
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
|
||||
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" : ""); ?>);
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
$this->syntaxHighlighting($tables);
|
||||
$this->databasesPrint($missing);
|
||||
$actions = array();
|
||||
if (DB == "" || !$missing) {
|
||||
@@ -1048,6 +1044,34 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
|
||||
}
|
||||
}
|
||||
|
||||
/** Set up syntax highlight for code and <textarea>
|
||||
* @param array result of table_status()
|
||||
*/
|
||||
function syntaxHighlighting($tables) {
|
||||
global $connection;
|
||||
// this is matched by compile.php
|
||||
echo script_src("../externals/jush/modules/jush.js");
|
||||
echo script_src("../externals/jush/modules/jush-textarea.js");
|
||||
echo script_src("../externals/jush/modules/jush-txt.js");
|
||||
echo script_src("../externals/jush/modules/jush-js.js");
|
||||
if (support("sql")) {
|
||||
echo script_src("../externals/jush/modules/jush-" . JUSH . ".js");
|
||||
echo "<script" . nonce() . ">\n";
|
||||
if ($tables) {
|
||||
$links = array();
|
||||
foreach ($tables as $table => $type) {
|
||||
$links[] = preg_quote($table, '/');
|
||||
}
|
||||
echo "var jushLinks = { " . JUSH . ": [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
|
||||
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
|
||||
echo "jushLinks.$val = jushLinks." . JUSH . ";\n";
|
||||
}
|
||||
}
|
||||
echo "</script>\n";
|
||||
}
|
||||
echo script("bodyLoad('" . (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '\1', $connection->server_info) : "") . "'" . ($connection->maria ? ", true" : "") . ");");
|
||||
}
|
||||
|
||||
/** Prints databases list in menu
|
||||
* @param string
|
||||
* @return null
|
||||
@@ -1064,14 +1088,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
|
||||
? "<select name='db'>" . optionlist(array("" => "") + $databases, DB) . "</select>$db_events"
|
||||
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') . ": <select name='ns'>" . optionlist(array("" => "") + $adminer->schemas(), $_GET["ns"]) . "</select>$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"]);
|
||||
}
|
||||
|
@@ -19,7 +19,17 @@ if ($_COOKIE["adminer_permanent"]) {
|
||||
|
||||
function add_invalid_login() {
|
||||
global $adminer;
|
||||
$fp = file_open_lock(get_temp_dir() . "/adminer.invalid");
|
||||
$base = get_temp_dir() . "/adminer.invalid";
|
||||
// adminer.invalid may not be writable by us, try the files with random suffixes
|
||||
foreach (glob("$base*") ?: array($base) as $filename) {
|
||||
$fp = file_open_lock($filename);
|
||||
if ($fp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$fp) {
|
||||
$fp = file_open_lock("$base-" . rand_string());
|
||||
}
|
||||
if (!$fp) {
|
||||
return;
|
||||
}
|
||||
@@ -42,7 +52,15 @@ function add_invalid_login() {
|
||||
|
||||
function check_invalid_login() {
|
||||
global $adminer;
|
||||
$invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist
|
||||
$invalids = array();
|
||||
foreach (glob(get_temp_dir() . "/adminer.invalid*") as $filename) {
|
||||
$fp = file_open_lock($filename);
|
||||
if ($fp) {
|
||||
$invalids = unserialize(stream_get_contents($fp));
|
||||
file_unlock($fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : array());
|
||||
$next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts
|
||||
if ($next_attempt > 0) { //! do the same with permanent login
|
||||
@@ -61,7 +79,7 @@ if ($auth) {
|
||||
set_password($vendor, $server, $username, $password);
|
||||
$_SESSION["db"][$vendor][$server][$username][$db] = true;
|
||||
if ($auth["permanent"]) {
|
||||
$key = base64_encode($vendor) . "-" . base64_encode($server) . "-" . base64_encode($username) . "-" . base64_encode($db);
|
||||
$key = implode("-", array_map('base64_encode', array($vendor, $server, $username, $db)));
|
||||
$private = $adminer->permanentLogin(true);
|
||||
$permanent[$key] = "$key:" . base64_encode($private ? encrypt_string($password, $private) : "");
|
||||
cookie("adminer_permanent", implode(" ", $permanent));
|
||||
@@ -164,9 +182,14 @@ if (isset($_GET["username"]) && is_string(get_password())) {
|
||||
}
|
||||
check_invalid_login();
|
||||
$connection = connect($adminer->credentials());
|
||||
$driver = new Driver($connection);
|
||||
if ($adminer->operators === null) {
|
||||
$adminer->operators = $driver->operators;
|
||||
if (is_object($connection)) {
|
||||
$driver = new Driver($connection);
|
||||
if ($adminer->operators === null) {
|
||||
$adminer->operators = $driver->operators;
|
||||
}
|
||||
if (isset($connection->maria) || $connection->cockroach) {
|
||||
save_settings(array("vendor-" . SERVER => $drivers[DRIVER]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ namespace Adminer;
|
||||
|
||||
include "../adminer/include/version.inc.php";
|
||||
include "../adminer/include/errors.inc.php";
|
||||
// this is matched by compile.php
|
||||
include "../adminer/include/coverage.inc.php";
|
||||
|
||||
// disable filter.default
|
||||
@@ -21,6 +22,7 @@ if (function_exists("mb_internal_encoding")) {
|
||||
}
|
||||
|
||||
include "../adminer/include/functions.inc.php";
|
||||
include "../adminer/include/html.inc.php";
|
||||
|
||||
// used only in compiled file
|
||||
if (isset($_GET["file"])) {
|
||||
@@ -28,7 +30,9 @@ if (isset($_GET["file"])) {
|
||||
}
|
||||
|
||||
if ($_GET["script"] == "version") {
|
||||
$fp = file_open_lock(get_temp_dir() . "/adminer.version");
|
||||
$filename = get_temp_dir() . "/adminer.version";
|
||||
unlink($filename); // it may not be writable by us
|
||||
$fp = file_open_lock($filename);
|
||||
if ($fp) {
|
||||
file_write_unlock($fp, serialize(array("signature" => $_POST["signature"], "version" => $_POST["version"])));
|
||||
}
|
||||
@@ -62,7 +66,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,9 +76,9 @@ 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);
|
||||
// this is matched by compile.php
|
||||
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
|
||||
|
||||
define('Adminer\JUSH', Driver::$jush);
|
||||
|
@@ -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);
|
||||
|
@@ -2,9 +2,9 @@
|
||||
namespace Adminer;
|
||||
|
||||
// coverage is used in tests and removed in compilation
|
||||
if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer_coverage.ser")) {
|
||||
if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer.coverage")) {
|
||||
function save_coverage() {
|
||||
$coverage_filename = sys_get_temp_dir() . "/adminer_coverage.ser";
|
||||
$coverage_filename = sys_get_temp_dir() . "/adminer.coverage";
|
||||
$coverage = unserialize(file_get_contents($coverage_filename));
|
||||
foreach (xdebug_get_code_coverage() as $filename => $lines) {
|
||||
foreach ($lines as $l => $val) {
|
||||
|
@@ -28,19 +28,25 @@ 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"); ?>
|
||||
<?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">
|
||||
<link rel="stylesheet" href="../adminer/static/default.css">
|
||||
<?php
|
||||
$css = $adminer->css();
|
||||
$dark = (count($css) == 1 ? !!preg_match('~-dark~', $css[0]) : null);
|
||||
if ($dark !== false) {
|
||||
echo "<link rel='stylesheet'" . ($dark ? "" : " media='(prefers-color-scheme: dark)'") . " href='../adminer/static/dark.css'>\n";
|
||||
}
|
||||
echo "<meta name='color-scheme' content='" . ($dark === null ? "light dark" : ($dark ? "dark" : "light")) . "'>\n";
|
||||
// this is matched by compile.php
|
||||
echo script_src("../adminer/static/functions.js");
|
||||
echo script_src("static/editing.js");
|
||||
if ($adminer->head($dark)) {
|
||||
echo "<link rel='shortcut icon' type='image/x-icon' href='../adminer/static/favicon.ico'>\n";
|
||||
echo "<link rel='apple-touch-icon' href='../adminer/static/favicon.ico'>\n";
|
||||
}
|
||||
foreach ($css as $val) {
|
||||
echo "<link rel='stylesheet'" . (preg_match('~-dark~', $val) && !$dark ? " media='(prefers-color-scheme: dark)'" : "") . " href='" . h($val) . "'>\n";
|
||||
}
|
||||
echo "\n<body class='" . lang('ltr') . " nojs'>\n";
|
||||
$filename = get_temp_dir() . "/adminer.version";
|
||||
if (!$_COOKIE["adminer_version"] && function_exists('openssl_verify') && file_exists($filename) && filemtime($filename) + 86400 > time()) { // 86400 - 1 day in seconds
|
||||
$version = unserialize(file_get_contents($filename));
|
||||
@@ -58,21 +64,16 @@ fQIDAQAB
|
||||
$_COOKIE["adminer_version"] = $version["version"]; // doesn't need to send to the browser
|
||||
}
|
||||
}
|
||||
?>
|
||||
<script<?php echo nonce(); ?>>
|
||||
mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick<?php
|
||||
echo (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '$VERSION', '" . js_escape(ME) . "', '" . get_token() . "')"); // $token may be empty in auth.inc.php
|
||||
?>});
|
||||
echo script("mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick"
|
||||
. (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '$VERSION', '" . js_escape(ME) . "', '" . get_token() . "')") // $token may be empty in auth.inc.php
|
||||
. "});
|
||||
document.body.className = document.body.className.replace(/ nojs/, ' js');
|
||||
var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>';
|
||||
var thousandsSeparator = '<?php echo js_escape(lang(',')); ?>';
|
||||
</script>
|
||||
|
||||
<div id="help" class="jush-<?php echo JUSH; ?> jsonly hidden"></div>
|
||||
<?php echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"); ?>
|
||||
|
||||
<div id="content">
|
||||
<?php
|
||||
var offlineMessage = '" . js_escape(lang('You are offline.')) . "';
|
||||
var thousandsSeparator = '" . js_escape(lang(',')) . "';")
|
||||
;
|
||||
echo "<div id='help' class='jush-" . JUSH . " jsonly hidden'></div>\n";
|
||||
echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});");
|
||||
echo "<div id='content'>\n";
|
||||
if ($breadcrumb !== null) {
|
||||
$link = substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1);
|
||||
echo '<p id="breadcrumb"><a href="' . h($link ?: ".") . '">' . $drivers[DRIVER] . '</a> » ';
|
||||
@@ -192,7 +193,7 @@ function page_footer($missing = "") {
|
||||
<?php if ($missing != "auth") { ?>
|
||||
<form action="" method="post">
|
||||
<p class="logout">
|
||||
<?php echo h($_GET["username"]) . "\n"; ?>
|
||||
<span><?php echo h($_GET["username"]) . "\n"; ?></span>
|
||||
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" id="logout">
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</p>
|
||||
|
@@ -26,23 +26,23 @@ 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
|
||||
@@ -59,6 +59,20 @@ abstract class SqlDriver {
|
||||
return array_map('array_keys', $this->types);
|
||||
}
|
||||
|
||||
/** Get enum values
|
||||
* @param array
|
||||
* @return string or null
|
||||
*/
|
||||
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]
|
||||
@@ -84,7 +98,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);
|
||||
}
|
||||
@@ -194,8 +208,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)
|
||||
);
|
||||
}
|
||||
|
@@ -90,7 +90,8 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
|
||||
if ($link) {
|
||||
$val = "<a href='" . h($link) . "'" . (is_url($link) ? target_blank() : '') . ">$val</a>";
|
||||
}
|
||||
echo "<td>$val";
|
||||
// https://dev.mysql.com/doc/dev/mysql-server/latest/field__types_8h.html
|
||||
echo "<td" . ($types[$key] <= 9 || $types[$key] == 246 ? " class='number'" : "") . ">$val";
|
||||
}
|
||||
}
|
||||
echo ($i ? "</table>\n</div>" : "<p class='message'>" . lang('No rows.')) . "\n";
|
||||
@@ -119,31 +120,6 @@ function referencable_primary($self) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get settings stored in a cookie
|
||||
* @return array
|
||||
*/
|
||||
function adminer_settings() {
|
||||
parse_str($_COOKIE["adminer_settings"], $settings);
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/** Get setting stored in a cookie
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
function adminer_setting($key) {
|
||||
$settings = adminer_settings();
|
||||
return $settings[$key];
|
||||
}
|
||||
|
||||
/** Store settings to a cookie
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function set_adminer_settings($settings) {
|
||||
return cookie("adminer_settings", http_build_query($settings + adminer_settings()));
|
||||
}
|
||||
|
||||
/** Print SQL <textarea> tag
|
||||
* @param string
|
||||
* @param string or array in which case [0] of every element is used
|
||||
@@ -209,7 +185,7 @@ function json_row($key, $val = null) {
|
||||
function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_types = array()) {
|
||||
global $driver;
|
||||
$type = $field["type"];
|
||||
?><td><select name="<?php echo h($key); ?>[type]" class="type" aria-labelledby="label-type"><?php
|
||||
echo "<td><select name='" . h($key) . "[type]' class='type' aria-labelledby='label-type'>";
|
||||
if ($type && !array_key_exists($type, $driver->types()) && !isset($foreign_keys[$type]) && !in_array($type, $extra_types)) {
|
||||
$extra_types[] = $type;
|
||||
}
|
||||
@@ -218,19 +194,24 @@ function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_ty
|
||||
$structured_types[lang('Foreign keys')] = $foreign_keys;
|
||||
}
|
||||
echo optionlist(array_merge($extra_types, $structured_types), $type);
|
||||
?></select><td><input
|
||||
name="<?php echo h($key); ?>[length]"
|
||||
value="<?php echo h($field["length"]); ?>"
|
||||
size="3"
|
||||
<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); //! type="number" with enabled JavaScript ?>
|
||||
aria-labelledby="label-length"><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 "</select><td>";
|
||||
echo "<input name='" . h($key) . "[length]' value='" . h($field["length"]) . "' size='3'"
|
||||
. (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : "") //! type="number" with enabled JavaScript
|
||||
. " aria-labelledby='label-length'>";
|
||||
echo "<td class='options'>";
|
||||
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 +288,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))
|
||||
)
|
||||
));
|
||||
@@ -343,54 +324,51 @@ function type_class($type) {
|
||||
function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = array()) {
|
||||
global $driver;
|
||||
$fields = array_values($fields);
|
||||
$default_class = (($_POST ? $_POST["defaults"] : adminer_setting("defaults")) ? "" : " class='hidden'");
|
||||
$comment_class = (($_POST ? $_POST["comments"] : adminer_setting("comments")) ? "" : " class='hidden'");
|
||||
$default_class = (($_POST ? $_POST["defaults"] : get_setting("defaults")) ? "" : " class='hidden'");
|
||||
$comment_class = (($_POST ? $_POST["comments"] : get_setting("comments")) ? "" : " class='hidden'");
|
||||
?>
|
||||
<thead><tr>
|
||||
<?php echo ($type == "PROCEDURE" ? "<td>" : ""); ?>
|
||||
<th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?>
|
||||
<td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("qs('#enum-edit').onblur = editingLengthBlur;"); ?>
|
||||
<td id="label-length"><?php echo lang('Length'); ?>
|
||||
<td><?php echo lang('Options'); /* no label required, options have their own label */ ?>
|
||||
<?php if ($type == "TABLE") { ?>
|
||||
<td id="label-null">NULL
|
||||
<td><input type="radio" name="auto_increment_col" value=""><abbr id="label-ai" title="<?php echo lang('Auto Increment'); ?>">AI</abbr><?php echo doc_link(array(
|
||||
'sql' => "example-auto-increment.html",
|
||||
'mariadb' => "auto_increment/",
|
||||
'sqlite' => "autoinc.html",
|
||||
'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL",
|
||||
'mssql' => "t-sql/statements/create-table-transact-sql-identity-property",
|
||||
)); ?>
|
||||
<td id="label-default"<?php echo $default_class; ?>><?php echo lang('Default value'); ?>
|
||||
<?php echo (support("comment") ? "<td id='label-comment'$comment_class>" . lang('Comment') : ""); ?>
|
||||
<?php } ?>
|
||||
<td><?php echo "<input type='image' class='icon' name='add[" . (support("move_col") ? 0 : count($fields)) . "]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>" . script("row_count = " . count($fields) . ";"); ?>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
<td><?php
|
||||
echo lang('Options'); // no label required, options have their own label
|
||||
if ($type == "TABLE") {
|
||||
echo "<td id='label-null'>NULL\n";
|
||||
echo "<td><input type='radio' name='auto_increment_col' value=''><abbr id='label-ai' title='" . lang('Auto Increment') . "'>AI</abbr>";
|
||||
echo doc_link(array(
|
||||
'sql' => "example-auto-increment.html",
|
||||
'mariadb' => "auto_increment/",
|
||||
'sqlite' => "autoinc.html",
|
||||
'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL",
|
||||
'mssql' => "t-sql/statements/create-table-transact-sql-identity-property",
|
||||
));
|
||||
echo "<td id='label-default'$default_class>" . lang('Default value');
|
||||
echo (support("comment") ? "<td id='label-comment'$comment_class>" . lang('Comment') : "");
|
||||
}
|
||||
echo "<td><input type='image' class='icon' name='add[" . (support("move_col") ? 0 : count($fields)) . "]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>" . script("row_count = " . count($fields) . ";");
|
||||
echo "</thead>\n<tbody>\n";
|
||||
echo script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});");
|
||||
foreach ($fields as $i => $field) {
|
||||
$i++;
|
||||
$orig = $field[($_POST ? "orig" : "field")];
|
||||
$display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i])) && (support("drop_col") || $orig == "");
|
||||
?>
|
||||
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
|
||||
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $driver->inout), $field["inout"]) : "") . "<th>"; ?>
|
||||
<?php if ($display) { ?>
|
||||
<input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" data-maxlength="64" autocapitalize="off" aria-labelledby="label-name">
|
||||
<?php } ?>
|
||||
<input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($orig); ?>"><?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?>
|
||||
<?php
|
||||
echo "<tr" . ($display ? "" : " style='display: none;'") . ">\n";
|
||||
echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $driver->inout), $field["inout"]) : "") . "<th>";
|
||||
if ($display) {
|
||||
echo "<input name='fields[$i][field]' value='" . h($field["field"]) . "' data-maxlength='64' autocapitalize='off' aria-labelledby='label-name'>\n";
|
||||
}
|
||||
echo "<input type='hidden' name='fields[$i][orig]' value='" . h($orig) . "'>";
|
||||
edit_type("fields[$i]", $field, $collations, $foreign_keys);
|
||||
if ($type == "TABLE") {
|
||||
?>
|
||||
<td><?php echo checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"); ?>
|
||||
<td><label class="block"><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php echo ($field["auto_increment"] ? " checked" : ""); ?> aria-labelledby="label-ai"></label><td<?php echo $default_class; ?>><?php
|
||||
echo ($driver->generated
|
||||
? "<select name='fields[$i][generated]'>" . optionlist(array_merge(array("", "DEFAULT"), $driver->generated), $field["generated"]) . "</select> "
|
||||
echo "<td>" . checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null");
|
||||
echo "<td><label class='block'><input type='radio' name='auto_increment_col' value='$i'" . ($field["auto_increment"] ? " checked" : "") . " aria-labelledby='label-ai'></label>";
|
||||
echo "<td$default_class>" . ($driver->generated
|
||||
? html_select("fields[$i][generated]", array_merge(array("", "DEFAULT"), $driver->generated), $field["generated"]) . " "
|
||||
: checkbox("fields[$i][generated]", 1, $field["generated"], "", "", "", "label-default")
|
||||
);
|
||||
?>
|
||||
<input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" aria-labelledby="label-default"><?php
|
||||
echo "<input name='fields[$i][default]' value='" . h($field["default"]) . "' aria-labelledby='label-default'>";
|
||||
echo (support("comment") ? "<td$comment_class><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' data-maxlength='" . (min_version(5.5) ? 1024 : 255) . "' aria-labelledby='label-comment'>" : "");
|
||||
}
|
||||
echo "<td>";
|
||||
@@ -624,22 +602,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
|
||||
|
@@ -20,6 +20,14 @@ function adminer() {
|
||||
return $adminer;
|
||||
}
|
||||
|
||||
/** Get Driver object
|
||||
* @return Driver
|
||||
*/
|
||||
function driver() {
|
||||
global $driver;
|
||||
return $driver;
|
||||
}
|
||||
|
||||
/** Get Adminer version
|
||||
* @return string
|
||||
*/
|
||||
@@ -40,6 +48,15 @@ function idf_unescape($idf) {
|
||||
return str_replace($last . $last, $last, substr($idf, 1, -1));
|
||||
}
|
||||
|
||||
/** Shortcut for $connection->quote($string)
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function q($string) {
|
||||
global $connection;
|
||||
return $connection->quote($string);
|
||||
}
|
||||
|
||||
/** Escape string to use inside ''
|
||||
* @param string
|
||||
* @return string
|
||||
@@ -122,164 +139,6 @@ function charset($connection) {
|
||||
return (min_version("5.5.3", 0, $connection) ? "utf8mb4" : "utf8"); // SHOW CHARSET would require an extra query
|
||||
}
|
||||
|
||||
/** Return <script> element
|
||||
* @param string
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function script($source, $trailing = "\n") {
|
||||
return "<script" . nonce() . ">$source</script>$trailing";
|
||||
}
|
||||
|
||||
/** Return <script src> element
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function script_src($url) {
|
||||
return "<script src='" . h($url) . "'" . nonce() . "></script>\n";
|
||||
}
|
||||
|
||||
/** Get a nonce="" attribute with CSP nonce
|
||||
* @return string
|
||||
*/
|
||||
function nonce() {
|
||||
return ' nonce="' . get_nonce() . '"';
|
||||
}
|
||||
|
||||
/** Get a target="_blank" attribute
|
||||
* @return string
|
||||
*/
|
||||
function target_blank() {
|
||||
return ' target="_blank" rel="noreferrer noopener"';
|
||||
}
|
||||
|
||||
/** Escape for HTML
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function h($string) {
|
||||
return str_replace("\0", "�", htmlspecialchars($string, ENT_QUOTES, 'utf-8'));
|
||||
}
|
||||
|
||||
/** Convert \n to <br>
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function nl_br($string) {
|
||||
return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
|
||||
}
|
||||
|
||||
/** Generate HTML checkbox
|
||||
* @param string
|
||||
* @param string
|
||||
* @param bool
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function checkbox($name, $value, $checked, $label = "", $onclick = "", $class = "", $labelled_by = "") {
|
||||
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'"
|
||||
. ($checked ? " checked" : "")
|
||||
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
|
||||
. ">"
|
||||
. ($onclick ? script("qsl('input').onclick = function () { $onclick };", "") : "")
|
||||
;
|
||||
return ($label != "" || $class ? "<label" . ($class ? " class='$class'" : "") . ">$return" . h($label) . "</label>" : $return);
|
||||
}
|
||||
|
||||
/** Generate list of HTML options
|
||||
* @param array array of strings or arrays (creates optgroup)
|
||||
* @param mixed
|
||||
* @param bool always use array keys for value="", otherwise only string keys are used
|
||||
* @return string
|
||||
*/
|
||||
function optionlist($options, $selected = null, $use_keys = false) {
|
||||
$return = "";
|
||||
foreach ($options as $k => $v) {
|
||||
$opts = array($k => $v);
|
||||
if (is_array($v)) {
|
||||
$return .= '<optgroup label="' . h($k) . '">';
|
||||
$opts = $v;
|
||||
}
|
||||
foreach ($opts as $key => $val) {
|
||||
$return .= '<option'
|
||||
. ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '')
|
||||
. ($selected !== null && ($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '')
|
||||
. '>' . h($val)
|
||||
;
|
||||
}
|
||||
if (is_array($v)) {
|
||||
$return .= '</optgroup>';
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** 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 };", "") : "")
|
||||
;
|
||||
}
|
||||
$return = "";
|
||||
foreach ($options as $key => $val) {
|
||||
$return .= "<label><input type='radio' name='" . h($name) . "' value='" . h($key) . "'" . ($key == $value ? " checked" : "") . ">" . h($val) . "</label>";
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get onclick confirmation
|
||||
* @param string
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function confirm($message = "", $selector = "qsl('input')") {
|
||||
return script("$selector.onclick = function () { return confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "'); };", "");
|
||||
}
|
||||
|
||||
/** Print header for hidden fieldset (close by </div></fieldset>)
|
||||
* @param string
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return null
|
||||
*/
|
||||
function print_fieldset($id, $legend, $visible = false) {
|
||||
echo "<fieldset><legend>";
|
||||
echo "<a href='#fieldset-$id'>$legend</a>";
|
||||
echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", "");
|
||||
echo "</legend>";
|
||||
echo "<div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
|
||||
}
|
||||
|
||||
/** Return class='active' if $bold is true
|
||||
* @param bool
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function bold($bold, $class = "") {
|
||||
return ($bold ? " class='active $class'" : ($class ? " class='$class'" : ""));
|
||||
}
|
||||
|
||||
/** Escape string for JavaScript apostrophes
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function js_escape($string) {
|
||||
return addcslashes($string, "\r\n'\\/"); // slash for <script>
|
||||
}
|
||||
|
||||
/** Get INI boolean value
|
||||
* @param string
|
||||
* @return bool
|
||||
@@ -328,13 +187,14 @@ function get_password() {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Shortcut for $connection->quote($string)
|
||||
/** Get single value from database
|
||||
* @param string
|
||||
* @return string
|
||||
* @param int
|
||||
* @return string or false if error
|
||||
*/
|
||||
function q($string) {
|
||||
function get_val($query, $field = 0) {
|
||||
global $connection;
|
||||
return $connection->quote($string);
|
||||
return $connection->result($query, $field);
|
||||
}
|
||||
|
||||
/** Get list of values from database
|
||||
@@ -442,14 +302,14 @@ 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
|
||||
: " = " . unconvert_field($fields[$key], q($val))
|
||||
)))
|
||||
: (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";
|
||||
}
|
||||
}
|
||||
@@ -519,6 +379,34 @@ function cookie($name, $value, $lifetime = 2592000) {
|
||||
);
|
||||
}
|
||||
|
||||
/** Get settings stored in a cookie
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
function get_settings($cookie) {
|
||||
parse_str($_COOKIE[$cookie], $settings);
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/** Get setting stored in a cookie
|
||||
* @param string
|
||||
* @param string
|
||||
* @return mixed
|
||||
*/
|
||||
function get_setting($key, $cookie = "adminer_settings") {
|
||||
$settings = get_settings($cookie);
|
||||
return $settings[$key];
|
||||
}
|
||||
|
||||
/** Store settings to a cookie
|
||||
* @param array
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function save_settings($settings, $cookie = "adminer_settings") {
|
||||
return cookie($cookie, http_build_query($settings + get_settings($cookie)));
|
||||
}
|
||||
|
||||
/** Restart stopped session
|
||||
* @return null
|
||||
*/
|
||||
@@ -703,24 +591,13 @@ function remove_from_uri($param = "") {
|
||||
return substr(preg_replace("~(?<=[?&])($param" . (SID ? "" : "|" . session_name()) . ")=[^&]*&~", '', relative_uri() . "&"), 0, -1);
|
||||
}
|
||||
|
||||
/** Generate page number for pagination
|
||||
* @param int
|
||||
* @param int
|
||||
* @return string
|
||||
*/
|
||||
function pagination($page, $current) {
|
||||
return " " . ($page == $current
|
||||
? $page + 1
|
||||
: '<a href="' . h(remove_from_uri("page") . ($page ? "&page=$page" . ($_GET["next"] ? "&next=" . urlencode($_GET["next"]) : "") : "")) . '">' . ($page + 1) . "</a>"
|
||||
);
|
||||
}
|
||||
|
||||
/** 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;
|
||||
@@ -742,17 +619,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;
|
||||
}
|
||||
|
||||
@@ -814,36 +691,6 @@ function friendly_url($val) {
|
||||
return preg_replace('~\W~i', '-', $val);
|
||||
}
|
||||
|
||||
/** Print hidden fields
|
||||
* @param array
|
||||
* @param array
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function hidden_fields($process, $ignore = array(), $prefix = '') {
|
||||
$return = false;
|
||||
foreach ($process as $key => $val) {
|
||||
if (!in_array($key, $ignore)) {
|
||||
if (is_array($val)) {
|
||||
hidden_fields($val, array(), $key);
|
||||
} else {
|
||||
$return = true;
|
||||
echo '<input type="hidden" name="' . h($prefix ? $prefix . "[$key]" : $key) . '" value="' . h($val) . '">';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Print hidden fields for GET forms
|
||||
* @return null
|
||||
*/
|
||||
function hidden_fields_get() {
|
||||
echo (sid() ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : '');
|
||||
echo (SERVER !== null ? '<input type="hidden" name="' . DRIVER . '" value="' . h(SERVER) . '">' : "");
|
||||
echo '<input type="hidden" name="username" value="' . h($_GET["username"]) . '">';
|
||||
}
|
||||
|
||||
/** Get status of a single table and fall back to name on error
|
||||
* @param string
|
||||
* @param bool
|
||||
@@ -869,180 +716,6 @@ function column_foreign_keys($table) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Print enum input field
|
||||
* @param string "radio"|"checkbox"
|
||||
* @param string
|
||||
* @param array
|
||||
* @param mixed int|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>" : "");
|
||||
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>';
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Print edit input field
|
||||
* @param array one field from fields()
|
||||
* @param mixed
|
||||
* @param string
|
||||
* @return null
|
||||
*/
|
||||
function input($field, $value, $function) {
|
||||
global $driver, $adminer;
|
||||
$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
|
||||
$function = "json";
|
||||
}
|
||||
$reset = (JUSH == "mssql" && $field["auto_increment"]);
|
||||
if ($reset && !$_POST["save"]) {
|
||||
$function = null;
|
||||
}
|
||||
$functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
|
||||
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
|
||||
$attrs = " name='fields[$name]'$disabled";
|
||||
$types = $driver->types();
|
||||
$structured_types = $driver->structuredTypes();
|
||||
if (in_array($field["type"], (array) $structured_types[lang('User types')])) {
|
||||
$enums = type_values($types[$field["type"]]);
|
||||
if ($enums) {
|
||||
$field["type"] = "enum";
|
||||
$field["length"] = $enums;
|
||||
}
|
||||
}
|
||||
if ($field["type"] == "enum") {
|
||||
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
|
||||
} else {
|
||||
$has_function = (in_array($function, $functions) || isset($functions[$function]));
|
||||
echo (count($functions) > 1
|
||||
? "<select name='function[$name]'$disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
|
||||
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
|
||||
. script("qsl('select').onchange = functionChange;", "")
|
||||
: h(reset($functions))
|
||||
) . '<td>';
|
||||
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
|
||||
if ($input != "") {
|
||||
echo $input;
|
||||
} 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
|
||||
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>';
|
||||
}
|
||||
} elseif (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
|
||||
echo "<input type='file' name='fields-$name'>";
|
||||
} elseif (($text = preg_match('~text|lob|memo~i', $field["type"])) || preg_match("~\n~", $value)) {
|
||||
if ($text && JUSH != "sqlite") {
|
||||
$attrs .= " cols='50' rows='12'";
|
||||
} else {
|
||||
$rows = min(12, substr_count($value, "\n") + 1);
|
||||
$attrs .= " cols='30' rows='$rows'" . ($rows == 1 ? " style='height: 1.2em;'" : ""); // 1.2em - line-height
|
||||
}
|
||||
echo "<textarea$attrs>" . h($value) . '</textarea>';
|
||||
} elseif ($function == "json" || preg_match('~^jsonb?$~', $field["type"])) {
|
||||
echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
|
||||
} else {
|
||||
// int(3) is only a display hint
|
||||
$maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match)
|
||||
? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0))
|
||||
: ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)
|
||||
);
|
||||
if (JUSH == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
|
||||
$maxlength += 7; // microtime
|
||||
}
|
||||
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
|
||||
echo "<input"
|
||||
. ((!$has_function || $function === "") && preg_match('~(?<!o)int(?!er)~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "")
|
||||
. " value='" . h($value) . "'" . ($maxlength ? " data-maxlength='$maxlength'" : "")
|
||||
. (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "")
|
||||
. "$attrs>"
|
||||
;
|
||||
}
|
||||
echo $adminer->editHint($_GET["edit"], $field, $value);
|
||||
// skip 'original'
|
||||
$first = 0;
|
||||
foreach ($functions as $key => $val) {
|
||||
if ($key === "" || !$val) {
|
||||
break;
|
||||
}
|
||||
$first++;
|
||||
}
|
||||
if ($first) {
|
||||
echo script("mixin(qsl('td'), {onchange: partial(skipOriginal, $first), oninput: function () { this.onchange(); }});");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Process edit input field
|
||||
* @param one field from fields()
|
||||
* @return string or false to leave the original value
|
||||
*/
|
||||
function process_input($field) {
|
||||
global $adminer, $driver;
|
||||
|
||||
if (stripos($field["default"], "GENERATED ALWAYS AS ") === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$idf = bracket_escape($field["field"]);
|
||||
$function = $_POST["function"][$idf];
|
||||
$value = $_POST["fields"][$idf];
|
||||
if ($field["type"] == "enum") {
|
||||
if ($value == -1) {
|
||||
return false;
|
||||
}
|
||||
if ($value == "") {
|
||||
return "NULL";
|
||||
}
|
||||
return +$value;
|
||||
}
|
||||
if ($field["auto_increment"] && $value == "") {
|
||||
return null;
|
||||
}
|
||||
if ($function == "orig") {
|
||||
return (preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"]) ? idf_escape($field["field"]) : false);
|
||||
}
|
||||
if ($function == "NULL") {
|
||||
return "NULL";
|
||||
}
|
||||
if ($field["type"] == "set") {
|
||||
return array_sum((array) $value);
|
||||
}
|
||||
if ($function == "json") {
|
||||
$function = "";
|
||||
$value = json_decode($value, true);
|
||||
if (!is_array($value)) {
|
||||
return false; //! report errors
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
if (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
|
||||
$file = get_file("fields-$idf");
|
||||
if (!is_string($file)) {
|
||||
return false; //! report errors
|
||||
}
|
||||
return $driver->quoteBinary($file);
|
||||
}
|
||||
return $adminer->processInput($field, $value, $function);
|
||||
}
|
||||
|
||||
/** Compute fields() from $_POST edit data
|
||||
* @return array
|
||||
*/
|
||||
@@ -1060,7 +733,7 @@ function fields_from_edit() {
|
||||
$name = bracket_escape($key, 1); // 1 - back
|
||||
$return[$name] = array(
|
||||
"field" => $name,
|
||||
"privileges" => array("insert" => 1, "update" => 1),
|
||||
"privileges" => array("insert" => 1, "update" => 1, "where" => 1, "order" => 1),
|
||||
"null" => 1,
|
||||
"auto_increment" => ($key == $driver->primary),
|
||||
);
|
||||
@@ -1068,29 +741,6 @@ function fields_from_edit() {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Print results of search in all tables
|
||||
* @uses $_GET["where"][0]
|
||||
* @uses $_POST["tables"]
|
||||
* @return null
|
||||
*/
|
||||
function search_tables() {
|
||||
global $adminer, $connection;
|
||||
$_GET["where"][0]["val"] = $_POST["query"];
|
||||
$sep = "<ul>\n";
|
||||
foreach (table_status('', true) as $table => $table_status) {
|
||||
$name = $adminer->tableName($table_status);
|
||||
if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) {
|
||||
$result = $connection->query("SELECT" . limit("1 FROM " . table($table), " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())), 1));
|
||||
if (!$result || $result->fetch_row()) {
|
||||
$print = "<a href='" . h(ME . "select=" . urlencode($table) . "&where[0][op]=" . urlencode($_GET["where"][0]["op"]) . "&where[0][val]=" . urlencode($_GET["where"][0]["val"])) . "'>$name</a>";
|
||||
echo "$sep<li>" . ($result ? $print : "<p class='error'>$print: " . error()) . "\n";
|
||||
$sep = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
echo ($sep ? "<p class='message'>" . lang('No tables.') : "</ul>") . "\n";
|
||||
}
|
||||
|
||||
/** Send headers for export
|
||||
* @param string
|
||||
* @param bool
|
||||
@@ -1156,15 +806,18 @@ function get_temp_dir() {
|
||||
* @return resource or null for error
|
||||
*/
|
||||
function file_open_lock($filename) {
|
||||
$fp = @fopen($filename, "r+"); // @ - may not exist
|
||||
if (!$fp) { // c+ is available since PHP 5.2.6
|
||||
$fp = @fopen($filename, "w"); // @ - may not be writable
|
||||
if (!$fp) {
|
||||
return;
|
||||
}
|
||||
chmod($filename, 0660);
|
||||
if (is_link($filename)) {
|
||||
return; // https://cwe.mitre.org/data/definitions/61.html
|
||||
}
|
||||
$fp = @fopen($filename, "c+"); // @ - may not be writable
|
||||
if (!$fp) {
|
||||
return;
|
||||
}
|
||||
chmod($filename, 0660);
|
||||
if (!flock($fp, LOCK_EX)) {
|
||||
fclose($fp);
|
||||
return;
|
||||
}
|
||||
flock($fp, LOCK_EX);
|
||||
return $fp;
|
||||
}
|
||||
|
||||
@@ -1176,6 +829,13 @@ function file_write_unlock($fp, $data) {
|
||||
rewind($fp);
|
||||
fwrite($fp, $data);
|
||||
ftruncate($fp, strlen($data));
|
||||
file_unlock($fp);
|
||||
}
|
||||
|
||||
/** Unlock and close a file
|
||||
* @param resource
|
||||
*/
|
||||
function file_unlock($fp) {
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
}
|
||||
@@ -1186,16 +846,19 @@ function file_write_unlock($fp, $data) {
|
||||
*/
|
||||
function password_file($create) {
|
||||
$filename = get_temp_dir() . "/adminer.key";
|
||||
$return = @file_get_contents($filename); // @ - may not exist
|
||||
if ($return || !$create) {
|
||||
return $return;
|
||||
if (!$create && !file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
$fp = @fopen($filename, "w"); // @ - can have insufficient rights //! is not atomic
|
||||
if ($fp) {
|
||||
chmod($filename, 0660);
|
||||
$fp = file_open_lock($filename);
|
||||
if (!$fp) {
|
||||
return false;
|
||||
}
|
||||
$return = stream_get_contents($fp);
|
||||
if (!$return) {
|
||||
$return = rand_string();
|
||||
fwrite($fp, $return);
|
||||
fclose($fp);
|
||||
file_write_unlock($fp, $return);
|
||||
} else {
|
||||
file_unlock($fp);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -1302,18 +965,10 @@ function slow_query($query) {
|
||||
$db = $adminer->database();
|
||||
$timeout = $adminer->queryTimeout();
|
||||
$slow_query = $driver->slowQuery($query, $timeout);
|
||||
$connection2 = null;
|
||||
if (!$slow_query && support("kill") && is_object($connection2 = connect($adminer->credentials())) && ($db == "" || $connection2->select_db($db))) {
|
||||
$kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
|
||||
?>
|
||||
<script<?php echo nonce(); ?>>
|
||||
var timeout = setTimeout(function () {
|
||||
ajax('<?php echo js_escape(ME); ?>script=kill', function () {
|
||||
}, 'kill=<?php echo $kill; ?>&token=<?php echo $token; ?>');
|
||||
}, <?php echo 1000 * $timeout; ?>);
|
||||
</script>
|
||||
<?php
|
||||
} else {
|
||||
$connection2 = null;
|
||||
echo script("var timeout = setTimeout(function () { ajax('" . js_escape(ME) . "script=kill', function () {}, 'kill=$kill&token=$token'); }, 1000 * $timeout);");
|
||||
}
|
||||
ob_flush();
|
||||
flush();
|
||||
@@ -1379,123 +1034,3 @@ function lzw_decompress($binary) {
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Return events to display help on mouse over
|
||||
* @param string JS expression
|
||||
* @param bool JS expression
|
||||
* @return string
|
||||
*/
|
||||
function on_help($command, $side = 0) {
|
||||
return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", "");
|
||||
}
|
||||
|
||||
/** Print edit data form
|
||||
* @param string
|
||||
* @param array
|
||||
* @param mixed
|
||||
* @param bool
|
||||
* @return null
|
||||
*/
|
||||
function edit_form($table, $fields, $row, $update) {
|
||||
global $adminer, $token, $error;
|
||||
$table_name = $adminer->tableName(table_status1($table, true));
|
||||
page_header(
|
||||
($update ? lang('Edit') : lang('Insert')),
|
||||
$error,
|
||||
array("select" => array($table, $table_name)),
|
||||
$table_name
|
||||
);
|
||||
$adminer->editRowPrint($table, $fields, $row, $update);
|
||||
if ($row === false) {
|
||||
echo "<p class='error'>" . lang('No rows.') . "\n";
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<form action="" method="post" enctype="multipart/form-data" id="form">
|
||||
<?php
|
||||
if (!$fields) {
|
||||
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
|
||||
} else {
|
||||
echo "<table class='layout'>" . script("qsl('table').onkeydown = editingKeydown;");
|
||||
$first = 0;
|
||||
foreach ($fields as $name => $field) {
|
||||
echo "<tr><th>" . $adminer->fieldName($field);
|
||||
$default = $_GET["set"][bracket_escape($name)];
|
||||
if ($default === null) {
|
||||
$default = $field["default"];
|
||||
if ($field["type"] == "bit" && preg_match("~^b'([01]*)'\$~", $default, $regs)) {
|
||||
$default = $regs[1];
|
||||
}
|
||||
}
|
||||
$value = ($row !== null
|
||||
? ($row[$name] != "" && JUSH == "sql" && preg_match("~enum|set~", $field["type"])
|
||||
? (is_array($row[$name]) ? array_sum($row[$name]) : +$row[$name])
|
||||
: (is_bool($row[$name]) ? +$row[$name] : $row[$name])
|
||||
)
|
||||
: (!$update && $field["auto_increment"]
|
||||
? ""
|
||||
: (isset($_GET["select"]) ? false : $default)
|
||||
)
|
||||
);
|
||||
if (!$_POST["save"] && is_string($value)) {
|
||||
$value = $adminer->editVal($value, $field);
|
||||
}
|
||||
$function = ($_POST["save"]
|
||||
? (string) $_POST["function"][$name]
|
||||
: ($update && preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"])
|
||||
? "now"
|
||||
: ($value === false ? null : ($value !== null ? '' : 'NULL'))
|
||||
)
|
||||
);
|
||||
if (!$_POST && !$update && $value == $field["default"] && preg_match('~^[\w.]+\(~', $value)) {
|
||||
$function = "SQL";
|
||||
}
|
||||
if (preg_match("~time~", $field["type"]) && preg_match('~^CURRENT_TIMESTAMP~i', $value)) {
|
||||
$value = "";
|
||||
$function = "now";
|
||||
}
|
||||
if ($field["type"] == "uuid" && $value == "uuid()") {
|
||||
$value = "";
|
||||
$function = "uuid";
|
||||
}
|
||||
if ($field["auto_increment"] || $function == "now" || $function == "uuid") {
|
||||
$first++;
|
||||
}
|
||||
input($field, $value, $function);
|
||||
echo "\n";
|
||||
}
|
||||
if (!support("table")) {
|
||||
echo "<tr>"
|
||||
. "<th><input name='field_keys[]'>"
|
||||
. script("qsl('input').oninput = fieldChange;")
|
||||
. "<td class='function'>" . html_select("field_funs[]", $adminer->editFunctions(array("null" => isset($_GET["select"]))))
|
||||
. "<td><input name='field_vals[]'>"
|
||||
. "\n"
|
||||
;
|
||||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
echo "<p>\n";
|
||||
if ($fields) {
|
||||
echo "<input type='submit' value='" . lang('Save') . "'>\n";
|
||||
if (!isset($_GET["select"])) {
|
||||
echo "<input type='submit' name='insert' value='" . ($update
|
||||
? lang('Save and continue edit')
|
||||
: lang('Save and insert next')
|
||||
) . "' title='Ctrl+Shift+Enter'>\n";
|
||||
echo ($update ? script("qsl('input').onclick = function () { return !ajaxForm(this.form, '" . lang('Saving') . "…', this); };") : "");
|
||||
}
|
||||
}
|
||||
echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n"
|
||||
: ($_POST || !$fields ? "" : script("focus(qsa('td', qs('#form'))[2*$first+1].firstChild);"))
|
||||
);
|
||||
if (isset($_GET["select"])) {
|
||||
hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"]));
|
||||
}
|
||||
?>
|
||||
<input type="hidden" name="referer" value="<?php echo h(isset($_POST["referer"]) ? $_POST["referer"] : $_SERVER["HTTP_REFERER"]); ?>">
|
||||
<input type="hidden" name="save" value="1">
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
520
adminer/include/html.inc.php
Normal file
520
adminer/include/html.inc.php
Normal file
@@ -0,0 +1,520 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
/** Return <script> element
|
||||
* @param string
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function script($source, $trailing = "\n") {
|
||||
return "<script" . nonce() . ">$source</script>$trailing";
|
||||
}
|
||||
|
||||
/** Return <script src> element
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function script_src($url) {
|
||||
return "<script src='" . h($url) . "'" . nonce() . "></script>\n";
|
||||
}
|
||||
|
||||
/** Get a nonce="" attribute with CSP nonce
|
||||
* @return string
|
||||
*/
|
||||
function nonce() {
|
||||
return ' nonce="' . get_nonce() . '"';
|
||||
}
|
||||
|
||||
/** Get a target="_blank" attribute
|
||||
* @return string
|
||||
*/
|
||||
function target_blank() {
|
||||
return ' target="_blank" rel="noreferrer noopener"';
|
||||
}
|
||||
|
||||
/** Escape for HTML
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function h($string) {
|
||||
return str_replace("\0", "�", htmlspecialchars($string, ENT_QUOTES, 'utf-8'));
|
||||
}
|
||||
|
||||
/** Convert \n to <br>
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function nl_br($string) {
|
||||
return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
|
||||
}
|
||||
|
||||
/** Generate HTML checkbox
|
||||
* @param string
|
||||
* @param string
|
||||
* @param bool
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function checkbox($name, $value, $checked, $label = "", $onclick = "", $class = "", $labelled_by = "") {
|
||||
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'"
|
||||
. ($checked ? " checked" : "")
|
||||
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
|
||||
. ">"
|
||||
. ($onclick ? script("qsl('input').onclick = function () { $onclick };", "") : "")
|
||||
;
|
||||
return ($label != "" || $class ? "<label" . ($class ? " class='$class'" : "") . ">$return" . h($label) . "</label>" : $return);
|
||||
}
|
||||
|
||||
/** Generate list of HTML options
|
||||
* @param array array of strings or arrays (creates optgroup)
|
||||
* @param mixed
|
||||
* @param bool always use array keys for value="", otherwise only string keys are used
|
||||
* @return string
|
||||
*/
|
||||
function optionlist($options, $selected = null, $use_keys = false) {
|
||||
$return = "";
|
||||
foreach ($options as $k => $v) {
|
||||
$opts = array($k => $v);
|
||||
if (is_array($v)) {
|
||||
$return .= '<optgroup label="' . h($k) . '">';
|
||||
$opts = $v;
|
||||
}
|
||||
foreach ($opts as $key => $val) {
|
||||
$return .= '<option'
|
||||
. ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '')
|
||||
. ($selected !== null && ($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '')
|
||||
. '>' . h($val)
|
||||
;
|
||||
}
|
||||
if (is_array($v)) {
|
||||
$return .= '</optgroup>';
|
||||
}
|
||||
}
|
||||
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
|
||||
* @return string
|
||||
*/
|
||||
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>";
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get onclick confirmation
|
||||
* @param string
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function confirm($message = "", $selector = "qsl('input')") {
|
||||
return script("$selector.onclick = function () { return confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "'); };", "");
|
||||
}
|
||||
|
||||
/** Print header for hidden fieldset (close by </div></fieldset>)
|
||||
* @param string
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return null
|
||||
*/
|
||||
function print_fieldset($id, $legend, $visible = false) {
|
||||
echo "<fieldset><legend>";
|
||||
echo "<a href='#fieldset-$id'>$legend</a>";
|
||||
echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", "");
|
||||
echo "</legend>";
|
||||
echo "<div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
|
||||
}
|
||||
|
||||
/** Return class='active' if $bold is true
|
||||
* @param bool
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function bold($bold, $class = "") {
|
||||
return ($bold ? " class='active $class'" : ($class ? " class='$class'" : ""));
|
||||
}
|
||||
|
||||
/** Escape string for JavaScript apostrophes
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function js_escape($string) {
|
||||
return addcslashes($string, "\r\n'\\/"); // slash for <script>
|
||||
}
|
||||
|
||||
/** Generate page number for pagination
|
||||
* @param int
|
||||
* @param int
|
||||
* @return string
|
||||
*/
|
||||
function pagination($page, $current) {
|
||||
return " " . ($page == $current
|
||||
? $page + 1
|
||||
: '<a href="' . h(remove_from_uri("page") . ($page ? "&page=$page" . ($_GET["next"] ? "&next=" . urlencode($_GET["next"]) : "") : "")) . '">' . ($page + 1) . "</a>"
|
||||
);
|
||||
}
|
||||
|
||||
/** Print hidden fields
|
||||
* @param array
|
||||
* @param array
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function hidden_fields($process, $ignore = array(), $prefix = '') {
|
||||
$return = false;
|
||||
foreach ($process as $key => $val) {
|
||||
if (!in_array($key, $ignore)) {
|
||||
if (is_array($val)) {
|
||||
hidden_fields($val, array(), $key);
|
||||
} else {
|
||||
$return = true;
|
||||
echo '<input type="hidden" name="' . h($prefix ? $prefix . "[$key]" : $key) . '" value="' . h($val) . '">';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Print hidden fields for GET forms
|
||||
* @return null
|
||||
*/
|
||||
function hidden_fields_get() {
|
||||
echo (sid() ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : '');
|
||||
echo (SERVER !== null ? '<input type="hidden" name="' . DRIVER . '" value="' . h(SERVER) . '">' : "");
|
||||
echo '<input type="hidden" name="username" value="' . h($_GET["username"]) . '">';
|
||||
}
|
||||
|
||||
/** Print enum input field
|
||||
* @param string "radio"|"checkbox"
|
||||
* @param string
|
||||
* @param 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 === $empty) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
|
||||
foreach ($matches[1] as $i => $val) {
|
||||
$val = stripcslashes(str_replace("''", "'", $val));
|
||||
$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;
|
||||
}
|
||||
|
||||
/** Print edit input field
|
||||
* @param array one field from fields()
|
||||
* @param mixed
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return null
|
||||
*/
|
||||
function input($field, $value, $function, $autofocus = false) {
|
||||
global $driver, $adminer;
|
||||
$name = h(bracket_escape($field["field"]));
|
||||
echo "<td class='function'>";
|
||||
if (is_array($value) && !$function) {
|
||||
$value = json_encode($value, 128); // 128 - JSON_PRETTY_PRINT available since PHP 5.4
|
||||
$function = "json";
|
||||
}
|
||||
$reset = (JUSH == "mssql" && $field["auto_increment"]);
|
||||
if ($reset && !$_POST["save"]) {
|
||||
$function = null;
|
||||
}
|
||||
$functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
|
||||
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
|
||||
$attrs = " name='fields[$name]'$disabled" . ($autofocus ? " autofocus" : "");
|
||||
$enums = $driver->enumLength($field);
|
||||
if ($enums) {
|
||||
$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 {
|
||||
$has_function = (in_array($function, $functions) || isset($functions[$function]));
|
||||
echo (count($functions) > 1
|
||||
? "<select name='function[$name]'$disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
|
||||
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
|
||||
. script("qsl('select').onchange = functionChange;", "")
|
||||
: h(reset($functions))
|
||||
) . '<td>';
|
||||
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
|
||||
if ($input != "") {
|
||||
echo $input;
|
||||
} 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") {
|
||||
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
|
||||
foreach ($matches[1] as $i => $val) {
|
||||
$val = stripcslashes(str_replace("''", "'", $val));
|
||||
$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'>";
|
||||
} elseif (($text = preg_match('~text|lob|memo~i', $field["type"])) || preg_match("~\n~", $value)) {
|
||||
if ($text && JUSH != "sqlite") {
|
||||
$attrs .= " cols='50' rows='12'";
|
||||
} else {
|
||||
$rows = min(12, substr_count($value, "\n") + 1);
|
||||
$attrs .= " cols='30' rows='$rows'" . ($rows == 1 ? " style='height: 1.2em;'" : ""); // 1.2em - line-height
|
||||
}
|
||||
echo "<textarea$attrs>" . h($value) . '</textarea>';
|
||||
} elseif ($function == "json" || preg_match('~^jsonb?$~', $field["type"])) {
|
||||
echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
|
||||
} else {
|
||||
// int(3) is only a display hint
|
||||
$types = $driver->types();
|
||||
$maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match)
|
||||
? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0))
|
||||
: ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)
|
||||
);
|
||||
if (JUSH == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
|
||||
$maxlength += 7; // microtime
|
||||
}
|
||||
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
|
||||
echo "<input"
|
||||
. ((!$has_function || $function === "") && preg_match('~(?<!o)int(?!er)~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "")
|
||||
. " value='" . h($value) . "'" . ($maxlength ? " data-maxlength='$maxlength'" : "")
|
||||
. (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "")
|
||||
. "$attrs>"
|
||||
;
|
||||
}
|
||||
echo $adminer->editHint($_GET["edit"], $field, $value);
|
||||
// skip 'original'
|
||||
$first = 0;
|
||||
foreach ($functions as $key => $val) {
|
||||
if ($key === "" || !$val) {
|
||||
break;
|
||||
}
|
||||
$first++;
|
||||
}
|
||||
if ($first) {
|
||||
echo script("mixin(qsl('td'), {onchange: partial(skipOriginal, $first), oninput: function () { this.onchange(); }});");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Process edit input field
|
||||
* @param one field from fields()
|
||||
* @return string or false to leave the original value
|
||||
*/
|
||||
function process_input($field) {
|
||||
global $adminer, $driver;
|
||||
if (stripos($field["default"], "GENERATED ALWAYS AS ") === 0) {
|
||||
return null;
|
||||
}
|
||||
$idf = bracket_escape($field["field"]);
|
||||
$function = $_POST["function"][$idf];
|
||||
$value = $_POST["fields"][$idf];
|
||||
if ($field["type"] == "enum" || $driver->enumLength($field)) {
|
||||
if ($value == -1) {
|
||||
return false;
|
||||
}
|
||||
if ($value == "") {
|
||||
return "NULL";
|
||||
}
|
||||
}
|
||||
if ($field["auto_increment"] && $value == "") {
|
||||
return null;
|
||||
}
|
||||
if ($function == "orig") {
|
||||
return (preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"]) ? idf_escape($field["field"]) : false);
|
||||
}
|
||||
if ($function == "NULL") {
|
||||
return "NULL";
|
||||
}
|
||||
if ($field["type"] == "set") {
|
||||
$value = implode(",", (array) $value);
|
||||
}
|
||||
if ($function == "json") {
|
||||
$function = "";
|
||||
$value = json_decode($value, true);
|
||||
if (!is_array($value)) {
|
||||
return false; //! report errors
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
if (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
|
||||
$file = get_file("fields-$idf");
|
||||
if (!is_string($file)) {
|
||||
return false; //! report errors
|
||||
}
|
||||
return $driver->quoteBinary($file);
|
||||
}
|
||||
return $adminer->processInput($field, $value, $function);
|
||||
}
|
||||
|
||||
/** Print results of search in all tables
|
||||
* @uses $_GET["where"][0]
|
||||
* @uses $_POST["tables"]
|
||||
* @return null
|
||||
*/
|
||||
function search_tables() {
|
||||
global $adminer, $connection;
|
||||
$_GET["where"][0]["val"] = $_POST["query"];
|
||||
$sep = "<ul>\n";
|
||||
foreach (table_status('', true) as $table => $table_status) {
|
||||
$name = $adminer->tableName($table_status);
|
||||
if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) {
|
||||
$result = $connection->query("SELECT" . limit("1 FROM " . table($table), " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())), 1));
|
||||
if (!$result || $result->fetch_row()) {
|
||||
$print = "<a href='" . h(ME . "select=" . urlencode($table) . "&where[0][op]=" . urlencode($_GET["where"][0]["op"]) . "&where[0][val]=" . urlencode($_GET["where"][0]["val"])) . "'>$name</a>";
|
||||
echo "$sep<li>" . ($result ? $print : "<p class='error'>$print: " . error()) . "\n";
|
||||
$sep = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
echo ($sep ? "<p class='message'>" . lang('No tables.') : "</ul>") . "\n";
|
||||
}
|
||||
|
||||
/** Return events to display help on mouse over
|
||||
* @param string JS expression
|
||||
* @param bool JS expression
|
||||
* @return string
|
||||
*/
|
||||
function on_help($command, $side = 0) {
|
||||
return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", "");
|
||||
}
|
||||
|
||||
/** Print edit data form
|
||||
* @param string
|
||||
* @param array
|
||||
* @param mixed
|
||||
* @param bool
|
||||
* @return null
|
||||
*/
|
||||
function edit_form($table, $fields, $row, $update) {
|
||||
global $adminer, $token, $error;
|
||||
$table_name = $adminer->tableName(table_status1($table, true));
|
||||
page_header(
|
||||
($update ? lang('Edit') : lang('Insert')),
|
||||
$error,
|
||||
array("select" => array($table, $table_name)),
|
||||
$table_name
|
||||
);
|
||||
$adminer->editRowPrint($table, $fields, $row, $update);
|
||||
if ($row === false) {
|
||||
echo "<p class='error'>" . lang('No rows.') . "\n";
|
||||
return;
|
||||
}
|
||||
echo "<form action='' method='post' enctype='multipart/form-data' id='form'>\n";
|
||||
if (!$fields) {
|
||||
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
|
||||
} else {
|
||||
echo "<table class='layout'>" . script("qsl('table').onkeydown = editingKeydown;");
|
||||
$autofocus = !$_POST;
|
||||
foreach ($fields as $name => $field) {
|
||||
echo "<tr><th>" . $adminer->fieldName($field);
|
||||
$default = $_GET["set"][bracket_escape($name)];
|
||||
if ($default === null) {
|
||||
$default = $field["default"];
|
||||
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])
|
||||
? implode(",", $row[$name])
|
||||
: (is_bool($row[$name]) ? +$row[$name] : $row[$name])
|
||||
)
|
||||
: (!$update && $field["auto_increment"]
|
||||
? ""
|
||||
: (isset($_GET["select"]) ? false : $default)
|
||||
)
|
||||
);
|
||||
if (!$_POST["save"] && is_string($value)) {
|
||||
$value = $adminer->editVal($value, $field);
|
||||
}
|
||||
$function = ($_POST["save"]
|
||||
? (string) $_POST["function"][$name]
|
||||
: ($update && preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"])
|
||||
? "now"
|
||||
: ($value === false ? null : ($value !== null ? '' : 'NULL'))
|
||||
)
|
||||
);
|
||||
if (!$_POST && !$update && $value == $field["default"] && preg_match('~^[\w.]+\(~', $value)) {
|
||||
$function = "SQL";
|
||||
}
|
||||
if (preg_match("~time~", $field["type"]) && preg_match('~^CURRENT_TIMESTAMP~i', $value)) {
|
||||
$value = "";
|
||||
$function = "now";
|
||||
}
|
||||
if ($field["type"] == "uuid" && $value == "uuid()") {
|
||||
$value = "";
|
||||
$function = "uuid";
|
||||
}
|
||||
if ($autofocus !== false) {
|
||||
$autofocus = ($field["auto_increment"] || $function == "now" || $function == "uuid" ? null : true); // null - don't autofocus this input but check the next one
|
||||
}
|
||||
input($field, $value, $function, $autofocus);
|
||||
if ($autofocus) {
|
||||
$autofocus = false;
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
if (!support("table")) {
|
||||
echo "<tr>"
|
||||
. "<th><input name='field_keys[]'>"
|
||||
. script("qsl('input').oninput = fieldChange;")
|
||||
. "<td class='function'>" . html_select("field_funs[]", $adminer->editFunctions(array("null" => isset($_GET["select"]))))
|
||||
. "<td><input name='field_vals[]'>"
|
||||
. "\n"
|
||||
;
|
||||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
echo "<p>\n";
|
||||
if ($fields) {
|
||||
echo "<input type='submit' value='" . lang('Save') . "'>\n";
|
||||
if (!isset($_GET["select"])) {
|
||||
echo "<input type='submit' name='insert' value='" . ($update
|
||||
? lang('Save and continue edit')
|
||||
: lang('Save and insert next')
|
||||
) . "' title='Ctrl+Shift+Enter'>\n";
|
||||
echo ($update ? script("qsl('input').onclick = function () { return !ajaxForm(this.form, '" . lang('Saving') . "…', this); };") : "");
|
||||
}
|
||||
}
|
||||
echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n" : "");
|
||||
if (isset($_GET["select"])) {
|
||||
hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"]));
|
||||
}
|
||||
?>
|
||||
<input type="hidden" name="referer" value="<?php echo h(isset($_POST["referer"]) ? $_POST["referer"] : $_SERVER["HTTP_REFERER"]); ?>">
|
||||
<input type="hidden" name="save" value="1">
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
</form>
|
||||
<?php
|
||||
}
|
@@ -63,10 +63,12 @@ function get_lang() {
|
||||
* @param int
|
||||
* @return string
|
||||
*/
|
||||
// this is matched by compile.php
|
||||
function lang($idf, $number = null) {
|
||||
global $LANG, $translations;
|
||||
$translation = ($translations[$idf] ?: $idf);
|
||||
if (is_array($translation)) {
|
||||
// this is matched by compile.php
|
||||
$pos = ($number == 1 ? 0
|
||||
: ($LANG == 'cs' || $LANG == 'sk' ? ($number && $number < 5 ? 1 : 2) // different forms for 1, 2-4, other
|
||||
: ($LANG == 'fr' ? (!$number ? 0 : 1) // different forms for 0-1, other
|
||||
@@ -74,9 +76,9 @@ 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
|
||||
: 1 // different forms for 1, other
|
||||
)))))))); // http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
|
||||
: (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];
|
||||
}
|
||||
$args = func_get_args();
|
||||
|
@@ -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);
|
||||
|
@@ -2,8 +2,7 @@
|
||||
namespace Adminer;
|
||||
|
||||
class TmpFile {
|
||||
var $handler;
|
||||
var $size;
|
||||
private $handler, $size;
|
||||
|
||||
function __construct() {
|
||||
$this->handler = tmpfile();
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
$VERSION = "5.0.1";
|
||||
$VERSION = "5.0.6";
|
||||
|
@@ -6,6 +6,7 @@
|
||||
* @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)
|
||||
*/
|
||||
// this is matched by compile.php
|
||||
|
||||
namespace Adminer;
|
||||
|
||||
@@ -15,6 +16,7 @@ include "./include/tmpfile.inc.php";
|
||||
if (isset($_GET["select"]) && ($_POST["edit"] || $_POST["clone"]) && !$_POST["save"]) {
|
||||
$_GET["edit"] = $_GET["select"];
|
||||
}
|
||||
// this is matched by compile.php
|
||||
if (isset($_GET["callf"])) {
|
||||
$_GET["call"] = $_GET["callf"];
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ if (JUSH == "mongo") { // doesn't support primary key
|
||||
}
|
||||
$row = $_POST;
|
||||
if ($row) {
|
||||
set_adminer_settings(array("index_options" => $row["options"]));
|
||||
save_settings(array("index_options" => $row["options"]));
|
||||
}
|
||||
if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
$alter = array();
|
||||
@@ -97,7 +97,7 @@ if (!$row) {
|
||||
$row["indexes"] = $indexes;
|
||||
}
|
||||
$lengths = (JUSH == "sql" || JUSH == "mssql");
|
||||
$show_options = ($_POST ? $_POST["options"] : adminer_setting("index_options"));
|
||||
$show_options = ($_POST ? $_POST["options"] : get_setting("index_options"));
|
||||
?>
|
||||
|
||||
<form action="" method="post">
|
||||
@@ -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"]);
|
||||
|
@@ -77,7 +77,7 @@ $translations = array(
|
||||
'Routine has been called, %d row(s) affected.' => 'تم استدعاء الروتين, عدد الأسطر المعدلة %d.',
|
||||
'Call' => 'استدعاء',
|
||||
'No extension' => 'امتداد غير موجود',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'إمتدادات php المدعومة غير موجودة.',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'إمتدادات php (%s) المدعومة غير موجودة.',
|
||||
'Session support must be enabled.' => 'عليك تفعيل نظام الجلسات.',
|
||||
'Session expired, please login again.' => 'إنتهت الجلسة، من فضلك أعد تسجيل الدخول.',
|
||||
'Text length' => 'طول النص',
|
||||
@@ -171,8 +171,8 @@ $translations = array(
|
||||
'Tables and views' => 'الجداول و العروض',
|
||||
'Engine' => 'المحرك',
|
||||
'Collation' => 'ترتيب',
|
||||
'Data Length' => 'طول المعطيات.',
|
||||
'Index Length' => 'طول المؤشر.',
|
||||
'Data Length' => 'طول المعطيات',
|
||||
'Index Length' => 'طول المؤشر',
|
||||
'Data Free' => 'المساحة الحرة',
|
||||
'Rows' => 'الأسطر',
|
||||
',' => ',',
|
||||
@@ -192,7 +192,7 @@ $translations = array(
|
||||
'Partitions' => 'التقسيمات',
|
||||
'Partition name' => 'اسم التقسيم',
|
||||
'Values' => 'القيم',
|
||||
'%d row(s) have been imported.' => 'تم استيراد %d سطرا',
|
||||
'%d row(s) have been imported.' => 'تم استيراد %d سطرا.',
|
||||
'anywhere' => 'في اي مكان',
|
||||
'Import' => 'استيراد',
|
||||
'Stop on error' => 'أوقف في حالة حدوث خطأ',
|
||||
@@ -251,8 +251,8 @@ $translations = array(
|
||||
'Network' => 'شبكة',
|
||||
'Geometry' => 'هندسة',
|
||||
'File exists.' => 'الملف موجود.',
|
||||
'Attachments' => 'ملفات مرفقة.',
|
||||
'Item%s has been inserted.' => 'تم إدراج العنصر.',
|
||||
'Attachments' => 'ملفات مرفقة',
|
||||
'Item%s has been inserted.' => '%sتم إدراج العنصر.',
|
||||
'now' => 'الآن',
|
||||
'%d query(s) executed OK.' => array('تم تنفيذ الاستعلام %d بنجاح.', 'تم تنفيذ الاستعلامات %d بنجاح.'),
|
||||
'Show only errors' => 'إظهار الأخطاء فقط',
|
||||
|
@@ -38,7 +38,7 @@ $translations = array(
|
||||
'select' => 'নির্বাচন',
|
||||
'Item has been deleted.' => 'বিষয়বস্তু মুছে ফেলা হয়েছে।',
|
||||
'Item has been updated.' => 'বিষয়বস্তু হালনাগাদ করা হয়েছে।',
|
||||
'Item%s has been inserted.' => 'বিষয়বস্তুসমূহ সংযোজন করা হয়েছে।',
|
||||
'Item%s has been inserted.' => 'বিষয়বস্তুসমূহ%s সংযোজন করা হয়েছে।',
|
||||
'Edit' => 'সম্পাদনা',
|
||||
'Insert' => 'সংযোজন',
|
||||
'Save and insert next' => 'সংরক্ষন ও পরবর্তী সংযোজন করুন',
|
||||
@@ -61,7 +61,7 @@ $translations = array(
|
||||
'edit' => 'সম্পাদনা',
|
||||
'Page' => 'পৃষ্ঠা',
|
||||
'Query executed OK, %d row(s) affected.' => array('কোয়্যারী সম্পাদন হয়েছে, %d সারি প্রভাবিত হয়েছে।', 'কোয়্যারী সম্পাদন হয়েছে, %d সারি প্রভাবিত হয়েছে।'),
|
||||
'Error in query' => 'অনুসন্ধানে ভুল আছে।',
|
||||
'Error in query' => 'অনুসন্ধানে ভুল আছে',
|
||||
'Execute' => 'সম্পাদন করো',
|
||||
'Table' => 'টেবিল',
|
||||
'Foreign keys' => 'ফরেন কী',
|
||||
@@ -139,7 +139,7 @@ $translations = array(
|
||||
'Routine' => 'রুটিন',
|
||||
'Grant' => 'অনুমতি',
|
||||
'Revoke' => 'প্রত্যাহার',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'খুব বড় POST ডাটা। ডাটা সংক্ষিপ্ত করো অথবা %s কনফিগারেশন নির্দেশ বৃদ্ধি করো',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'খুব বড় POST ডাটা। ডাটা সংক্ষিপ্ত করো অথবা %s কনফিগারেশন নির্দেশ বৃদ্ধি করো।',
|
||||
'Logged as: %s' => '%s হিসাবে লগড',
|
||||
'Move up' => 'উপরে স্থানান্তর',
|
||||
'Move down' => 'নীচে স্থানান্তর',
|
||||
@@ -175,7 +175,7 @@ $translations = array(
|
||||
'Check' => 'পরীক্ষা',
|
||||
'Repair' => 'মেরামত',
|
||||
'Truncate' => 'ছাঁটাই',
|
||||
'Tables have been truncated.' => 'টেবিল ছাঁটাই করা হয়েছে',
|
||||
'Tables have been truncated.' => 'টেবিল ছাঁটাই করা হয়েছে।',
|
||||
'Rows' => 'সারিসমূহ',
|
||||
',' => ',',
|
||||
'0123456789' => '০১২৩৪৫৬৭৮৯',
|
||||
@@ -186,7 +186,7 @@ $translations = array(
|
||||
'Save and continue edit' => 'সংরক্ষণ করুন এবং সম্পাদনা চালিয়ে যান',
|
||||
'original' => 'প্রকৃত',
|
||||
'Tables have been dropped.' => 'টেবিলসমূহ মুছে ফেলা হয়েছে।',
|
||||
'%d item(s) have been affected.' => '%d টি বিষয়বস্তু প্রভাবিত হয়েছে',
|
||||
'%d item(s) have been affected.' => '%d টি বিষয়বস্তু প্রভাবিত হয়েছে।',
|
||||
'Whole result' => 'সম্পূর্ণ ফলাফল',
|
||||
'Clone' => 'ক্লোন',
|
||||
'Maximum number of allowed fields exceeded. Please increase %s.' => 'অনুমোদিত ফিল্ড এর সর্বাধিক সংখ্যা অতিক্রম করে গেছে। অনুগ্রহপূর্বক %s বৃদ্ধি করুন।',
|
||||
@@ -207,7 +207,7 @@ $translations = array(
|
||||
'Relations' => 'সম্পর্ক',
|
||||
'Run file' => 'ফাইল চালাও',
|
||||
'Clear' => 'সাফ করো',
|
||||
'Maximum allowed file size is %sB.' => 'সর্বাধিক অনুমোদিত ফাইল সাইজ %sB.',
|
||||
'Maximum allowed file size is %sB.' => 'সর্বাধিক অনুমোদিত ফাইল সাইজ %sB।',
|
||||
'Numbers' => 'সংখ্যা',
|
||||
'Date and time' => 'তারিখ এবং সময়',
|
||||
'Strings' => 'স্ট্রিং',
|
||||
@@ -253,7 +253,7 @@ $translations = array(
|
||||
'Geometry' => 'জ্যামিতি',
|
||||
'File exists.' => 'ফাইল রয়েছে।',
|
||||
'Attachments' => 'সংযুক্তিগুলো',
|
||||
'%d query(s) executed OK.' => array('SQL-অনুসন্ধান সফলভাবে সম্পন্ন হয়েছে', '%d SQL-অনুসন্ধানসমূহ সফলভাবে সম্পন্ন হয়েছে'),
|
||||
'%d query(s) executed OK.' => array('SQL-অনুসন্ধান সফলভাবে সম্পন্ন হয়েছে।', '%d SQL-অনুসন্ধানসমূহ সফলভাবে সম্পন্ন হয়েছে।'),
|
||||
'Show only errors' => 'শুধুমাত্র ত্রুটিগুলো দেখান',
|
||||
'Refresh' => 'রিফ্রেশ',
|
||||
'Invalid schema.' => 'অবৈধ স্কিমা।',
|
||||
|
@@ -16,7 +16,7 @@ $translations = array(
|
||||
'Language' => 'Jezik',
|
||||
'Invalid CSRF token. Send the form again.' => 'Nevažeći CSRF kod. Proslijedite ponovo formu.',
|
||||
'No extension' => 'Bez dodataka',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Nijedan od podržanih PHP dodataka nije dostupan.',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Nijedan od podržanih PHP dodataka (%s) nije dostupan.',
|
||||
'Session support must be enabled.' => 'Morate omogućiti podršku za sesije.',
|
||||
'Session expired, please login again.' => 'Vaša sesija je istekla, prijavite se ponovo.',
|
||||
'%s version: %s through PHP extension %s' => '%s verzija: %s pomoću PHP dodatka je %s',
|
||||
|
@@ -4,7 +4,7 @@ namespace Adminer;
|
||||
$translations = array(
|
||||
'Login' => 'Login',
|
||||
'Logout successful.' => 'Abmeldung erfolgreich.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Danke, dass Sie Adminer genutzt haben. <a href="https://www.adminer.org/de/donation/">Spenden willkommen!</a>',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Danke, dass Sie Adminer genutzt haben. <a href="https://www.adminer.org/de/donation/">Spenden willkommen!</a>.',
|
||||
'Invalid credentials.' => 'Ungültige Anmelde-Informationen.',
|
||||
'Server' => 'Server',
|
||||
'Username' => 'Benutzer',
|
||||
@@ -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',
|
||||
);
|
||||
|
@@ -146,7 +146,7 @@ $translations = array(
|
||||
'Tables' => 'جدولها',
|
||||
'Tables and views' => 'جدولها و نمایه ها',
|
||||
'Table' => 'جدول',
|
||||
'No tables.' => 'جدولی وجود ندارد',
|
||||
'No tables.' => 'جدولی وجود ندارد.',
|
||||
'Alter table' => 'ویرایش جدول',
|
||||
'Create table' => 'ایجاد جدول',
|
||||
'Table has been dropped.' => 'جدول حذف شد.',
|
||||
@@ -238,7 +238,7 @@ $translations = array(
|
||||
'Action' => 'عملیات',
|
||||
'Full table scan' => 'اسکن کامل جدول',
|
||||
'Unable to select the table' => 'قادر به انتخاب جدول نیستید',
|
||||
'No rows.' => 'سطری وجود ندارد',
|
||||
'No rows.' => 'سطری وجود ندارد.',
|
||||
'%d / ' => '%d / ',
|
||||
'%d row(s)' => array('%d سطر', '%d سطر'),
|
||||
'Page' => 'صفحه',
|
||||
|
@@ -298,7 +298,7 @@ $translations = array(
|
||||
'The action will be performed after successful login with the same credentials.' => 'Cette action sera exécutée après s\'être connecté avec les mêmes données de connexion.',
|
||||
'Connecting to privileged ports is not allowed.' => 'La connexion aux ports privilégiés n\'est pas autorisée.',
|
||||
'There is a space in the input password which might be the cause.' => 'Il y a un espace dans le mot de passe entré qui pourrait en être la cause.',
|
||||
'Unknown error.' => 'Erreur inconnue',
|
||||
'Database does not support password.' => 'La base de données ne support pas les mots de passe',
|
||||
'Unknown error.' => 'Erreur inconnue.',
|
||||
'Database does not support password.' => 'La base de données ne support pas les mots de passe.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Désactiver %s ou activer %s or %s extensions.',
|
||||
);
|
||||
|
@@ -266,11 +266,11 @@ $translations = array(
|
||||
'Permanent link' => 'Ligazón permanente',
|
||||
'Edit all' => 'Editar todo',
|
||||
'HH:MM:SS' => 'HH:MM:SS',
|
||||
'Tables have been optimized.' => 'Optimizáronse as táboas',
|
||||
'Tables have been optimized.' => 'Optimizáronse as táboas.',
|
||||
'Materialized view' => 'Vista materializada',
|
||||
'Vacuum' => 'Baleirar',
|
||||
'Selected' => 'Selección',
|
||||
'File must be in UTF-8 encoding.' => 'O ficheiro ten que estar codificado con UTF-8',
|
||||
'File must be in UTF-8 encoding.' => 'O ficheiro ten que estar codificado con UTF-8.',
|
||||
'Modify' => 'Modificar',
|
||||
'Loading' => 'Cargando',
|
||||
'Load more data' => 'Cargar máis datos',
|
||||
@@ -278,14 +278,14 @@ $translations = array(
|
||||
'Limit rows' => 'Limitar filas',
|
||||
'Default value' => 'Valor por defecto',
|
||||
'Full table scan' => 'Escaneo completo da táboa',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('Demasiados intentos de conexión, intentao de novo en %d minuto', 'Demasiados intentos de conexión, intentao de novo en %d minutos'),
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('Demasiados intentos de conexión, intentao de novo en %d minuto.', 'Demasiados intentos de conexión, intentao de novo en %d minutos.'),
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'O contrasinal principal caducou. <a href="https://www.adminer.org/en/extension/"%s>Implementa</a> o método %s para facelo permanente.',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Se non enviaches esta petición dende o Adminer entón pecha esta páxina',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => 'Podes subir un ficheiro SQL de gran tamaño vía FTP e importalo dende o servidor',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Se non enviaches esta petición dende o Adminer entón pecha esta páxina.',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => 'Podes subir un ficheiro SQL de gran tamaño vía FTP e importalo dende o servidor.',
|
||||
'Size' => 'Tamaño',
|
||||
'Compute' => 'Calcular',
|
||||
'You are offline.' => 'Non tes conexión',
|
||||
'You have no privileges to update this table.' => 'Non tes privilexios para actualizar esta táboa',
|
||||
'You are offline.' => 'Non tes conexión.',
|
||||
'You have no privileges to update this table.' => 'Non tes privilexios para actualizar esta táboa.',
|
||||
'Saving' => 'Gardando',
|
||||
'yes' => 'si',
|
||||
'no' => 'non',
|
||||
|
@@ -280,7 +280,7 @@ $translations = array(
|
||||
'Default value' => 'ערך ברירת מחדל',
|
||||
'Full table scan' => 'סריקה טבלה מלאה',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => 'יותר מידי נסיונות כניסה נכשלו, אנא נסה עוד %d דקות',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'תודה שהשתמש ב-adminer אנא שקול <a href="https://www.adminer.org/en/donation/">לתרום</a>.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'תודה שהשתמש ב-adminer אנא שקול <a href="https://www.adminer.org/en/donation/">לתרום</a>',
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'סיסמת המאסטר פגה <a href="https://www.adminer.org/en/extension/"%s>התקן תוסף</a> על מנת להפוך את זה לתמידי',
|
||||
'If you did not send this request from Adminer then close this page.' => 'אם לא אתה שלחת בקשה ל-Adminer הינך יכול לסגור חלון זה',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => 'ניתן לעלות קבצים ב-FTP ואז למשוך אותם מהשרת',
|
||||
|
@@ -267,7 +267,7 @@ $translations = array(
|
||||
'Edit all' => 'Modifica tutto',
|
||||
'HH:MM:SS' => 'HH:MM:SS',
|
||||
'Drop %s?' => 'Scartare %s?',
|
||||
'Tables have been optimized.' => 'Le tabelle sono state ottimizzate',
|
||||
'Tables have been optimized.' => 'Le tabelle sono state ottimizzate.',
|
||||
'Materialized view' => 'Vista materializzata',
|
||||
'Vacuum' => 'Aspira',
|
||||
'Selected' => 'Selezionato',
|
||||
@@ -296,7 +296,7 @@ $translations = array(
|
||||
'You are offline.' => 'Sei disconnesso.',
|
||||
'You have no privileges to update this table.' => 'Non hai i privilegi per aggiornare questa tabella.',
|
||||
'Saving' => 'Salvataggio',
|
||||
'Unknown error.' => 'Errore sconosciuto',
|
||||
'Unknown error.' => 'Errore sconosciuto.',
|
||||
'Database does not support password.' => 'Il database non supporta password.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Disabilita %s o abilita %s oppure %s estensioni.',
|
||||
'yes' => 'si',
|
||||
|
@@ -122,7 +122,7 @@ $translations = array(
|
||||
'Indexes have been altered.' => '색인을 변경했습니다.',
|
||||
'Indexes' => '색인',
|
||||
'Insert' => '삽입',
|
||||
'Invalid credentials.' => '잘못된 로그인',
|
||||
'Invalid credentials.' => '잘못된 로그인.',
|
||||
'Invalid CSRF token. Send the form again.' => '잘못된 CSRF 토큰입니다. 다시 보내주십시오.',
|
||||
'Invalid database.' => '잘못된 데이터베이스입니다.',
|
||||
'Invalid schema.' => '잘못된 스키마입니다.',
|
||||
@@ -143,7 +143,7 @@ $translations = array(
|
||||
'Logout successful.' => '로그아웃을 성공했습니다.',
|
||||
'Logout' => '로그아웃',
|
||||
'ltr' => 'ltr',
|
||||
'Maximum allowed file size is %sB.' => '파일의 최대 크기 %sB',
|
||||
'Maximum allowed file size is %sB.' => '파일의 최대 크기 %sB.',
|
||||
'Maximum number of allowed fields exceeded. Please increase %s.' => '정의 가능한 최대 필드 수를 초과했습니다. %s(을)를 늘리십시오.',
|
||||
'Modify' => '수정',
|
||||
'Move down' => '아래로',
|
||||
@@ -154,7 +154,7 @@ $translations = array(
|
||||
'Network' => '네트워크 형',
|
||||
'New item' => '항목 만들기',
|
||||
'No commands to execute.' => '실행할 수 있는 명령이 없습니다.',
|
||||
'No extension' => '확장이 없습니다.',
|
||||
'No extension' => '확장이 없습니다',
|
||||
'No rows.' => '행이 없습니다.',
|
||||
'No tables.' => '테이블이 없습니다.',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'PHP 확장(%s)이 설치되어 있지 않습니다.',
|
||||
@@ -206,8 +206,8 @@ $translations = array(
|
||||
'Schema' => '스키마',
|
||||
'Search data in tables' => '테이블 내 데이터 검색',
|
||||
'Search' => '검색',
|
||||
'Select data' => '데이터를 선택하십시오.',
|
||||
'Select database' => '데이터베이스를 선택하십시오.',
|
||||
'Select data' => '데이터를 선택하십시오',
|
||||
'Select database' => '데이터베이스를 선택하십시오',
|
||||
'Select' => '선택',
|
||||
'select' => '선택',
|
||||
'Selected' => '선택됨',
|
||||
@@ -238,7 +238,7 @@ $translations = array(
|
||||
'Table name' => '테이블 이름',
|
||||
'Table' => '테이블',
|
||||
'Tables and views' => '테이블과 뷰',
|
||||
'Tables have been copied.' => '테이블을 복사했습니다',
|
||||
'Tables have been copied.' => '테이블을 복사했습니다.',
|
||||
'Tables have been dropped.' => '테이블을 삭제했습니다.',
|
||||
'Tables have been moved.' => '테이블을 옮겼습니다.',
|
||||
'Tables have been truncated.' => '테이블의 데이터 내용만 지웠습니다.',
|
||||
@@ -256,7 +256,7 @@ $translations = array(
|
||||
'Type has been created.' => '유형을 추가했습니다.',
|
||||
'Type has been dropped.' => '유형을 삭제했습니다.',
|
||||
'Type' => '형',
|
||||
'Unable to select the table' => '테이블을 선택할 수 없습니다.',
|
||||
'Unable to select the table' => '테이블을 선택할 수 없습니다',
|
||||
'Unable to upload a file.' => '파일을 업로드 할 수 없습니다.',
|
||||
'Use edit link to modify this value.' => '이 값을 수정하려면 편집 링크를 사용하십시오.',
|
||||
'Use' => '사용',
|
||||
|
@@ -38,7 +38,7 @@ $translations = array(
|
||||
'select' => 'izvēlēties',
|
||||
'Item has been deleted.' => 'Ieraksts dzests.',
|
||||
'Item has been updated.' => 'Ieraksts atjaunots.',
|
||||
'Item%s has been inserted.' => 'Ieraksti tika ievietoti.',
|
||||
'Item%s has been inserted.' => 'Ieraksti%s tika ievietoti.',
|
||||
'Edit' => 'Rediģēt',
|
||||
'Insert' => 'Ievietot',
|
||||
'Save and insert next' => 'Saglabāt un ievietot nākamo',
|
||||
|
@@ -254,7 +254,7 @@ $translations = array(
|
||||
'Geometry' => 'Geometrie',
|
||||
'File exists.' => 'Bestand bestaat reeds.',
|
||||
'Attachments' => 'Bijlagen',
|
||||
'%d query(s) executed OK.' => array('%d query succesvol uitgevoerd.', '%d querys succesvol uitgevoerd'),
|
||||
'%d query(s) executed OK.' => array('%d query succesvol uitgevoerd.', '%d querys succesvol uitgevoerd.'),
|
||||
'Show only errors' => 'Enkel fouten tonen',
|
||||
'Refresh' => 'Vernieuwen',
|
||||
'Invalid schema.' => 'Ongeldig schema.',
|
||||
@@ -277,7 +277,7 @@ $translations = array(
|
||||
'Modify' => 'Aanpassen',
|
||||
'Load more data' => 'Meer data inladen',
|
||||
'Loading' => 'Aan het laden',
|
||||
'ATTACH queries are not supported.' => 'ATTACH queries worden niet ondersteund',
|
||||
'ATTACH queries are not supported.' => 'ATTACH queries worden niet ondersteund.',
|
||||
'Warnings' => 'Waarschuwingen',
|
||||
'%d / ' => '%d / ',
|
||||
'Limit rows' => 'Rijen beperken',
|
||||
@@ -286,7 +286,7 @@ $translations = array(
|
||||
'Full table scan' => 'Full table scan',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('Teveel foutieve aanmeldpogingen, probeer opnieuw binnen %d minuut.', 'Teveel foutieve aanmeldpogingen, probeer opnieuw binnen %d minuten.'),
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Master wachtwoord verlopen. <a href="https://www.adminer.org/en/extension/"%s>Implementeer</a> de %s methode om het permanent te maken.',
|
||||
'The action will be performed after successful login with the same credentials.' => 'Deze actie zal uitgevoerd worden na het succesvol aanmelden met dezelfde gebruikersgegevens',
|
||||
'The action will be performed after successful login with the same credentials.' => 'Deze actie zal uitgevoerd worden na het succesvol aanmelden met dezelfde gebruikersgegevens.',
|
||||
'Connecting to privileged ports is not allowed.' => 'Verbindingen naar geprivilegieerde poorten is niet toegestaan.',
|
||||
'There is a space in the input password which might be the cause.' => 'Er staat een spatie in het wachtwoord, wat misschien de oorzaak is.',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Als u deze actie niet via Adminer hebt gedaan, gelieve deze pagina dan te sluiten.',
|
||||
@@ -296,7 +296,7 @@ $translations = array(
|
||||
'You are offline.' => 'U bent offline.',
|
||||
'You have no privileges to update this table.' => 'U bent niet gemachtigd om deze tabel aan te passen.',
|
||||
'Saving' => 'Opslaan',
|
||||
'Unknown error.' => 'Onbekende fout',
|
||||
'Unknown error.' => 'Onbekende fout.',
|
||||
'Database does not support password.' => 'Database ondersteunt het wachtwoord niet.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Schakel %s uit or schakel extensies %s of %s in.',
|
||||
'yes' => 'ja',
|
||||
|
@@ -9,11 +9,14 @@ $translations = array(
|
||||
'Password' => 'Hasło',
|
||||
'Permanent login' => 'Zapamiętaj sesję',
|
||||
'Login' => 'Zaloguj się',
|
||||
'Logout' => 'Wyloguj',
|
||||
'Logout' => 'Wyloguj się',
|
||||
'Logged as: %s' => 'Zalogowany jako: %s',
|
||||
'Logout successful.' => 'Wylogowano pomyślnie.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ proszę <a href="https://www.adminer.org/pl/donation/">dotację</a>.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ <a href="https://www.adminer.org/pl/donation/">dotację</a>.',
|
||||
'Invalid credentials.' => 'Nieprawidłowe dane logowania.',
|
||||
'There is a space in the input password which might be the cause.' => 'W haśle wejściowym znajduje się spacja, która może być przyczyną.',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer nie obsługuje dostępu do bazy danych bez hasła, <a href="https://www.adminer.org/pl/password/"%s>więcej informacji</a>.',
|
||||
'Database does not support password.' => 'Baza danych nie obsługuje hasła.',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('Za dużo nieudanych prób logowania, spróbuj ponownie za %d minutę.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minuty.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minut.'),
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ważność hasła głównego wygasła. <a href="https://www.adminer.org/pl/extension/"%s>Zaimplementuj</a> własną metodę %s, aby ustawić je na stałe.',
|
||||
'Language' => 'Język',
|
||||
@@ -22,8 +25,10 @@ $translations = array(
|
||||
'No extension' => 'Brak rozszerzenia',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Żadne z rozszerzeń PHP umożliwiających połączenie się z bazą danych (%s) nie jest dostępne.',
|
||||
'Connecting to privileged ports is not allowed.' => 'Łączenie do portów uprzywilejowanych jest niedozwolone.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Wyłącz %s lub włącz rozszerzenia %s lub %s.',
|
||||
'Session support must be enabled.' => 'Wymagana jest obsługa sesji w PHP.',
|
||||
'Session expired, please login again.' => 'Sesja wygasła, zaloguj się ponownie.',
|
||||
'The action will be performed after successful login with the same credentials.' => 'Czynność zostanie wykonana po pomyślnym zalogowaniu przy użyciu tych samych danych logowania.',
|
||||
'%s version: %s through PHP extension %s' => 'Wersja %s: %s za pomocą %s',
|
||||
'Refresh' => 'Odśwież',
|
||||
|
||||
@@ -53,6 +58,8 @@ $translations = array(
|
||||
'Query executed OK, %d row(s) affected.' => array('Zapytanie wykonane pomyślnie, zmieniono %d rekord.', 'Zapytanie wykonane pomyślnie, zmieniono %d rekordy.', 'Zapytanie wykonane pomyślnie, zmieniono %d rekordów.'),
|
||||
'No commands to execute.' => 'Nic do wykonania.',
|
||||
'Error in query' => 'Błąd w zapytaniu',
|
||||
'Unknown error.' => 'Nieznany błąd.',
|
||||
'Warnings' => 'Ostrzeżenia',
|
||||
'ATTACH queries are not supported.' => 'Zapytania ATTACH są niewspierane.',
|
||||
'Execute' => 'Wykonaj',
|
||||
'Stop on error' => 'Zatrzymaj w przypadku błędu',
|
||||
@@ -75,7 +82,7 @@ $translations = array(
|
||||
'You can upload a big SQL file via FTP and import it from server.' => 'Większe pliki SQL możesz wgrać na serwer poprzez FTP przed zaimportowaniem.',
|
||||
'You are offline.' => 'Jesteś offline.',
|
||||
|
||||
'Export' => 'Eksport',
|
||||
'Export' => 'Eksportuj',
|
||||
'Output' => 'Rezultat',
|
||||
'open' => 'otwórz',
|
||||
'save' => 'zapisz',
|
||||
@@ -83,6 +90,7 @@ $translations = array(
|
||||
'Data' => 'Dane',
|
||||
|
||||
'Database' => 'Baza danych',
|
||||
'DB' => 'BD',
|
||||
'Use' => 'Wybierz',
|
||||
'Select database' => 'Wybierz bazę danych',
|
||||
'Invalid database.' => 'Nie znaleziono bazy danych.',
|
||||
@@ -120,6 +128,7 @@ $translations = array(
|
||||
'Tables have been moved.' => 'Tabele zostały przeniesione.',
|
||||
'Copy' => 'Kopiuj',
|
||||
'Tables have been copied.' => 'Tabele zostały skopiowane.',
|
||||
'overwrite' => 'nadpisz',
|
||||
|
||||
'Routines' => 'Procedury i funkcje',
|
||||
'Routine has been called, %d row(s) affected.' => array('Procedura została uruchomiona, zmieniono %d rekord.', 'Procedura została uruchomiona, zmieniono %d rekordy.', 'Procedura została uruchomiona, zmieniono %d rekordów.'),
|
||||
@@ -165,15 +174,15 @@ $translations = array(
|
||||
'Column name' => 'Nazwa kolumny',
|
||||
'Type' => 'Typ',
|
||||
'Length' => 'Długość',
|
||||
'Auto Increment' => 'Auto Increment',
|
||||
'Auto Increment' => 'Automatyczny przyrost',
|
||||
'Options' => 'Opcje',
|
||||
'Comment' => 'Komentarz',
|
||||
'Default value' => 'Wartość domyślna',
|
||||
'Default values' => 'Wartości domyślne',
|
||||
'Drop' => 'Usuń',
|
||||
'Drop %s?' => 'Usunąć %s?',
|
||||
'Are you sure?' => 'Czy jesteś pewien?',
|
||||
'Size' => 'Wielkość',
|
||||
'Are you sure?' => 'Czy na pewno?',
|
||||
'Size' => 'Rozmiar',
|
||||
'Compute' => 'Oblicz',
|
||||
'Move up' => 'Przesuń w górę',
|
||||
'Move down' => 'Przesuń w dół',
|
||||
@@ -253,14 +262,14 @@ $translations = array(
|
||||
'Whole result' => 'Wybierz wszystkie',
|
||||
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtów'),
|
||||
|
||||
'Import' => 'Import',
|
||||
'Import' => 'Importuj',
|
||||
'%d row(s) have been imported.' => array('%d rekord został zaimportowany.', '%d rekordy zostały zaimportowane.', '%d rekordów zostało zaimportowanych.'),
|
||||
'File must be in UTF-8 encoding.' => 'Kodowanie pliku musi być ustawione na UTF-8.',
|
||||
|
||||
// in-place editing in select
|
||||
'Modify' => 'Zmień',
|
||||
'Ctrl+click on a value to modify it.' => 'Ctrl+kliknij wartość, aby ją edytować.',
|
||||
'Use edit link to modify this value.' => 'Użyj linku edycji aby zmienić tę wartość.',
|
||||
'Use edit link to modify this value.' => 'Użyj linku edycji, aby zmienić tę wartość.',
|
||||
|
||||
// %s can contain auto-increment value
|
||||
'Item%s has been inserted.' => 'Rekord%s został dodany.',
|
||||
@@ -281,7 +290,7 @@ $translations = array(
|
||||
'Selected' => 'Zaznaczone',
|
||||
'Clone' => 'Duplikuj',
|
||||
'Delete' => 'Usuń',
|
||||
'You have no privileges to update this table.' => 'Brak uprawnień do edycji tej tabeli',
|
||||
'You have no privileges to update this table.' => 'Brak uprawnień do edycji tej tabeli.',
|
||||
|
||||
'E-mail' => 'E-mail',
|
||||
'From' => 'Nadawca',
|
||||
@@ -338,4 +347,12 @@ $translations = array(
|
||||
'Type has been dropped.' => 'Typ został usunięty.',
|
||||
'Type has been created.' => 'Typ został utworzony.',
|
||||
'Alter type' => 'Zmień typ',
|
||||
|
||||
// Table check constraints
|
||||
'Checks' => 'Kontrole',
|
||||
'Create check' => 'Utwórz kontrolę',
|
||||
'Alter check' => 'Zmień kontrolę',
|
||||
'Check has been created.' => 'Kontrola została utworzona.',
|
||||
'Check has been altered.' => 'Kontrola została zmieniona.',
|
||||
'Check has been dropped.' => 'Kontrola została usunięta.',
|
||||
);
|
||||
|
@@ -261,7 +261,7 @@ $translations = array(
|
||||
'Please use one of the extensions %s.' => 'Folosiți una din următoarele extensii %s.',
|
||||
'now' => 'acum',
|
||||
'ltr' => 'ltr',
|
||||
'Tables have been copied.' => 'Tabelele au fost copiate',
|
||||
'Tables have been copied.' => 'Tabelele au fost copiate.',
|
||||
'Copy' => 'Copiază',
|
||||
'Permanent link' => 'Adresă permanentă',
|
||||
'Edit all' => 'Editează tot',
|
||||
|
@@ -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á.',
|
||||
);
|
||||
|
@@ -16,7 +16,7 @@ $translations = array(
|
||||
'Language' => 'Језик',
|
||||
'Invalid CSRF token. Send the form again.' => 'Неважећи CSRF код. Проследите поново форму.',
|
||||
'No extension' => 'Без додатака',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Ниједан од подржаних PHP додатака није доступан.',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Ниједан од подржаних PHP додатака (%s) није доступан.',
|
||||
'Session support must be enabled.' => 'Морате омогућити подршку за сесије.',
|
||||
'Session expired, please login again.' => 'Ваша сесија је истекла, пријавите се поново.',
|
||||
'%s version: %s through PHP extension %s' => '%s верзија: %s помоћу PHP додатка је %s',
|
||||
|
@@ -229,7 +229,7 @@ $translations = array(
|
||||
'Create sequence' => 'வரிசைமுறையை உருவாக்கு',
|
||||
'User types' => 'பயனாளர் வகைகள்',
|
||||
'Create type' => 'வகையை உருவாக்கு',
|
||||
'Item%s has been inserted.' => 'உருப்படி (Item) சேர்க்கப்பட்டது.',
|
||||
'Item%s has been inserted.' => 'உருப்படி (Item%s) சேர்க்கப்பட்டது.',
|
||||
'Schema has been dropped.' => 'அமைப்புமுறை நீக்கப்பட்டது.',
|
||||
'Schema has been created.' => 'அமைப்புமுறை உருவாக்கப்பட்டது.',
|
||||
'Schema has been altered.' => 'அமைப்புமுறை மாற்றப்பட்டது.',
|
||||
|
@@ -58,7 +58,7 @@ $translations = array(
|
||||
'ATTACH queries are not supported.' => 'ATTACH sorguları desteklenmiyor.',
|
||||
'Execute' => 'Çalıştır',
|
||||
'Stop on error' => 'Hata oluşursa dur',
|
||||
'Show only errors' => 'Sadece hataları göster.',
|
||||
'Show only errors' => 'Sadece hataları göster',
|
||||
// sprintf() format for time of the command
|
||||
'%.3f s' => '%.3f s',
|
||||
'History' => 'Geçmiş',
|
||||
@@ -225,7 +225,7 @@ $translations = array(
|
||||
'Trigger has been dropped.' => 'Tetik silindi.',
|
||||
'Trigger has been altered.' => 'Tetik değiştirildi.',
|
||||
'Trigger has been created.' => 'Tetik oluşturuldu.',
|
||||
'Alter trigger' => 'Tetiği değiştir.',
|
||||
'Alter trigger' => 'Tetiği değiştir',
|
||||
'Create trigger' => 'Tetik oluştur',
|
||||
'Time' => 'Zaman',
|
||||
'Event' => 'Olay',
|
||||
|
@@ -61,7 +61,7 @@ $translations = array(
|
||||
|
||||
'File upload' => 'Tải tệp lên',
|
||||
'From server' => 'Dùng tệp trên máy chủ',
|
||||
'Webserver file %s' => 'Tệp trên máy chủ',
|
||||
'Webserver file %s' => 'Tệp trên máy chủ %s',
|
||||
'Run file' => 'Chạy tệp',
|
||||
'File does not exist.' => 'Tệp không tồn tại.',
|
||||
'File uploads are disabled.' => 'Chức năng tải tệp lên đã bị cấm.',
|
||||
|
@@ -18,11 +18,12 @@ $translations = array(
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Xx, <a href="https://www.adminer.org/en/password/"%s>xx</a>.',
|
||||
'Database does not support password.' => 'Xx.',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => array('Xx %d.', 'Xx %d.'),
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '<a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Xx. <a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
|
||||
'Language' => 'Xx',
|
||||
'Invalid CSRF token. Send the form again.' => 'Xx.',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Xx.',
|
||||
'No extension' => 'Xx',
|
||||
// %s contains the list of the extensions, e.g. 'mysqli, PDO_MySQL'
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Xx (%s).',
|
||||
'Connecting to privileged ports is not allowed.' => 'Xx.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Xx %s xx %s xx %s xx.',
|
||||
@@ -33,7 +34,7 @@ $translations = array(
|
||||
'Refresh' => 'Xx',
|
||||
|
||||
// text direction - 'ltr' or 'rtl'
|
||||
'ltr' => 'xx',
|
||||
'ltr' => 'ltr',
|
||||
|
||||
'Privileges' => 'Xx',
|
||||
'Create user' => 'Xx',
|
||||
@@ -254,6 +255,7 @@ $translations = array(
|
||||
'Full table scan' => 'Xx',
|
||||
'Unable to select the table' => 'Xx',
|
||||
'No rows.' => 'Xx.',
|
||||
// used in SQL query limit and it is followed by another number, e.g. '10 / 50 rows' meaning 10 of 50 rows
|
||||
'%d / ' => '%d / ',
|
||||
'%d row(s)' => array('%d xx', '%d xx'),
|
||||
'Page' => 'Xx',
|
||||
@@ -272,7 +274,7 @@ $translations = array(
|
||||
'Ctrl+click on a value to modify it.' => 'Xx.',
|
||||
'Use edit link to modify this value.' => 'Xx.',
|
||||
|
||||
// %s can contain auto-increment value
|
||||
// %s can contain auto-increment value, e.g. ' 123'
|
||||
'Item%s has been inserted.' => 'Xx%s.',
|
||||
'Item has been deleted.' => 'Xx.',
|
||||
'Item has been updated.' => 'Xx.',
|
||||
|
@@ -12,10 +12,10 @@ $translations = array(
|
||||
'Logout' => '登出',
|
||||
'Logged as: %s' => '登錄為: %s',
|
||||
'Logout successful.' => '成功登出。',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感謝使用Adminer,請考慮為我們<a href="https://www.adminer.org/en/donation/">捐款(英文網頁)</a>.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感謝使用Adminer,請考慮為我們<a href="https://www.adminer.org/en/donation/">捐款(英文網頁)</a>。',
|
||||
'Invalid credentials.' => '無效的憑證。',
|
||||
'There is a space in the input password which might be the cause.' => '您輸入的密碼中有一個空格,這可能是導致問題的原因。',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer預設不支援訪問沒有密碼的資料庫,<a href="https://www.adminer.org/en/password/"%s>詳情見這裡</a>.',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer預設不支援訪問沒有密碼的資料庫,<a href="https://www.adminer.org/en/password/"%s>詳情見這裡</a>。',
|
||||
'Database does not support password.' => '資料庫不支援密碼。',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => '登錄失敗次數過多,請 %d 分鐘後重試。',
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '主密碼已過期。<a href="https://www.adminer.org/en/extension/"%s>請擴展</a> %s 方法讓它永久化。',
|
||||
@@ -47,7 +47,7 @@ $translations = array(
|
||||
'Revoke' => '廢除',
|
||||
|
||||
'Process list' => '處理程序列表',
|
||||
'%d process(es) have been killed.' => '%d 個 Process(es) 被終止',
|
||||
'%d process(es) have been killed.' => '%d 個 Process(es) 被終止。',
|
||||
'Kill' => '終止',
|
||||
|
||||
'Variables' => '變數',
|
||||
@@ -74,10 +74,10 @@ $translations = array(
|
||||
'From server' => '從伺服器',
|
||||
'Webserver file %s' => '網頁伺服器檔案 %s',
|
||||
'Run file' => '執行檔案',
|
||||
'File does not exist.' => '檔案不存在',
|
||||
'File does not exist.' => '檔案不存在。',
|
||||
'File uploads are disabled.' => '檔案上傳已經被停用。',
|
||||
'Unable to upload a file.' => '無法上傳檔案。',
|
||||
'Maximum allowed file size is %sB.' => '允許的檔案上限大小為 %sB',
|
||||
'Maximum allowed file size is %sB.' => '允許的檔案上限大小為 %sB。',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST 資料太大。減少資料或者增加 %s 的設定值。',
|
||||
'You can upload a big SQL file via FTP and import it from server.' => '您可以通過FTP上傳大型SQL檔並從伺服器導入。',
|
||||
'You are offline.' => '您離線了。',
|
||||
@@ -128,11 +128,11 @@ $translations = array(
|
||||
'Move' => '轉移',
|
||||
'Tables have been moved.' => '已轉移資料表。',
|
||||
'Copy' => '複製',
|
||||
'Tables have been copied.' => '資料表已經複製',
|
||||
'Tables have been copied.' => '資料表已經複製。',
|
||||
'overwrite' => '覆蓋',
|
||||
|
||||
'Routines' => '程序',
|
||||
'Routine has been called, %d row(s) affected.' => '程序已被執行,%d 行被影響',
|
||||
'Routine has been called, %d row(s) affected.' => '程序已被執行,%d 行被影響。',
|
||||
'Call' => '呼叫',
|
||||
'Parameter name' => '參數名稱',
|
||||
'Create procedure' => '建立預存程序',
|
||||
@@ -274,7 +274,7 @@ $translations = array(
|
||||
|
||||
// %s can contain auto-increment value
|
||||
'Item%s has been inserted.' => '已新增項目 %s。',
|
||||
'Item has been deleted.' => '該項目已被刪除',
|
||||
'Item has been deleted.' => '該項目已被刪除。',
|
||||
'Item has been updated.' => '已更新項目。',
|
||||
'%d item(s) have been affected.' => '%d 個項目受到影響。',
|
||||
'New item' => '新增項目',
|
||||
|
@@ -12,10 +12,10 @@ $translations = array(
|
||||
'Logout' => '登出',
|
||||
'Logged as: %s' => '登录用户:%s',
|
||||
'Logout successful.' => '成功登出。',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感谢使用Adminer,请考虑为我们<a href="https://www.adminer.org/en/donation/">捐款(英文页面)</a>.',
|
||||
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感谢使用Adminer,请考虑为我们<a href="https://www.adminer.org/en/donation/">捐款(英文页面)</a>。',
|
||||
'Invalid credentials.' => '无效凭据。',
|
||||
'There is a space in the input password which might be the cause.' => '您输入的密码中有一个空格,这可能是导致问题的原因。',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer默认不支持访问没有密码的数据库,<a href="https://www.adminer.org/en/password/"%s>详情见这里</a>.',
|
||||
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer默认不支持访问没有密码的数据库,<a href="https://www.adminer.org/en/password/"%s>详情见这里</a>。',
|
||||
'Database does not support password.' => '数据库不支持密码。',
|
||||
'Too many unsuccessful logins, try again in %d minute(s).' => '登录失败次数过多,请 %d 分钟后重试。',
|
||||
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '主密码已过期。<a href="https://www.adminer.org/en/extension/"%s>请扩展</a> %s 方法让它永久化。',
|
||||
@@ -47,7 +47,7 @@ $translations = array(
|
||||
'Revoke' => '废除',
|
||||
|
||||
'Process list' => '进程列表',
|
||||
'%d process(es) have been killed.' => '%d 个进程被终止',
|
||||
'%d process(es) have been killed.' => '%d 个进程被终止。',
|
||||
'Kill' => '终止',
|
||||
|
||||
'Variables' => '变量',
|
||||
@@ -208,7 +208,7 @@ $translations = array(
|
||||
'Alter indexes' => '修改索引',
|
||||
'Add next' => '下一行插入',
|
||||
'Index Type' => '索引类型',
|
||||
'Column (length)' => '列(长度)',
|
||||
// 'Column (length)' => '列(长度)',
|
||||
|
||||
'Foreign keys' => '外键',
|
||||
'Foreign key' => '外键',
|
||||
|
@@ -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">
|
||||
|
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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", "?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,19 +7,28 @@ $indexes = indexes($TABLE);
|
||||
$fields = fields($TABLE);
|
||||
$foreign_keys = column_foreign_keys($TABLE);
|
||||
$oid = $table_status["Oid"];
|
||||
parse_str($_COOKIE["adminer_import"], $adminer_import);
|
||||
$adminer_import = get_settings("adminer_import");
|
||||
|
||||
$rights = array(); // privilege => 0
|
||||
$columns = array(); // selectable columns
|
||||
$search_columns = array(); // searchable columns
|
||||
$order_columns = array(); // searchable columns
|
||||
$text_length = null;
|
||||
foreach ($fields as $key => $field) {
|
||||
$name = $adminer->fieldName($field);
|
||||
$name_plain = html_entity_decode(strip_tags($name), ENT_QUOTES);
|
||||
if (isset($field["privileges"]["select"]) && $name != "") {
|
||||
$columns[$key] = html_entity_decode(strip_tags($name), ENT_QUOTES);
|
||||
$columns[$key] = $name_plain;
|
||||
if (is_shortable($field)) {
|
||||
$text_length = $adminer->selectLengthProcess();
|
||||
}
|
||||
}
|
||||
if (isset($field["privileges"]["where"]) && $name != "") {
|
||||
$search_columns[$key] = $name_plain;
|
||||
}
|
||||
if (isset($field["privileges"]["order"]) && $name != "") {
|
||||
$order_columns[$key] = $name_plain;
|
||||
}
|
||||
$rights += $field["privileges"];
|
||||
}
|
||||
|
||||
@@ -74,16 +83,15 @@ if ($_POST && !$error) {
|
||||
}
|
||||
$where_check = ($where_check ? "\nWHERE " . implode(" AND ", $where_check) : "");
|
||||
if ($_POST["export"]) {
|
||||
cookie("adminer_import", "output=" . urlencode($_POST["output"]) . "&format=" . urlencode($_POST["format"]));
|
||||
save_settings(array("output" => $_POST["output"], "format" => $_POST["format"]), "adminer_import");
|
||||
dump_headers($TABLE);
|
||||
$adminer->dumpTable($TABLE, "");
|
||||
$from = ($select ? implode(", ", $select) : "*")
|
||||
. convert_fields($columns, $fields, $select)
|
||||
. "\nFROM " . table($TABLE);
|
||||
$group_by = ($group && $is_group ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : "");
|
||||
if (!is_array($_POST["check"]) || $primary) {
|
||||
$query = "SELECT $from$where_check$group_by";
|
||||
} else {
|
||||
$query = "SELECT $from$where_check$group_by";
|
||||
if (is_array($_POST["check"]) && !$primary) {
|
||||
$union = array();
|
||||
foreach ($_POST["check"] as $val) {
|
||||
// where is not unique so OR can't be used
|
||||
@@ -92,6 +100,7 @@ if ($_POST && !$error) {
|
||||
$query = implode(" UNION ALL ", $union);
|
||||
}
|
||||
$adminer->dumpData($TABLE, "table", $query);
|
||||
$adminer->dumpFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -186,7 +195,7 @@ if ($_POST && !$error) {
|
||||
} elseif (!preg_match('~~u', $file)) {
|
||||
$error = lang('File must be in UTF-8 encoding.');
|
||||
} else {
|
||||
cookie("adminer_import", "output=" . urlencode($adminer_import["output"]) . "&format=" . urlencode($_POST["separator"]));
|
||||
save_settings(array("output" => $adminer_import["output"], "format" => $_POST["separator"]), "adminer_import");
|
||||
$result = true;
|
||||
$cols = array_keys($fields);
|
||||
preg_match_all('~(?>"[^"]*"|[^"\r\n]+)+~', $file, $matches);
|
||||
@@ -253,8 +262,8 @@ if (!$columns && support("table")) {
|
||||
echo '<input type="hidden" name="select" value="' . h($TABLE) . '">';
|
||||
echo "</div>\n";
|
||||
$adminer->selectColumnsPrint($select, $columns);
|
||||
$adminer->selectSearchPrint($where, $columns, $indexes);
|
||||
$adminer->selectOrderPrint($order, $columns, $indexes);
|
||||
$adminer->selectSearchPrint($where, $search_columns, $indexes);
|
||||
$adminer->selectOrderPrint($order, $order_columns, $indexes);
|
||||
$adminer->selectLimitPrint($limit);
|
||||
$adminer->selectLengthPrint($text_length);
|
||||
$adminer->selectActionPrint($indexes);
|
||||
@@ -262,7 +271,7 @@ if (!$columns && support("table")) {
|
||||
|
||||
$page = $_GET["page"];
|
||||
if ($page == "last") {
|
||||
$found_rows = $connection->result(count_rows($TABLE, $where, $is_group, $group));
|
||||
$found_rows = get_val(count_rows($TABLE, $where, $is_group, $group));
|
||||
$page = floor(max(0, $found_rows - 1) / $limit);
|
||||
}
|
||||
|
||||
@@ -309,7 +318,7 @@ if (!$columns && support("table")) {
|
||||
|
||||
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
|
||||
if ($_GET["page"] != "last" && $limit != "" && $group && $is_group && JUSH == "sql") {
|
||||
$found_rows = $connection->result(" SELECT FOUND_ROWS()"); // space to allow mysql.trace_mode
|
||||
$found_rows = get_val(" SELECT FOUND_ROWS()"); // space to allow mysql.trace_mode
|
||||
}
|
||||
|
||||
if (!$rows) {
|
||||
@@ -339,12 +348,15 @@ if (!$columns && support("table")) {
|
||||
$column = idf_escape($key);
|
||||
$href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($key);
|
||||
$desc = "&desc%5B0%5D=1";
|
||||
$sortable = isset($field["privileges"]["order"]);
|
||||
echo "<th id='th[" . h(bracket_escape($key)) . "]'>" . script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});", "");
|
||||
echo '<a href="' . h($href . ($order[0] == $column || $order[0] == $key || (!$order && $is_group && $group[0] == $column) ? $desc : '')) . '">'; // $order[0] == $key - COUNT(*)
|
||||
echo apply_sql_function($val["fun"], $name) . "</a>"; //! columns looking like functions
|
||||
$fun = apply_sql_function($val["fun"], $name); //! columns looking like functions
|
||||
echo ($sortable ? '<a href="' . h($href . ($order[0] == $column || $order[0] == $key || (!$order && $is_group && $group[0] == $column) ? $desc : '')) . '">' . "$fun</a>" : $fun); // $order[0] == $key - COUNT(*)
|
||||
echo "<span class='column hidden'>";
|
||||
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
|
||||
if (!$val["fun"]) {
|
||||
if ($sortable) {
|
||||
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
|
||||
}
|
||||
if (!$val["fun"] && isset($field["privileges"]["where"])) {
|
||||
echo '<a href="#fieldset-search" title="' . lang('Search') . '" class="text jsonly"> =</a>';
|
||||
echo script("qsl('a').onclick = partial(selectSearch, '" . js_escape($key) . "');");
|
||||
}
|
||||
@@ -440,8 +452,8 @@ 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"]);
|
||||
echo "<td id='$id'";
|
||||
$text = preg_match('~text|json|lob~', $field["type"]);
|
||||
echo "<td id='$id'" . (preg_match(number_type(), $field["type"]) && is_numeric(strip_tags($val)) ? " class='number'" : "");
|
||||
if (($_GET["modify"] && $editable) || $value !== null) {
|
||||
$h_value = h($value !== null ? $value : $row[$key]);
|
||||
echo ">" . ($text ? "<textarea name='$id' cols='30' rows='" . (substr_count($row[$key], "\n") + 1) . "'>$h_value</textarea>" : "<input name='$id' value='$h_value' size='$lengths[$key]'>");
|
||||
@@ -576,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>";
|
||||
|
@@ -2,9 +2,11 @@
|
||||
namespace Adminer;
|
||||
|
||||
if (!$error && $_POST["export"]) {
|
||||
save_settings(array("output" => $_POST["output"], "format" => $_POST["format"]), "adminer_import");
|
||||
dump_headers("sql");
|
||||
$adminer->dumpTable("", "");
|
||||
$adminer->dumpData("", "table", $_POST["query"]);
|
||||
$adminer->dumpFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -30,7 +32,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
|
||||
@@ -63,7 +65,7 @@ if (!$error && $_POST) {
|
||||
$errors = array();
|
||||
$parse = '[\'"' . (JUSH == "sql" ? '`#' : (JUSH == "sqlite" ? '`[' : (JUSH == "mssql" ? '[' : ''))) . ']|/\*|-- |$' . (JUSH == "pgsql" ? '|\$[^$]*\$' : '');
|
||||
$total_start = microtime(true);
|
||||
parse_str($_COOKIE["adminer_export"], $adminer_export);
|
||||
$adminer_export = get_settings("adminer_import"); // this doesn't offer SQL export so we match the import/export style at select
|
||||
$dump_format = $adminer->dumpFormat();
|
||||
unset($dump_format["sql"]);
|
||||
|
||||
@@ -88,8 +90,8 @@ if (!$error && $_POST) {
|
||||
$pattern = ($found == '/*' ? '\*/'
|
||||
: ($found == '[' ? ']'
|
||||
: (preg_match('~^-- |^#~', $found) ? "\n"
|
||||
: preg_quote($found) . ($c_style_escapes ? "|\\\\." : "")
|
||||
)));
|
||||
: preg_quote($found) . ($c_style_escapes ? "|\\\\." : "")))
|
||||
);
|
||||
|
||||
while (preg_match("($pattern|\$)s", $query, $match, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$s = $match[0][0];
|
||||
|
46
adminer/static/dark.css
Normal file
46
adminer/static/dark.css
Normal file
@@ -0,0 +1,46 @@
|
||||
/** @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; }
|
||||
tbody tr:hover td, tbody tr:hover th { background: #133553; }
|
||||
pre.jush { background: #11385a; }
|
||||
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; }
|
@@ -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,18 +48,16 @@ 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%; }
|
||||
.explain { white-space: pre; }
|
||||
.explain table { white-space: pre; }
|
||||
.icon { width: 18px; height: 18px; background-color: navy; }
|
||||
.icon:hover { background-color: red; }
|
||||
.size { width: 7ex; }
|
||||
|
@@ -665,7 +665,7 @@ function indexesAddColumn(prefix) {
|
||||
* @param string
|
||||
*/
|
||||
function sqlSubmit(form, root) {
|
||||
if (encodeURIComponent(form['query'].value).length < 2e3) {
|
||||
if (encodeURIComponent(form['query'].value).length < 500) {
|
||||
form.action = root
|
||||
+ '&sql=' + encodeURIComponent(form['query'].value)
|
||||
+ (form['limit'].value ? '&limit=' + +form['limit'].value : '')
|
||||
|
@@ -65,7 +65,7 @@ function mixin(target, source) {
|
||||
/** Add or remove CSS class
|
||||
* @param HTMLElement
|
||||
* @param string
|
||||
* @param [bool]
|
||||
* @param [boolean]
|
||||
*/
|
||||
function alterClass(el, className, enable) {
|
||||
if (el) {
|
||||
@@ -79,7 +79,7 @@ function alterClass(el, className, enable) {
|
||||
*/
|
||||
function toggle(id) {
|
||||
var el = qs('#' + id);
|
||||
el.className = (el.className == 'hidden' ? '' : 'hidden');
|
||||
alterClass(el, 'hidden', !/(^|\s)hidden(\s|$)/.test(el.className));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -880,16 +880,6 @@ function addEvent(el, action, handler) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Defer focusing element
|
||||
* @param HTMLElement
|
||||
*/
|
||||
function focus(el) {
|
||||
setTimeout(function () {
|
||||
// this has to be an anonymous function because Firefox passes some arguments to setTimeout callback
|
||||
el.focus();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/** Clone node and setup submit highlighting
|
||||
* @param HTMLElement
|
||||
* @return HTMLElement
|
||||
|
@@ -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"])
|
||||
|
@@ -56,7 +56,7 @@ if ($_POST && !$error) {
|
||||
$pass = $_POST["pass"];
|
||||
if ($pass != '' && !$_POST["hashed"] && !min_version(8)) {
|
||||
// compute hash in a separate query so that plain text password is not saved to history
|
||||
$pass = $connection->result("SELECT PASSWORD(" . q($pass) . ")");
|
||||
$pass = get_val("SELECT PASSWORD(" . q($pass) . ")");
|
||||
$error = !$pass;
|
||||
}
|
||||
|
||||
@@ -120,11 +120,11 @@ if ($_POST && !$error) {
|
||||
|
||||
page_header((isset($_GET["host"]) ? lang('Username') . ": " . h("$USER@$_GET[host]") : lang('Create user')), $error, array("privileges" => array('', lang('Privileges'))));
|
||||
|
||||
if ($_POST) {
|
||||
$row = $_POST;
|
||||
$row = $_POST;
|
||||
if ($row) {
|
||||
$grants = $new_grants;
|
||||
} else {
|
||||
$row = $_GET + array("host" => $connection->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)")); // create user on the same domain by default
|
||||
$row = $_GET + array("host" => get_val("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)")); // create user on the same domain by default
|
||||
$row["pass"] = $old_pass;
|
||||
if ($old_pass != "") {
|
||||
$row["hashed"] = true;
|
||||
@@ -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";
|
||||
|
315
changes.txt
315
changes.txt
@@ -1,22 +1,70 @@
|
||||
Adminer 5.0.6 (released 2025-03-17):
|
||||
Align numbers right (bug #912)
|
||||
Display comment in title of field
|
||||
Remember export setting at SQL command
|
||||
Shorten queries saved from SQL command to URL (bug #917)
|
||||
SQL textarea: Open help on Ctrl+click
|
||||
Security: Disallow writing temporary files to symlinks (bug SF-855)
|
||||
MariaDB: Display MariaDB instead of MySQL
|
||||
CSS: Dark mode syntax highlighting
|
||||
CSS: Dark input fields in dark mode
|
||||
Designs named adminer-dark.css use dark basic style
|
||||
Plugins: Add method syntaxHighlighting()
|
||||
|
||||
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 SF-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 SF-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 SF-884)
|
||||
CockroachDB: Add support via PostgreSQL driver
|
||||
Elasticsearch: Add support for "where" and "order" field privilege
|
||||
|
||||
Adminer 5.0.1 (released 2025-03-07):
|
||||
Fix bulk operations with tables
|
||||
Remove duplicate columns from select (bug #670)
|
||||
MariaDB: Fix link to status variable doc (bug #658)
|
||||
Fix bulk operations with tables (regression from 5.0.0)
|
||||
Remove duplicate columns from select (bug SF-670)
|
||||
MariaDB: Fix link to status variable doc (bug SF-658)
|
||||
PostgreSQL: Support indexes on materialized views (PR #467)
|
||||
Elasticsearch: Drop support for version < 7
|
||||
|
||||
Adminer 5.0.0 (released 2025-03-07):
|
||||
Speed up with disabled output buffering
|
||||
Allow creating generated columns (bug #857)
|
||||
Allow creating generated columns (bug SF-857)
|
||||
Don't autofocus computed fields in insert form
|
||||
Skip generated columns in multi-edit (bug #882)
|
||||
Skip generated columns in multi-edit (bug SF-882)
|
||||
MySQL: Display generated value in table structure
|
||||
MySQL: Drop support for MySQL 4
|
||||
PostgreSQL: Compute size of all databases (bug #881)
|
||||
PostgreSQL: Compute size of all databases (bug SF-881)
|
||||
PostgreSQL: Do not alter indexes with expressions
|
||||
PostgreSQL: Fix export of indexes with expressions (bug #768)
|
||||
PostgreSQL: Fix export of indexes with expressions (bug SF-768)
|
||||
PostgreSQL: Display ENUM types
|
||||
PostgreSQL: Export ENUM types (bug #587)
|
||||
PostgreSQL: Display ? instead of -1 rows in table overview (bug #883)
|
||||
PostgreSQL: Export ENUM types (bug SF-587)
|
||||
PostgreSQL: Display ? instead of -1 rows in table overview (bug SF-883)
|
||||
PostgreSQL: Show accessible databases to non-owners (regression from 4.9.1)
|
||||
PostgreSQL: Skip editing generated columns
|
||||
PostgreSQL, MS SQL, Oracle: Hide table actions for information_schema
|
||||
@@ -25,10 +73,10 @@ SQLite: Support generated columns
|
||||
SQLite: Add command Check tables
|
||||
SQLite: Display all rows of variable values
|
||||
SQLite: Remove support for SQLite version 2
|
||||
MS SQL: Support export (bug #480)
|
||||
MS SQL: Support export (bug SF-480)
|
||||
MS SQL: Display foreign keys ON UPDATE and ON DELETE
|
||||
MS SQL: Support computed columns
|
||||
MS SQL: Fix CSV import (bug #859)
|
||||
MS SQL: Fix CSV import (bug SF-859)
|
||||
MS SQL: Fix altering foreign key
|
||||
MS SQL PDO: Support offset
|
||||
MS SQL: Remove support for MSSQL extension
|
||||
@@ -47,28 +95,28 @@ Hide index column options by default
|
||||
Offer original values in multi-row editing (regression from 4.16.0)
|
||||
Print SQL errors as comments in export (regression from 3.2.0)
|
||||
MySQL, PostgreSQL, MS SQL: Support CHECK constraint
|
||||
MySQL: Show comments at routine call (bug #874)
|
||||
MySQL: Show comments at routine call (bug SF-874)
|
||||
MySQL: Don't offer empty enum value in edit
|
||||
MySQL 9+: Support vector type
|
||||
PostgreSQL: Link user defined types
|
||||
PostgreSQL: Constraint enum values in editing (bug #270)
|
||||
PostgreSQL: Constraint enum values in editing (bug SF-270)
|
||||
PostgreSQL: Export functions
|
||||
PostgreSQL 8+: Fix exporting table constraints
|
||||
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: Allow altering table in non-default schema (bug SF-405)
|
||||
MS SQL: Fix default values (bug SF-732, bug SF-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 SF-847)
|
||||
Mobile devices: Use device width
|
||||
|
||||
Adminer 4.16.0 (released 2025-02-20):
|
||||
MySQL: Fix saving bit(64) values (bug #839)
|
||||
PostgreSQL: Preserve whitespace in EXPLAIN (bug #827)
|
||||
MySQL: Fix saving bit(64) values (bug SF-839)
|
||||
PostgreSQL: Preserve whitespace in EXPLAIN (bug SF-827)
|
||||
PostgreSQL: Support SSL
|
||||
PostgreSQL: Support altering auto_increment (bug #761)
|
||||
SQLite: Fix altering forign keys (bug #841)
|
||||
SQLite: Fix expressions in default values (bug #860)
|
||||
MS SQL: Foreign keys in non-default schema (bug #833)
|
||||
PostgreSQL: Support altering auto_increment (bug SF-761)
|
||||
SQLite: Fix altering forign keys (bug SF-841)
|
||||
SQLite: Fix expressions in default values (bug SF-860)
|
||||
MS SQL: Foreign keys in non-default schema (bug SF-833)
|
||||
Oracle: Include tables granted by other user
|
||||
MongoDB: Execute commands against the selected DB
|
||||
|
||||
@@ -77,6 +125,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
|
||||
@@ -134,28 +183,28 @@ PostgreSQL: Don't reset table comments (regression from 4.2.0)
|
||||
PostgreSQL PDO: Allow editing rows identified by boolean column (PR #380)
|
||||
|
||||
Adminer 4.8.1 (released 2021-05-14):
|
||||
Internet Explorer or PDO in Adminer 4.7.8-4.8.0: Fix XSS in doc_link (bug #797)
|
||||
Fix more PHP 8 warnings (bug #781)
|
||||
Avoid PHP warnings with PDO drivers (bug #786, regression from 4.7.8)
|
||||
MySQL: Allow moving views to other DB and renaming DB with views (bug #783)
|
||||
Internet Explorer or PDO in Adminer 4.7.8-4.8.0: Fix XSS in doc_link (bug SF-797)
|
||||
Fix more PHP 8 warnings (bug SF-781)
|
||||
Avoid PHP warnings with PDO drivers (bug SF-786, regression from 4.7.8)
|
||||
MySQL: Allow moving views to other DB and renaming DB with views (bug SF-783)
|
||||
MariaDB: Do not treat sequences as views (PR #416)
|
||||
PostgreSQL: Support UPDATE OF triggers (bug #789)
|
||||
PostgreSQL: Support UPDATE OF triggers (bug SF-789)
|
||||
PostgreSQL: Support triggers with more events (OR)
|
||||
PostgreSQL: Fix parsing of foreign keys with non-ASCII column names
|
||||
PostgreSQL < 10 PDO: Avoid displaying GENERATED ALWAYS BY IDENTITY everywhere (bug #785, regression from 4.7.9)
|
||||
SQLite: Fix displayed types (bug #784, regression from 4.8.0)
|
||||
PostgreSQL < 10 PDO: Avoid displaying GENERATED ALWAYS BY IDENTITY everywhere (bug SF-785, regression from 4.7.9)
|
||||
SQLite: Fix displayed types (bug SF-784, regression from 4.8.0)
|
||||
|
||||
Adminer 4.8.0 (released 2021-02-10):
|
||||
Support function default values in insert (bug #713)
|
||||
Support function default values in insert (bug SF-713)
|
||||
Allow SQL pseudo-function in insert
|
||||
Skip date columns for non-date values in search anywhere
|
||||
Add DB version to comment in export
|
||||
Support PHP 8 in create table (regression from 4.7.9)
|
||||
MySQL 8: Fix EXPLAIN in SQL command
|
||||
PostgreSQL: Create PRIMARY KEY for auto increment columns
|
||||
PostgreSQL: Avoid exporting empty sequence last value (bug #768)
|
||||
PostgreSQL: Avoid exporting empty sequence last value (bug SF-768)
|
||||
PostgreSQL: Do not show triggers from other schemas (PR #412)
|
||||
PostgreSQL: Fix multi-parameter functions in default values (bug #736)
|
||||
PostgreSQL: Fix multi-parameter functions in default values (bug SF-736)
|
||||
PostgreSQL: Fix displaying NULL bytea fields
|
||||
PostgreSQL PDO: Do not select NULL function for false values in edit
|
||||
Oracle: Alter indexes
|
||||
@@ -166,21 +215,21 @@ MongoDB: Handle errors
|
||||
SimpleDB, Firebird, ClickHouse: Move to plugin
|
||||
|
||||
Adminer 4.7.9 (released 2021-02-07):
|
||||
Fix XSS in browsers which don't encode URL parameters (bug #775, regression from 4.7.0)
|
||||
Fix XSS in browsers which don't encode URL parameters (bug SF-775, regression from 4.7.0)
|
||||
Elasticsearch, ClickHouse: Do not print response if HTTP code is not 200
|
||||
Don't syntax highlight during IME composition (bug #747)
|
||||
Quote values with leading and trailing zeroes in CSV export (bug #777)
|
||||
Don't syntax highlight during IME composition (bug SF-747)
|
||||
Quote values with leading and trailing zeroes in CSV export (bug SF-777)
|
||||
Link URLs in SQL command (PR #411)
|
||||
Fix displayed foreign key columns from other DB (bug #766)
|
||||
Fix displayed foreign key columns from other DB (bug SF-766)
|
||||
Re-enable PHP warnings (regression from 4.7.8)
|
||||
MySQL: Do not export names in quotes with sql_mode='ANSI_QUOTES' (bug #749)
|
||||
MySQL: Do not export names in quotes with sql_mode='ANSI_QUOTES' (bug SF-749)
|
||||
MySQL: Avoid error in PHP 8 when connecting to socket (PR #409)
|
||||
MySQL: Don't quote default value of text fields (bug #779)
|
||||
MySQL: Don't quote default value of text fields (bug SF-779)
|
||||
PostgreSQL: Export all FKs after all CREATE TABLE (PR #351)
|
||||
PostgreSQL: Fix dollar-quoted syntax highlighting (bug #738)
|
||||
PostgreSQL: Fix dollar-quoted syntax highlighting (bug SF-738)
|
||||
PostgreSQL: Do not show view definition from other schema (PR #392)
|
||||
PostgreSQL: Use bigserial for bigint auto increment (bug #765, regression from 3.0.0)
|
||||
PostgreSQL PDO: Support PgBouncer, unsupport PostgreSQL < 9.1 (bug #771)
|
||||
PostgreSQL: Use bigserial for bigint auto increment (bug SF-765, regression from 3.0.0)
|
||||
PostgreSQL PDO: Support PgBouncer, unsupport PostgreSQL < 9.1 (bug SF-771)
|
||||
PostgreSQL 10: Support GENERATED ALWAYS BY IDENTITY (PR #386)
|
||||
PostgreSQL 10: Support partitioned tables (PR #396)
|
||||
PostgreSQL 11: Create PRIMARY KEY for auto increment columns
|
||||
@@ -188,12 +237,12 @@ SQLite: Set busy_timeout to 500
|
||||
MS SQL: Don't truncate comments to 30 chars (PR #376)
|
||||
Elasticsearch 6: Fix displaying type mapping (PR #402)
|
||||
MongoDB: Fix password-less check in the mongo extension (PR #405)
|
||||
Editor: Cast to string when searching (bug #325)
|
||||
Editor: Cast to string when searching (bug SF-325)
|
||||
Editor: Avoid trailing dot in export filename
|
||||
|
||||
Adminer 4.7.8 (released 2020-12-06):
|
||||
Support PHP 8
|
||||
Disallow connecting to privileged ports (bug #769)
|
||||
Disallow connecting to privileged ports (bug SF-769)
|
||||
|
||||
Adminer 4.7.7 (released 2020-05-11):
|
||||
Fix open redirect if Adminer is accessible at //adminer.php%2F@
|
||||
@@ -202,15 +251,15 @@ Adminer 4.7.6 (released 2020-01-31):
|
||||
Speed up alter table form (regression from 4.4.0)
|
||||
Fix clicking on non-input fields in alter table (regression from 4.6.2)
|
||||
Display time of procedure execution
|
||||
Disallow connecting to ports > 65535 (bug #730)
|
||||
Disallow connecting to ports > 65535 (bug SF-730)
|
||||
MySQL: Always set foreign_key_checks in export
|
||||
PostgreSQL: Support exporting views
|
||||
Editor: Fix focusing foreign key search in select
|
||||
|
||||
Adminer 4.7.5 (released 2019-11-13):
|
||||
Add id="" to cells with failed inline edit (bug #708)
|
||||
PostgreSQL: Fix getting default value in PostgreSQL 12 (bug #719)
|
||||
PostgreSQL, Oracle: Set schema for EXPLAIN queries in SQL command (bug #706)
|
||||
Add id="" to cells with failed inline edit (bug SF-708)
|
||||
PostgreSQL: Fix getting default value in PostgreSQL 12 (bug SF-719)
|
||||
PostgreSQL, Oracle: Set schema for EXPLAIN queries in SQL command (bug SF-706)
|
||||
ClickHouse: SQL command
|
||||
Swedish translation
|
||||
|
||||
@@ -218,40 +267,40 @@ Adminer 4.7.4 (released 2019-10-22):
|
||||
Fix XSS if Adminer is accessible at URL /data:
|
||||
|
||||
Adminer 4.7.3 (released 2019-08-27):
|
||||
Allow editing foreign keys pointing to tables in other database/schema (bug #694)
|
||||
Fix blocking of concurrent instances in PHP >7.2 (bug #703)
|
||||
MySQL: Speed up displaying tables in large databases (bug #700, regression from 4.7.2)
|
||||
MySQL: Allow editing rows identified by negative floats (bug #695)
|
||||
Allow editing foreign keys pointing to tables in other database/schema (bug SF-694)
|
||||
Fix blocking of concurrent instances in PHP >7.2 (bug SF-703)
|
||||
MySQL: Speed up displaying tables in large databases (bug SF-700, regression from 4.7.2)
|
||||
MySQL: Allow editing rows identified by negative floats (bug SF-695)
|
||||
MySQL: Skip editing generated columns
|
||||
SQLite: Quote strings stored in integer columns in export (bug #696)
|
||||
SQLite: Handle error in altering table (bug #697)
|
||||
SQLite: Quote strings stored in integer columns in export (bug SF-696)
|
||||
SQLite: Handle error in altering table (bug SF-697)
|
||||
SQLite: Allow setting auto increment for empty tables
|
||||
SQLite: Preserve auto increment when recreating table
|
||||
MS SQL: Support foreign keys to other DB
|
||||
MongoDB: Allow setting authSource from environment variable
|
||||
|
||||
Adminer 4.7.2 (released 2019-07-18):
|
||||
Do not attempt logging in without password (bug #676)
|
||||
Stretch footer over the whole table width (bug #624)
|
||||
Do not attempt logging in without password (bug SF-676)
|
||||
Stretch footer over the whole table width (bug SF-624)
|
||||
Allow overwriting tables when copying them
|
||||
Fix displaying SQL command after Save and continue edit
|
||||
Cache busting for adminer.css
|
||||
MySQL: Fix displaying multi-columns foreign keys (bug #675, regression from 4.7.0)
|
||||
MySQL: Fix creating users and changing password in MySQL 8 (bug #663)
|
||||
MySQL: Fix displaying multi-columns foreign keys (bug SF-675, regression from 4.7.0)
|
||||
MySQL: Fix creating users and changing password in MySQL 8 (bug SF-663)
|
||||
MySQL: Pass SRID to GeomFromText
|
||||
PostgreSQL: Fix setting column comments on new table
|
||||
PostgreSQL: Display definitions of materialized views (bug #682)
|
||||
PostgreSQL: Fix table status in PostgreSQL 12 (bug #683)
|
||||
PostgreSQL: Display definitions of materialized views (bug SF-682)
|
||||
PostgreSQL: Fix table status in PostgreSQL 12 (bug SF-683)
|
||||
MS SQL: Support comments
|
||||
Elasticsearch: Fix setting number of rows
|
||||
|
||||
Adminer 4.7.1 (released 2019-01-24):
|
||||
Display the tables scrollbar (bug #647)
|
||||
Remember visible columns in Create Table form (bug #493)
|
||||
Display the tables scrollbar (bug SF-647)
|
||||
Remember visible columns in Create Table form (bug SF-493)
|
||||
Add autocomplete attributes to login form
|
||||
PHP <5.4 compatibility even with ClickHouse enabled (regression from 4.7.0)
|
||||
SQLite: Hide server field in login form
|
||||
Editor: Allow disabling boolean fields in PostgreSQL (bug #640)
|
||||
Editor: Allow disabling boolean fields in PostgreSQL (bug SF-640)
|
||||
|
||||
Adminer 4.7.0 (released 2018-11-24):
|
||||
Simplify storing executed SQL queries to bookmarks
|
||||
@@ -259,16 +308,16 @@ Warn when using password with leading or trailing spaces
|
||||
Hide import from server if importServerPath() returns an empty string
|
||||
Fix inline editing of empty cells (regression from 4.6.3)
|
||||
Allow adding more than two indexes and forign key columns at a time (regression from 4.4.0)
|
||||
Avoid overwriting existing tables when copying tables (bug #642)
|
||||
Avoid overwriting existing tables when copying tables (bug SF-642)
|
||||
Fix function change with set data type
|
||||
Increase username maxlength to 80 (bug #623)
|
||||
Increase username maxlength to 80 (bug SF-623)
|
||||
Make maxlength in all fields a soft limit
|
||||
Make tables horizontally scrollable
|
||||
MySQL: Support foreign keys created with ANSI quotes (bug #620)
|
||||
MySQL: Recognize ON UPDATE current_timestamp() (bug #632, bug #638)
|
||||
MySQL: Descending indexes in MySQL 8 (bug #643)
|
||||
PostgreSQL: Quote array values in export (bug #621)
|
||||
PostgreSQL: Export DESC indexes (bug #639)
|
||||
MySQL: Support foreign keys created with ANSI quotes (bug SF-620)
|
||||
MySQL: Recognize ON UPDATE current_timestamp() (bug SF-632, bug SF-638)
|
||||
MySQL: Descending indexes in MySQL 8 (bug SF-643)
|
||||
PostgreSQL: Quote array values in export (bug SF-621)
|
||||
PostgreSQL: Export DESC indexes (bug SF-639)
|
||||
PostgreSQL: Support GENERATED BY DEFAULT AS IDENTITY in PostgreSQL 10
|
||||
MS SQL: Pass database when connecting
|
||||
ClickHouse: Connect, databases list, tables list, select, SQL command
|
||||
@@ -280,26 +329,26 @@ Copy triggers when copying table
|
||||
Stop session before connecting
|
||||
Simplify running slow queries
|
||||
Decrease timeout for running slow queries from 5 seconds to 2 seconds
|
||||
Fix displaying info about non-alphabetical objects (bug #599)
|
||||
Fix displaying info about non-alphabetical objects (bug SF-599)
|
||||
Use secure cookies on HTTP if session.cookie_secure is set
|
||||
PDO: Support binary fields download
|
||||
MySQL: Disallow LOAD DATA LOCAL INFILE
|
||||
MySQL: Use CONVERT() only when searching for non-ASCII (bug #603)
|
||||
MySQL: Order database names in MySQL 8 (bug #613)
|
||||
PostgreSQL: Fix editing data in views (bug #605, regression from 4.6.0)
|
||||
PostgreSQL: Do not cast date/time/number/uuid searches to text (bug #608)
|
||||
PostgreSQL: Export false as 0 in PDO (bug #619)
|
||||
MySQL: Use CONVERT() only when searching for non-ASCII (bug SF-603)
|
||||
MySQL: Order database names in MySQL 8 (bug SF-613)
|
||||
PostgreSQL: Fix editing data in views (bug SF-605, regression from 4.6.0)
|
||||
PostgreSQL: Do not cast date/time/number/uuid searches to text (bug SF-608)
|
||||
PostgreSQL: Export false as 0 in PDO (bug SF-619)
|
||||
MS SQL: Support port with sqlsrv
|
||||
Editor: Do not check boolean checkboxes with false in PostgreSQL (bug #607)
|
||||
Editor: Do not check boolean checkboxes with false in PostgreSQL (bug SF-607)
|
||||
|
||||
Adminer 4.6.2 (released 2018-02-20):
|
||||
Semi-transparent border on table actions
|
||||
Shorten JSON values in select (bug #594)
|
||||
Shorten JSON values in select (bug SF-594)
|
||||
Speed up alter table form (regression from 4.4.0)
|
||||
Store current version without authentication and in Editor
|
||||
PostgreSQL: Fix exporting string default values
|
||||
PostgreSQL: Fix exporting sequences in PostgreSQL 10
|
||||
PostgreSQL: Add IF EXISTS to DROP SEQUENCE in export (bug #595)
|
||||
PostgreSQL: Add IF EXISTS to DROP SEQUENCE in export (bug SF-595)
|
||||
Editor: Fix displaying of true boolean values (regression from 4.5.0)
|
||||
|
||||
Adminer 4.6.1 (released 2018-02-09):
|
||||
@@ -308,12 +357,12 @@ Speed up rendering of long tables (regression from 4.4.0)
|
||||
Display notification about performing action after relogin
|
||||
Add system tables help links
|
||||
MySQL: Support non-utf8 charset in search in column
|
||||
MySQL: Support geometry in MySQL 8 (bug #574)
|
||||
MySQL: Support geometry in MySQL 8 (bug SF-574)
|
||||
MariaDB: Links to documentation
|
||||
SQLite: Allow deleting PRIMARY KEY from tables with auto increment
|
||||
PostgreSQL: Support binary files in bytea fields
|
||||
PostgreSQL: Don't treat interval type as number (bug #474)
|
||||
PostgreSQL: Cast to string when searching using LIKE (bug #325)
|
||||
PostgreSQL: Don't treat interval type as number (bug SF-474)
|
||||
PostgreSQL: Cast to string when searching using LIKE (bug SF-325)
|
||||
PostgreSQL: Fix condition for selecting no rows
|
||||
PostgreSQL: Support TRUNCATE+INSERT export
|
||||
Customization: Support connecting to MySQL via SSL
|
||||
@@ -334,34 +383,34 @@ MySQL: Add FIND_IN_SET search operator
|
||||
MariaDB: Support JSON since MariaDB 10.2
|
||||
SQLite, PostgreSQL: Limit rows in data manipulation without unique key
|
||||
PostgreSQL: Support routines
|
||||
PostgreSQL: Allow editing views with uppercase letters (bug #467)
|
||||
PostgreSQL: Allow now() as default value (bug #525)
|
||||
PostgreSQL: Allow editing views with uppercase letters (bug SF-467)
|
||||
PostgreSQL: Allow now() as default value (bug SF-525)
|
||||
SimpleDB: Document that allow_url_fopen is required
|
||||
Malay translation
|
||||
|
||||
Adminer 4.5.0 (released 2018-01-24):
|
||||
Display name of the object in confirmation when dropping it
|
||||
Display newlines in column comments (bug #573)
|
||||
Support current_timestamp() as default of time fields (bug #572)
|
||||
Hide window.opener from pages opened in a new window (bug #561)
|
||||
Display newlines in column comments (bug SF-573)
|
||||
Support current_timestamp() as default of time fields (bug SF-572)
|
||||
Hide window.opener from pages opened in a new window (bug SF-561)
|
||||
Display error when getting row to edit
|
||||
Store current Adminer version server-side to avoid excessive requests
|
||||
Adminer: Fix Search data in tables (regression from 4.4.0)
|
||||
CSP: Allow any styles, images, media and fonts, disallow base-uri
|
||||
MySQL: Support geometry in MySQL 8 (bug #574)
|
||||
MySQL: Support routines with comments in parameters (bug #460)
|
||||
MariaDB: Support fulltext and spatial indexes in InnoDB (bug #583)
|
||||
MySQL: Support geometry in MySQL 8 (bug SF-574)
|
||||
MySQL: Support routines with comments in parameters (bug SF-460)
|
||||
MariaDB: Support fulltext and spatial indexes in InnoDB (bug SF-583)
|
||||
SQLite: Enable foreign key checks
|
||||
PostgreSQL: Respect NULL default value
|
||||
PostgreSQL: Display foreign tables (bug #576)
|
||||
PostgreSQL: Display foreign tables (bug SF-576)
|
||||
PostgreSQL: Do not export triggers if not requested
|
||||
PostgreSQL: Export DROP SEQUENCE if dropping table
|
||||
PostgreSQL: Display boolean values as code (bug #562)
|
||||
PostgreSQL: Display boolean values as code (bug SF-562)
|
||||
MS SQL: Support freetds
|
||||
non-MySQL: Avoid CONVERT() (bug #509)
|
||||
non-MySQL: Avoid CONVERT() (bug SF-509)
|
||||
Elasticsearch: Insert, update, delete
|
||||
MongoDB: Support mongodb PHP extension
|
||||
Editor: Fix displaying of false values in PostgreSQL (bug #568)
|
||||
Editor: Fix displaying of false values in PostgreSQL (bug SF-568)
|
||||
|
||||
Adminer 4.4.0 (released 2018-01-17):
|
||||
Add Content Security Policy
|
||||
@@ -381,7 +430,7 @@ Customization: Always send security headers
|
||||
Hebrew translation
|
||||
|
||||
Adminer 4.3.1 (released 2017-04-14):
|
||||
Fix permanent login after logout (bug #539)
|
||||
Fix permanent login after logout (bug SF-539)
|
||||
Fix SQL command autofocus (regression from 4.0.0)
|
||||
PostgreSQL: Support JSON and JSONB data types
|
||||
PostgreSQL: Fix index size computation in PostgreSQL < 9.0 (regression from 4.3.0)
|
||||
@@ -428,16 +477,16 @@ MySQL: Use utf8mb4 in export only if required
|
||||
SQLite: Use EXPLAIN QUERY PLAN in SQL query
|
||||
|
||||
Adminer 4.2.0 (released 2015-02-07):
|
||||
Fix XSS in login form (bug #436)
|
||||
Fix XSS in login form (bug SF-436)
|
||||
Allow limiting number of displayed rows in SQL command
|
||||
Fix reading routine column collations
|
||||
Unlock session in alter database
|
||||
Make master key unreadable to others (bug #410)
|
||||
Make master key unreadable to others (bug SF-410)
|
||||
Fix edit by long non-utf8 string
|
||||
Specify encoding for PHP 5.6 with invalid default_charset
|
||||
Fix saving NULL value, bug since Adminer 4.0.3
|
||||
Send 403 for auth error
|
||||
Report offline and other AJAX errors (bug #419)
|
||||
Report offline and other AJAX errors (bug SF-419)
|
||||
Don't alter table comment if not changed
|
||||
Add links to documentation on table status page
|
||||
Fix handling of 64 bit numbers in auto_increment
|
||||
@@ -445,7 +494,7 @@ Add referrer: never meta tag
|
||||
MySQL: Use utf8mb4 if available
|
||||
MySQL: Support foreign keys in NDB storage
|
||||
PostgreSQL: Materialized views
|
||||
SQLite: Support CURRENT_* default values (bug #417)
|
||||
SQLite: Support CURRENT_* default values (bug SF-417)
|
||||
Elasticsearch: Use where in select
|
||||
Firebird: Alpha version
|
||||
Danish translation
|
||||
@@ -458,9 +507,9 @@ Display edit form after error in clone or multi-edit
|
||||
Trim trailing non-breaking spaces in SQL textarea
|
||||
Display time of the select command
|
||||
Print elapsed time in HTML instead of SQL command comment
|
||||
Improve gzip export ratio (bug #387)
|
||||
Improve gzip export ratio (bug SF-387)
|
||||
Use rel="noreferrer" for external links, skip adminer.org redirect in WebKit
|
||||
MySQL: Fix enum types in routines (bug #391)
|
||||
MySQL: Fix enum types in routines (bug SF-391)
|
||||
MySQL: Fix editing rows by binary values, bug since Adminer 3.7.1
|
||||
MySQL: Respect daylight saving time in dump, bug since Adminer 3.6.4
|
||||
MySQL 5.6.5+: Support ON UPDATE on datatime column
|
||||
@@ -528,7 +577,7 @@ Adminer 3.7.1 (released 2013-06-29):
|
||||
Increase click target for checkboxes
|
||||
Use shadow for highlighting default button
|
||||
Don't use LIMIT 1 if inline updating unique row
|
||||
Don't check previous checkbox on added column in create table (bug #326)
|
||||
Don't check previous checkbox on added column in create table (bug SF-326)
|
||||
Order table list by name
|
||||
Verify UTF-8 encoding of CSV import
|
||||
Notify user about expired master password for permanent login
|
||||
@@ -539,8 +588,8 @@ Display error on invalid alter table and view pages
|
||||
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
|
||||
PostgreSQL: Handle timestamp types (bug SF-324)
|
||||
Korean translation
|
||||
|
||||
Adminer 3.7.0 (released 2013-05-19):
|
||||
Allow more SQL files to be uploaded at the same time
|
||||
@@ -552,17 +601,17 @@ Disable SQL export when applying functions in select
|
||||
Allow using lang() in plugins (customization)
|
||||
Remove bzip2 compression support
|
||||
Constraint memory used in TAR export
|
||||
Allow exporting views dependent on each other (bug #214)
|
||||
Fix resetting search (bug #318)
|
||||
Don't use LIMIT 1 if updating unique row (bug #320)
|
||||
Allow exporting views dependent on each other (bug SF-214)
|
||||
Fix resetting search (bug SF-318)
|
||||
Don't use LIMIT 1 if updating unique row (bug SF-320)
|
||||
Restrict editing rows without unique identifier to search results
|
||||
Display navigation below main content on mobile browsers
|
||||
Get number of rows on export page asynchronously
|
||||
Respect 'whole result' even if some rows are checked (bug #339 since Adminer 3.7.0)
|
||||
Respect 'whole result' even if some rows are checked (bug SF-339 since Adminer 3.7.0)
|
||||
MySQL: Optimize create table page and Editor navigation
|
||||
MySQL: Display bit type as binary number
|
||||
MySQL: Improve export of binary data types
|
||||
MySQL: Fix handling of POINT data type (bug #282)
|
||||
MySQL: Fix handling of POINT data type (bug SF-282)
|
||||
MySQL: Don't export binary and geometry columns twice in select
|
||||
MySQL: Fix EXPLAIN in MySQL < 5.1, bug since Adminer 3.6.4
|
||||
SQLite: Export views
|
||||
@@ -577,11 +626,11 @@ Recover original view, trigger, routine if creating fails
|
||||
Do not store plain text password to history in creating user
|
||||
Selectable ON UPDATE CURRENT_TIMESTAMP field in create table
|
||||
Open database to a new window after selecting it with Ctrl
|
||||
Clear column name after resetting search (bug #296)
|
||||
Explain partitions in SQL query (bug #294)
|
||||
Allow loading more data with inline edit (bug #299)
|
||||
Stay on the same page after deleting rows (bug #301)
|
||||
Respect checked tables in export filename (bug #133)
|
||||
Clear column name after resetting search (bug SF-296)
|
||||
Explain partitions in SQL query (bug SF-294)
|
||||
Allow loading more data with inline edit (bug SF-299)
|
||||
Stay on the same page after deleting rows (bug SF-301)
|
||||
Respect checked tables in export filename (bug SF-133)
|
||||
Respect PHP configuration max_input_vars
|
||||
Fix unsetting permanent login after logout
|
||||
Disable autocapitalize in identifiers on mobile browsers
|
||||
@@ -666,11 +715,11 @@ Ukrainian translation
|
||||
Bengali translation
|
||||
|
||||
Adminer 3.3.4 (released 2012-03-07):
|
||||
Foreign keys default actions (bug #188)
|
||||
Foreign keys default actions (bug SF-188)
|
||||
SET DEFAULT foreign key action
|
||||
Fix minor parser bug in SQL command with webserver file
|
||||
Ctrl+click on button opens form to a blank window
|
||||
Trim table and column names (bug #195)
|
||||
Trim table and column names (bug SF-195)
|
||||
Error message with no response from server in AJAX
|
||||
Esc to cancel AJAX request
|
||||
Move AJAX loading indicator to the right
|
||||
@@ -682,9 +731,9 @@ Ability to disable export (customization)
|
||||
Extensible list of databases (customization)
|
||||
MySQL: set autocommit after connect
|
||||
SQLite, PostgreSQL: vacuum
|
||||
SQLite, PostgreSQL: don't use LIKE for numbers (bug #202)
|
||||
SQLite, PostgreSQL: don't use LIKE for numbers (bug SF-202)
|
||||
PostgreSQL: fix alter foreign key
|
||||
PostgreSQL over PDO: connect if the eponymous database does not exist (bug #185)
|
||||
PostgreSQL over PDO: connect if the eponymous database does not exist (bug SF-185)
|
||||
Boolean search (Editor)
|
||||
Persian translation
|
||||
|
||||
@@ -712,8 +761,8 @@ Adminer 3.3.0 (released 2011-07-19):
|
||||
Use Esc to disable in-place edit
|
||||
Shortcut for database privileges
|
||||
Editable index names
|
||||
Append new index with auto index selection (bug #138)
|
||||
Preserve original timestamp value in multiple update (bug #158)
|
||||
Append new index with auto index selection (bug SF-138)
|
||||
Preserve original timestamp value in multiple update (bug SF-158)
|
||||
Bit type default value
|
||||
Display foreign key name in tooltip
|
||||
Display default column value in table overview
|
||||
@@ -727,7 +776,7 @@ Display foreign keys from other schemas (PostgreSQL)
|
||||
Pagination support (Oracle)
|
||||
Autocomplete for big foreign keys (Editor)
|
||||
Display name of the referenced record in PostgreSQL (Editor)
|
||||
Prefer NULL to empty string (Editor, bug #162)
|
||||
Prefer NULL to empty string (Editor, bug SF-162)
|
||||
Display searched columns (Editor)
|
||||
Customizable favicon (customization)
|
||||
Method name can return a link (customization)
|
||||
@@ -739,8 +788,8 @@ Fix AJAX history after reload
|
||||
|
||||
Adminer 3.2.1 (released 2011-03-23):
|
||||
Ability to save expression in edit
|
||||
Respect default database collation (bug #119)
|
||||
Don't export triggers without table (bug #123)
|
||||
Respect default database collation (bug SF-119)
|
||||
Don't export triggers without table (bug SF-123)
|
||||
Esc to focus next field in Tab textarea
|
||||
Send forms by Ctrl+Enter on <select>
|
||||
Enum editor and textarea Ctrl+Enter working in IE
|
||||
@@ -763,8 +812,8 @@ Get long texts and slow information by AJAX
|
||||
Most links and forms by AJAX in browsers with support for history.pushState
|
||||
Copy tables
|
||||
Ability to search by expression in select
|
||||
Export SQL command result (bug #99)
|
||||
Focus first field with insert (bug #106)
|
||||
Export SQL command result (bug SF-99)
|
||||
Focus first field with insert (bug SF-106)
|
||||
Permanent link in schema
|
||||
Display total time in show only errors mode in SQL command
|
||||
History: edit all
|
||||
@@ -777,7 +826,7 @@ Utilize oids in PostgreSQL
|
||||
Homepage customization
|
||||
Use IN for search in numeric fields (Editor)
|
||||
Use password input for _md5 and _sha1 fields (Editor)
|
||||
Work without session.use_cookies (bug #107)
|
||||
Work without session.use_cookies (bug SF-107)
|
||||
Fix saving schema to cookie in Opera
|
||||
Portuguese, Slovenian and Turkish translation
|
||||
|
||||
@@ -790,10 +839,10 @@ Recognize $$ strings in SQL command (PostgreSQL)
|
||||
Highlight and edit SQL command in processlist
|
||||
Always display all drivers
|
||||
Timestamp at the end of export
|
||||
Link to refresh database cache (bug #96)
|
||||
Link to refresh database cache (bug SF-96)
|
||||
Support for virtual foreign keys
|
||||
Disable XSS "protection" of IE8
|
||||
Immunity against zend.ze1_compatibility_mode (bug #86)
|
||||
Immunity against zend.ze1_compatibility_mode (bug SF-86)
|
||||
Fix last page with empty result set
|
||||
Arabic translation and RTL support
|
||||
Dual licensing: Apache or GPL
|
||||
@@ -841,7 +890,7 @@ Add Drop button to Alter pages (regression from 2.0.0)
|
||||
Link COUNT(*) result to listing
|
||||
Newlines in select query edit
|
||||
Return to referrer after edit
|
||||
Respect session.auto_start (bug #42)
|
||||
Respect session.auto_start (bug SF-42)
|
||||
|
||||
Adminer 2.3.0 (released 2010-02-26):
|
||||
Support for permanent login (customization required)
|
||||
@@ -870,7 +919,7 @@ Link URLs in select
|
||||
Display number of manipulated rows in JS confirm
|
||||
Set required memory in SQL command
|
||||
Fix removed default in ALTER
|
||||
Display whitespace in texts (bug #11)
|
||||
Display whitespace in texts (bug SF-11)
|
||||
ClickJacking protection in modern browsers
|
||||
E-mail attachments (Editor)
|
||||
Optional year in date (Editor)
|
||||
@@ -889,7 +938,7 @@ Use ON DUPLICATE KEY UPDATE for CSV import
|
||||
Print ALTER export instead of executing it
|
||||
Click on row selects it
|
||||
Fix Editor date format
|
||||
Fix long SQL query crash (bug #3)
|
||||
Fix long SQL query crash (bug SF-3)
|
||||
Speed up simple alter table
|
||||
Traditional Chinese translation
|
||||
|
||||
@@ -945,7 +994,7 @@ Use \n in SQL commands
|
||||
|
||||
phpMinAdmin 1.10.1 (released 2009-05-07):
|
||||
Highlight odd and hover rows
|
||||
Partition editing comfort (bug #12)
|
||||
Partition editing comfort (bug SF-12)
|
||||
Allow full length in limited int
|
||||
|
||||
phpMinAdmin 1.10.0 (released 2009-04-28):
|
||||
@@ -953,7 +1002,7 @@ Partitioning (MySQL 5.1)
|
||||
CSV import
|
||||
Plus and minus functions
|
||||
Option to stop on error in SQL command
|
||||
Cross links to select and table (bug #5), link new item
|
||||
Cross links to select and table (bug SF-5), link new item
|
||||
Suhosin compatibility
|
||||
Remove max_allowed_packet from export
|
||||
Read style from phpMinAdmin.css if exists
|
||||
@@ -1032,7 +1081,7 @@ phpMinAdmin 1.4.0 (released 2007-08-15):
|
||||
Privileges
|
||||
New design
|
||||
Dutch translation
|
||||
Use NULL for auto_increment (bug #1)
|
||||
Use NULL for auto_increment (bug SF-1)
|
||||
Fix dropping procedure parameters
|
||||
|
||||
phpMinAdmin 1.3.2 (released 2007-08-06):
|
||||
|
206
compile.php
206
compile.php
@@ -3,6 +3,7 @@
|
||||
include __DIR__ . "/adminer/include/version.inc.php";
|
||||
include __DIR__ . "/adminer/include/errors.inc.php";
|
||||
include __DIR__ . "/externals/JsShrink/jsShrink.php";
|
||||
include __DIR__ . "/externals/PhpShrink/phpShrink.php";
|
||||
|
||||
function add_apo_slashes($s) {
|
||||
return addcslashes($s, "\\'");
|
||||
@@ -36,31 +37,16 @@ function lang_ids($match) {
|
||||
}
|
||||
|
||||
function put_file($match) {
|
||||
global $project, $VERSION, $driver;
|
||||
global $project, $vendor;
|
||||
if (basename($match[2]) == '$LANG.inc.php') {
|
||||
return $match[0]; // processed later
|
||||
}
|
||||
$return = file_get_contents(__DIR__ . "/$project/$match[2]");
|
||||
$return = str_replace("namespace Adminer;\n", "", $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"]) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
exit;
|
||||
}
|
||||
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 365*24*60*60) . " GMT");
|
||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
||||
header("Cache-Control: immutable");
|
||||
'), $return, $count);
|
||||
if (!$count) {
|
||||
echo "adminer/file.inc.php: Caching headers placeholder not found\n";
|
||||
}
|
||||
}
|
||||
if ($driver && preg_match('~/drivers/~', $match[2])) {
|
||||
$return = preg_replace('~^if \(isset\(\$_GET\["' . $driver . '"]\)\) \{(.*)^}~ms', '\1', $return);
|
||||
$return = preg_replace('~namespace Adminer;\s*~', '', $return);
|
||||
if ($vendor && preg_match('~/drivers/~', $match[2])) {
|
||||
$return = preg_replace('~^if \(isset\(\$_GET\["' . $vendor . '"]\)\) \{(.*)^}~ms', '\1', $return);
|
||||
// check function definition in drivers
|
||||
if ($driver != "mysql") {
|
||||
if ($vendor != "mysql") {
|
||||
preg_match_all(
|
||||
'~\bfunction ([^(]+)~',
|
||||
preg_replace('~class Driver.*\n\t}~sU', '', file_get_contents(__DIR__ . "/adminer/drivers/mysql.inc.php")),
|
||||
@@ -88,10 +74,10 @@ header("Cache-Control: immutable");
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($functions["__construct"], $functions["__destruct"], $functions["set_charset"]);
|
||||
unset($functions["__construct"], $functions["__destruct"], $functions["set_charset"], $functions["fetch_column"]);
|
||||
foreach ($functions as $val) {
|
||||
if (!strpos($return, "$val(")) {
|
||||
fprintf(STDERR, "Missing $val in $driver\n");
|
||||
fprintf(STDERR, "Missing $val in $vendor\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,7 +106,7 @@ header("Cache-Control: immutable");
|
||||
|
||||
function lang(\$translation, \$number = null) {
|
||||
if (is_array(\$translation)) {
|
||||
\$pos = $match2[2]\t\t\t: " . (preg_match("~\\\$LANG == '$_SESSION[lang]'.* \\? (.+)\n~U", $match2[1], $match3) ? $match3[1] : "1") . '
|
||||
\$pos = $match2[2]\t\t\t: " . (preg_match("~'$_SESSION[lang]'.* \\? (.+)\n~U", $match2[1], $match3) ? $match3[1] : "1") . '
|
||||
);
|
||||
$translation = $translation[$pos];
|
||||
}
|
||||
@@ -212,126 +198,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 +224,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;
|
||||
}
|
||||
@@ -382,13 +242,13 @@ if ($_SERVER["argv"][1] == "editor") {
|
||||
array_shift($_SERVER["argv"]);
|
||||
}
|
||||
|
||||
$driver = "";
|
||||
$vendor = "";
|
||||
$driver_path = "/adminer/drivers/" . $_SERVER["argv"][1] . ".inc.php";
|
||||
if (!file_exists(__DIR__ . $driver_path)) {
|
||||
$driver_path = "/plugins/drivers/" . $_SERVER["argv"][1] . ".php";
|
||||
}
|
||||
if (file_exists(__DIR__ . $driver_path)) {
|
||||
$driver = $_SERVER["argv"][1];
|
||||
$vendor = $_SERVER["argv"][1];
|
||||
array_shift($_SERVER["argv"]);
|
||||
}
|
||||
|
||||
@@ -408,11 +268,13 @@ if ($_SERVER["argv"][1]) {
|
||||
|
||||
include __DIR__ . "/adminer/include/pdo.inc.php";
|
||||
include __DIR__ . "/adminer/include/driver.inc.php";
|
||||
$connection = new stdClass; // used in support()
|
||||
$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");
|
||||
if ($driver) {
|
||||
$_GET[$driver] = true; // to load the driver
|
||||
$file = preg_replace('~\*/~', "* @version $VERSION\n*/", $file, 1);
|
||||
if ($vendor) {
|
||||
$_GET[$vendor] = true; // to load the driver
|
||||
include_once __DIR__ . $driver_path;
|
||||
foreach ($features as $key => $feature) {
|
||||
if (!Adminer\support($feature)) {
|
||||
@@ -428,36 +290,39 @@ if ($driver) {
|
||||
}
|
||||
$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file);
|
||||
$file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file);
|
||||
if ($driver) {
|
||||
if ($vendor) {
|
||||
if (preg_match('~^/plugins/~', $driver_path)) {
|
||||
$file = preg_replace('((include "..)/adminer/drivers/mysql.inc.php)', "\\1$driver_path", $file);
|
||||
}
|
||||
$file = preg_replace('(include "../adminer/drivers/(?!' . preg_quote($driver) . '\.).*\s*)', '', $file);
|
||||
$file = preg_replace('(include "../adminer/drivers/(?!' . preg_quote($vendor) . '\.).*\s*)', '', $file);
|
||||
}
|
||||
$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php
|
||||
if ($driver) {
|
||||
if ($vendor) {
|
||||
foreach ($features as $feature) {
|
||||
if (!Adminer\support($feature)) {
|
||||
$file = preg_replace("((\t*)" . preg_quote('if (support("' . $feature . '")') . ".*?\n\\1\\}( else)?)s", '', $file);
|
||||
}
|
||||
}
|
||||
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 ($project != "editor" && count($drivers) == 1) {
|
||||
$file = str_replace('html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);")', "\"<input type='hidden' name='auth[driver]' value='" . ($vendor == "mysql" ? "server" : $vendor) . "'>" . reset($drivers) . "\"", $file, $count);
|
||||
if (!$count) {
|
||||
echo "auth[driver] form field not found\n";
|
||||
}
|
||||
$file = str_replace(" . script(\"qs('#username').form['auth[driver]'].onchange();\")", "", $file);
|
||||
if ($vendor == "sqlite") {
|
||||
$file = str_replace(");\n\t\techo \$this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name=\"auth[server]", ' . \'<input type="hidden" name="auth[server]"', $file);
|
||||
}
|
||||
}
|
||||
$file = preg_replace('(;\s*../externals/jush/modules/jush-(?!textarea\.|txt\.|js\.|' . preg_quote($driver == "mysql" ? "sql" : $driver) . '\.)[^.]+.js)', '', $file);
|
||||
$file = preg_replace_callback('~doc_link\(array\((.*)\)\)~sU', function ($match) use ($driver) {
|
||||
$file = preg_replace('(;\s*../externals/jush/modules/jush-(?!textarea\.|txt\.|js\.|' . preg_quote($vendor == "mysql" ? "sql" : $vendor) . '\.)[^.]+.js)', '', $file);
|
||||
$file = preg_replace_callback('~doc_link\(array\((.*)\)\)~sU', function ($match) use ($vendor) {
|
||||
list(, $links) = $match;
|
||||
$links = preg_replace("~'(?!(" . ($driver == "mysql" ? "sql|mariadb" : $driver) . ")')[^']*' => [^,]*,?~", '', $links);
|
||||
$links = preg_replace("~'(?!(" . ($vendor == "mysql" ? "sql|mariadb" : $vendor) . ")')[^']*' => [^,]*,?~", '', $links);
|
||||
return (trim($links) ? "doc_link(array($links))" : "''");
|
||||
}, $file);
|
||||
//! strip doc_link() definition
|
||||
}
|
||||
if ($project == "editor") {
|
||||
$file = preg_replace('~;.\.\/externals/jush/jush\.css~', '', $file);
|
||||
$file = preg_replace('~;.\.\/externals/jush/jush(-dark)?\.css~', '', $file);
|
||||
$file = preg_replace('~compile_file\(\'\.\./(externals/jush/modules/jush\.js|adminer/static/[^.]+\.gif)[^)]+\)~', "''", $file);
|
||||
}
|
||||
$file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file);
|
||||
@@ -469,18 +334,19 @@ 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 = preg_replace('~echo .*/jush(-dark)?.css\'>.*~', '', $file); // merged into default.css or dark.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/(default\.css)~', '<?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);
|
||||
if (function_exists('phpShrink')) {
|
||||
$file = phpShrink($file);
|
||||
}
|
||||
|
||||
$filename = $project . (preg_match('~-dev$~', $VERSION) ? "" : "-$VERSION") . ($driver ? "-$driver" : "") . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php";
|
||||
$filename = $project . (preg_match('~-dev$~', $VERSION) ? "" : "-$VERSION") . ($vendor ? "-$vendor" : "") . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php";
|
||||
file_put_contents($filename, $file);
|
||||
echo "$filename created (" . strlen($file) . " B).\n";
|
||||
|
@@ -6,8 +6,8 @@
|
||||
"database"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://sourceforge.net/p/adminer/bugs-and-features/",
|
||||
"forum": "https://sourceforge.net/p/adminer/discussion/",
|
||||
"issues": "https://github.com/vrana/adminer/issues",
|
||||
"forum": "https://github.com/vrana/adminer/discussions",
|
||||
"source": "https://github.com/vrana/adminer/"
|
||||
},
|
||||
"authors": [
|
||||
@@ -33,6 +33,7 @@
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "php compile.php"
|
||||
"clean": "rm -f adminer*.php editor*.php",
|
||||
"compile": "@php compile.php"
|
||||
}
|
||||
}
|
||||
|
33
coverage.php
33
coverage.php
@@ -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();
|
||||
@@ -22,19 +23,20 @@ function xhtml_open_tags($s) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
$coverage_filename = sys_get_temp_dir() . "/adminer_coverage.ser";
|
||||
$coverage_filename = sys_get_temp_dir() . "/adminer.coverage";
|
||||
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>
|
||||
|
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Dark Theme for Adminer by 'Muhammad Bilal Yameen' [github.com/bilal-yameen/dark-theme-for-adminer]
|
||||
*/
|
||||
html,body,header,footer,aside,menu,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;outline:0;border:none;background:transparent;font-size:10pt;font-weight:normal}
|
||||
ol,ul{list-style:none}
|
||||
blockquote,q{quotes:none}
|
||||
blockquote:before,blockquote:after,q:before,q:after{content:none}
|
||||
:focus{outline:0}
|
||||
ins{text-decoration:none}
|
||||
del{text-decoration:line-through}
|
||||
table{border-collapse:collapse;border-spacing:0}
|
||||
aside,menu{display:block}
|
||||
input[type='submit'],input[type='checkbox'],input[type='radio'],input[type='file'],select,label{cursor:pointer}
|
||||
input[disabled=""]{opacity:.5;cursor:not-allowed;color:#666 !important;border-color:#aaa !important}
|
||||
input[type='text']{-webkit-user-modify:read-write-plaintext-only}
|
||||
@font-face{font-family:'entypo';src:url('../fonts/entypo.eot');src:url('../fonts/entypo.eot?#iefix') format('embedded-opentype'),url('../fonts/entypo.woff') format('woff'),url('../fonts/entypo.ttf') format('truetype'),url('../fonts/entypo.svg#entypo') format('svg');font-weight:normal;font-style:normal}
|
||||
html{overflow-y:scroll;-webkit-text-size-adjust:none}
|
||||
body{font-family:"Helvetica Neue",Helvetica,Verdana,Arial,sans-serif;background:#22252a;color:#a5a8ad;width:100%}
|
||||
a,a:visited{padding:4px 0;color:#0c83d9;transition:color .1s ease 0s,background-color .1s ease 0s}
|
||||
a:link:hover,a:visited:hover{color:#0063a9;text-decoration:none}
|
||||
a sup{padding:0 5px}
|
||||
#logins a,#tables a,#tables span{background:none}
|
||||
.active:before{font-weight:normal}
|
||||
label{padding:3px 10px}
|
||||
input::-webkit-input-placeholder{color:#999}
|
||||
input::-moz-placeholder{color:#999}
|
||||
input:-ms-input-placeholder{color:#999}
|
||||
input:not([type]),input[type="text"],input[type="email"],input[type="password"],input[type="search"],input[type="number"],textarea,pre[contenteditable="true"],select{padding:4px 5px !important;border:1px solid #ccc !important;border-radius:2px;font-size:10pt;background:#202225;color:#a5a8ad;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
input:not([type]),input[type="text"],input[type="email"],input[type="password"],input[type="search"],input[type="number"],textarea{-webkit-appearance:none}
|
||||
input:not([type]),input[type="text"],input[type="email"],input[type="password"],input[type="search"],input[type="number"],select{height:28px}
|
||||
input[type="submit"]{display:inline-block;padding:7px 15px;border:1px solid #0c83d9;border-radius:2px;background:#0c83d9;color:#fff;text-align:center;text-decoration:none;font-size:10pt;transition:background-color .1s ease 0s;-webkit-appearance:none}
|
||||
input[type="submit"]:hover{background:#0063a9;border-color:#0063a9}
|
||||
input[type="submit"][disabled=""]:hover{background:#22252a}
|
||||
input[type="submit"].default{box-shadow:none}
|
||||
input[type="image"]{border:4px solid #22252a;outline:1px solid #0a83d9;-moz-outline-radius:2px;margin-right:5px}
|
||||
input[type="image"]:last-child{margin-right:0}
|
||||
input[type="image"]:hover{border-color:#282b2f}
|
||||
input[type="checkbox"],input[type="radio"]{margin:7px 5px 7px 0}
|
||||
fieldset{margin:5px 5px 10px 0;padding:5px 10px;border:1px solid rgba(255,255,255,0.1);border-radius:2px;background:#282b2f;min-height:55px}
|
||||
fieldset input[type="submit"]{padding:3px 10px;border-color:#0c83d9;background:#22252a;color:#0c83d9}
|
||||
fieldset input[type="submit"]:hover{background:#0c82d4;color:#fff}
|
||||
fieldset input[type="submit"].default{border-color:#0c83d9;background:#0c83d9;color:#22252a}
|
||||
fieldset input[type="submit"].default:hover{background:#0063a9;border-color:#0063a9}
|
||||
fieldset a{padding:6px 8px}
|
||||
fieldset+table,table+fieldset{margin-top:10px}
|
||||
fieldset legend a{position:relative;padding:4px 0 50px}
|
||||
fieldset>div>div,fieldset>div>p,fieldset>div>a,fieldset>div>code,fieldset>div>input,fieldset>div>select,fieldset>a{position:relative}
|
||||
legend{margin-bottom:3px}
|
||||
legend:before,legend:after{content:" "}
|
||||
p input,p select,p label,fieldset input,fieldset select{margin:0 5px 5px 0}
|
||||
.js fieldset>.hidden{display:block;margin-top:5px;text-align:center}
|
||||
.js fieldset>.hidden *{display:none !important}
|
||||
.js fieldset>.hidden:before{content:"⏶";font-family:"entypo",sans-serif;font-size:40pt;line-height:0;vertical-align:middle;color:#e2e2e2}
|
||||
#fieldset-select.hidden:before{content:"⚏"}
|
||||
#fieldset-search.hidden:before{content:"🔍"}
|
||||
#fieldset-sort.hidden:before{content:"⏷"}
|
||||
#fieldset-export.hidden:before{content:"📤"}
|
||||
#fieldset-import.hidden:before{content:"📥"}
|
||||
#fieldset-history.hidden:before{content:""}
|
||||
#fieldset-history br{display:block;margin-bottom:20px}
|
||||
#fieldset-history.hidden br{display:none}
|
||||
#fieldset-partition.hidden:before{content:""}
|
||||
.size{width:8ex}
|
||||
.sqlarea{width:100% !important;height:350px}
|
||||
@media only screen and (max-width:768px){
|
||||
input:not([type]),input[type="text"],input[type="email"],input[type="password"],input[type="search"],input[type="number"],textarea,pre[contenteditable="true"],select{font-size:12pt;vertical-align:-1px}
|
||||
input:not([type]),input[type="text"],input[type="email"],input[type="password"],input[type="search"],input[type="number"],select{height:32px}
|
||||
fieldset input[type="submit"]{padding:6px 15px}
|
||||
.sqlarea{height:250px}
|
||||
}
|
||||
@media only screen and (max-width:360px){
|
||||
input:not([type]),input[type="text"],input[type="email"],input[type="password"],input[type="search"],input[type="number"],textarea,pre[contenteditable="true"],select{width:100%}
|
||||
input[type="submit"],fieldset input[type="submit"]{padding-left:10px;padding-right:10px}
|
||||
}
|
||||
#lang{position:fixed;right:0;top:0;left:auto;border:none;padding:0 0 0 10px;width:190px;height:40px;line-height:30px;font-size:0;z-index:101;background:#282b2f}
|
||||
#lang select{padding:2px 3px;margin:6px 0;width:100px}
|
||||
.logout{position:fixed;right:10px;margin:0;z-index:101;overflow:hidden}
|
||||
.logout input[type="submit"]{border:none;margin:0;padding:0 10px;height:40px;background:transparent;color:#0c83d9}
|
||||
.logout input[type="submit"]:hover{background:transparent;color:#0063a9}
|
||||
@media only screen and (max-width:768px){
|
||||
#lang{position:static;left:0;top:0;width:auto;border-top:1px solid rgba(255,255,255,0.1);background:#282b2f}
|
||||
#lang select{margin:4px 10px 0 10px}
|
||||
.logout{position:relative;float:right;margin-top:-40px}
|
||||
}
|
||||
@media only screen and (max-width:360px){
|
||||
#lang select{margin-left:0}
|
||||
}
|
||||
#content{position:relative;margin:0 0 0 261px;padding:41px 20px 80px 20px}
|
||||
#content:before{position:fixed;left:0;top:0;content:"";display:block;width:100%;height:40px;background:#282b2f;border-bottom:1px solid rgba(255,255,255,0.1)}
|
||||
#content .links+p{color:#999}
|
||||
#breadcrumb{position:fixed;left:261px;top:0;right:0;margin:0;padding:0 0 0 20px;border-right:205px solid #282b2f;background:#282b2f;height:40px;line-height:40px;z-index:100;overflow:hidden;text-overflow:ellipsis}
|
||||
#breadcrumb a{display:inline-block;padding:0;height:40px;line-height:40px}
|
||||
h2{margin:20px 0;font-size:20pt;color:#a5a8ad}
|
||||
h3{margin:30px 0 10px 0;font-size:16pt}
|
||||
p{margin:10px 0}
|
||||
code{display:block;padding:10px;margin:5px 0;border-left:7px solid #58595a;border-radius:2px;background:#2d3135;overflow:auto}
|
||||
td code,th code,fieldset code:first-child{display:inline;margin:0;padding:0;background:none;border:none}
|
||||
pre code{margin:0}
|
||||
fieldset code+i{display:none}
|
||||
.time{margin-left:10px;float:right;font-size:8pt;color:#bbb}
|
||||
.error,.message{margin:20px 0;padding:10px;border-left:7px solid #cec}
|
||||
.error{color:#900;border-color:#ecc}
|
||||
.message pre{margin:15px 0 5px 0}
|
||||
.message p{margin:0 0 5px 0}
|
||||
pre+.message,pre+.error{margin-top:0}
|
||||
#help{z-index:200;border:1px solid rgba(255,255,255,0.1);border-radius:2px;background:#282b2f;padding:5px 7px}
|
||||
.icon{background-color:#0c83d9}
|
||||
.icon:hover{background-color:#0063a9}
|
||||
@media only screen and (max-width:768px){
|
||||
#content{margin-left:0}
|
||||
#breadcrumb{left:0;padding-left:50px;border-right-width:0}
|
||||
}
|
||||
@media only screen and (max-width:360px){
|
||||
#content{padding:41px 10px 20px}
|
||||
h2{margin:15px 0;font-size:16pt}
|
||||
}
|
||||
h1{height:40px;white-space:nowrap;overflow:hidden}
|
||||
h1 #h1{display:inline-block;padding:0;background:url("../images/logo.png?3") 10px center no-repeat;background-size:120px;text-indent:-100px;width:135px;height:40px}
|
||||
.version,#version{position:relative;top:-7px;vertical-align:bottom;font-size:8pt;font-style:italic;color:#bbb}
|
||||
#version{padding:5px;color:#0c83d9}
|
||||
#version:hover{color:#0063a9}
|
||||
#menu{position:fixed;left:0;top:0;bottom:0;width:260px;margin:0;padding:0;border-right:1px solid rgba(255,255,255,0.1);overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;background:#22252a;z-index:100}
|
||||
#menu p{padding:10px;border-bottom:none}
|
||||
#menu .links{background:#282b2f;border-bottom:1px solid rgba(255,255,255,0.1);padding:0 10px 7px 10px}
|
||||
#menu .message{background:transparent;border:none;border-bottom:1px solid rgba(255,255,255,0.1);color:#bbb}
|
||||
#filter-field{margin:0;width:100%}
|
||||
.menu-list{border-bottom:1px solid rgba(255,255,255,0.1) !important;padding:0 !important;margin-bottom:25px !important }
|
||||
.menu-link{display:block;padding:2px 10px;width:auto;height:20px;line-height:20px;color:#a5a8ad;overflow:hidden;text-overflow:ellipsis}
|
||||
.menu-link.active{background:#282b2f;color:#0c83d9}
|
||||
.menu-link.active:hover{background:#1b1f25}
|
||||
p#dbs{border-top:1px solid rgba(255,255,255,0.1);background:#282b2f;color:#282b2f;font-size:0}
|
||||
p#dbs span{font-size:0}
|
||||
p#dbs select{margin:0;width:100%}
|
||||
#tables{border-bottom:1px solid rgba(255,255,255,0.1) !important;padding:0 !important;margin-bottom:25px !important }
|
||||
#tables li{position:relative}
|
||||
#tables li:hover{background:#282b2f}
|
||||
#tables a strong{font-weight:bold}
|
||||
#tables a.structure{display:block;padding:2px 10px;width:auto;height:20px;line-height:20px;color:#a5a8ad;overflow:hidden;text-overflow:ellipsis;padding-right:0}
|
||||
#tables a.structure.active{background:#282b2f;color:#0c83d9}
|
||||
#tables a.structure.active:hover{background:#1b1f25}
|
||||
#tables a.select{position:absolute;right:0;top:0;display:block;padding:2px 7px;height:20px;line-height:20px;color:#999;overflow:hidden;width:16px}
|
||||
#tables a.select:before{content:"📄 ";font-family:entypo,sans-serif;font-size:24pt;line-height:0;vertical-align:-3px}
|
||||
#tables li:first-of-type a{padding-top:7px}
|
||||
#tables li:last-child a{padding-bottom:7px}
|
||||
#tables a.active+a{background:#282b2f;color:#0c83d9;font-weight:bold}
|
||||
#tables a.active+a:hover{background:#1b1f25}
|
||||
#tables a.active:hover+a{background:#1b1f25}
|
||||
#tables a:hover+a.active{background:#1b1f25}
|
||||
#tables br{display:none}
|
||||
#tables.simple a{display:block;padding:2px 10px;width:auto;height:20px;line-height:20px;color:#a5a8ad;overflow:hidden;text-overflow:ellipsis}
|
||||
#tables.simple a.active{background:#282b2f;color:#0c83d9}
|
||||
#tables.simple a.active:hover{background:#1b1f25}
|
||||
#logins{border-bottom:1px solid rgba(255,255,255,0.1) !important;padding:0 !important;margin-bottom:25px !important ;border-top:1px solid rgba(255,255,255,0.1)}
|
||||
#logins a{display:block;padding:2px 10px;width:auto;height:20px;line-height:20px;color:#a5a8ad;overflow:hidden;text-overflow:ellipsis}
|
||||
#logins a.active{background:#282b2f;color:#0c83d9}
|
||||
#logins a.active:hover{background:#1b1f25}
|
||||
#logins a:hover{background:#282b2f}
|
||||
#logins a:first-of-type{padding-top:7px}
|
||||
#logins a:last-of-type{padding-bottom:7px}
|
||||
#logins br{display:none}
|
||||
@media only screen and (max-width:768px){
|
||||
h1:before{float:left;position:relative;left:4px;top:4px;width:30px;height:30px;content:"☰";font-family:"entypo",sans-serif;font-size:32pt;line-height:30px;border:1px solid #0c83d9;border-radius:2px;text-align:center;vertical-align:middle;background:#22252a;cursor:pointer}
|
||||
h1 #h1{margin-left:10px}
|
||||
#menu{width:40px;height:40px;bottom:auto;border:none;overflow:hidden;background:transparent}
|
||||
#menu form,#menu p{display:none}
|
||||
#menu.open{width:260px;height:auto;max-width:100%;max-height:100%;border-right:1px solid rgba(255,255,255,0.1);border-bottom:5px solid rgba(255,255,255,0.1);background:#22252a;box-shadow:2px 2px 10px rgba(0,0,0,0.03);z-index:200;overflow-y:auto}
|
||||
#menu.open form,#menu.open p{display:block}
|
||||
}
|
||||
@media only screen and (max-width:270px){
|
||||
#menu.open{border-right:none}
|
||||
}
|
||||
@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:1.5),only screen and (min-device-pixel-ratio:1.5){
|
||||
h1 #h1{background-image:url("../images/logo-hres.png?3");background-size:120px}
|
||||
}
|
||||
a[href*="&sql="]:before{content:"✎";padding:0 5px;font-family:entypo,sans-serif;font-size:24pt;line-height:10pt;vertical-align:-3px}
|
||||
.links{line-height:22px}
|
||||
.links a:before{content:"⏴ ";font-family:entypo,sans-serif;font-size:24pt;line-height:10pt;vertical-align:-3px}
|
||||
.links a[href*="&sql="]:before{content:"";margin-left:-4px;margin-right:3px}
|
||||
.links a[href*="&import="]:before{content:"📥 "}
|
||||
.links a[href*="&dump="]:before{content:"📤 "}
|
||||
.links a[href*="&create="]:before,.links a[href*="&db="][href*="&database="]:before,.links a[href*="&indexes="]:before{content:"✎ "}
|
||||
.links a[href$="&create="]:before,.links a[href$="&database="]:before,.links a[href$="&indexes="]:before{content:"➕ "}
|
||||
.links a[href*="&schema="]:before{content:"🕪 "}
|
||||
.links a[href*="&privileges="]:before{content:"👥 "}
|
||||
.links a[href*="&view="]:before{content:" "}
|
||||
.links a[href*="&procedure="]:before,.links a[href*="&function="]:before{content:" "}
|
||||
.links a[href*="&event="]:before{content:"🔁 "}
|
||||
.links a[href*="&edit="]:before{content:"⊕ "}
|
||||
.links a[href*="&table="]:before{content:"⚙ "}
|
||||
.links a[href*="&select="]:before{content:"📄 "}
|
||||
.links a[href*="&processlist="]:before{content:" "}
|
||||
.links a[href*="&status="]:before{content:"📿 "}
|
||||
.links a[href*="&variables="]:before{content:" "}
|
||||
.links a[href*="&user="]:before{content:" "}
|
||||
.links a[href*="&foreign="]:before,.links a[href*="&trigger="]:before{content:"➕ "}
|
||||
table{border:1px solid rgba(255,255,255,0.1);margin:20px 0 10px 0}
|
||||
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 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}
|
||||
tbody td[align="right"]{text-align:right}
|
||||
tbody td[align="right"] label.block{text-align:right}
|
||||
tbody th span{padding-top:4px}
|
||||
table.checkable .checked{background:#282b2f}
|
||||
table.checkable input[type="checkbox"],table.checkable input[type="radio"]{margin:2px 5px 2px 0}
|
||||
table.checkable>thead a{padding:7px 0}
|
||||
table.checkable>thead input[type="checkbox"],table.checkable>thead input[type="radio"]{margin:2px 5px 2px 0}
|
||||
table.checkable>tbody>tr:hover{background:#282b2f}
|
||||
table.checkable>tbody>tr.checked:hover{background:#1b1f25}
|
||||
.scrollable{display:table-cell;padding-right:20px}
|
||||
.loadmore{margin:0;padding:10px 0}
|
||||
.footer{position:relative;padding:0}
|
||||
.footer>div{padding:0}
|
||||
.footer>p{position:fixed;left:261px;right:0;bottom:0;margin:0;padding:0 10px;border:none;border-top:1px solid rgba(255,255,255,0.1);background:#282b2f;z-index:102;font-weight:bold}
|
||||
.footer>p a,.footer>p label{display:inline-block;margin:0;padding:0 10px;height:40px;line-height:40px}
|
||||
.footer+div{line-height:36px}
|
||||
.footer+div a{padding:10px 0}
|
||||
.js .column{background:#22252a;padding:0;margin:-36px 0 0 -62px;border:1px solid #3e4144;border-radius:2px;z-index:10}
|
||||
.js .column a{display:inline-block;padding:0;width:30px;height:30px;overflow:hidden;vertical-align:middle}
|
||||
.js .column a:before{display:inline-block;width:30px;height:30px;line-height:30px;font-family:entypo,sans-serif;font-size:24pt;text-align:center;vertical-align:-3px}
|
||||
.js .column a:hover:before{background:#282b2f}
|
||||
.js .column a[href*='&select=']:before{content:"⬇"}
|
||||
.js .column a[href='#fieldset-search']:before{content:"🔍"}
|
||||
@media only screen and (max-width:768px){
|
||||
.footer>p{position:static;margin:-10px 0 10px 0;border-top:none;border-left:1px solid rgba(255,255,255,0.1);border-right:1px solid rgba(255,255,255,0.1);border-bottom:1px solid rgba(255,255,255,0.1)}
|
||||
.scrollable{display:block;margin:0 -20px;padding:0 20px;overflow-x:scroll}
|
||||
}
|
||||
a.jush-custom:hover,a.jush-help:hover{color:inherit;text-decoration:underline}
|
||||
.json{border-color:#58595a;border-left:7px solid #58595a;background:#282b2f;margin:5px 0 3px 0}
|
||||
.json tr{border-bottom:1px solid #58595a}
|
||||
.json tr:last-child{border-bottom:none}
|
||||
.json th{border-right:1px solid #58595a;vertical-align:top}
|
||||
.json code{padding:4px 10px}
|
||||
.json+textarea{margin-top:6px}
|
||||
a.json-icon{background:transparent;text-indent:0}
|
||||
a.json-icon:hover{background:transparent}
|
||||
a.json-icon:before{display:inline-block;width:20px;height:18px;line-height:18px;font-family:entypo,sans-serif;font-size:24pt;vertical-align:-3px;content:"▸"}
|
||||
a.json-icon.json-up{background:transparent;text-indent:0}
|
||||
a.json-icon.json-up:before{content:"▾"}
|
||||
a.json-link{padding-left:0}
|
||||
a.json-link:before{width:10px}
|
||||
a.json-link span{color:inherit}
|
||||
.footer{border-image: linear-gradient(rgb(34 37 42 / 22%),#22252a) 100% 0;}
|
||||
.footer > div{background: #22252a;}
|
||||
.jush a {color: #1383d9;}
|
||||
a.jush-custom:hover, a.jush-help:hover{color:#fff;}
|
||||
.jush {color: #a5a8ad;}
|
||||
.error {background: #ff00001a;color: #d8bfbf;}
|
||||
.message {color: #cceecc;background: #0075001c;}
|
||||
::-webkit-scrollbar {width: 10px;height: 10px;}
|
||||
::-webkit-scrollbar-track {background: #3e3e3e;}
|
||||
::-webkit-scrollbar-thumb {background: #888;}
|
||||
::-webkit-scrollbar-thumb:hover {background: #555;}
|
||||
input[type=checkbox] {display:inline-block;padding-left:25px;height:20px;outline:0;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgd2lkdGg9IjIwcHQiCiAgIGhlaWdodD0iNDBwdCIKICAgdmlld0JveD0iMCAwIDIwIDQwIgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmcyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ4LjUgcjEwMDQwIgogICBzb2RpcG9kaTpkb2NuYW1lPSJjaGVjay5zdmciPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTE5Ij4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTciIC8+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxOTIwIgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEwMTciCiAgICAgaWQ9Im5hbWVkdmlldzE1IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSIxNiIKICAgICBpbmtzY2FwZTpjeD0iNDMuNzAyNjQ2IgogICAgIGlua3NjYXBlOmN5PSIzMS45NTE3ODMiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjE5MTIiCiAgICAgaW5rc2NhcGU6d2luZG93LXk9Ii04IgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMiIgLz4KICA8ZwogICAgIHN0eWxlPSJmaWxsOiMwMDAwMDAiCiAgICAgaWQ9ImczMDY4IgogICAgIHRyYW5zZm9ybT0ic2NhbGUoMC44LDAuOCkiPgogICAgPHBhdGgKICAgICAgIGlkPSJwYXRoMzA1OCIKICAgICAgIGQ9Ik0gMTksNSBWIDE5IEggNSBWIDUgSCAxOSBNIDE5LDMgSCA1IEMgMy45LDMgMywzLjkgMyw1IHYgMTQgYyAwLDEuMSAwLjksMiAyLDIgaCAxNCBjIDEuMSwwIDIsLTAuOSAyLC0yIFYgNSBDIDIxLDMuOSAyMC4xLDMgMTksMyB6IgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIgLz4KICAgIDxwYXRoCiAgICAgICBpZD0icGF0aDMwNjAiCiAgICAgICBkPSJNIDAsMCBIIDI0IFYgMjQgSCAwIHoiCiAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgc3R5bGU9ImZpbGw6bm9uZSIgLz4KICA8L2c+CiAgPGcKICAgICBzdHlsZT0iZmlsbDojMDAwMDAwIgogICAgIGlkPSJnMzA4NCIKICAgICB0cmFuc2Zvcm09Im1hdHJpeCgwLjgsMCwwLDAuOCwwLDIwKSI+CiAgICA8cGF0aAogICAgICAgaWQ9InBhdGgzMDc0IgogICAgICAgZD0iTSAwLDAgSCAyNCBWIDI0IEggMCB6IgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIHN0eWxlPSJmaWxsOm5vbmUiIC8+CiAgICA8cGF0aAogICAgICAgaWQ9InBhdGgzMDc2IgogICAgICAgZD0iTSAxOSwzIEggNSBDIDMuODksMyAzLDMuOSAzLDUgdiAxNCBjIDAsMS4xIDAuODksMiAyLDIgaCAxNCBjIDEuMTEsMCAyLC0wLjkgMiwtMiBWIDUgQyAyMSwzLjkgMjAuMTEsMyAxOSwzIHogTSAxMCwxNyA1LDEyIDYuNDEsMTAuNTkgMTAsMTQuMTcgMTcuNTksNi41OCAxOSw4IDEwLDE3IHoiCiAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIiAvPgogIDwvZz4KPC9zdmc+Cg==);background-position:00;background-size:20px;background-repeat:no-repeat;vertical-align:middle;font-size:20px;line-height:20px;cursor:pointer;-webkit-appearance:none;-webkit-user-select:none;user-select:none;filter:invert();}
|
||||
input[type=checkbox]:checked {background-position:0-20px;}
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -133,7 +133,7 @@ th {
|
||||
background:white;
|
||||
}
|
||||
|
||||
.odds tbody tr:nth-child(2n) td {
|
||||
.odds tbody tr:nth-child(2n) {
|
||||
background:#fcfaf5;
|
||||
}
|
||||
|
||||
|
@@ -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;}
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -132,7 +132,7 @@ th {
|
||||
background:white;
|
||||
}
|
||||
|
||||
.odds tbody tr:nth-child(2n) td {
|
||||
.odds tbody tr:nth-child(2n) {
|
||||
background:#fcfaf5;
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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}
|
||||
|
@@ -1 +1,3 @@
|
||||
Copy adminer.css alongside Adminer PHP script to use an alternative design.
|
||||
|
||||
If the design supports dark mode then it should be named adminer-dark.css.
|
||||
|
@@ -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}
|
||||
|
@@ -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}
|
@@ -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}
|
||||
|
@@ -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"]);
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
function adminer_object() {
|
||||
|
||||
class AdminerCds extends Adminer\Adminer {
|
||||
|
||||
function name() {
|
||||
|
@@ -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>";
|
||||
@@ -34,7 +34,7 @@ class Adminer {
|
||||
if ($connection) {
|
||||
$databases = $this->databases(false);
|
||||
return (!$databases
|
||||
? $connection->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)") // username without the database list
|
||||
? get_val("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)") // username without the database list
|
||||
: $databases[(information_schema($databases[0]) ? 1 : 0)] // first available database
|
||||
);
|
||||
}
|
||||
@@ -59,15 +59,17 @@ class Adminer {
|
||||
return csp();
|
||||
}
|
||||
|
||||
function head() {
|
||||
function head($dark = null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function css() {
|
||||
$return = array();
|
||||
$filename = "adminer.css";
|
||||
if (file_exists($filename)) {
|
||||
$return[] = $filename;
|
||||
foreach (array("", "-dark") as $mode) {
|
||||
$filename = "adminer$mode.css";
|
||||
if (file_exists($filename)) {
|
||||
$return[] = "$filename?v=" . crc32(file_get_contents($filename));
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -90,7 +92,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 +180,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) . ")");
|
||||
}
|
||||
@@ -208,9 +213,8 @@ ORDER BY ORDINAL_POSITION", null, "") as $row //! requires MySQL 5
|
||||
if ($link) {
|
||||
$return = "<a href='$link'" . (is_url($link) ? target_blank() : "") . ">$return</a>";
|
||||
}
|
||||
if (!$link && !like_bool($field) && preg_match(number_type(), $field["type"])) {
|
||||
$return = "<div class='number'>$return</div>"; // Firefox doesn't support <colgroup>
|
||||
} elseif (preg_match('~date~', $field["type"])) {
|
||||
// Firefox doesn't support <colgroup>
|
||||
if (preg_match('~date~', $field["type"])) {
|
||||
$return = "<div class='datetime'>$return</div>";
|
||||
}
|
||||
return $return;
|
||||
@@ -248,7 +252,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 +486,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 +578,9 @@ qsl('div').onclick = whisperClick;", "")
|
||||
return $ext;
|
||||
}
|
||||
|
||||
function dumpFooter() {
|
||||
}
|
||||
|
||||
function importServerPath() {
|
||||
}
|
||||
|
||||
@@ -620,6 +627,9 @@ qsl('div').onclick = whisperClick;", "")
|
||||
}
|
||||
}
|
||||
|
||||
function syntaxHighlighting($tables) {
|
||||
}
|
||||
|
||||
function databasesPrint($missing) {
|
||||
}
|
||||
|
||||
@@ -629,7 +639,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,16 +661,15 @@ qsl('div').onclick = whisperClick;", "")
|
||||
}
|
||||
}
|
||||
|
||||
function _foreignKeyOptions($table, $column, $value = null) {
|
||||
global $connection;
|
||||
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"));
|
||||
}
|
||||
if (!$return && $value !== null) {
|
||||
return $connection->result("SELECT $name FROM " . table($target) . " WHERE $id = " . q($value));
|
||||
return get_val("SELECT $name FROM " . table($target) . " WHERE $id = " . q($value));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
2
externals/JsShrink
vendored
2
externals/JsShrink
vendored
Submodule externals/JsShrink updated: 17cbfacae6...18dcc3849a
1
externals/PhpShrink
vendored
Submodule
1
externals/PhpShrink
vendored
Submodule
Submodule externals/PhpShrink added at b6fc11da47
2
externals/jush
vendored
2
externals/jush
vendored
Submodule externals/jush updated: 792086f0fd...a80237e93e
27
lang.php
27
lang.php
@@ -32,27 +32,40 @@ foreach (glob(__DIR__ . "/adminer/lang/" . ($_SESSION["lang"] ?: "*") . ".inc.ph
|
||||
$messages = $messages_all;
|
||||
$file = file_get_contents($filename);
|
||||
$file = str_replace("\r", "", $file);
|
||||
preg_match_all("~^(\\s*(?:// [^'].*\\s+)?)(?:// )?(('(?:[^\\\\']+|\\\\.)*') => .*[^,\n]),?~m", $file, $matches, PREG_SET_ORDER);
|
||||
preg_match_all("~^(\\s*(?:// [^'].*\\s+)?)(?:// )?(('(?:[^\\\\']+|\\\\.)*') => (.*[^,\n])),?~m", $file, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
|
||||
$s = "";
|
||||
$lang = basename($filename, ".inc.php");
|
||||
$fullstop = ($lang == "bn" ? '।' : (preg_match('~^(ja|zh)~', $lang) ? '。' : ($lang == 'he' ? '[^.]' : '\.')));
|
||||
foreach ($matches as $match) {
|
||||
if (isset($messages[$match[3]])) {
|
||||
list(, list($indent), list($line, $offset), list($en), list($translation)) = $match;
|
||||
if (isset($messages[$en])) {
|
||||
// keep current messages
|
||||
$s .= "$match[1]$match[2],\n";
|
||||
unset($messages[$match[3]]);
|
||||
$s .= "$indent$line,\n";
|
||||
unset($messages[$en]);
|
||||
$en_fullstop = (substr($en, -2, 1) == ".");
|
||||
//! check in array
|
||||
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";
|
||||
}
|
||||
}
|
||||
if (preg_match('~%~', $en) xor preg_match('~%~', $translation)) {
|
||||
echo "$filename:" . (substr_count($file, "\n", 0, $offset) + 1) . ":Not matching placeholder.\n";
|
||||
}
|
||||
} else {
|
||||
// comment deprecated messages
|
||||
$s .= "$match[1]// $match[2],\n";
|
||||
$s .= "$indent// $line,\n";
|
||||
}
|
||||
}
|
||||
if ($messages) {
|
||||
if (basename($filename) != "en.inc.php") {
|
||||
if ($lang != "en") {
|
||||
$s .= "\n";
|
||||
}
|
||||
foreach ($messages as $idf => $val) {
|
||||
// add new messages
|
||||
if ($val == "," && strpos($idf, "%d")) {
|
||||
$s .= "\t$idf => array(),\n";
|
||||
} elseif (basename($filename) != "en.inc.php") {
|
||||
} elseif ($lang != "en") {
|
||||
$s .= "\t$idf => null,\n";
|
||||
}
|
||||
}
|
||||
|
64
phpcs.xml
64
phpcs.xml
@@ -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,20 +22,29 @@
|
||||
<!-- 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"/>
|
||||
|
||||
<!-- TODO: Ignore only in <?php if () { ?><?php } ?> -->
|
||||
<!-- False positives. -->
|
||||
<exclude name="Generic.WhiteSpace.ScopeIndent.Incorrect"/>
|
||||
<exclude name="Generic.WhiteSpace.ScopeIndent.IncorrectExact"/>
|
||||
</rule>
|
||||
|
||||
<rule ref="Generic.WhiteSpace.ScopeIndent">
|
||||
<properties>
|
||||
<property name="ignoreIndentationTokens" type="array">
|
||||
<element value="T_OPEN_TAG"/>
|
||||
</property>
|
||||
</properties>
|
||||
</rule>
|
||||
|
||||
<rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
|
||||
<exclude-pattern>adminer/drivers/</exclude-pattern>
|
||||
<exclude-pattern>adminer/include/pdo.inc.php</exclude-pattern>
|
||||
@@ -46,7 +53,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 +86,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>
|
||||
|
@@ -11,7 +11,7 @@
|
||||
class AdminerDotJs {
|
||||
const FILENAME = "adminer.js";
|
||||
|
||||
function head() {
|
||||
function head($dark = null) {
|
||||
if (file_exists(self::FILENAME)) {
|
||||
echo Adminer\script_src(self::FILENAME . "?v=" . crc32(file_get_contents(self::FILENAME))), "\n";
|
||||
}
|
||||
|
92
plugins/codemirror.php
Normal file
92
plugins/codemirror.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/** Use Codemirror 5 for syntax highlighting and SQL <textarea> including type-ahead of keywords and tables
|
||||
* @link https://codemirror.net/5/
|
||||
* @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 AdminerCodemirror {
|
||||
private $root;
|
||||
|
||||
function __construct($root = "codemirror5") {
|
||||
$this->root = $root;
|
||||
}
|
||||
|
||||
function syntaxHighlighting($tableStatuses) {
|
||||
$connection = Adminer\connection();
|
||||
?>
|
||||
<style>
|
||||
@import url(<?php echo $this->root; ?>/lib/codemirror.css);
|
||||
@import url(<?php echo $this->root; ?>/addon/hint/show-hint.css);
|
||||
.CodeMirror { border: 1px inset #ccc; resize: both; }
|
||||
</style>
|
||||
<?php
|
||||
echo Adminer\script_src("$this->root/lib/codemirror.js");
|
||||
echo Adminer\script_src("$this->root/addon/runmode/runmode.js");
|
||||
echo Adminer\script_src("$this->root/addon/hint/show-hint.js");
|
||||
echo Adminer\script_src("$this->root/mode/javascript/javascript.js");
|
||||
if (Adminer\support("sql")) {
|
||||
echo Adminer\script_src("$this->root/mode/sql/sql.js");
|
||||
echo Adminer\script_src("$this->root/addon/hint/sql-hint.js");
|
||||
}
|
||||
$tables = array();
|
||||
foreach ($tableStatuses as $status) {
|
||||
foreach (Adminer\fields($status["Name"]) as $name => $field) {
|
||||
$tables[$status["Name"]][] = $name;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<script <?php echo Adminer\nonce(); ?>>
|
||||
function getCmMode(el) {
|
||||
const match = el.className.match(/(^|\s)jush-([^ ]+)/);
|
||||
if (match) {
|
||||
const modes = {
|
||||
js: 'application/json',
|
||||
sql: 'text/x-<?php echo ($connection->maria ? "mariadb" : "mysql"); ?>',
|
||||
oracle: 'text/x-sql',
|
||||
clickhouse: 'text/x-sql',
|
||||
firebird: 'text/x-sql'
|
||||
};
|
||||
return modes[match[2]] || 'text/x-' + match[2];
|
||||
}
|
||||
}
|
||||
|
||||
for (const el of qsa('code')) {
|
||||
const mode = getCmMode(el);
|
||||
if (mode) {
|
||||
el.className += ' cm-s-default';
|
||||
CodeMirror.runMode(el.textContent, mode, el);
|
||||
}
|
||||
}
|
||||
|
||||
for (const el of qsa('textarea')) {
|
||||
const mode = getCmMode(el);
|
||||
if (mode) {
|
||||
const width = el.clientWidth;
|
||||
const height = el.clientHeight;
|
||||
const cm = CodeMirror.fromTextArea(el, {
|
||||
mode: mode,
|
||||
extraKeys: { 'Ctrl-Space': 'autocomplete' },
|
||||
hintOptions: {
|
||||
completeSingle: false,
|
||||
tables: <?php echo json_encode($tables); ?>,
|
||||
defaultTable: <?php echo json_encode($_GET["trigger"] ? $_GET["trigger"] : ($_GET["check"] ? $_GET["check"] : null)); ?>
|
||||
}
|
||||
});
|
||||
cm.setSize(width, height);
|
||||
cm.on('inputRead', function () {
|
||||
const token = cm.getTokenAt(cm.getCursor());
|
||||
if (/^[.`"\w]\w*$/.test(token.string)) {
|
||||
CodeMirror.commands.autocomplete(cm);
|
||||
}
|
||||
});
|
||||
setupSubmitHighlightInput(cm.getWrapperElement());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user