mirror of
https://github.com/vrana/adminer.git
synced 2025-09-16 00:52:14 +02:00
Compare commits
84 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6f339bac6c | ||
|
f32f84cf57 | ||
|
ce063a64dd | ||
|
1d5d441271 | ||
|
fd28e64d8c | ||
|
3874148064 | ||
|
0640326df4 | ||
|
16f7080ff2 | ||
|
516530485d | ||
|
f921dafa61 | ||
|
d1831641a9 | ||
|
b1c825484d | ||
|
6c662e1f96 | ||
|
7ef0949539 | ||
|
9fc63eb9d0 | ||
|
2041d5c6e3 | ||
|
fc2ab7de16 | ||
|
2db30ba7e2 | ||
|
8d6ed3fffa | ||
|
9e0db9f1cd | ||
|
a979b4be22 | ||
|
26319460ef | ||
|
b41699624b | ||
|
17a0e84718 | ||
|
5c5f7d17fe | ||
|
4ad7eb0b70 | ||
|
b83da41739 | ||
|
e551efb031 | ||
|
6d0351ec7c | ||
|
dcf11d8fc9 | ||
|
0de6a057d3 | ||
|
18b62aba38 | ||
|
10ff74552d | ||
|
f5c7ab54f7 | ||
|
cc110c448c | ||
|
6f766f8c52 | ||
|
9a60d158f1 | ||
|
6dec0d63b0 | ||
|
c9a52cd28c | ||
|
9424b7431e | ||
|
35b2b969be | ||
|
165f1b241c | ||
|
4d75f822e9 | ||
|
5e9c185596 | ||
|
cfd69dfd8c | ||
|
1fc5acb389 | ||
|
8ca0e36970 | ||
|
9e8de24e3d | ||
|
4cb09852e3 | ||
|
e115dccdae | ||
|
1ba410cad1 | ||
|
0764a20a19 | ||
|
b2c4574325 | ||
|
466eceff40 | ||
|
27c5f6d21b | ||
|
2744538c8c | ||
|
41456c9eb7 | ||
|
9745c12769 | ||
|
f24f72ac51 | ||
|
2b52a9b653 | ||
|
9ba4b86916 | ||
|
1cc3fdf915 | ||
|
b960c41d63 | ||
|
3ec750ef7e | ||
|
737b631dda | ||
|
8fc450946c | ||
|
e282d6eb89 | ||
|
86ffeb2a1e | ||
|
31530ba03e | ||
|
146d3539d8 | ||
|
04068a631e | ||
|
4698686232 | ||
|
57b6afc8cb | ||
|
e589c80f42 | ||
|
acfebf1788 | ||
|
246c3c489b | ||
|
92b95606c1 | ||
|
ac8318f387 | ||
|
d1c2679acd | ||
|
caf6e495dc | ||
|
ec5ad85470 | ||
|
307fabaf22 | ||
|
1862b84612 | ||
|
e76be9f890 |
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -7,12 +7,14 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Adminer version:** please use latest published or Git
|
||||
**Adminer version:** <!-- please use latest published or Git -->
|
||||
**Compiled:** single file / single language / source codes / custom compilation
|
||||
**Driver:** e.g. MySQLi
|
||||
**Database version:** e.g. 10.2.12-MariaDB
|
||||
**Driver:** <!-- e.g. MySQLi -->
|
||||
**Database version:** <!-- e.g. 10.2.12-MariaDB -->
|
||||
**Plugins used:**
|
||||
|
||||
_Please provide reproducible steps including a SQL dump (with no personal information) if applicable.
|
||||
<!--
|
||||
Please provide reproducible steps including a SQL dump (with no personal information) if applicable.
|
||||
Also please include a screenshot.
|
||||
Report issues with Adminer Docker image at https://github.com/TimWolla/docker-adminer._
|
||||
-->
|
||||
|
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,3 +1,36 @@
|
||||
## Adminer 5.4.0 (released 2025-09-08)
|
||||
- Allow specifying operator in search anywhere
|
||||
- Do not order descending in GROUP BY select
|
||||
- Allow exporting SQL in SQL command (bug #1092)
|
||||
- Add section links in database overview
|
||||
- Warn about exceeded max_file_uploads in import
|
||||
- Display @ after username without server in existing logins
|
||||
- Display data length and index length for materialized views
|
||||
- Link routines from syntax highlighting
|
||||
- Autofocus added field in alter table
|
||||
- Executed SQL commands: Add button for copy to clipboard
|
||||
- Load more: run syntax highlighter
|
||||
- Allow connecting to IPv6 (bug #1095)
|
||||
- MySQL: Fix saving empty enum (bug #1152)
|
||||
- MySQL 5.0-: Do not load partitioning info in alter table (bug #1099)
|
||||
- MariaDB: Parse COLLATE in routine definition (bug #1104)
|
||||
- PostgreSQL: Show structure of inherited tables
|
||||
- PostgreSQL: Display index expressions
|
||||
- PostgreSQL: Add SQL operator to select
|
||||
- PostgreSQL: Hide only partitions, not all inherited tables from menu
|
||||
- PostgreSQL: Allow comparing json columns (bug #1107)
|
||||
- PostgreSQL: Shorten values in hstore columns
|
||||
- PostgreSQL: Quote edit value with interval operator
|
||||
- PostgreSQL: Fix calling functions with name-less parameters
|
||||
- PostgreSQL: Fix calling functions returing table
|
||||
- PostgreSQL: Don't treat user types containing 'file' as blobs (bug #1118)
|
||||
- PostgreSQL: Export DROP and CREATE DATABASE (bug #1140)
|
||||
- PostgreSQL 11-: Avoid duplicate oid in table status (bug #1089)
|
||||
- Elasticsearch: Support dropping aliases
|
||||
- Plugins: Methods afterConnect(), processList() and killProcess()
|
||||
- New plugin: Display row numbers in select (bug #1106)
|
||||
- New plugin: Specify query timeout
|
||||
|
||||
## Adminer 5.3.0 (released 2025-05-04)
|
||||
- Align numeric functions right
|
||||
- Autocomplete: Support table aliases
|
||||
|
@@ -36,7 +36,7 @@ if (!$error && $_POST) {
|
||||
}
|
||||
}
|
||||
|
||||
$query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")";
|
||||
$query = (isset($_GET["callf"]) ? "SELECT " : "CALL ") . ($routine["returns"]["type"] == "record" ? "* FROM " : "") . table($PROCEDURE) . "(" . implode(", ", $call) . ")";
|
||||
$start = microtime(true);
|
||||
$result = connection()->multi_query($query);
|
||||
$affected = connection()->affected_rows; // getting warnings overwrites this
|
||||
|
@@ -3,7 +3,7 @@ namespace Adminer;
|
||||
|
||||
$TABLE = $_GET["create"];
|
||||
$partition_by = driver()->partitionBy;
|
||||
$partitions_info = driver()->partitionsInfo($TABLE);
|
||||
$partitions_info = ($partition_by ? driver()->partitionsInfo($TABLE) : array());
|
||||
|
||||
$referencable_primary = referencable_primary($TABLE);
|
||||
$foreign_keys = array();
|
||||
|
@@ -64,12 +64,13 @@ if (adminer()->homepage()) {
|
||||
echo "<form action='' method='post'>\n";
|
||||
if (support("table")) {
|
||||
echo "<fieldset><legend>" . lang('Search data in tables') . " <span id='selected2'></span></legend><div>";
|
||||
echo "<input type='search' name='query' value='" . h($_POST["query"]) . "'>";
|
||||
echo html_select("op", adminer()->operators(), idx($_POST, "op", JUSH == "elastic" ? "should" : "LIKE %%"));
|
||||
echo " <input type='search' name='query' value='" . h($_POST["query"]) . "'>";
|
||||
echo script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');", "");
|
||||
echo " <input type='submit' name='search' value='" . lang('Search') . "'>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
if ($_POST["search"] && $_POST["query"] != "") {
|
||||
$_GET["where"][0]["op"] = driver()->convertOperator("LIKE %%");
|
||||
$_GET["where"][0]["op"] = $_POST["op"];
|
||||
search_tables();
|
||||
}
|
||||
}
|
||||
@@ -95,8 +96,9 @@ if (adminer()->homepage()) {
|
||||
$id = h("Table-" . $name);
|
||||
echo '<tr><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array("$name", $tables_views, true), "", "", "", $id); // "$name" to check numeric table names
|
||||
echo '<th>' . (support("table") || support("indexes") ? "<a href='" . h(ME) . "table=" . urlencode($name) . "' title='" . lang('Show structure') . "' id='$id'>" . h($name) . '</a>' : h($name));
|
||||
if ($view) {
|
||||
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '" title="' . lang('Alter view') . '">' . (preg_match('~materialized~i', $type) ? lang('Materialized view') : lang('View')) . '</a>';
|
||||
if ($view && !preg_match('~materialized~i', $type)) {
|
||||
$title = lang('View');
|
||||
echo '<td colspan="6">' . (support("view") ? "<a href='" . h(ME) . "view=" . urlencode($name) . "' title='" . lang('Alter view') . "'>$title</a>" : $title);
|
||||
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '" title="' . lang('Select data') . '">?</a>';
|
||||
} else {
|
||||
foreach (
|
||||
@@ -131,6 +133,7 @@ if (adminer()->homepage()) {
|
||||
echo "\n";
|
||||
|
||||
echo "</table>\n";
|
||||
echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');");
|
||||
echo "</div>\n";
|
||||
if (!information_schema(DB)) {
|
||||
echo "<div class='footer'><div>\n";
|
||||
@@ -147,18 +150,23 @@ if (adminer()->homepage()) {
|
||||
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . on_help(JUSH == "sqlite" ? "'DELETE'" : "'TRUNCATE" . (JUSH == "pgsql" ? "'" : " TABLE'")) . confirm()
|
||||
. "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . on_help("'DROP TABLE'") . confirm() . "\n";
|
||||
$databases = (support("scheme") ? adminer()->schemas() : adminer()->databases());
|
||||
echo "</div></fieldset>\n";
|
||||
$script = "";
|
||||
if (count($databases) != 1 && JUSH != "sqlite") {
|
||||
echo "<fieldset><legend>" . lang('Move to other database') . " <span id='selected3'></span></legend><div>";
|
||||
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
|
||||
echo "<p><label>" . lang('Move to other database') . ": ";
|
||||
echo ($databases ? html_select("target", $databases, $db) : '<input name="target" value="' . h($db) . '" autocapitalize="off">');
|
||||
echo "</label> <input type='submit' name='move' value='" . lang('Move') . "'>";
|
||||
echo (support("copy") ? " <input type='submit' name='copy' value='" . lang('Copy') . "'> " . checkbox("overwrite", 1, $_POST["overwrite"], lang('overwrite')) : "");
|
||||
echo "\n";
|
||||
echo "</div></fieldset>\n";
|
||||
$script = " selectCount('selected3', formChecked(this, /^(tables|views)\[/));";
|
||||
}
|
||||
echo "<input type='hidden' name='all' value=''>"; // used by trCheck()
|
||||
echo script("qsl('input').onclick = function () { selectCount('selected', formChecked(this, /^(tables|views)\[/));" . (support("table") ? " selectCount('selected2', formChecked(this, /^tables\[/) || $tables);" : "") . " }");
|
||||
echo script("qsl('input').onclick = function () { selectCount('selected', formChecked(this, /^(tables|views)\[/));"
|
||||
. (support("table") ? " selectCount('selected2', formChecked(this, /^tables\[/) || $tables);" : "")
|
||||
. "$script }")
|
||||
;
|
||||
echo input_token();
|
||||
echo "</div></fieldset>\n";
|
||||
echo "</div></div>\n";
|
||||
}
|
||||
echo "</form>\n";
|
||||
@@ -239,9 +247,5 @@ if (adminer()->homepage()) {
|
||||
}
|
||||
echo '<p class="links"><a href="' . h(ME) . 'event=">' . lang('Create event') . "</a>\n";
|
||||
}
|
||||
|
||||
if ($tables_list) {
|
||||
echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ if (isset($_GET["mssql"])) {
|
||||
$this->error = rtrim($this->error);
|
||||
}
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
$connection_info = array("UID" => $username, "PWD" => $password, "CharacterSet" => "UTF-8");
|
||||
$ssl = adminer()->connectSsl();
|
||||
if (isset($ssl["Encrypt"])) {
|
||||
@@ -39,7 +39,8 @@ if (isset($_GET["mssql"])) {
|
||||
if ($db != "") {
|
||||
$connection_info["Database"] = $db;
|
||||
}
|
||||
$this->link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info);
|
||||
list($host, $port) = host_port($server);
|
||||
$this->link = @sqlsrv_connect($host . ($port ? ",$port" : ""), $connection_info);
|
||||
if ($this->link) {
|
||||
$info = sqlsrv_server_info($this->link);
|
||||
$this->server_info = $info['SQLServerVersion'];
|
||||
@@ -181,8 +182,9 @@ if (isset($_GET["mssql"])) {
|
||||
class Db extends MssqlDb {
|
||||
public $extension = "PDO_SQLSRV";
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
return $this->dsn("sqlsrv:Server=" . str_replace(":", ",", $server), $username, $password);
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
list($host, $port) = host_port($server);
|
||||
return $this->dsn("sqlsrv:Server=$host" . ($port ? ",$port" : ""), $username, $password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +192,9 @@ if (isset($_GET["mssql"])) {
|
||||
class Db extends MssqlDb {
|
||||
public $extension = "PDO_DBLIB";
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
return $this->dsn("dblib:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)), $username, $password);
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
list($host, $port) = host_port($server);
|
||||
return $this->dsn("dblib:charset=utf8;host=$host" . ($port ? (is_numeric($port) ? ";port=" : ";unix_socket=") . $port : ""), $username, $password);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +217,7 @@ if (isset($_GET["mssql"])) {
|
||||
public $generated = array("PERSISTED", "VIRTUAL");
|
||||
public $onActions = "NO ACTION|CASCADE|SET NULL|SET DEFAULT";
|
||||
|
||||
static function connect(?string $server, string $username, string $password) {
|
||||
static function connect(string $server, string $username, string $password) {
|
||||
if ($server == "") {
|
||||
$server = "localhost:1433";
|
||||
}
|
||||
@@ -678,7 +681,7 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)) as $row
|
||||
return "TRUNCATE TABLE " . table($table);
|
||||
}
|
||||
|
||||
function use_sql($database) {
|
||||
function use_sql($database, $style = "") {
|
||||
return "USE " . idf_escape($database);
|
||||
}
|
||||
|
||||
|
@@ -16,9 +16,9 @@ if (!defined('Adminer\DRIVER')) {
|
||||
parent::init();
|
||||
}
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4
|
||||
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
|
||||
list($host, $port) = host_port($server);
|
||||
$ssl = adminer()->connectSsl();
|
||||
if ($ssl) {
|
||||
$this->ssl_set($ssl['key'], $ssl['cert'], $ssl['ca'], '', '');
|
||||
@@ -32,7 +32,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
(is_numeric($port) ? null : $port),
|
||||
($ssl ? ($ssl['verify'] !== false ? 2048 : 64) : 0) // 2048 - MYSQLI_CLIENT_SSL, 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16)
|
||||
);
|
||||
$this->options(MYSQLI_OPT_LOCAL_INFILE, false);
|
||||
$this->options(MYSQLI_OPT_LOCAL_INFILE, 0);
|
||||
return ($return ? '' : $this->error);
|
||||
}
|
||||
|
||||
@@ -58,14 +58,14 @@ if (!defined('Adminer\DRIVER')) {
|
||||
class Db extends SqlDb {
|
||||
/** @var resource */ private $link;
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
if (ini_bool("mysql.allow_local_infile")) {
|
||||
return lang('Disable %s or enable %s or %s extensions.', "'mysql.allow_local_infile'", "MySQLi", "PDO_MySQL");
|
||||
}
|
||||
$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")),
|
||||
($server . $username != "" ? $username : ini_get("mysql.default_user")),
|
||||
($server . $username . $password != "" ? $password : ini_get("mysql.default_password")),
|
||||
true,
|
||||
131072 // CLIENT_MULTI_RESULTS for CALL
|
||||
);
|
||||
@@ -158,7 +158,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
class Db extends PdoDb {
|
||||
public $extension = "PDO_MySQL";
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
$options = array(\PDO::MYSQL_ATTR_LOCAL_INFILE => false);
|
||||
$ssl = adminer()->connectSsl();
|
||||
if ($ssl) {
|
||||
@@ -175,8 +175,9 @@ if (!defined('Adminer\DRIVER')) {
|
||||
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $ssl['verify'];
|
||||
}
|
||||
}
|
||||
list($host, $port) = host_port($server);
|
||||
return $this->dsn(
|
||||
"mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)),
|
||||
"mysql:charset=utf8;host=$host" . ($port ? (is_numeric($port) ? ";port=" : ";unix_socket=") . $port : ""),
|
||||
$username,
|
||||
$password,
|
||||
$options
|
||||
@@ -211,7 +212,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
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");
|
||||
|
||||
static function connect(?string $server, string $username, string $password) {
|
||||
static function connect(string $server, string $username, string $password) {
|
||||
$connection = parent::connect($server, $username, $password);
|
||||
if (is_string($connection)) {
|
||||
if (function_exists('iconv') && !is_utf8($connection) && strlen($s = iconv("windows-1250", "utf-8", $connection)) > strlen($connection)) { // windows-1250 - most common Windows encoding
|
||||
@@ -340,7 +341,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
|
||||
function partitionsInfo(string $table): array {
|
||||
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table);
|
||||
$result = connection()->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
$result = $this->conn->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
$return = array();
|
||||
list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row();
|
||||
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
|
||||
@@ -457,7 +458,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
|
||||
/** Get table status
|
||||
* @param bool $fast return only "Name", "Engine" and "Comment" fields
|
||||
* @return TableStatus[]
|
||||
* @return array<string, TableStatus>
|
||||
*/
|
||||
function table_status(string $name = "", bool $fast = false): array {
|
||||
$return = array();
|
||||
@@ -695,7 +696,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @param string $name new name
|
||||
* @param list<array{string, list<string>, string}> $fields of [$orig, $process_field, $after]
|
||||
* @param string[] $foreign
|
||||
* @param numeric-string $auto_increment
|
||||
* @param numeric-string|'' $auto_increment
|
||||
* @param ?Partitions $partitioning null means remove partitioning
|
||||
* @return Result|bool
|
||||
*/
|
||||
@@ -896,7 +897,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
$space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
|
||||
$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,]+)['\"]?)?";
|
||||
. "\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?(?:\\s*COLLATE\\s*['\"]?([^'\"\\s,]+)['\"]?)?"; //! store COLLATE
|
||||
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : driver()->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
|
||||
$create = get_val("SHOW CREATE $type " . idf_escape($name), 2);
|
||||
preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match);
|
||||
@@ -928,7 +929,7 @@ if (!defined('Adminer\DRIVER')) {
|
||||
* @return list<string[]> ["SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => ]
|
||||
*/
|
||||
function routines(): array {
|
||||
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
|
||||
return get_rows("SELECT SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
|
||||
}
|
||||
|
||||
/** Get list of available routine languages
|
||||
@@ -983,8 +984,17 @@ if (!defined('Adminer\DRIVER')) {
|
||||
}
|
||||
|
||||
/** Get SQL command to change database */
|
||||
function use_sql(string $database): string {
|
||||
return "USE " . idf_escape($database);
|
||||
function use_sql(string $database, string $style = ""): string {
|
||||
$name = idf_escape($database);
|
||||
$return = "";
|
||||
if (preg_match('~CREATE~', $style) && ($create = get_val("SHOW CREATE DATABASE $name", 1))) {
|
||||
set_utf8mb4($create);
|
||||
if ($style == "DROP+CREATE") {
|
||||
$return = "DROP DATABASE IF EXISTS $name;\n";
|
||||
}
|
||||
$return .= "$create;\n";
|
||||
}
|
||||
return $return . "USE $name";
|
||||
}
|
||||
|
||||
/** Get SQL commands to create triggers */
|
||||
@@ -1067,11 +1077,11 @@ if (!defined('Adminer\DRIVER')) {
|
||||
}
|
||||
|
||||
/** Kill a process
|
||||
* @param numeric-string $val
|
||||
* @param numeric-string $id
|
||||
* @return Result|bool
|
||||
*/
|
||||
function kill_process(string $val) {
|
||||
return queries("KILL " . number($val));
|
||||
function kill_process(string $id) {
|
||||
return queries("KILL " . number($id));
|
||||
}
|
||||
|
||||
/** Return query to get connection ID */
|
||||
|
@@ -20,7 +20,7 @@ if (isset($_GET["oracle"])) {
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
$this->link = @oci_new_connect($username, $password, $server, "AL32UTF8");
|
||||
if ($this->link) {
|
||||
$this->server_info = oci_server_version($this->link);
|
||||
@@ -60,6 +60,10 @@ if (isset($_GET["oracle"])) {
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function timeout(int $ms): bool {
|
||||
return oci_set_call_timeout($this->link, $ms);
|
||||
}
|
||||
}
|
||||
|
||||
class Result {
|
||||
@@ -106,7 +110,7 @@ if (isset($_GET["oracle"])) {
|
||||
public $extension = "PDO_OCI";
|
||||
public $_current_db;
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
return $this->dsn("oci:dbname=//$server;charset=AL32UTF8", $username, $password);
|
||||
}
|
||||
|
||||
@@ -165,7 +169,7 @@ if (isset($_GET["oracle"])) {
|
||||
}
|
||||
}
|
||||
if (
|
||||
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && connection()->affected_rows)
|
||||
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $this->conn->affected_rows)
|
||||
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"))
|
||||
) {
|
||||
return false;
|
||||
|
@@ -20,10 +20,11 @@ if (isset($_GET["pgsql"])) {
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
$db = adminer()->database();
|
||||
set_error_handler(array($this, '_error'));
|
||||
$this->string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
|
||||
list($host, $port) = host_port(addcslashes($server, "'\\"));
|
||||
$this->string = "host='$host'" . ($port ? " port='$port'" : "") . " user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
|
||||
$ssl = adminer()->connectSsl();
|
||||
if (isset($ssl["mode"])) {
|
||||
$this->string .= " sslmode='" . $ssl["mode"] . "'";
|
||||
@@ -143,10 +144,11 @@ if (isset($_GET["pgsql"])) {
|
||||
public $extension = "PDO_PgSQL";
|
||||
public $timeout = 0;
|
||||
|
||||
function attach(?string $server, string $username, string $password): string {
|
||||
function attach(string $server, string $username, string $password): string {
|
||||
$db = adminer()->database();
|
||||
list($host, $port) = host_port(addcslashes($server, "'\\"));
|
||||
//! client_encoding is supported since 9.1, but we can't yet use min_version here
|
||||
$dsn = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'";
|
||||
$dsn = "pgsql:host='$host'" . ($port ? " port='$port'" : "") . " client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'";
|
||||
$ssl = adminer()->connectSsl();
|
||||
if (isset($ssl["mode"])) {
|
||||
$dsn .= " sslmode='" . $ssl["mode"] . "'";
|
||||
@@ -204,13 +206,13 @@ if (isset($_GET["pgsql"])) {
|
||||
static $extensions = array("PgSQL", "PDO_PgSQL");
|
||||
static $jush = "pgsql";
|
||||
|
||||
public $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT ILIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
|
||||
public $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT ILIKE", "NOT IN", "IS NOT NULL", "SQL"); //! SQL - same-site CSRF
|
||||
public $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
|
||||
public $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
|
||||
public string $nsOid = "(SELECT oid FROM pg_namespace WHERE nspname = current_schema())";
|
||||
|
||||
static function connect(?string $server, string $username, string $password) {
|
||||
static function connect(string $server, string $username, string $password) {
|
||||
$connection = parent::connect($server, $username, $password);
|
||||
if (is_string($connection)) {
|
||||
return $connection;
|
||||
@@ -288,7 +290,7 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
}
|
||||
if (
|
||||
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && connection()->affected_rows)
|
||||
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $this->conn->affected_rows)
|
||||
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"))
|
||||
) {
|
||||
return false;
|
||||
@@ -340,7 +342,7 @@ if (isset($_GET["pgsql"])) {
|
||||
}
|
||||
|
||||
function partitionsInfo(string $table): array {
|
||||
$row = connection()->query("SELECT * FROM pg_partitioned_table WHERE partrelid = " . driver()->tableOid($table))->fetch_assoc();
|
||||
$row = (min_version(10) ? $this->conn->query("SELECT * FROM pg_partitioned_table WHERE partrelid = " . $this->tableOid($table))->fetch_assoc() : null);
|
||||
if ($row) {
|
||||
$attrs = get_vals("SELECT attname FROM pg_attribute WHERE attrelid = $row[partrelid] AND attnum IN (" . str_replace(" ", ", ", $row["partattrs"]) . ")"); //! ordering
|
||||
$by = array('h' => 'HASH', 'l' => 'LIST', 'r' => 'RANGE');
|
||||
@@ -359,7 +361,7 @@ if (isset($_GET["pgsql"])) {
|
||||
function indexAlgorithms(array $tableStatus): array {
|
||||
static $return = array();
|
||||
if (!$return) {
|
||||
$return = get_vals("SELECT amname FROM pg_am" . (min_version(9.6) ? " WHERE amtype = 'i'" : "") . " ORDER BY amname = 'btree' DESC, amname");
|
||||
$return = get_vals("SELECT amname FROM pg_am" . (min_version(9.6) ? " WHERE amtype = 'i'" : "") . " ORDER BY amname = '" . ($this->conn->flavor == 'cockroach' ? "prefix" : "btree") . "' DESC, amname");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -448,15 +450,14 @@ ORDER BY 1";
|
||||
get_rows("SELECT
|
||||
relname AS \"Name\",
|
||||
CASE relkind WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' ELSE 'table' END AS \"Engine\"" . ($has_size ? ",
|
||||
pg_table_size(oid) AS \"Data_length\",
|
||||
pg_indexes_size(oid) AS \"Index_length\"" : "") . ",
|
||||
obj_description(oid, 'pg_class') AS \"Comment\",
|
||||
pg_table_size(c.oid) AS \"Data_length\",
|
||||
pg_indexes_size(c.oid) AS \"Index_length\"" : "") . ",
|
||||
obj_description(c.oid, 'pg_class') AS \"Comment\",
|
||||
" . (min_version(12) ? "''" : "CASE WHEN relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\",
|
||||
reltuples as \"Rows\",
|
||||
inhparent AS inherited,
|
||||
reltuples AS \"Rows\",
|
||||
" . (min_version(10) ? "relispartition::int AS partition," : "") . "
|
||||
current_schema() AS nspname
|
||||
FROM pg_class
|
||||
LEFT JOIN pg_inherits ON inhrelid = oid
|
||||
FROM pg_class c
|
||||
WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
|
||||
AND relnamespace = " . driver()->nsOid . "
|
||||
" . ($name != "" ? "AND relname = " . q($name) : "ORDER BY relname")) as $row //! Auto_increment
|
||||
@@ -530,7 +531,7 @@ ORDER BY a.attnum") as $row
|
||||
$table_oid = driver()->tableOid($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, pg_am.amname as algorithm, pg_get_expr(pg_index.indpred, pg_index.indrelid, true) AS partial
|
||||
get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, amname, pg_get_expr(indpred, indrelid, true) AS partial, pg_get_expr(indexprs, indrelid) AS indexpr
|
||||
FROM pg_index
|
||||
JOIN pg_class ON indexrelid = oid
|
||||
JOIN pg_am ON pg_am.oid = pg_class.relam
|
||||
@@ -538,18 +539,17 @@ WHERE indrelid = $table_oid
|
||||
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]["type"] = ($row["partial"] ? "INDEX" : ($row["indisprimary"] ? "PRIMARY" : ($row["indisunique"] ? "UNIQUE" : "INDEX")));
|
||||
$return[$relname]["columns"] = array();
|
||||
$return[$relname]["descs"] = array();
|
||||
$return[$relname]["algorithm"] = $row["algorithm"];
|
||||
$return[$relname]["algorithm"] = $row["amname"];
|
||||
$return[$relname]["partial"] = $row["partial"];
|
||||
if ($row["indkey"]) {
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$relname]["columns"][] = $columns[$indkey];
|
||||
}
|
||||
foreach (explode(" ", $row["indoption"]) as $indoption) {
|
||||
$return[$relname]["descs"][] = (intval($indoption) & 1 ? '1' : null); // 1 - INDOPTION_DESC
|
||||
}
|
||||
$indexpr = preg_split('~(?<=\)), (?=\()~', $row["indexpr"]); //! '), (' used in expression
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$relname]["columns"][] = ($indkey ? $columns[$indkey] : array_shift($indexpr));
|
||||
}
|
||||
foreach (explode(" ", $row["indoption"]) as $indoption) {
|
||||
$return[$relname]["descs"][] = (intval($indoption) & 1 ? '1' : null); // 1 - INDOPTION_DESC
|
||||
}
|
||||
$return[$relname]["lengths"] = array();
|
||||
}
|
||||
@@ -824,7 +824,7 @@ FROM information_schema.routines
|
||||
WHERE routine_schema = current_schema() AND specific_name = ' . q($name));
|
||||
$return = idx($rows, 0, array());
|
||||
$return["returns"] = array("type" => $return["type_udt_name"]);
|
||||
$return["fields"] = get_rows('SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout
|
||||
$return["fields"] = get_rows('SELECT COALESCE(parameter_name, ordinal_position::text) AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout
|
||||
FROM information_schema.parameters
|
||||
WHERE specific_schema = current_schema() AND specific_name = ' . q($name) . '
|
||||
ORDER BY ordinal_position');
|
||||
@@ -1015,8 +1015,16 @@ AND typelem = 0"
|
||||
}
|
||||
|
||||
|
||||
function use_sql($database) {
|
||||
return "\connect " . idf_escape($database);
|
||||
function use_sql($database, $style = "") {
|
||||
$name = idf_escape($database);
|
||||
$return = "";
|
||||
if (preg_match('~CREATE~', $style)) {
|
||||
if ($style == "DROP+CREATE") {
|
||||
$return = "DROP DATABASE IF EXISTS $name;\n";
|
||||
}
|
||||
$return .= "CREATE DATABASE $name;\n"; //! get info from pg_database
|
||||
}
|
||||
return "$return\\connect $name";
|
||||
}
|
||||
|
||||
function show_variables() {
|
||||
|
@@ -11,7 +11,7 @@ if (isset($_GET["sqlite"])) {
|
||||
public $extension = "SQLite3";
|
||||
private $link;
|
||||
|
||||
function attach(?string $filename, string $username, string $password): string {
|
||||
function attach(string $filename, string $username, string $password): string {
|
||||
$this->link = new \SQLite3($filename);
|
||||
$version = $this->link->version();
|
||||
$this->server_info = $version["versionString"];
|
||||
@@ -75,11 +75,8 @@ if (isset($_GET["sqlite"])) {
|
||||
abstract class SqliteDb extends PdoDb {
|
||||
public $extension = "PDO_SQLite";
|
||||
|
||||
function attach(?string $filename, string $username, string $password): string {
|
||||
$this->dsn(DRIVER . ":$filename", "", "");
|
||||
$this->query("PRAGMA foreign_keys = 1");
|
||||
$this->query("PRAGMA busy_timeout = 500");
|
||||
return '';
|
||||
function attach(string $filename, string $username, string $password): string {
|
||||
return $this->dsn(DRIVER . ":$filename", "", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +84,7 @@ if (isset($_GET["sqlite"])) {
|
||||
|
||||
if (class_exists('Adminer\SqliteDb')) {
|
||||
class Db extends SqliteDb {
|
||||
function attach(?string $filename, string $username, string $password): string {
|
||||
function attach(string $filename, string $username, string $password): string {
|
||||
parent::attach($filename, $username, $password);
|
||||
$this->query("PRAGMA foreign_keys = 1");
|
||||
$this->query("PRAGMA busy_timeout = 500");
|
||||
@@ -122,7 +119,7 @@ if (isset($_GET["sqlite"])) {
|
||||
public $functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
|
||||
public $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
|
||||
|
||||
static function connect(?string $server, string $username, string $password) {
|
||||
static function connect(string $server, string $username, string $password) {
|
||||
if ($password != "") {
|
||||
return lang('Database does not support password.');
|
||||
}
|
||||
@@ -452,7 +449,7 @@ if (isset($_GET["sqlite"])) {
|
||||
* @param list<list<string>> $fields [process_field()], empty to preserve
|
||||
* @param string[] $originals [$original => idf_escape($new_column)], empty to preserve
|
||||
* @param string[] $foreign [format_foreign_key()], empty to preserve
|
||||
* @param numeric-string $auto_increment set auto_increment to this value, "" to preserve
|
||||
* @param numeric-string|'' $auto_increment set auto_increment to this value, "" to preserve
|
||||
* @param list<array{string, string, list<string>|'DROP'}> $indexes [[$type, $name, $columns]], empty to preserve
|
||||
* @param string $drop_check CHECK constraint to drop
|
||||
* @param string $add_check CHECK constraint to add
|
||||
@@ -680,7 +677,7 @@ if (isset($_GET["sqlite"])) {
|
||||
return "DELETE FROM " . table($table);
|
||||
}
|
||||
|
||||
function use_sql($database) {
|
||||
function use_sql($database, $style = "") {
|
||||
}
|
||||
|
||||
function trigger_sql($table) {
|
||||
|
@@ -41,16 +41,9 @@ 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 = 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";
|
||||
}
|
||||
echo "$create;\n";
|
||||
}
|
||||
if ($is_sql) {
|
||||
if ($style) {
|
||||
echo use_sql($db) . ";\n\n";
|
||||
echo use_sql($db, $style) . ";\n\n";
|
||||
}
|
||||
$out = "";
|
||||
|
||||
|
@@ -85,6 +85,10 @@ class Adminer {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/** Called after connecting and selecting a database */
|
||||
function afterConnect(): void {
|
||||
}
|
||||
|
||||
/** Headers to send before HTML output */
|
||||
function headers(): void {
|
||||
}
|
||||
@@ -197,10 +201,10 @@ class Adminer {
|
||||
$is_view = false;
|
||||
if (support("table")) {
|
||||
$is_view = is_view($tableStatus);
|
||||
if ($is_view) {
|
||||
$links["view"] = lang('Alter view');
|
||||
} else {
|
||||
if (!$is_view) {
|
||||
$links["create"] = lang('Alter table');
|
||||
} elseif (support("view")) {
|
||||
$links["view"] = lang('Alter view');
|
||||
}
|
||||
}
|
||||
if ($set !== null) {
|
||||
@@ -300,7 +304,7 @@ class Adminer {
|
||||
: (preg_match('~json~', $field["type"]) ? "<code class='jush-js'>$val</code>"
|
||||
: $val)
|
||||
));
|
||||
if (preg_match('~blob|bytea|raw|file~', $field["type"]) && !is_utf8($val)) {
|
||||
if (is_blob($field) && !is_utf8($val)) {
|
||||
$return = "<i>" . lang('%d byte(s)', strlen($original)) . "</i>";
|
||||
}
|
||||
return ($link ? "<a href='" . h($link) . "'" . (is_url($link) ? target_blank() : "") . ">$return</a>" : $return);
|
||||
@@ -664,7 +668,7 @@ class Adminer {
|
||||
}
|
||||
$history[$_GET["db"]][] = array($query, time(), $time); // not DB - $_GET["db"] is changed in database.inc.php //! respect $_GET["ns"]
|
||||
$sql_id = "sql-" . count($history[$_GET["db"]]);
|
||||
$return = "<a href='#$sql_id' class='toggle'>" . lang('SQL command') . "</a>\n";
|
||||
$return = "<a href='#$sql_id' class='toggle'>" . lang('SQL command') . "</a> <a href='' class='jsonly copy'>🗐</a>\n";
|
||||
if (!$failed && ($warnings = driver()->warnings())) {
|
||||
$id = "warnings-" . count($history[$_GET["db"]]);
|
||||
$return = "<a href='#$id' class='toggle'>" . lang('Warnings') . "</a>, $return<div id='$id' class='hidden'>\n$warnings</div>\n";
|
||||
@@ -699,7 +703,7 @@ class Adminer {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($key && $functions && !preg_match('~set|blob|bytea|raw|file|bool~', $field["type"])) {
|
||||
if ($key && $functions && !preg_match('~set|bool~', $field["type"]) && !is_blob($field)) {
|
||||
$return .= "/SQL";
|
||||
}
|
||||
}
|
||||
@@ -713,13 +717,13 @@ class Adminer {
|
||||
* @param ?string $table null in call.inc.php
|
||||
* @param Field $field
|
||||
* @param string $attrs attributes to use inside the tag
|
||||
* @param string|string[]|false|null $value false means original value
|
||||
* @return string custom input field or empty string for default
|
||||
*/
|
||||
function editInput(?string $table, array $field, string $attrs, ?string $value): string {
|
||||
function editInput(?string $table, array $field, string $attrs, $value): string {
|
||||
if ($field["type"] == "enum") {
|
||||
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
|
||||
. ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "")
|
||||
. enum_input("radio", $attrs, $field, $value, $value === 0 ? 0 : null) // 0 - empty value
|
||||
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='orig' checked><i>" . lang('original') . "</i></label> " : "")
|
||||
. enum_input("radio", $attrs, $field, $value, "NULL")
|
||||
;
|
||||
}
|
||||
return "";
|
||||
@@ -750,7 +754,7 @@ class Adminer {
|
||||
} elseif (preg_match('~^([+-]|\|\|)$~', $function)) {
|
||||
$return = idf_escape($name) . " $function $return";
|
||||
} elseif (preg_match('~^[+-] interval$~', $function)) {
|
||||
$return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) ? $value : $return);
|
||||
$return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) && JUSH != "pgsql" ? $value : $return);
|
||||
} elseif (preg_match('~^(addtime|subtime|concat)$~', $function)) {
|
||||
$return = "$function(" . idf_escape($name) . ", $return)";
|
||||
} elseif (preg_match('~^(md5|sha1|password|encrypt)$~', $function)) {
|
||||
@@ -839,7 +843,7 @@ class Adminer {
|
||||
}
|
||||
}
|
||||
}
|
||||
$result = connection()->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers
|
||||
$result = connection()->query($query, 1); // 1 - MYSQLI_USE_RESULT
|
||||
if ($result) {
|
||||
$insert = "";
|
||||
$buffer = "";
|
||||
@@ -915,7 +919,7 @@ class Adminer {
|
||||
* @return string filename without extension
|
||||
*/
|
||||
function dumpFilename(string $identifier): string {
|
||||
return friendly_url($identifier != "" ? $identifier : (SERVER != "" ? SERVER : "localhost"));
|
||||
return friendly_url($identifier != "" ? $identifier : (SERVER ?: "localhost"));
|
||||
}
|
||||
|
||||
/** Send headers for export
|
||||
@@ -962,6 +966,12 @@ class Adminer {
|
||||
echo (support("scheme") ? "<a href='" . h(ME) . "scheme='>" . ($_GET["ns"] != "" ? lang('Alter schema') : lang('Create schema')) . "</a>\n" : "");
|
||||
echo ($_GET["ns"] !== "" ? '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n" : "");
|
||||
echo (support("privileges") ? "<a href='" . h(ME) . "privileges='>" . lang('Privileges') . "</a>\n" : "");
|
||||
if ($_GET["ns"] !== "") {
|
||||
echo (support("routine") ? "<a href='#routines'>" . lang('Routines') . "</a>\n" : "");
|
||||
echo (support("sequence") ? "<a href='#sequences'>" . lang('Sequences') . "</a>\n" : "");
|
||||
echo (support("type") ? "<a href='#user-types'>" . lang('User types') . "</a>\n" : "");
|
||||
echo (support("event") ? "<a href='#events'>" . lang('Events') . "</a>\n" : "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -984,7 +994,7 @@ class Adminer {
|
||||
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)) . "'>($name) " . h($username . ($server != "" ? "@" . adminer()->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
|
||||
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($name) " . h("$username@" . ($server != "" ? adminer()->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1042,7 +1052,15 @@ class Adminer {
|
||||
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";
|
||||
echo "var jushLinks = { " . JUSH . ":";
|
||||
json_row(js_escape(ME) . (support("table") ? "table" : "select") . '=$&', '/\b(' . implode('|', $links) . ')\b/g', false);
|
||||
if (support('routine')) {
|
||||
foreach (routines() as $row) {
|
||||
json_row(js_escape(ME) . 'function=' . urlencode($row["SPECIFIC_NAME"]) . '&name=$&', '/\b' . preg_quote($row["ROUTINE_NAME"], '/') . '(?=["`]?\()/g', false);
|
||||
}
|
||||
}
|
||||
json_row('');
|
||||
echo "};\n";
|
||||
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
|
||||
echo "jushLinks.$val = jushLinks." . JUSH . ";\n";
|
||||
}
|
||||
@@ -1100,7 +1118,7 @@ class Adminer {
|
||||
foreach ($tables as $table => $status) {
|
||||
$table = "$table"; // do not highlight "0" as active everywhere
|
||||
$name = adminer()->tableName($status);
|
||||
if ($name != "" && !$status["inherited"]) {
|
||||
if ($name != "" && !$status["partition"]) {
|
||||
echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"'
|
||||
. bold($_GET["select"] == $table || $_GET["edit"] == $table, "select")
|
||||
. " title='" . lang('Select data') . "'>" . lang('select') . "</a> "
|
||||
@@ -1115,4 +1133,19 @@ class Adminer {
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
|
||||
/** Get process list
|
||||
* @return list<string[]> [$row]
|
||||
*/
|
||||
function processList(): array {
|
||||
return process_list();
|
||||
}
|
||||
|
||||
/** Kill a process
|
||||
* @param numeric-string $id
|
||||
* @return Result|bool
|
||||
*/
|
||||
function killProcess(string $id) {
|
||||
return kill_process($id);
|
||||
}
|
||||
}
|
||||
|
@@ -172,7 +172,7 @@ if (isset($_GET["username"]) && !class_exists('Adminer\Db')) {
|
||||
|
||||
$connection = '';
|
||||
if (isset($_GET["username"]) && is_string(get_password())) {
|
||||
list($host, $port) = explode(":", SERVER, 2);
|
||||
list(, $port) = host_port(SERVER);
|
||||
if (preg_match('~^\s*([-+]?\d+)~', $port, $match) && ($match[1] < 1024 || $match[1] > 65535)) { // is_numeric('80#') would still connect to port 80
|
||||
auth_error(lang('Connecting to privileged ports is not allowed.'), $permanent);
|
||||
}
|
||||
|
@@ -91,8 +91,8 @@ Adminer::$instance =
|
||||
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
|
||||
|
||||
define('Adminer\JUSH', Driver::$jush);
|
||||
define('Adminer\SERVER', $_GET[DRIVER]); // read from pgsql=localhost, '' means default server, null means no server
|
||||
define('Adminer\DB', $_GET["db"]); // for the sake of speed and size
|
||||
define('Adminer\SERVER', "" . $_GET[DRIVER]); // read from pgsql=localhost, '' means default server
|
||||
define('Adminer\DB', "$_GET[db]"); // for the sake of speed and size
|
||||
define(
|
||||
'Adminer\ME',
|
||||
preg_replace('~\?.*~', '', relative_uri()) . '?'
|
||||
@@ -108,3 +108,5 @@ include "../adminer/include/xxtea.inc.php";
|
||||
include "../adminer/include/auth.inc.php";
|
||||
include "./include/editing.inc.php";
|
||||
include "./include/connect.inc.php";
|
||||
|
||||
adminer()->afterConnect();
|
||||
|
@@ -18,7 +18,7 @@ abstract class SqlDb {
|
||||
/** Connect to server
|
||||
* @return string error message
|
||||
*/
|
||||
abstract function attach(?string $server, string $username, string $password): string;
|
||||
abstract function attach(string $server, string $username, string $password): string;
|
||||
|
||||
/** Quote string to use in SQL
|
||||
* @return string escaped string enclosed in '
|
||||
|
@@ -34,7 +34,7 @@ abstract class SqlDriver {
|
||||
/** Connect to the database
|
||||
* @return Db|string string for error
|
||||
*/
|
||||
static function connect(?string $server, string $username, string $password) {
|
||||
static function connect(string $server, string $username, string $password) {
|
||||
$connection = new Db;
|
||||
return ($connection->attach($server, $username, $password) ?: $connection);
|
||||
}
|
||||
@@ -189,11 +189,6 @@ abstract class SqlDriver {
|
||||
return $idf;
|
||||
}
|
||||
|
||||
/** Convert operator so it can be used in search */
|
||||
function convertOperator(string $operator): string {
|
||||
return $operator;
|
||||
}
|
||||
|
||||
/** Convert value returned by database to actual value
|
||||
* @param Field $field
|
||||
*/
|
||||
@@ -258,8 +253,7 @@ abstract class SqlDriver {
|
||||
return !is_view($table_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of supported index algorithms, first one is default
|
||||
/** Return list of supported index algorithms, first one is default
|
||||
* @param TableStatus $tableStatus
|
||||
* @return list<string>
|
||||
*/
|
||||
@@ -281,7 +275,7 @@ AND CHECK_CLAUSE NOT LIKE '% IS NOT NULL'", $this->conn); // ignore default IS N
|
||||
}
|
||||
|
||||
/** Get all fields in the current schema
|
||||
* @return array<list<array{field:string, null:bool, type:string, length:?numeric-string, primary?:numeric-string}>>
|
||||
* @return array<list<array{field:string, null:bool, type:string, length:?numeric-string}>> optionally also 'primary'
|
||||
*/
|
||||
function allFields(): array {
|
||||
$return = array();
|
||||
|
@@ -150,13 +150,13 @@ function select_input(string $attrs, array $options, ?string $value = "", string
|
||||
* @param string $key or "" to close the object
|
||||
* @param string|int $val
|
||||
*/
|
||||
function json_row(string $key, $val = null): void {
|
||||
function json_row(string $key, $val = null, bool $escape = true): void {
|
||||
static $first = true;
|
||||
if ($first) {
|
||||
echo "{";
|
||||
}
|
||||
if ($key != "") {
|
||||
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : 'null');
|
||||
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? ($escape ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : $val) : 'null');
|
||||
$first = false;
|
||||
} else {
|
||||
echo "\n}\n";
|
||||
@@ -314,7 +314,7 @@ function edit_fields(array $fields, array $collations, $type = "TABLE", array $f
|
||||
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'>";
|
||||
echo "<input name='fields[$i][field]' value='" . h($field["field"]) . "' data-maxlength='64' autocapitalize='off' aria-labelledby='label-name'" . (isset($_POST["add"][$i-1]) ? " autofocus" : "") . ">";
|
||||
}
|
||||
echo input_hidden("fields[$i][orig]", $orig);
|
||||
edit_type("fields[$i]", $field, $collations, $foreign_keys);
|
||||
|
@@ -264,9 +264,10 @@ function where(array $where, array $fields = array()): string {
|
||||
$field_type = $field["type"];
|
||||
$return[] = $column
|
||||
. (JUSH == "sql" && $field_type == "json" ? " = CAST(" . q($val) . " AS JSON)"
|
||||
: (JUSH == "pgsql" && preg_match('~^json~', $field_type) ? "::jsonb = " . q($val) . "::jsonb"
|
||||
: (JUSH == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
|
||||
: (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($field, q($val)))))
|
||||
: " = " . unconvert_field($field, q($val))))))
|
||||
; //! enum and set
|
||||
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";
|
||||
@@ -291,7 +292,7 @@ function where_check(string $val, array $fields = array()): string {
|
||||
* @param int $i condition order
|
||||
* @param string $column column identifier
|
||||
*/
|
||||
function where_link(int $i, string $column, string $value, string $operator = "="): string {
|
||||
function where_link(int $i, string $column, ?string $value, string $operator = "="): string {
|
||||
return "&where%5B$i%5D%5Bcol%5D=" . urlencode($column) . "&where%5B$i%5D%5Bop%5D=" . urlencode(($value !== null ? $operator : "IS NULL")) . "&where%5B$i%5D%5Bval%5D=" . urlencode($value);
|
||||
}
|
||||
|
||||
@@ -337,11 +338,11 @@ function get_settings(string $cookie): array {
|
||||
}
|
||||
|
||||
/** Get setting stored in a cookie
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
function get_setting(string $key, string $cookie = "adminer_settings") {
|
||||
$settings = get_settings($cookie);
|
||||
return $settings[$key];
|
||||
function get_setting(string $key, string $cookie = "adminer_settings", $default = null) {
|
||||
return idx(get_settings($cookie), $key, $default);
|
||||
}
|
||||
|
||||
/** Store settings to a cookie
|
||||
@@ -685,7 +686,7 @@ function file_open_lock(string $filename) {
|
||||
if (!$fp) {
|
||||
return;
|
||||
}
|
||||
chmod($filename, 0660);
|
||||
@chmod($filename, 0660); // @ - may not be permitted
|
||||
if (!flock($fp, LOCK_EX)) {
|
||||
fclose($fp);
|
||||
return;
|
||||
@@ -790,6 +791,13 @@ function select_value($val, string $link, array $field, ?string $text_length): s
|
||||
return adminer()->selectVal($return, $link, $field, $val);
|
||||
}
|
||||
|
||||
/** Check whether the field type is blob or equivalent
|
||||
* @param Field $field
|
||||
*/
|
||||
function is_blob(array $field): bool {
|
||||
return preg_match('~blob|bytea|raw|file~', $field["type"]) && !in_array($field["type"], idx(driver()->structuredTypes(), lang('User types'), array()));
|
||||
}
|
||||
|
||||
/** Check whether the string is e-mail address */
|
||||
function is_mail(?string $email): bool {
|
||||
$atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name
|
||||
@@ -808,7 +816,17 @@ function is_url(?string $string): bool {
|
||||
* @param Field $field
|
||||
*/
|
||||
function is_shortable(array $field): bool {
|
||||
return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea~', $field["type"]);
|
||||
return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea|hstore~', $field["type"]);
|
||||
}
|
||||
|
||||
/** Split server into host and (port or socket)
|
||||
* @return array{0: string, 1: string}
|
||||
*/
|
||||
function host_port(string $server) {
|
||||
return (preg_match('~^(\[(.+)]|([^:]+)):([^:]+)$~', $server, $match) // [a:b] - IPv6
|
||||
? array($match[2] . $match[3], $match[4])
|
||||
: array($server, '')
|
||||
);
|
||||
}
|
||||
|
||||
/** Get query to compute number of found rows
|
||||
|
@@ -179,15 +179,17 @@ function hidden_fields_get(): void {
|
||||
/** Print enum or set input field
|
||||
* @param 'radio'|'checkbox' $type
|
||||
* @param Field $field
|
||||
* @param mixed $value string|array
|
||||
* @param string|string[]|false|null $value false means original value
|
||||
*/
|
||||
function enum_input(string $type, string $attrs, array $field, $value, ?string $empty = null): string {
|
||||
function enum_input(string $type, string $attrs, array $field, $value, string $empty = ""): string {
|
||||
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) {
|
||||
$prefix = ($field["type"] == "enum" ? "val-" : "");
|
||||
$checked = (is_array($value) ? in_array("null", $value) : $value === null);
|
||||
$return = ($field["null"] && $prefix ? "<label><input type='$type'$attrs value='null'" . ($checked ? " checked" : "") . "><i>$empty</i></label>" : "");
|
||||
foreach ($matches[1] as $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>';
|
||||
$checked = (is_array($value) ? in_array($prefix . $val, $value) : $value === $val);
|
||||
$return .= " <label><input type='$type'$attrs value='" . h($prefix . $val) . "'" . ($checked ? ' checked' : '') . '>' . h(adminer()->editVal($val, $field)) . '</label>';
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
@@ -208,13 +210,13 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false
|
||||
$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;
|
||||
}
|
||||
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
|
||||
$attrs = " name='fields[$name]" . ($field["type"] == "enum" || $field["type"] == "set" ? "[]" : "") . "'$disabled" . ($autofocus ? " autofocus" : "");
|
||||
echo driver()->unconvertFunction($field) . " ";
|
||||
$table = $_GET["edit"] ?: $_GET["select"];
|
||||
if ($field["type"] == "enum") {
|
||||
@@ -234,13 +236,8 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false
|
||||
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 enum_input("checkbox", $attrs, $field, (is_string($value) ? explode(",", $value) : $value));
|
||||
} elseif (is_blob($field) && ini_bool("file_uploads")) {
|
||||
echo "<input type='file' name='fields-$name'>";
|
||||
} elseif ($function == "json" || preg_match('~^jsonb?$~', $field["type"])) {
|
||||
echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
|
||||
@@ -295,14 +292,16 @@ function process_input(array $field) {
|
||||
}
|
||||
$idf = bracket_escape($field["field"]);
|
||||
$function = idx($_POST["function"], $idf);
|
||||
$value = $_POST["fields"][$idf];
|
||||
$value = idx($_POST["fields"], $idf);
|
||||
if ($field["type"] == "enum" || driver()->enumLength($field)) {
|
||||
if ($value == -1) {
|
||||
$value = $value[0];
|
||||
if ($value == "orig") {
|
||||
return false;
|
||||
}
|
||||
if ($value == "") {
|
||||
if ($value == "null") {
|
||||
return "NULL";
|
||||
}
|
||||
$value = substr($value, 4); // 4 - strlen("val-")
|
||||
}
|
||||
if ($field["auto_increment"] && $value == "") {
|
||||
return null;
|
||||
@@ -324,7 +323,7 @@ function process_input(array $field) {
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
if (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
|
||||
if (is_blob($field) && ini_bool("file_uploads")) {
|
||||
$file = get_file("fields-$idf");
|
||||
if (!is_string($file)) {
|
||||
return false; //! report errors
|
||||
|
@@ -67,7 +67,7 @@ class Plugins {
|
||||
function __call(string $name, array $params) {
|
||||
$args = array();
|
||||
foreach ($params as $key => $val) {
|
||||
// some plugins accept params by reference - we don't need to propage it outside, just to the other plugins
|
||||
// some plugins accept params by reference - we don't need to propagate it outside, just to the other plugins
|
||||
$args[] = &$params[$key];
|
||||
}
|
||||
$return = null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
namespace Adminer;
|
||||
|
||||
const VERSION = "5.3.0";
|
||||
const VERSION = "5.4.0";
|
||||
|
@@ -12,6 +12,7 @@ if (preg_match('~MyISAM|M?aria' . (min_version(5.7, '10.2.2') ? '|InnoDB' : '')
|
||||
$index_types[] = "SPATIAL";
|
||||
}
|
||||
$indexes = indexes($TABLE);
|
||||
$fields = fields($TABLE);
|
||||
$primary = array();
|
||||
if (JUSH == "mongo") { // doesn't support primary key
|
||||
$primary = $indexes["_id_"];
|
||||
@@ -38,7 +39,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
if ($column != "") {
|
||||
$length = idx($index["lengths"], $key);
|
||||
$desc = idx($index["descs"], $key);
|
||||
$set[] = idf_escape($column) . ($length ? "(" . (+$length) . ")" : "") . ($desc ? " DESC" : "");
|
||||
$set[] = ($fields[$column] ? idf_escape($column) : $column) . ($length ? "(" . (+$length) . ")" : "") . ($desc ? " DESC" : "");
|
||||
$columns[] = $column;
|
||||
$lengths[] = ($length ?: null);
|
||||
$descs[] = $desc;
|
||||
@@ -81,7 +82,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
|
||||
|
||||
page_header(lang('Indexes'), $error, array("table" => $TABLE), h($TABLE));
|
||||
|
||||
$fields = array_keys(fields($TABLE));
|
||||
$fields_keys = array_keys($fields);
|
||||
if ($_POST["add"]) {
|
||||
foreach ($row["indexes"] as $key => $index) {
|
||||
if ($index["columns"][count($index["columns"])] != "") {
|
||||
@@ -138,7 +139,7 @@ if (support("partial_indexes")) {
|
||||
if ($primary) {
|
||||
echo "<tr><td>PRIMARY<td>";
|
||||
foreach ($primary["columns"] as $key => $column) {
|
||||
echo select_input(" disabled", $fields, $column);
|
||||
echo select_input(" disabled", $fields_keys, $column);
|
||||
echo "<label><input disabled type='checkbox'>" . lang('descending') . "</label> ";
|
||||
}
|
||||
echo "<td><td>\n";
|
||||
@@ -158,7 +159,7 @@ foreach ($row["indexes"] as $index) {
|
||||
foreach ($index["columns"] as $key => $column) {
|
||||
echo "<span>" . select_input(
|
||||
" name='indexes[$j][columns][$i]' title='" . lang('Column') . "'",
|
||||
($fields ? array_combine($fields, $fields) : $fields),
|
||||
($fields && ($column == "" || $fields[$column]) ? array_combine($fields_keys, $fields_keys) : array()),
|
||||
$column,
|
||||
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape(JUSH == "sql" ? "" : $_GET["indexes"] . "_") . "')"
|
||||
);
|
||||
|
@@ -27,7 +27,7 @@ Lang::$translations = array(
|
||||
'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
|
||||
'Disable %s or enable %s or %s extensions.' => 'Zakažte %s nebo povolte rozšíření %s nebo %s.',
|
||||
'Session support must be enabled.' => 'Session proměnné musí být povolené.',
|
||||
'Session expired, please login again.' => 'Session vypršela, přihlašte se prosím znovu.',
|
||||
'Session expired, please login again.' => 'Session vypršela, přihlaste se prosím znovu.',
|
||||
'The action will be performed after successful login with the same credentials.' => 'Akce bude provedena po úspěšném přihlášení se stejnými přihlašovacími údaji.',
|
||||
'%s version: %s through PHP extension %s' => 'Verze %s: %s přes PHP rozšíření %s',
|
||||
'Refresh' => 'Obnovit',
|
||||
@@ -76,6 +76,7 @@ Lang::$translations = array(
|
||||
'Webserver file %s' => 'Soubor %s na webovém serveru',
|
||||
'Run file' => 'Spustit soubor',
|
||||
'File does not exist.' => 'Soubor neexistuje.',
|
||||
'Increase %s.' => 'Zvyšte %s.',
|
||||
'File uploads are disabled.' => 'Nahrávání souborů není povoleno.',
|
||||
'Unable to upload a file.' => 'Nepodařilo se nahrát soubor.',
|
||||
'Maximum allowed file size is %sB.' => 'Maximální povolená velikost souboru je %sB.',
|
||||
@@ -195,6 +196,7 @@ Lang::$translations = array(
|
||||
'Partition name' => 'Název oddílu',
|
||||
'Values' => 'Hodnoty',
|
||||
'Inherits from' => 'Zděděná z',
|
||||
'Inherited by' => 'Zděděné',
|
||||
|
||||
'View' => 'Pohled',
|
||||
'Materialized view' => 'Materializovaný pohled',
|
||||
|
@@ -5,8 +5,8 @@ Lang::$translations = array(
|
||||
'Login' => 'ログイン',
|
||||
'Logout successful.' => 'ログアウトしました。',
|
||||
'Invalid credentials.' => '不正なログインです。',
|
||||
'Server' => 'サーバ',
|
||||
'Username' => 'ユーザ名',
|
||||
'Server' => 'サーバー',
|
||||
'Username' => 'ユーザー名',
|
||||
'Password' => 'パスワード',
|
||||
'Loaded plugins' => '読込済プラグイン',
|
||||
'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>)',
|
||||
@@ -20,14 +20,14 @@ Lang::$translations = array(
|
||||
'Select database' => 'データベースを選択してください',
|
||||
'Invalid database.' => '不正なデータベースです。',
|
||||
'Table has been dropped.' => 'テーブルを削除しました。',
|
||||
'Table has been altered.' => 'テーブルを変更しました。',
|
||||
'Table has been altered.' => 'テーブルの設定を変更しました。',
|
||||
'Table has been created.' => 'テーブルを作成しました。',
|
||||
'Alter table' => 'テーブルを変更',
|
||||
'Alter table' => 'テーブルの設定を変更',
|
||||
'Create table' => 'テーブルを作成',
|
||||
'Table name' => 'テーブル名',
|
||||
'engine' => 'エンジン',
|
||||
'collation' => '照合順序',
|
||||
'Column name' => '列名',
|
||||
'collation' => 'コレーション',
|
||||
'Column name' => 'カラム名',
|
||||
'Type' => '型',
|
||||
'Length' => '長さ',
|
||||
'Auto Increment' => '連番',
|
||||
@@ -38,16 +38,16 @@ Lang::$translations = array(
|
||||
'Database has been dropped.' => 'データベースを削除しました。',
|
||||
'Database has been created.' => 'データベースを作成しました。',
|
||||
'Database has been renamed.' => 'データベースの名前を変えました。',
|
||||
'Database has been altered.' => 'データベースを変更しました。',
|
||||
'Alter database' => 'データベースを変更',
|
||||
'Database has been altered.' => 'データベースの設定を変更しました。',
|
||||
'Alter database' => 'データベースの設定を変更',
|
||||
'Create database' => 'データベースを作成',
|
||||
'SQL command' => 'SQLコマンド',
|
||||
'Logout' => 'ログアウト',
|
||||
'Use' => '使用',
|
||||
'No tables.' => 'テーブルがありません。',
|
||||
'select' => '選択',
|
||||
'Item has been deleted.' => '項目を削除しました。',
|
||||
'Item has been updated.' => '項目を更新しました。',
|
||||
'Item has been deleted.' => 'レコードを削除しました。',
|
||||
'Item has been updated.' => 'レコードを更新しました。',
|
||||
'Edit' => '編集',
|
||||
'Insert' => '挿入',
|
||||
'Save and insert next' => '保存/追加',
|
||||
@@ -56,18 +56,18 @@ Lang::$translations = array(
|
||||
'Database' => 'データベース',
|
||||
'DB' => 'DB',
|
||||
'Routines' => 'ルーチン',
|
||||
'Indexes have been altered.' => '索引を変更しました。',
|
||||
'Indexes' => '索引',
|
||||
'Alter indexes' => '索引の変更',
|
||||
'Indexes have been altered.' => 'インデックスを変更しました。',
|
||||
'Indexes' => 'インデックス',
|
||||
'Alter indexes' => 'インデックスを変更',
|
||||
'Add next' => '追加',
|
||||
'Language' => '言語',
|
||||
'Select' => '選択',
|
||||
'New item' => '項目の作成',
|
||||
'New item' => '新規レコードを挿入',
|
||||
'Search' => '検索',
|
||||
'Sort' => 'ソート',
|
||||
'descending' => '降順',
|
||||
'Limit' => '制約',
|
||||
'Limit rows' => '行数の制約',
|
||||
'Limit rows' => '表示行数を制限',
|
||||
'No rows.' => '行がありません。',
|
||||
'Action' => '動作',
|
||||
'edit' => '編集',
|
||||
@@ -82,17 +82,17 @@ Lang::$translations = array(
|
||||
'Foreign keys' => '外部キー',
|
||||
'Triggers' => 'トリガー',
|
||||
'View' => 'ビュー',
|
||||
'Materialized view' => 'マテビュー',
|
||||
'Full table scan' => 'テーブルの全スキャン',
|
||||
'Materialized view' => 'マテリアライズドビュー',
|
||||
'Full table scan' => 'テーブルを全スキャン',
|
||||
'Unable to select the table' => 'テーブルを選択できません',
|
||||
'Invalid CSRF token. Send the form again.' => '不正なCSRFトークン。再送信してください。',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Adminerからのリクエストを送信しない場合はこのページを閉じてください。',
|
||||
'Invalid CSRF token. Send the form again.' => '不正なCSRFトークンです。フォームを再送信してください。',
|
||||
'If you did not send this request from Adminer then close this page.' => 'Adminerからのリクエストでない場合はこのページを閉じてください。',
|
||||
'Comment' => 'コメント',
|
||||
'Default values' => '規定値',
|
||||
'Default values' => '既定値',
|
||||
'%d byte(s)' => '%d バイト',
|
||||
'No commands to execute.' => '実行するコマンドがありません。',
|
||||
'Unable to upload a file.' => 'ファイルをアップロードできません。',
|
||||
'File upload' => 'ファイルをアップロード',
|
||||
'File upload' => 'アップロード',
|
||||
'File uploads are disabled.' => 'ファイルのアップロードが無効です。',
|
||||
'Routine has been called, %d row(s) affected.' => 'ルーチンを呼びました。%d 行を変更しました。',
|
||||
'Call' => '呼出し',
|
||||
@@ -103,7 +103,7 @@ Lang::$translations = array(
|
||||
'Session support must be enabled.' => 'セッションを有効にしてください。',
|
||||
'Session expired, please login again.' => 'セッションの期限切れ。ログインし直してください。',
|
||||
'The action will be performed after successful login with the same credentials.' => '同じアカウントで正しくログインすると作業を実行します。',
|
||||
'Text length' => '文字列の長さ',
|
||||
'Text length' => '文字数を丸める',
|
||||
'Foreign key has been dropped.' => '外部キーを削除しました。',
|
||||
'Foreign key has been altered.' => '外部キーを変更しました。',
|
||||
'Foreign key has been created.' => '外部キーを作成しました。',
|
||||
@@ -112,12 +112,12 @@ Lang::$translations = array(
|
||||
'Change' => '変更',
|
||||
'Source' => 'ソース',
|
||||
'Target' => 'ターゲット',
|
||||
'Add column' => '列を追加',
|
||||
'Add column' => 'カラムを追加',
|
||||
'Alter' => '変更',
|
||||
'Add foreign key' => '外部キーを追加',
|
||||
'ON DELETE' => 'ON DELETE',
|
||||
'ON UPDATE' => 'ON UPDATE',
|
||||
'Index Type' => '索引の型',
|
||||
'Index Type' => 'インデックスの型',
|
||||
'length' => '長さ',
|
||||
'View has been dropped.' => 'ビューを削除しました。',
|
||||
'View has been altered.' => 'ビューを変更しました。',
|
||||
@@ -126,25 +126,25 @@ Lang::$translations = array(
|
||||
'Create view' => 'ビューを作成',
|
||||
'Name' => '名称',
|
||||
'Process list' => 'プロセス一覧',
|
||||
'%d process(es) have been killed.' => '%d プロセスを強制終了しました。',
|
||||
'Kill' => '強制終了',
|
||||
'Parameter name' => '参数名',
|
||||
'Database schema' => '構造',
|
||||
'Create procedure' => 'プロシージャの作成',
|
||||
'Create function' => '関数の作成',
|
||||
'Routine has been dropped.' => 'ルーチンを作成しました。',
|
||||
'%d process(es) have been killed.' => '%d プロセスを終了しました。',
|
||||
'Kill' => 'プロセスを終了',
|
||||
'Parameter name' => 'パラメータ名',
|
||||
'Database schema' => 'スキーマ',
|
||||
'Create procedure' => 'プロシージャを作成',
|
||||
'Create function' => '関数を作成',
|
||||
'Routine has been dropped.' => 'ルーチンを削除しました。',
|
||||
'Routine has been altered.' => 'ルーチンを変更しました。',
|
||||
'Routine has been created.' => 'ルーチンを作成しました。',
|
||||
'Alter function' => '関数の変更',
|
||||
'Alter procedure' => 'プロシージャの変更',
|
||||
'Alter function' => '関数を変更',
|
||||
'Alter procedure' => 'プロシージャを変更',
|
||||
'Return type' => '戻り値の型',
|
||||
'Add trigger' => 'トリガーの追加',
|
||||
'Add trigger' => 'トリガーを追加',
|
||||
'Trigger has been dropped.' => 'トリガーを削除しました。',
|
||||
'Trigger has been altered.' => 'トリガーを変更しました。',
|
||||
'Trigger has been created.' => 'トリガーを追加しました。',
|
||||
'Alter trigger' => 'トリガーの変更',
|
||||
'Create trigger' => 'トリガーの作成',
|
||||
'Time' => '時間',
|
||||
'Alter trigger' => 'トリガーを変更',
|
||||
'Create trigger' => 'トリガーを作成',
|
||||
'Time' => 'タイミング',
|
||||
'Event' => 'イベント',
|
||||
'%s version: %s through PHP extension %s' => '%sバージョン:%s、 PHP拡張機能 %s',
|
||||
'%d / ' => '%d / ',
|
||||
@@ -157,11 +157,11 @@ Lang::$translations = array(
|
||||
'User has been altered.' => 'ユーザを変更しました。',
|
||||
'User has been created.' => 'ユーザを作成しました。',
|
||||
'Hashed' => 'Hashed',
|
||||
'Column' => '列',
|
||||
'Columns' => '列',
|
||||
'Column' => 'カラム',
|
||||
'Columns' => 'カラム',
|
||||
'Routine' => 'ルーチン',
|
||||
'Grant' => '権限の付与',
|
||||
'Revoke' => '権限の取消し',
|
||||
'Grant' => '権限を付与',
|
||||
'Revoke' => '権限を取り消す',
|
||||
'Logged as: %s' => 'ログ:%s',
|
||||
'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.' => '大きなSQLファイルは、FTP経由でアップロードしてサーバからインポートしてください。',
|
||||
@@ -172,16 +172,16 @@ Lang::$translations = array(
|
||||
'Tables' => 'テーブル',
|
||||
'Data' => 'データ',
|
||||
'Output' => '出力',
|
||||
'open' => '開く',
|
||||
'open' => 'ブラウザに表示',
|
||||
'save' => '保存',
|
||||
'Format' => '形式',
|
||||
'Functions' => '関数',
|
||||
'Aggregation' => '集合',
|
||||
'Aggregation' => '集約関数',
|
||||
'Event has been dropped.' => 'イベントを削除しました。',
|
||||
'Event has been altered.' => 'イベントを変更しました。',
|
||||
'Event has been created.' => 'イベントを作成しました。',
|
||||
'Alter event' => '変更',
|
||||
'Create event' => '作成',
|
||||
'Alter event' => 'イベントを変更',
|
||||
'Create event' => 'イベントを作成',
|
||||
'Start' => '開始',
|
||||
'End' => '終了',
|
||||
'Every' => '毎回',
|
||||
@@ -194,24 +194,24 @@ Lang::$translations = array(
|
||||
'Tables have been moved.' => 'テーブルを移動しました。',
|
||||
'Tables and views' => 'テーブルとビュー',
|
||||
'Engine' => 'エンジン',
|
||||
'Collation' => '照合順序',
|
||||
'Collation' => 'コレーション',
|
||||
'Data Length' => 'データ長',
|
||||
'Index Length' => '索引長',
|
||||
'Index Length' => 'インデックス長',
|
||||
'Data Free' => '空き',
|
||||
'Rows' => '行数',
|
||||
',' => ',',
|
||||
'0123456789' => '0123456789',
|
||||
'Analyze' => '分析',
|
||||
'Optimize' => '最適化',
|
||||
'Vacuum' => '不要領域の回収',
|
||||
'Check' => 'チェック',
|
||||
'Vacuum' => '不要領域を回収(Vacuum)',
|
||||
'Check' => '検査',
|
||||
'Repair' => '修復',
|
||||
'Truncate' => '空にする',
|
||||
'Move to other database' => '別のデータベースへ移動',
|
||||
'Move to other database' => '他のデータベースへ移動',
|
||||
'Move' => '移動',
|
||||
'Save and continue edit' => '保存して継続',
|
||||
'original' => '元',
|
||||
'%d item(s) have been affected.' => '%d 個を更新しました。',
|
||||
'%d item(s) have been affected.' => '%d レコードを更新しました。',
|
||||
'Whole result' => '全結果',
|
||||
'Tables have been dropped.' => 'テーブルを削除しました。',
|
||||
'Tables have been optimized.' => 'テーブルを最適化しました。',
|
||||
@@ -223,7 +223,7 @@ Lang::$translations = array(
|
||||
'Values' => '値',
|
||||
'%d row(s) have been imported.' => '%d 行をインポートしました。',
|
||||
'File must be in UTF-8 encoding.' => 'ファイルをUTF-8で保存してください。',
|
||||
'Show structure' => '構造',
|
||||
'Show structure' => 'スキーマ',
|
||||
'anywhere' => '任意',
|
||||
'Import' => 'インポート',
|
||||
'Stop on error' => 'エラーの場合は停止',
|
||||
@@ -233,9 +233,9 @@ Lang::$translations = array(
|
||||
'[yyyy]-mm-dd' => '[yyyy]/mm/dd',
|
||||
'History' => '履歴',
|
||||
'Variables' => '変数',
|
||||
'Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.' => 'ソースとターゲットの列は同じデータ型でなければなりません。ターゲット列に索引があり、データが存在しなければなりません。',
|
||||
'Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.' => 'ソースとターゲットのカラムは同じデータ型でなければなりません。ターゲットカラムにインデックスがあり、データが存在しなければなりません。',
|
||||
'Relations' => '関係',
|
||||
'Run file' => 'ファイルを実行',
|
||||
'Run file' => '実行',
|
||||
'Clear' => '消去',
|
||||
'Maximum allowed file size is %sB.' => '最大ファイルサイズは %sB です。',
|
||||
'Numbers' => '数字',
|
||||
@@ -244,7 +244,7 @@ Lang::$translations = array(
|
||||
'Binary' => 'バイナリ',
|
||||
'Lists' => 'リスト',
|
||||
'Editor' => 'エディタ',
|
||||
'Webserver file %s' => 'Webサーバファイル %s',
|
||||
'Webserver file %s' => 'ファイル名 %s',
|
||||
'File does not exist.' => 'ファイルは存在しません。',
|
||||
'%d in total' => '合計 %d',
|
||||
'Permanent login' => '永続的にログイン',
|
||||
@@ -268,15 +268,15 @@ Lang::$translations = array(
|
||||
'Type has been dropped.' => 'ユーザー定義型を削除しました。',
|
||||
'Type has been created.' => 'ユーザー定義型を追加しました。',
|
||||
'Ctrl+click on a value to modify it.' => 'Ctrl+クリックで値を修正します。',
|
||||
'Use edit link to modify this value.' => 'この値を修正するとリンクを編集します。',
|
||||
'Use edit link to modify this value.' => 'この値を修正するにはリンクを使用してください。',
|
||||
'last' => '最終',
|
||||
'From server' => 'サーバーから実行',
|
||||
'From server' => 'サーバー上のファイル',
|
||||
'System' => 'データベース種類',
|
||||
'empty' => '空',
|
||||
'Network' => 'ネットワーク型',
|
||||
'Geometry' => 'ジオメトリ型',
|
||||
'File exists.' => 'ファイルが既に存在します。',
|
||||
'Item%s has been inserted.' => '%s項目を挿入しました。',
|
||||
'Item%s has been inserted.' => '%sレコードを挿入しました。',
|
||||
'now' => '現在の日時',
|
||||
'%d query(s) executed OK.' => '%d クエリーを実行しました。',
|
||||
'Show only errors' => 'エラーのみ表示',
|
||||
@@ -287,29 +287,30 @@ Lang::$translations = array(
|
||||
'Tables have been copied.' => 'テーブルをコピーしました。',
|
||||
'Copy' => 'コピー',
|
||||
'overwrite' => '上書き',
|
||||
'Permanent link' => 'パーマネントリンク',
|
||||
'Edit all' => 'すべて編集',
|
||||
'Permanent link' => '固定リンク',
|
||||
'Edit all' => '一括編集',
|
||||
'Selected' => '選択中',
|
||||
'Modify' => '編集',
|
||||
'Load more data' => 'さらにデータを表示',
|
||||
'Compute' => '再計算',
|
||||
'Saving' => '保存しています...',
|
||||
'Checks' => 'CHECK制約',
|
||||
'Create check' => 'CHECK制約を追加',
|
||||
'Alter check' => 'CHECK制約を編集',
|
||||
'Check has been created.' => 'CHECK制約を追加しました。',
|
||||
'Check has been altered.' => 'CHECK制約を編集しました。',
|
||||
'Check has been dropped.' => 'CHECK制約を削除しました。',
|
||||
|
||||
'screenshot' => 'スクリーンショット',
|
||||
'Algorithm' => 'アルゴリズム',
|
||||
'Condition' => '条件',
|
||||
'Inherits from' => '継承元',
|
||||
'HH:MM:SS' => '時:分:秒',
|
||||
'Selected' => '選択済',
|
||||
'Modify' => '修正',
|
||||
'Load more data' => '続きを読み込み',
|
||||
'Loading' => '読み込み中',
|
||||
'Size' => 'サイズ',
|
||||
'Compute' => '算出',
|
||||
'Saving' => '保存中',
|
||||
'yes' => 'はい',
|
||||
'no' => 'いいえ',
|
||||
'Default value' => '既定値',
|
||||
|
||||
// Table check constraints
|
||||
'Checks' => 'チェック',
|
||||
'Create check' => 'チェックを作成',
|
||||
'Alter check' => 'チェックを変更',
|
||||
'Check has been created.' => 'チェックを作成しました。',
|
||||
'Check has been altered.' => 'チェックを変更しました。',
|
||||
'Check has been dropped.' => 'チェックを削除しました。',
|
||||
|
||||
'screenshot' => 'スクリーンショット',
|
||||
);
|
||||
|
||||
// run `php ../../lang.php ja` to update this file
|
||||
|
@@ -76,6 +76,7 @@ Lang::$translations = array(
|
||||
'Webserver file %s' => 'Plik %s na serwerze',
|
||||
'Run file' => 'Uruchom z pliku',
|
||||
'File does not exist.' => 'Plik nie istnieje.',
|
||||
'Increase %s.' => 'Zwiększ %s.',
|
||||
'File uploads are disabled.' => 'Wgrywanie plików jest wyłączone.',
|
||||
'Unable to upload a file.' => 'Wgranie pliku było niemożliwe.',
|
||||
'Maximum allowed file size is %sB.' => 'Maksymalna wielkość pliku to %sB.',
|
||||
@@ -196,6 +197,7 @@ Lang::$translations = array(
|
||||
'Partition name' => 'Nazwa partycji',
|
||||
'Values' => 'Wartości',
|
||||
'Inherits from' => 'Dziedziczy po',
|
||||
'Inherited by' => 'Odziedziczone przez',
|
||||
|
||||
'View' => 'Perspektywa',
|
||||
'Materialized view' => 'Zmaterializowana perspektywa',
|
||||
|
@@ -77,6 +77,7 @@ Lang::$translations = array(
|
||||
'Webserver file %s' => 'Xx %s',
|
||||
'Run file' => 'Xx',
|
||||
'File does not exist.' => 'Xx.',
|
||||
'Increase %s.' => 'Xx %s.',
|
||||
'File uploads are disabled.' => 'Xx.',
|
||||
'Unable to upload a file.' => 'Xx.',
|
||||
'Maximum allowed file size is %sB.' => 'Xx %sB.',
|
||||
@@ -197,6 +198,7 @@ Lang::$translations = array(
|
||||
'Partition name' => 'Xx',
|
||||
'Values' => 'Xx',
|
||||
'Inherits from' => 'Xx',
|
||||
'Inherited by' => 'Xx',
|
||||
|
||||
'View' => 'Xx',
|
||||
'Materialized view' => 'Xx',
|
||||
|
@@ -62,7 +62,7 @@ if (isset($_GET["function"])) {
|
||||
</table>
|
||||
<?php echo script("editFields();"); ?>
|
||||
</div>
|
||||
<p><?php textarea("definition", $row["definition"]); ?>
|
||||
<p><?php textarea("definition", $row["definition"], 20); ?>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if ($PROCEDURE != "") { ?>
|
||||
|
@@ -5,7 +5,7 @@ if (support("kill")) {
|
||||
if ($_POST && !$error) {
|
||||
$killed = 0;
|
||||
foreach ((array) $_POST["kill"] as $val) {
|
||||
if (kill_process($val)) {
|
||||
if (adminer()->killProcess($val)) {
|
||||
$killed++;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ page_header(lang('Process list'), $error);
|
||||
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
|
||||
// HTML valid because there is always at least one process
|
||||
$i = -1;
|
||||
foreach (process_list() as $i => $row) {
|
||||
foreach (adminer()->processList() as $i => $row) {
|
||||
if (!$i) {
|
||||
echo "<thead><tr lang='en'>" . (support("kill") ? "<th>" : "");
|
||||
foreach ($row as $key => $val) {
|
||||
|
@@ -18,7 +18,8 @@ $base_left = -1;
|
||||
/** @var array{fields:Field[], pos:array{float, float}, references:string[][][]}[] */
|
||||
$schema = array(); // table => array("fields" => array(name => field), "pos" => array(top, left), "references" => array(table => array(left => array(source, target))))
|
||||
$referenced = array(); // target_table => array(table => array(left => target_column))
|
||||
$lefts = array(); // float => bool
|
||||
/** @var array<numeric-string, bool> */
|
||||
$lefts = array();
|
||||
$all_fields = driver()->allFields();
|
||||
foreach (table_status('', true) as $table => $table_status) {
|
||||
if (is_view($table_status)) {
|
||||
|
@@ -7,7 +7,7 @@ if ($_GET["script"] == "db") {
|
||||
$sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
|
||||
foreach (table_status() as $name => $table_status) {
|
||||
json_row("Comment-$name", h($table_status["Comment"]));
|
||||
if (!is_view($table_status)) {
|
||||
if (!is_view($table_status) || preg_match('~materialized~i', $table_status["Engine"])) {
|
||||
foreach (array("Engine", "Collation") as $key) {
|
||||
json_row("$key-$name", h($table_status[$key]));
|
||||
}
|
||||
|
@@ -354,7 +354,7 @@ if (!$columns && support("table")) {
|
||||
echo "<th id='th[" . h(bracket_escape($key)) . "]'>" . script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});", "");
|
||||
$fun = apply_sql_function($val["fun"], $name); //! columns looking like functions
|
||||
$sortable = isset($field["privileges"]["order"]) || $fun;
|
||||
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 ($sortable ? "<a href='" . h($href . ($order[0] == $column || $order[0] == $key ? $desc : '')) . "'>$fun</a>" : $fun); // $order[0] == $key - COUNT(*)
|
||||
echo "<span class='column hidden'>";
|
||||
if ($sortable) {
|
||||
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
|
||||
@@ -423,7 +423,7 @@ if (!$columns && support("table")) {
|
||||
}
|
||||
|
||||
$link = "";
|
||||
if (preg_match('~blob|bytea|raw|file~', $field["type"]) && $val != "") {
|
||||
if (is_blob($field) && $val != "") {
|
||||
$link = ME . 'download=' . urlencode($TABLE) . '&field=' . urlencode($key) . $unique_idf;
|
||||
}
|
||||
if (!$link && $val !== null) { // link related items
|
||||
|
@@ -4,9 +4,13 @@ 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();
|
||||
if ($_POST["format"] == "sql") {
|
||||
echo "$_POST[query]\n";
|
||||
} else {
|
||||
adminer()->dumpTable("", "");
|
||||
adminer()->dumpData("", "table", $_POST["query"]);
|
||||
adminer()->dumpFooter();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -65,11 +69,9 @@ if (!$error && $_POST) {
|
||||
}
|
||||
$commands = 0;
|
||||
$errors = array();
|
||||
$parse = '[\'"' . (JUSH == "sql" ? '`#' : (JUSH == "sqlite" ? '`[' : (JUSH == "mssql" ? '[' : ''))) . ']|/\*|' . $line_comment . '|$' . (JUSH == "pgsql" ? '|\$[^$]*\$' : '');
|
||||
$parse = '[\'"' . (JUSH == "sql" ? '`#' : (JUSH == "sqlite" ? '`[' : (JUSH == "mssql" ? '[' : ''))) . ']|/\*|' . $line_comment . '|$' . (JUSH == "pgsql" ? '|\$([a-zA-Z]\w*)?\$' : '');
|
||||
$total_start = microtime(true);
|
||||
$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"]);
|
||||
|
||||
while ($query != "") {
|
||||
if (!$offset && preg_match("~^$space*+DELIMITER\\s+(\\S+)~i", $query, $match)) {
|
||||
@@ -174,7 +176,7 @@ if (!$error && $_POST) {
|
||||
$id = "export-$commands";
|
||||
echo ", <a href='#$id'>" . lang('Export') . "</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "") . "<span id='$id' class='hidden'>: "
|
||||
. html_select("output", adminer()->dumpOutput(), $adminer_export["output"]) . " "
|
||||
. html_select("format", $dump_format, $adminer_export["format"])
|
||||
. html_select("format", adminer()->dumpFormat(), $adminer_export["format"])
|
||||
. input_hidden("query", $q)
|
||||
. "<input type='submit' name='export' value='" . lang('Export') . "'>" . input_token() . "</span>\n"
|
||||
. "</form>\n"
|
||||
@@ -250,8 +252,11 @@ if (!isset($_GET["import"])) {
|
||||
} else {
|
||||
echo "<fieldset><legend>" . lang('File upload') . "</legend><div>";
|
||||
$gz = (extension_loaded("zlib") ? "[.gz]" : "");
|
||||
$max_file_uploads = "max_file_uploads";
|
||||
$max_file_uploads_value = ini_get($max_file_uploads);
|
||||
echo (ini_bool("file_uploads")
|
||||
? "SQL$gz (< " . ini_get("upload_max_filesize") . "B): <input type='file' name='sql_file[]' multiple>\n$execute" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary
|
||||
? "SQL$gz (< " . ini_get("upload_max_filesize") . "B): <input type='file' name='sql_file[]' multiple>\n" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary
|
||||
. script("qsl('input').onchange = partialArg(fileChange, $max_file_uploads_value, '" . lang('Increase %s.', "$max_file_uploads = $max_file_uploads_value") . "')") . $execute
|
||||
: lang('File uploads are disabled.')
|
||||
);
|
||||
echo "</div></fieldset>\n";
|
||||
|
@@ -128,14 +128,18 @@ input.wayoff { left: -1000px; position: absolute; }
|
||||
.js .foot { display: none; }
|
||||
.js #menuopen { display: block; position: absolute; top: 3px; left: 6px; }
|
||||
.nojs #menu { position: static; }
|
||||
.rtl.js #foot { left: auto; right: 0; }
|
||||
.rtl .pages { right: auto; }
|
||||
.rtl #content { margin-right: 10px; }
|
||||
.rtl #breadcrumb { right: auto; }
|
||||
.rtl.js #menuopen { left: auto; right: 6px; }
|
||||
.rtl #content { margin-left: 0 !important; margin-right: 10px; }
|
||||
.rtl #breadcrumb { left: auto !important; right: 48px; }
|
||||
}
|
||||
|
||||
@media print {
|
||||
#lang, #menu { display: none; }
|
||||
#lang, #menu, .logout { display: none; }
|
||||
#content { margin-left: 1em; }
|
||||
#breadcrumb { left: 1em; }
|
||||
.rtl #content { margin-left: auto; margin-right: 1em; }
|
||||
.rtl #breadcrumb { left: auto; right: 1em; }
|
||||
.nowrap td, .nowrap th, td.nowrap { white-space: normal; }
|
||||
}
|
||||
|
@@ -93,6 +93,13 @@ function messagesPrint(parent) {
|
||||
for (const el of qsa('.toggle', parent)) {
|
||||
el.onclick = partial(toggle, el.getAttribute('href').substr(1));
|
||||
}
|
||||
for (const el of qsa('.copy', parent)) {
|
||||
el.onclick = () => {
|
||||
navigator.clipboard.writeText(qs('code', el.parentElement).innerText).then(() => el.textContent = '✓');
|
||||
setTimeout(() => el.textContent = '🗐', 1000);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -384,7 +391,7 @@ function editingAddRow(focus) {
|
||||
*/
|
||||
function editingRemoveRow(name) {
|
||||
const field = formField(this.form, this.name.replace(/[^[]+(.+)/, name));
|
||||
field.parentNode.removeChild(field);
|
||||
field.remove();
|
||||
parentTag(this, 'tr').style.display = 'none';
|
||||
return false;
|
||||
}
|
||||
@@ -456,7 +463,7 @@ function editingLengthChange() {
|
||||
*/
|
||||
function editingLengthFocus() {
|
||||
const td = this.parentNode;
|
||||
if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) {
|
||||
if (/^(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) {
|
||||
const edit = qs('#enum-edit');
|
||||
edit.value = enumValues(this.value);
|
||||
td.appendChild(edit);
|
||||
@@ -665,6 +672,17 @@ function sqlSubmit(form, root) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if PHP can handle the uploaded files
|
||||
* @param number
|
||||
* @param string
|
||||
* @param Event
|
||||
*/
|
||||
function fileChange(event, maxFileUploads, message) {
|
||||
if (event.target.files.length > maxFileUploads) {
|
||||
alert(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Handle changing trigger time or event
|
||||
|
@@ -235,8 +235,8 @@ function formChecked(input, name) {
|
||||
function tableClick(event, click) {
|
||||
const td = parentTag(event.target, 'td');
|
||||
let text;
|
||||
if (td && (text = td.getAttribute('data-text'))) {
|
||||
if (selectClick.call(td, event, +text, td.getAttribute('data-warning'))) {
|
||||
if (td && (text = td.dataset.text)) {
|
||||
if (selectClick.call(td, event, +text, td.dataset.warning)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -525,14 +525,14 @@ function functionChange() {
|
||||
if (selectValue(this)) {
|
||||
if (input.origType === undefined) {
|
||||
input.origType = input.type;
|
||||
input.origMaxLength = input.getAttribute('data-maxlength');
|
||||
input.origMaxLength = input.dataset.maxlength;
|
||||
}
|
||||
input.removeAttribute('data-maxlength');
|
||||
delete input.dataset.maxlength;
|
||||
input.type = 'text';
|
||||
} else if (input.origType) {
|
||||
input.type = input.origType;
|
||||
if (input.origMaxLength >= 0) {
|
||||
input.setAttribute('data-maxlength', input.origMaxLength);
|
||||
input.dataset.maxlength = input.origMaxLength;
|
||||
}
|
||||
}
|
||||
oninput({target: input});
|
||||
@@ -736,9 +736,10 @@ function selectLoadMore(limit, loading) {
|
||||
return !ajax(href, request => {
|
||||
const tbody = document.createElement('tbody');
|
||||
tbody.innerHTML = request.responseText;
|
||||
adminerHighlighter(qsa('code', tbody));
|
||||
qs('#table').appendChild(tbody);
|
||||
if (tbody.children.length < limit) {
|
||||
a.parentNode.removeChild(a);
|
||||
a.remove();
|
||||
} else {
|
||||
a.href = href.replace(/\d+$/, page => +page + 1);
|
||||
a.innerHTML = title;
|
||||
@@ -843,7 +844,7 @@ function cloneNode(el) {
|
||||
|
||||
oninput = event => {
|
||||
const target = event.target;
|
||||
const maxLength = target.getAttribute('data-maxlength');
|
||||
const maxLength = target.dataset.maxlength;
|
||||
alterClass(target, 'maxlength', target.value && maxLength != null && target.value.length > maxLength); // maxLength could be 0
|
||||
};
|
||||
|
||||
|
@@ -22,7 +22,14 @@ if ($comment != "") {
|
||||
echo "<p class='nowrap'>" . lang('Comment') . ": " . h($comment) . "\n";
|
||||
}
|
||||
|
||||
function tables_links($tables) {
|
||||
if ($fields) {
|
||||
adminer()->tableStructurePrint($fields, $table_status);
|
||||
}
|
||||
|
||||
/** Print links to tables
|
||||
* @param list<string> $tables
|
||||
*/
|
||||
function tables_links(array $tables): void {
|
||||
echo "<ul>\n";
|
||||
foreach ($tables as $table) {
|
||||
echo "<li><a href='" . h(ME . "table=" . urlencode($table)) . "'>" . h($table) . "</a>";
|
||||
@@ -34,8 +41,6 @@ $inherits = driver()->inheritsFrom($TABLE);
|
||||
if ($inherits) {
|
||||
echo "<h3>" . lang('Inherits from') . "</h3>\n";
|
||||
tables_links($inherits);
|
||||
} elseif ($fields) {
|
||||
adminer()->tableStructurePrint($fields, $table_status);
|
||||
}
|
||||
|
||||
if (support("indexes") && driver()->supportsIndex($table_status)) {
|
||||
@@ -110,7 +115,7 @@ if (support(is_view($table_status) ? "view_trigger" : "trigger")) {
|
||||
|
||||
$inherited = driver()->inheritedTables($TABLE);
|
||||
if ($inherited) {
|
||||
echo "<h3 id='partitions'>" . lang('Partitions') . "</h3>\n";
|
||||
echo "<h3 id='partitions'>" . lang('Inherited by') . "</h3>\n";
|
||||
$partition = driver()->partitionsInfo($TABLE);
|
||||
if ($partition) {
|
||||
echo "<p><code class='jush-" . JUSH . "'>BY " . h("$partition[partition_by]($partition[partition])") . "</code>\n";
|
||||
|
@@ -16,33 +16,62 @@ Icons from http://FlatIcon.com:
|
||||
Background adapted from "All Work and No Play", http://thenewcode.com/1008/SVG-Movie-Backgrounds-Andys-Room-and-Overlook-Hotel
|
||||
*/
|
||||
html {
|
||||
--bg: #41658a;
|
||||
--bleu: #41658a;
|
||||
--lahtbleu: var(--bleu);
|
||||
--poiple: #414073;
|
||||
--lahtpoiple: var(--poiple);
|
||||
--oringe: #ec5f12;
|
||||
--oringe-c-fru: rgba(236, 95, 18, 0.6);
|
||||
--pail-oringe: #f39561;
|
||||
--menu-w: 20em;
|
||||
--icon-w: 2em;
|
||||
--bg: var(--bleu);
|
||||
--inv-fg: #fff;
|
||||
--shado: var(--fg);
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
:focus {
|
||||
outline: thin solid var(--oringe-c-fru);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
--bleu: #314c68;
|
||||
--lahtbleu: #649dd6;
|
||||
--lahtpoiple: #706fc7;
|
||||
--inv-fg: #eee;
|
||||
--pail-oringe: #c66734;
|
||||
--fg: var(--inv-fg);
|
||||
--dim: #111;
|
||||
--shado: var(--dim);
|
||||
}
|
||||
.jush {
|
||||
--text-color: #f0f0f0;
|
||||
}
|
||||
pre.jush {
|
||||
background-color: var(--dim);
|
||||
}
|
||||
}
|
||||
body {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
background: #41658a;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
p {
|
||||
margin-right: 0;
|
||||
}
|
||||
a {
|
||||
color: #41658a;
|
||||
color: var(--lahtbleu);
|
||||
}
|
||||
a:visited {
|
||||
color: #414073;
|
||||
color: var(--lahtpoiple);
|
||||
}
|
||||
a:link:hover,
|
||||
a:visited:hover,
|
||||
a:link:focus,
|
||||
a:visited:focus {
|
||||
color: #ec5f12;
|
||||
color: var(--oringe);
|
||||
text-decoration: underline;
|
||||
outline: none;
|
||||
}
|
||||
@@ -59,11 +88,18 @@ textarea,
|
||||
fieldset {
|
||||
border: thin solid rgba(65, 101, 138, 0.3);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
input:not([type="image"]),
|
||||
select,
|
||||
textarea {
|
||||
background: #333;
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.sqlarea {
|
||||
background: #fff;
|
||||
border: thin solid rgba(65, 101, 138, 0.3) !important;
|
||||
width: auto !important;
|
||||
}
|
||||
@@ -80,7 +116,7 @@ input[type="button"] {
|
||||
.error,
|
||||
.message {
|
||||
margin-right: 0;
|
||||
color: #fff;
|
||||
color: var(--inv-fg);
|
||||
}
|
||||
.error,
|
||||
.error b {
|
||||
@@ -99,7 +135,9 @@ input[type="button"] {
|
||||
.message .time {
|
||||
color: #e7ffaf;
|
||||
}
|
||||
thead a sup,
|
||||
.js .checkable .checked a,
|
||||
thead a,
|
||||
thead th a,
|
||||
.error > a,
|
||||
.error div > a,
|
||||
.error p > a,
|
||||
@@ -108,10 +146,10 @@ thead a sup,
|
||||
.message p > a {
|
||||
color: #cce2f8;
|
||||
}
|
||||
thead a:link:hover,
|
||||
thead a:visited:hover,
|
||||
thead a:link:focus,
|
||||
thead a:visited:focus,
|
||||
thead a:hover,
|
||||
thead a:focus,
|
||||
thead th a:hover,
|
||||
thead th a:focus,
|
||||
.error > a:link:hover,
|
||||
.error > a:visited:hover,
|
||||
.error > a:link:focus,
|
||||
@@ -136,11 +174,17 @@ thead a:visited:focus,
|
||||
.message p > a:visited:hover,
|
||||
.message p > a:link:focus,
|
||||
.message p > a:visited:focus {
|
||||
color: #f39561;
|
||||
color: var(--pail-oringe);
|
||||
}
|
||||
thead a sup {
|
||||
color: inherit;
|
||||
}
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
code {
|
||||
background: var(--dim);
|
||||
}
|
||||
code.jush-sql {
|
||||
display: inline-block;
|
||||
padding: 0.3em 0.5em 0.2em;
|
||||
@@ -152,21 +196,21 @@ th > code {
|
||||
background: transparent;
|
||||
}
|
||||
.version {
|
||||
color: #fff;
|
||||
color: inherit;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#content,
|
||||
#menu,
|
||||
.rtl #content,
|
||||
.rtl #menu {
|
||||
margin: 0;
|
||||
margin: 0 !important;
|
||||
padding: 0 20px 1.5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#content {
|
||||
order: 2;
|
||||
flex: 1 1 auto;
|
||||
max-width: calc(100% - 20em);
|
||||
flex: 0 0 auto;
|
||||
width: calc(100vw - var(--menu-w));
|
||||
}
|
||||
#content,
|
||||
.footer {
|
||||
@@ -186,12 +230,12 @@ h2,
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
color: var(--inv-fg);
|
||||
}
|
||||
#breadcrumb {
|
||||
z-index: 2;
|
||||
white-space: normal;
|
||||
background: #70a37f;
|
||||
color: #fff;
|
||||
padding: 0.1em 2.5em 0.1em 20px;
|
||||
height: auto;
|
||||
margin: 0 -20px -2em;
|
||||
@@ -212,9 +256,9 @@ thead a:visited,
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
padding: 2em 20px 0.5em;
|
||||
padding: var(--icon-w) 20px 0.5em;
|
||||
border-bottom-style: none;
|
||||
color: #fff;
|
||||
color: var(--inv-fg);
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
h1,
|
||||
@@ -233,12 +277,28 @@ h2 a {
|
||||
h2 {
|
||||
background: #79b473;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#content,
|
||||
.footer {
|
||||
background-color: var(--dim);
|
||||
}
|
||||
#breadcrumb {
|
||||
background: #547a5f;
|
||||
}
|
||||
h2 {
|
||||
background: #5f8c59;
|
||||
}
|
||||
}
|
||||
h2 + *,
|
||||
h2 + .hidden + *,
|
||||
h2 + * > :first-child,
|
||||
h2 + .hidden + * > :first-child {
|
||||
h2 + * > :first-child:not(fieldset),
|
||||
h2 + .hidden + * > :first-child:not(fieldset) {
|
||||
margin-top: 0;
|
||||
}
|
||||
h2 + form:has( > fieldset:first-child),
|
||||
h2 + .hidden + form:has( > fieldset:first-child) {
|
||||
margin-top: -0.8em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
@@ -251,14 +311,17 @@ fieldset {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
input.default {
|
||||
background-color: #414073;
|
||||
background-color: var(--poiple);
|
||||
box-shadow: none;
|
||||
}
|
||||
input.required {
|
||||
outline: thin dashed #ec5f12;
|
||||
outline: thin dashed var(--oringe);
|
||||
outline-offset: 1px;
|
||||
box-shadow: none;
|
||||
}
|
||||
.odds tbody tr:nth-child(2n) {
|
||||
background: transparent;
|
||||
}
|
||||
table {
|
||||
border-style: none;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
@@ -287,9 +350,13 @@ th:last-child {
|
||||
}
|
||||
thead th,
|
||||
thead td {
|
||||
border-color: #fff;
|
||||
border-color: var(--inv-fg);
|
||||
padding: 0.5em 0.8em 0.6em;
|
||||
color: #fff;
|
||||
}
|
||||
.js .checkable thead .checked th,
|
||||
thead th,
|
||||
thead td {
|
||||
color: var(--inv-fg);
|
||||
}
|
||||
thead th {
|
||||
text-align: left;
|
||||
@@ -297,7 +364,7 @@ thead th {
|
||||
}
|
||||
.js .checkable thead .checked th,
|
||||
thead th {
|
||||
background: #414073;
|
||||
background: var(--poiple);
|
||||
position: relative;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
@@ -306,14 +373,15 @@ thead th {
|
||||
}
|
||||
.js .checkable thead .checked td,
|
||||
thead td {
|
||||
background: #41658a;
|
||||
background: var(--bleu);
|
||||
}
|
||||
.js .column {
|
||||
z-index: 1;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
line-height: 1.25em
|
||||
line-height: 1.25em;
|
||||
border: none;
|
||||
}
|
||||
.column a {
|
||||
margin-left: 0.2em;
|
||||
@@ -332,7 +400,7 @@ thead td {
|
||||
}
|
||||
.column a:hover,
|
||||
.column a:focus {
|
||||
background-color: #ec5f12;
|
||||
background-color: var(--oringe);
|
||||
}
|
||||
tbody tr:nth-child(even) td {
|
||||
background: rgba(65, 101, 138, 0.06);
|
||||
@@ -346,6 +414,13 @@ tbody tr:nth-child(n):hover td {
|
||||
tbody tr:nth-child(n):hover th {
|
||||
background: rgba(236, 72, 18, 0.2);
|
||||
}
|
||||
.js .checkable tbody .checked td,
|
||||
.js .checkable tbody .checked th {
|
||||
color: var(--fg);
|
||||
}
|
||||
.js .checkable tbody .checked td code {
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.js .checkable tbody .checked td {
|
||||
background: rgba(236, 72, 18, 0.25);
|
||||
}
|
||||
@@ -362,27 +437,47 @@ tbody tr:nth-child(n):hover th {
|
||||
.js .checkable tbody .checked:hover th {
|
||||
background: rgba(236, 72, 18, 0.45);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
table {
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
td,
|
||||
th {
|
||||
border-color: #494c4f;
|
||||
}
|
||||
thead th,
|
||||
thead td {
|
||||
border-color: #444;
|
||||
}
|
||||
tbody tr:nth-child(even) td {
|
||||
background: rgba(65, 101, 138, 0.09);
|
||||
}
|
||||
tbody tr:nth-child(even) th {
|
||||
background: rgba(65, 64, 115, 0.09);
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
width: 1.2em;
|
||||
background-color: #4c3957;
|
||||
background-size: 66%;
|
||||
filter: none;
|
||||
}
|
||||
.icon-plus {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' width='512px' height='512px' viewBox='0 0 456 456' style='enable-background:new 0 0 456 456;'%3E%3Cg%3E%3Cpolygon points='456,157.566 298.433,157.566 298.433,0 157.567,0 157.567,157.566 0,157.566 0,298.434 157.567,298.434 157.567,456 298.433,456 298.433,298.434 456,298.434' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' width='512px' height='512px' viewBox='0 0 456 456'%3E%3Cg%3E%3Cpolygon points='456,157.566 298.433,157.566 298.433,0 157.567,0 157.567,157.566 0,157.566 0,298.434 157.567,298.434 157.567,456 298.433,456 298.433,298.434 456,298.434' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.column a[href*="&asc%5B"],
|
||||
.icon-up {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' viewBox='0 0 490 490' style='enable-background:new 0 0 490 490;' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M490,474.459H0L245.009,15.541L490,474.459z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 490 490' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M490,474.459H0L245.009,15.541L490,474.459z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.column a[href*="&desc%5B"],
|
||||
.icon-down {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' viewBox='0 0 490 490' style='enable-background:new 0 0 490 490;' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M0,15.541h490L244.991,474.459L0,15.541z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 490 490' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M0,15.541h490L244.991,474.459L0,15.541z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.icon-cross {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' viewBox='0 0 174.239 174.239' style='enable-background:new 0 0 174.239 174.239;' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M146.537,1.047c-1.396-1.396-3.681-1.396-5.077,0L89.658,52.849c-1.396,1.396-3.681,1.396-5.077,0L32.78,1.047 c-1.396-1.396-3.681-1.396-5.077,0L1.047,27.702c-1.396,1.396-1.396,3.681,0,5.077l51.802,51.802c1.396,1.396,1.396,3.681,0,5.077 L1.047,141.46c-1.396,1.396-1.396,3.681,0,5.077l26.655,26.655c1.396,1.396,3.681,1.396,5.077,0l51.802-51.802 c1.396-1.396,3.681-1.396,5.077,0l51.801,51.801c1.396,1.396,3.681,1.396,5.077,0l26.655-26.655c1.396-1.396,1.396-3.681,0-5.077 l-51.801-51.801c-1.396-1.396-1.396-3.681,0-5.077l51.801-51.801c1.396-1.396,1.396-3.681,0-5.077L146.537,1.047z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 174.239 174.239' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M146.537,1.047c-1.396-1.396-3.681-1.396-5.077,0L89.658,52.849c-1.396,1.396-3.681,1.396-5.077,0L32.78,1.047 c-1.396-1.396-3.681-1.396-5.077,0L1.047,27.702c-1.396,1.396-1.396,3.681,0,5.077l51.802,51.802c1.396,1.396,1.396,3.681,0,5.077 L1.047,141.46c-1.396,1.396-1.396,3.681,0,5.077l26.655,26.655c1.396,1.396,3.681,1.396,5.077,0l51.802-51.802 c1.396-1.396,3.681-1.396,5.077,0l51.801,51.801c1.396,1.396,3.681,1.396,5.077,0l26.655-26.655c1.396-1.396,1.396-3.681,0-5.077 l-51.801-51.801c-1.396-1.396-1.396-3.681,0-5.077l51.801-51.801c1.396-1.396,1.396-3.681,0-5.077L146.537,1.047z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.column a[href="#fieldset-search"] {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' viewBox='0 0 310.088 310.088' enable-background='new 0 0 310.088 310.088' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='m299.85,250.413l-62.808-62.808c-3.982-3.982-10.437-3.982-14.418,0l-3.539,3.539-18.586-18.586c29.709-42.872 25.472-102.152-12.716-140.34-42.958-42.958-112.606-42.958-155.563,0s-42.958,112.606 0,155.563c38.189,38.188 97.468,42.425 140.34,12.716l18.586,18.586-3.539,3.539c-3.982,3.981-3.982,10.437 0,14.418l62.808,62.808c13.651,13.651 35.785,13.651 49.436,0s13.65-35.784-0.001-49.435zm-251.368-78.895c-33.921-33.921-33.921-89.115-0.001-123.036 33.922-33.921 89.117-33.922 123.037-0.001v0.001c33.922,33.921 33.922,89.115 0,123.036-16.96,16.961-39.239,25.441-61.518,25.441-22.279,0-44.558-8.48-61.518-25.441z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 310.088 310.088' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='m299.85,250.413l-62.808-62.808c-3.982-3.982-10.437-3.982-14.418,0l-3.539,3.539-18.586-18.586c29.709-42.872 25.472-102.152-12.716-140.34-42.958-42.958-112.606-42.958-155.563,0s-42.958,112.606 0,155.563c38.189,38.188 97.468,42.425 140.34,12.716l18.586,18.586-3.539,3.539c-3.982,3.981-3.982,10.437 0,14.418l62.808,62.808c13.651,13.651 35.785,13.651 49.436,0s13.65-35.784-0.001-49.435zm-251.368-78.895c-33.921-33.921-33.921-89.115-0.001-123.036 33.922-33.921 89.117-33.922 123.037-0.001v0.001c33.922,33.921 33.922,89.115 0,123.036-16.96,16.961-39.239,25.441-61.518,25.441-22.279,0-44.558-8.48-61.518-25.441z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.loadmore,
|
||||
.rtl .loadmore {
|
||||
@@ -402,27 +497,33 @@ tbody tr:nth-child(n):hover th {
|
||||
.footer ~ div {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
.js #menuopen,
|
||||
#lang,
|
||||
.logout {
|
||||
z-index: 3;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
position: fixed;
|
||||
width: var(--icon-w);
|
||||
height: var(--icon-w);
|
||||
box-shadow: none;
|
||||
}
|
||||
#lang,
|
||||
.logout {
|
||||
position: fixed;
|
||||
}
|
||||
#lang {
|
||||
top: 0;
|
||||
left: 18em;
|
||||
--lang-offset: calc(var(--menu-w) - var(--icon-w));
|
||||
left: var(--lang-offset);
|
||||
}
|
||||
.rtl #lang {
|
||||
right: 18em;
|
||||
right: var(--lang-offset);
|
||||
}
|
||||
.rtl .logout {
|
||||
margin: 0;
|
||||
}
|
||||
.js #menuopen button,
|
||||
#lang select,
|
||||
#logout {
|
||||
opacity: 0;
|
||||
@@ -434,8 +535,9 @@ tbody tr:nth-child(n):hover th {
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
#lang:before,
|
||||
.logout:before {
|
||||
.js #menuopen::before,
|
||||
#lang label::before,
|
||||
.logout::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -447,33 +549,70 @@ tbody tr:nth-child(n):hover th {
|
||||
background: #2d3047 center no-repeat;
|
||||
background-size: 70%;
|
||||
}
|
||||
#lang:before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' viewBox='0 0 470 470' enable-background='new 0 0 470 470' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='m432.5,227.5h-77.031c-0.611-37.438-5.782-73.616-14.771-105.694h50.518c4.143,0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-55.112c-8.018-24.165-18.316-45.521-30.553-62.656-2.408-3.371-7.093-4.153-10.462-1.745-3.371,2.407-4.152,7.092-1.745,10.462 10.618,14.868 19.688,33.199 26.965,53.939h-77.809v-69.306c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v69.306h-77.81c7.277-20.74 16.347-39.071 26.965-53.939 2.407-3.37 1.626-8.055-1.745-10.462-3.372-2.407-8.055-1.625-10.462,1.745-12.237,17.135-22.535,38.492-30.553,62.656h-55.112c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5 7.5,7.5h50.518c-8.988,32.078-14.159,68.256-14.771,105.694h-77.03c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5 7.5,7.5h77.031c0.611,37.438 5.782,73.616 14.771,105.694h-50.519c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5 7.5,7.5h55.112c8.019,24.169 18.32,45.529 30.56,62.666 1.464,2.049 3.77,3.142 6.11,3.142 1.508,0 3.031-0.454 4.353-1.397 3.37-2.408 4.151-7.092 1.744-10.463-10.621-14.869-19.693-33.204-26.972-53.947h77.81v69.305c0,4.143 3.357,7.5 7.5,7.5s7.5-3.357 7.5-7.5v-69.306h77.81c-7.278,20.744-16.351,39.078-26.972,53.947-2.407,3.371-1.626,8.055 1.744,10.463 1.321,0.943 2.844,1.397 4.353,1.397 2.341,0 4.646-1.093 6.11-3.142 12.24-17.137 22.54-38.497 30.56-62.666h55.112c4.143,0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-50.519c8.989-32.078 14.16-68.256 14.771-105.694h77.031c4.143,0 7.5-3.357 7.5-7.5s-3.357-7.499-7.5-7.499zm-107.36-105.694c9.313,31.683 14.695,67.958 15.326,105.694h-97.966v-105.694h82.64zm-180.28,0h82.64v105.694h-97.966c0.632-37.737 6.013-74.011 15.326-105.694zm0,226.388c-9.313-31.683-14.695-67.958-15.326-105.694h97.966v105.694h-82.64zm180.28,0h-82.64v-105.694h97.966c-0.632,37.737-6.013,74.012-15.326,105.694z' fill='%23ECEBE4'/%3E%3Cpath d='M401.17,68.83C356.784,24.444,297.771,0,235,0S113.216,24.444,68.83,68.83S0,172.229,0,235.001 c0,46.271,13.391,90.899,38.764,129.316l-28.718,86.148c-0.898,2.695-0.197,5.667,1.812,7.676c2.009,2.008,4.979,2.708,7.676,1.812 l86.15-28.716C144.102,456.609,188.729,470,235,470c62.771,0,121.784-24.444,166.17-68.83S470,297.771,470,235.001 C470,172.229,445.556,113.216,401.17,68.83z M235,455c-44.491,0-87.355-13.222-123.961-38.235 c-1.262-0.862-2.739-1.308-4.231-1.308c-0.797,0-1.598,0.127-2.372,0.385L29.02,440.979l25.14-75.414 c0.741-2.225,0.399-4.668-0.923-6.604C28.222,322.357,15,279.492,15,235.001C15,113.692,113.691,15,235,15s220,98.692,220,220.001 C455,356.309,356.309,455,235,455z' fill='%23ECEBE4'/%3E%3C/g%3E%3C/svg%3E");
|
||||
#lang label::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 470 470' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='m432.5,227.5h-77.031c-0.611-37.438-5.782-73.616-14.771-105.694h50.518c4.143,0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-55.112c-8.018-24.165-18.316-45.521-30.553-62.656-2.408-3.371-7.093-4.153-10.462-1.745-3.371,2.407-4.152,7.092-1.745,10.462 10.618,14.868 19.688,33.199 26.965,53.939h-77.809v-69.306c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v69.306h-77.81c7.277-20.74 16.347-39.071 26.965-53.939 2.407-3.37 1.626-8.055-1.745-10.462-3.372-2.407-8.055-1.625-10.462,1.745-12.237,17.135-22.535,38.492-30.553,62.656h-55.112c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5 7.5,7.5h50.518c-8.988,32.078-14.159,68.256-14.771,105.694h-77.03c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5 7.5,7.5h77.031c0.611,37.438 5.782,73.616 14.771,105.694h-50.519c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5 7.5,7.5h55.112c8.019,24.169 18.32,45.529 30.56,62.666 1.464,2.049 3.77,3.142 6.11,3.142 1.508,0 3.031-0.454 4.353-1.397 3.37-2.408 4.151-7.092 1.744-10.463-10.621-14.869-19.693-33.204-26.972-53.947h77.81v69.305c0,4.143 3.357,7.5 7.5,7.5s7.5-3.357 7.5-7.5v-69.306h77.81c-7.278,20.744-16.351,39.078-26.972,53.947-2.407,3.371-1.626,8.055 1.744,10.463 1.321,0.943 2.844,1.397 4.353,1.397 2.341,0 4.646-1.093 6.11-3.142 12.24-17.137 22.54-38.497 30.56-62.666h55.112c4.143,0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-50.519c8.989-32.078 14.16-68.256 14.771-105.694h77.031c4.143,0 7.5-3.357 7.5-7.5s-3.357-7.499-7.5-7.499zm-107.36-105.694c9.313,31.683 14.695,67.958 15.326,105.694h-97.966v-105.694h82.64zm-180.28,0h82.64v105.694h-97.966c0.632-37.737 6.013-74.011 15.326-105.694zm0,226.388c-9.313-31.683-14.695-67.958-15.326-105.694h97.966v105.694h-82.64zm180.28,0h-82.64v-105.694h97.966c-0.632,37.737-6.013,74.012-15.326,105.694z' fill='%23ECEBE4'/%3E%3Cpath d='M401.17,68.83C356.784,24.444,297.771,0,235,0S113.216,24.444,68.83,68.83S0,172.229,0,235.001 c0,46.271,13.391,90.899,38.764,129.316l-28.718,86.148c-0.898,2.695-0.197,5.667,1.812,7.676c2.009,2.008,4.979,2.708,7.676,1.812 l86.15-28.716C144.102,456.609,188.729,470,235,470c62.771,0,121.784-24.444,166.17-68.83S470,297.771,470,235.001 C470,172.229,445.556,113.216,401.17,68.83z M235,455c-44.491,0-87.355-13.222-123.961-38.235 c-1.262-0.862-2.739-1.308-4.231-1.308c-0.797,0-1.598,0.127-2.372,0.385L29.02,440.979l25.14-75.414 c0.741-2.225,0.399-4.668-0.923-6.604C28.222,322.357,15,279.492,15,235.001C15,113.692,113.691,15,235,15s220,98.692,220,220.001 C455,356.309,356.309,455,235,455z' fill='%23ECEBE4'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.logout:before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' viewBox='0 0 512 512' enable-background='new 0 0 512 512' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='m256,501c-129.6,0-235-102.2-235-227.8 0-87.8 50.6-166.3 132.1-204.9 10.2-4.8 22.4-0.5 27.2,9.7 4.8,10.2 0.5,22.4-9.7,27.2-67.1,31.8-108.7,96.1-108.7,168-7.10543e-15,103.1 87.1,187 194.1,187 107,0 194.1-83.9 194.1-187 0-72.4-44-138.9-112.2-169.5-10.3-4.6-14.9-16.7-10.3-27 4.6-10.3 16.7-14.9 27-10.2 82.9,37.1 136.4,118.3 136.4,206.7 0,125.6-105.4,227.8-235,227.8z' fill='%23FFFFFF'/%3E%3Cpath d='m256,287.9c-11.3,0-20.4-9.1-20.4-20.4v-236.1c0-11.3 9.2-20.4 20.4-20.4 11.3,0 20.4,9.1 20.4,20.4v236.1c0,11.3-9.1,20.4-20.4,20.4z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
.logout::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 512 512' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='m256,501c-129.6,0-235-102.2-235-227.8 0-87.8 50.6-166.3 132.1-204.9 10.2-4.8 22.4-0.5 27.2,9.7 4.8,10.2 0.5,22.4-9.7,27.2-67.1,31.8-108.7,96.1-108.7,168-7.10543e-15,103.1 87.1,187 194.1,187 107,0 194.1-83.9 194.1-187 0-72.4-44-138.9-112.2-169.5-10.3-4.6-14.9-16.7-10.3-27 4.6-10.3 16.7-14.9 27-10.2 82.9,37.1 136.4,118.3 136.4,206.7 0,125.6-105.4,227.8-235,227.8z' fill='%23FFFFFF'/%3E%3Cpath d='m256,287.9c-11.3,0-20.4-9.1-20.4-20.4v-236.1c0-11.3 9.2-20.4 20.4-20.4 11.3,0 20.4,9.1 20.4,20.4v236.1c0,11.3-9.1,20.4-20.4,20.4z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
#lang:focus-within:before,
|
||||
#lang:hover:before,
|
||||
.logout:focus-within:before,
|
||||
.logout:hover:before {
|
||||
background-color: #ec5f12;
|
||||
.js #menuopen::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg version='1.1' baseProfile='full' xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cdefs%3E%3Cpath id='bar' fill='%23FFFFFF' d='m87,-3 a3 3 180 0 1 0,6 h-84 a3 3 180 0 1 0,-6 z'/%3E%3C/defs%3E%3Cuse href='%23bar' x='15' y='18'/%3E%3Cuse href='%23bar' x='15' y='60'/%3E%3Cuse href='%23bar' x='15' y='102'/%3E%3C/svg%3E");
|
||||
}
|
||||
.js #menuopen:focus-within::before,
|
||||
.js #menuopen:hover::before,
|
||||
#lang label:focus-within::before,
|
||||
#lang label:hover::before,
|
||||
.logout:focus-within::before,
|
||||
.logout:hover::before {
|
||||
background-color: var(--oringe);
|
||||
}
|
||||
.foot,
|
||||
#menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
#foot {
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
width: var(--menu-w);
|
||||
}
|
||||
#menu {
|
||||
position: relative;
|
||||
top: 0;
|
||||
width: auto;
|
||||
flex: 0 0 20em;
|
||||
max-width: 20em;
|
||||
z-index: 1;
|
||||
position: static;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
h1 {
|
||||
background: #414073;
|
||||
background: var(--poiple);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#h1 {
|
||||
font-style: normal;
|
||||
}
|
||||
#dbs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
color: transparent;
|
||||
}
|
||||
#dbs label {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#dbs label::before {
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin-inline-end: -1em;
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 58.201 58.201' width='512px' height='512px'%3E%3Cg%3E%3Cpath d='M31.707,33.07c-0.87,0.027-1.74,0.042-2.606,0.042c-0.869,0-1.742-0.014-2.614-0.042 c-7.341-0.201-13.191-1.238-17.403-2.717C7.104,29.685,5.409,28.899,4.1,28v7.111v0.5v0.5V37.4c2.846,2.971,12.394,5.711,25,5.711 s22.154-2.74,25-5.711v-1.289v-0.5v-0.5V28c-1.318,0.905-3.028,1.697-5.025,2.367C44.865,31.839,39.027,32.87,31.707,33.07z' fill='%23FFFFFF'/%3E%3Cpath d='M4.1,14.889V22v0.5V23v1.289c2.638,2.754,11.033,5.31,22.286,5.668c0.115,0.004,0.233,0.005,0.349,0.008 c0.326,0.009,0.651,0.018,0.982,0.023C28.174,29.996,28.635,30,29.1,30s0.926-0.004,1.383-0.011 c0.33-0.005,0.656-0.014,0.982-0.023c0.116-0.003,0.234-0.005,0.349-0.008c11.253-0.359,19.648-2.915,22.286-5.668V23v-0.5V22 v-7.111C49.233,18.232,38.944,20,29.1,20S8.968,18.232,4.1,14.889z' fill='%23FFFFFF'/%3E%3Cpath d='M53.965,8.542C52.843,4.241,44.215,0,29.1,0C14.023,0,5.404,4.22,4.247,8.51C4.162,8.657,4.1,8.818,4.1,9v0.5v1.806 C6.937,14.267,16.417,17,29.1,17s22.164-2.733,25-5.694V9.5V9C54.1,8.832,54.044,8.681,53.965,8.542z' fill='%23FFFFFF'/%3E%3Cpath d='M4.1,41v8.201c0,0.162,0.043,0.315,0.117,0.451c1.181,4.895,11.747,8.549,24.883,8.549c13.106,0,23.655-3.639,24.875-8.516 c0.08-0.144,0.125-0.309,0.125-0.484v-8.199c-4.135,2.911-12.655,5.199-25,5.199C16.754,46.201,8.234,43.911,4.1,41z' fill='%23FFFFFF'/%3E%3C/g%3E%3C/svg%3E") center no-repeat;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
#dbs select {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#menu p {
|
||||
margin: 1.5em 0 0;
|
||||
}
|
||||
@@ -487,6 +626,13 @@ h1 {
|
||||
#menu .error {
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
p:has(#filter-field) {
|
||||
display: flex;
|
||||
}
|
||||
#filter-field {
|
||||
flex: 1 1 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
.tables-filter {
|
||||
padding: 0;
|
||||
margin-top: 1.2em;
|
||||
@@ -500,7 +646,7 @@ button,
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
background-color: #4c3957;
|
||||
color: #fff;
|
||||
color: var(--inv-fg);
|
||||
padding: 0.5em 0.8em 0.6em;
|
||||
margin: 0;
|
||||
border-style: none;
|
||||
@@ -517,9 +663,11 @@ button:focus,
|
||||
.links a:link:hover,
|
||||
.links a:visited:hover,
|
||||
.links a:link:focus,
|
||||
.links a:visited:focus {
|
||||
color: #fff;
|
||||
background-color: #ec5f12;
|
||||
.links a:visited:focus,
|
||||
#menu .links a:hover,
|
||||
#menu .links a:focus {
|
||||
color: var(--inv-fg);
|
||||
background-color: var(--oringe);
|
||||
text-decoration: none;
|
||||
}
|
||||
input[type="submit"]:disabled,
|
||||
@@ -534,7 +682,7 @@ input[type="file"]::-ms-browse {
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
background: #4c3957;
|
||||
color: #fff;
|
||||
color: var(--inv-fg);
|
||||
padding: 0.5em 0.8em 0.6em;
|
||||
margin: 0 0.5em;
|
||||
border-style: none;
|
||||
@@ -542,8 +690,8 @@ input[type="file"]::-ms-browse {
|
||||
}
|
||||
input[type="file"]:hover::-ms-browse,
|
||||
input[type="file"]:focus::-ms-browse {
|
||||
color: #fff;
|
||||
background: #ec5f12;
|
||||
color: var(--inv-fg);
|
||||
background: var(--oringe);
|
||||
text-decoration: none;
|
||||
}
|
||||
input[type="file"]:disabled::-ms-browse {
|
||||
@@ -556,7 +704,7 @@ input[type="file"]::-webkit-file-upload-button {
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
background: #4c3957;
|
||||
color: #fff;
|
||||
color: var(--inv-fg);
|
||||
padding: 0.5em 0.8em 0.6em;
|
||||
margin: 0 0.5em;
|
||||
border-style: none;
|
||||
@@ -564,8 +712,8 @@ input[type="file"]::-webkit-file-upload-button {
|
||||
}
|
||||
input[type="file"]:hover::-webkit-file-upload-button,
|
||||
input[type="file"]:focus::-webkit-file-upload-button {
|
||||
color: #fff;
|
||||
background: #ec5f12;
|
||||
color: var(--inv-fg);
|
||||
background: var(--oringe);
|
||||
text-decoration: none;
|
||||
}
|
||||
input[type="file"]:disabled::-webkit-file-upload-button {
|
||||
@@ -577,7 +725,7 @@ input[type="file"]::file-selector-button {
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
background: #4c3957;
|
||||
color: #fff;
|
||||
color: var(--inv-fg);
|
||||
padding: 0.5em 0.8em 0.6em;
|
||||
margin: 0 0.5em;
|
||||
border-style: none;
|
||||
@@ -585,24 +733,25 @@ input[type="file"]::file-selector-button {
|
||||
}
|
||||
input[type="file"]:hover::file-selector-button,
|
||||
input[type="file"]:focus::file-selector-button {
|
||||
color: #fff;
|
||||
background: #ec5f12;
|
||||
color: var(--inv-fg);
|
||||
background: var(--oringe);
|
||||
text-decoration: none;
|
||||
}
|
||||
input[type="file"]:disabled::file-selector-button {
|
||||
background-color: rgba(76, 57, 87, 0.35);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.links .active {
|
||||
#menu .active {
|
||||
color: var(--inv-fg);
|
||||
font-weight: normal;
|
||||
background-color: #414073;
|
||||
background-color: var(--poiple);
|
||||
}
|
||||
#menu .links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 1em -5px -5px;
|
||||
}
|
||||
#menu .links:after {
|
||||
#menu .links::after {
|
||||
content: " ";
|
||||
display: table;
|
||||
clear: both;
|
||||
@@ -613,23 +762,26 @@ input[type="file"]:disabled::file-selector-button {
|
||||
}
|
||||
#logins,
|
||||
#tables {
|
||||
flex-grow: 1;
|
||||
margin: 0.7em -20px -20px;
|
||||
padding: 0 20px 20px;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
#logins:focus-within,
|
||||
#tables:focus-within,
|
||||
#logins:hover,
|
||||
#tables:hover {
|
||||
overflow: visible !important;
|
||||
}
|
||||
#logins li,
|
||||
#tables li {
|
||||
background: #41658a;
|
||||
background: var(--bleu);
|
||||
}
|
||||
#logins a,
|
||||
#tables a,
|
||||
#tables span {
|
||||
background: #41658a;
|
||||
color: #fff;
|
||||
background: var(--bleu);
|
||||
color: var(--inv-fg);
|
||||
padding: 0.2em 0.4em 0.3em 0;
|
||||
}
|
||||
.rtl #logins a,
|
||||
@@ -649,18 +801,14 @@ input[type="file"]:disabled::file-selector-button {
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
color: transparent;
|
||||
margin-left: -0.2em;
|
||||
margin-inline-start: -0.2em;
|
||||
white-space: nowrap;
|
||||
padding: 0.1em 0.2em;
|
||||
top: 0.4em;
|
||||
}
|
||||
.rtl #tables a.select {
|
||||
margin-left: 0;
|
||||
margin-right: -0.2em;
|
||||
}
|
||||
#tables a.select:before {
|
||||
#tables a.select::before {
|
||||
content: ' ';
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' width='512px' height='512px' viewBox='0 0 16 16'%3E%3Cg%3E%3Cpath fill='%23FFFFFF' d='M0 1v15h16v-15h-16zM5 15h-4v-2h4v2zM5 12h-4v-2h4v2zM5 9h-4v-2h4v2zM5 6h-4v-2h4v2zM10 15h-4v-2h4v2zM10 12h-4v-2h4v2zM10 9h-4v-2h4v2zM10 6h-4v-2h4v2zM15 15h-4v-2h4v2zM15 12h-4v-2h4v2zM15 9h-4v-2h4v2zM15 6h-4v-2h4v2z'/%3E%3C/g%3E%3C/svg%3E") center no-repeat;
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' width='512px' height='512px' viewBox='0 0 16 16'%3E%3Cg%3E%3Cpath fill='%23FFFFFF' d='M0 1v15h16v-15h-16zM5 15h-4v-2h4v2zM5 12h-4v-2h4v2zM5 9h-4v-2h4v2zM5 6h-4v-2h4v2zM10 15h-4v-2h4v2zM10 12h-4v-2h4v2zM10 9h-4v-2h4v2zM10 6h-4v-2h4v2zM15 15h-4v-2h4v2zM15 12h-4v-2h4v2zM15 9h-4v-2h4v2zM15 6h-4v-2h4v2z'/%3E%3C/g%3E%3C/svg%3E") center no-repeat;
|
||||
background-size: contain;
|
||||
display: block;
|
||||
height: 100%;
|
||||
@@ -668,23 +816,16 @@ input[type="file"]:disabled::file-selector-button {
|
||||
#tables a.select:hover,
|
||||
#tables a.select:focus,
|
||||
#tables a.select.active {
|
||||
background-color: #ec5f12;
|
||||
background-color: var(--oringe);
|
||||
}
|
||||
#tables a.select.active ~ .structure {
|
||||
font-weight: bold;
|
||||
}
|
||||
#routines + .links a {
|
||||
margin-right: 0.45em;
|
||||
margin-inline-end: 0.45em;
|
||||
}
|
||||
#routines + .links a:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.rtl #routines + .links a {
|
||||
margin-right: 0;
|
||||
margin-left: 0.45em;
|
||||
}
|
||||
.rtl #routines + .links a:last-child {
|
||||
margin-left: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
.rtl p,
|
||||
.rtl table,
|
||||
@@ -694,11 +835,22 @@ input[type="file"]:disabled::file-selector-button {
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px) {
|
||||
body {
|
||||
.js body {
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
.js #menuopen {
|
||||
left: 14px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: var(--icon-w);
|
||||
height: var(--icon-w);
|
||||
}
|
||||
.rtl.js #menuopen {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.js #menu {
|
||||
border: none;
|
||||
box-shadow: 0 0 10px 2px var(--shado);
|
||||
}
|
||||
body,
|
||||
#content,
|
||||
@@ -712,24 +864,33 @@ input[type="file"]:disabled::file-selector-button {
|
||||
#menu {
|
||||
max-width: none;
|
||||
padding: 0 10px 2em;
|
||||
width: auto;
|
||||
width: 100vw;
|
||||
}
|
||||
#foot {
|
||||
width: 100vw;
|
||||
}
|
||||
.rtl #breadcrumb,
|
||||
#breadcrumb {
|
||||
padding: 0 10px;
|
||||
margin: 0 -10px;
|
||||
}
|
||||
#breadcrumb {
|
||||
padding: 0 28px;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
margin: 0 -10px;
|
||||
overflow: auto;
|
||||
position: static;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.rtl #breadcrumb {
|
||||
padding: 0 10px 0 0;
|
||||
margin: 0 -10px;
|
||||
.js #breadcrumb {
|
||||
padding-left: calc(10px + var(--icon-w));
|
||||
}
|
||||
#breadcrumb:after {
|
||||
.rtl.js #breadcrumb {
|
||||
padding-left: 10px;
|
||||
padding-right: calc(10px + var(--icon-w));
|
||||
}
|
||||
#breadcrumb::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 2.4em;
|
||||
@@ -742,6 +903,12 @@ input[type="file"]:disabled::file-selector-button {
|
||||
margin: 0 -10px 1em;
|
||||
padding: 1em 10px 0.5em;
|
||||
}
|
||||
.js #menuopen ~ h2 {
|
||||
padding-top: var(--icon-w);
|
||||
}
|
||||
.js #menuopen ~ #breadcrumb ~ h2 {
|
||||
padding-top: 1em;
|
||||
}
|
||||
#content .links a {
|
||||
white-space: normal;
|
||||
margin-bottom: 0.2em;
|
||||
@@ -752,16 +919,19 @@ input[type="file"]:disabled::file-selector-button {
|
||||
.logout {
|
||||
position: absolute;
|
||||
}
|
||||
.js .logout {
|
||||
top: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
#lang {
|
||||
margin-left: auto;
|
||||
margin: -1.5em -10px 0 auto;
|
||||
position: relative;
|
||||
top: auto;
|
||||
left: auto;
|
||||
margin-bottom: -2em;
|
||||
}
|
||||
.rtl #lang {
|
||||
right: auto;
|
||||
margin-left: 0;
|
||||
margin-left: -10px;
|
||||
margin-right: auto;
|
||||
}
|
||||
#logins,
|
||||
|
2
designs/win98/README.md
Normal file
2
designs/win98/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Screenshot
|
||||

|
298
designs/win98/adminer.css
Normal file
298
designs/win98/adminer.css
Normal file
@@ -0,0 +1,298 @@
|
||||
/* inspired by https://github.com/jdan/98.css */
|
||||
|
||||
:root {
|
||||
--text-color: #222222;
|
||||
--button-face: #dfdfdf;
|
||||
--window-frame: #0a0a0a;
|
||||
--dialog-blue-light: #1084d0;
|
||||
--link-blue: #0000ff;
|
||||
}
|
||||
|
||||
body {
|
||||
background: teal;
|
||||
color: var(--text-color);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
button, input[type=reset], input[type=submit] {
|
||||
background: silver;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px white, inset -2px -2px grey, inset 2px 2px var(--button-face);
|
||||
box-sizing: border-box;
|
||||
color: transparent;
|
||||
font-size: 12px;
|
||||
min-height: 23px;
|
||||
min-width: 75px;
|
||||
padding: 0 12px;
|
||||
text-shadow: 0 0 var(--text-color);
|
||||
}
|
||||
|
||||
button.default, input[type=reset].default, input[type=submit].default {
|
||||
box-shadow: inset -2px -2px var(--window-frame), inset 1px 1px var(--window-frame), inset 2px 2px white, inset -3px -3px grey, inset 3px 3px var(--button-face);
|
||||
}
|
||||
|
||||
button:not(:disabled):active, input[type=reset]:not(:disabled):active, input[type=submit]:not(:disabled):active {
|
||||
box-shadow: inset -1px -1px white, inset 1px 1px var(--window-frame), inset -2px -2px var(--button-face), inset 2px 2px grey;
|
||||
text-shadow: 1px 1px var(--text-color);
|
||||
}
|
||||
|
||||
button.default:not(:disabled):active, input[type=reset].default:not(:disabled):active, input[type=submit].default:not(:disabled):active {
|
||||
box-shadow: inset 2px 2px var(--window-frame), inset -1px -1px var(--window-frame), inset -2px -2px white, inset 3px 3px grey, inset -3px -3px var(--button-face);
|
||||
}
|
||||
|
||||
button:focus, input[type=reset]:focus, input[type=submit]:focus {
|
||||
outline: 1px dotted black;
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner, input[type=reset]::-moz-focus-inner, input[type=submit]::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
:disabled, :disabled + label, input[readonly], input[readonly] + label, input[type=submit]:disabled, input[type=reset]:disabled, input[type=submit]:disabled {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
:disabled + label, button:disabled, input[type=reset]:disabled, input[type=submit]:disabled {
|
||||
text-shadow: 1px 1px 0 white;
|
||||
}
|
||||
|
||||
#content, #menu, .footer, #breadcrumb {
|
||||
background: silver;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px var(--button-face), inset -2px -2px grey, inset 2px 2px white;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#content h2 {
|
||||
align-items: center;
|
||||
background: linear-gradient(90deg, navy, var(--dialog-blue-light));
|
||||
color: white;
|
||||
display: flex;
|
||||
font-size: 120%;
|
||||
font-weight: normal;
|
||||
justify-content: space-between;
|
||||
letter-spacing: 0;
|
||||
margin: -13px -13px 16px -13px;
|
||||
padding: 3px 2px 3px 3px;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='5' height='5' fill='gray' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h5v5H0V2h2v1h1V2H0' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h4v4H0V1h1v2h2V1H0'/%3E%3C/svg%3E") 2;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
padding-block-start: 8px;
|
||||
}
|
||||
|
||||
legend {
|
||||
background: silver;
|
||||
}
|
||||
|
||||
input[type=email], input[type=number], input[type=password], input[type=search], input[type=tel], input[type=text], input:not([type]) {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
input[type=email], input[type=number], input[type=password], input[type=search], input[type=tel], input[type=text], select, input:not([type]) {
|
||||
background-color: white;
|
||||
box-shadow: inset -1px -1px white, inset 1px 1px grey, inset -2px -2px var(--button-face), inset 2px 2px var(--window-frame);
|
||||
box-sizing: border-box;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
select, textarea {
|
||||
border: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: white;
|
||||
border-radius: 0;
|
||||
box-shadow: inset -1px -1px white, inset 1px 1px grey, inset -2px -2px var(--button-face), inset 2px 2px var(--window-frame);
|
||||
box-sizing: border-box;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
input[type=email], input[type=password], input[type=search], input[type=tel], input[type=text], input[type=number], select {
|
||||
min-height: 21px;
|
||||
}
|
||||
|
||||
input[type=search]::-ms-clear, input[type=search]::-ms-reveal {
|
||||
display: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration, input[type=search]::-webkit-search-results-button, input[type=search]::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type=email]:disabled, input[type=email]:read-only, input[type=number]:disabled, input[type=number]:read-only, input[type=password]:disabled, input[type=password]:read-only, input[type=search]:disabled, input[type=search]:read-only, input[type=tel]:disabled, input[type=tel]:read-only, input[type=text]:disabled, input[type=text]:read-only, textarea:disabled {
|
||||
background-color: silver;
|
||||
}
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0v16h1V1h14V0z' fill='%23DFDFDF'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1v14h1V2h12V1H2z' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H0v-1h15V0h1v17z' fill='%23000'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1h-1v14H1v1h14V1z' fill='gray'/%3E%3Cpath fill='silver' d='M2 2h12v13H2z'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 6H4v1h1v1h1v1h1v1h1V9h1V8h1V7h1V6z' fill='%23000'/%3E%3C/svg%3E");
|
||||
background-position: top 2px right 2px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0;
|
||||
padding-right: 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type=email]:focus, input[type=number]:focus, input[type=password]:focus, input[type=search]:focus, input[type=tel]:focus, input[type=text]:focus, select:focus, textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
background-color: navy;
|
||||
color: white;
|
||||
}
|
||||
|
||||
select:focus option {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
select:active {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h16v17H0V0zm1 16h14V1H1v15z' fill='gray'/%3E%3Cpath fill='silver' d='M1 1h14v15H1z'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 7H5v1h1v1h1v1h1v1h1v-1h1V9h1V8h1V7z' fill='%23000'/%3E%3C/svg%3E")
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link-blue);
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 1px dotted var(--link-blue);
|
||||
}
|
||||
|
||||
pre {
|
||||
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='5' height='5' fill='gray' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h5v5H0V2h2v1h1V2H0' fill='%23fff'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h4v4H0V1h1v2h2V1H0'/%3E%3C/svg%3E") 2;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
margin: 0;
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
table > thead > tr > * {
|
||||
background: silver;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px white, inset -2px -2px grey, inset 2px 2px var(--button-face);
|
||||
}
|
||||
|
||||
table.interactive > tbody > tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#fieldset-sort > div:not(:last-of-type), #fieldset-search > div:not(:last-of-type), #fieldset-select > div:not(:last-of-type) {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
#fieldset-partition p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#logins a, #tables a, #tables span {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.jush-autocomplete, .jush-autocomplete:active {
|
||||
background: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.logout {
|
||||
box-shadow: none;
|
||||
margin-top: .8em;
|
||||
}
|
||||
|
||||
#breadcrumb {
|
||||
height: auto;
|
||||
margin: 0;
|
||||
padding: 2px 16px;
|
||||
top: calc(1.5em - 14px);
|
||||
}
|
||||
|
||||
code {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#menu {
|
||||
margin: 0;
|
||||
top: 3em;
|
||||
width: 18em;
|
||||
}
|
||||
|
||||
#menu h1 {
|
||||
background: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#menu h1 a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
#menu .links a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#lang {
|
||||
top: -2.8em;
|
||||
}
|
||||
|
||||
#lang label {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-top: 3em;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.footer > div {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.js .column {
|
||||
background: silver;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: inset -1px -1px var(--window-frame), inset 1px 1px var(--button-face), inset -2px -2px grey, inset 2px 2px white;
|
||||
margin-top: -.4em;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px) {
|
||||
.js .logout {
|
||||
box-shadow: none;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#lang label {
|
||||
color: initial;
|
||||
}
|
||||
}
|
@@ -59,6 +59,9 @@ class Adminer {
|
||||
return 5;
|
||||
}
|
||||
|
||||
function afterConnect() {
|
||||
}
|
||||
|
||||
function headers() {
|
||||
}
|
||||
|
||||
@@ -214,9 +217,9 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
}
|
||||
|
||||
function selectVal($val, $link, $field, $original) {
|
||||
$return = $val;
|
||||
$return = "$val";
|
||||
$link = h($link);
|
||||
if (preg_match('~blob|bytea~', $field["type"]) && !is_utf8($val)) {
|
||||
if (is_blob($field) && !is_utf8($val)) {
|
||||
$return = lang('%d byte(s)', strlen($original));
|
||||
if (preg_match("~^(GIF|\xFF\xD8\xFF|\x89PNG\x0D\x0A\x1A\x0A)~", $original)) { // GIF|JPG|PNG, getimagetype() works with filename
|
||||
$return = "<img src='$link' alt='$return'>";
|
||||
@@ -261,14 +264,14 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
$fields = fields($_GET["select"]);
|
||||
foreach ($columns as $name => $desc) {
|
||||
$field = $fields[$name];
|
||||
if (preg_match("~enum~", $field["type"]) || like_bool($field)) { //! set - uses 1 << $i and FIND_IN_SET()
|
||||
if ($field["type"] == "enum" || like_bool($field)) { //! set - uses 1 << $i and FIND_IN_SET()
|
||||
$key = $keys[$name];
|
||||
$i--;
|
||||
echo "<div>" . h($desc) . ":" . input_hidden("where[$i][col]", $name);
|
||||
$val = idx($where[$key], "val");
|
||||
echo (like_bool($field)
|
||||
? "<select name='where[$i][val]'>" . optionlist(array("" => "", lang('no'), lang('yes')), $val, true) . "</select>"
|
||||
: enum_input("checkbox", " name='where[$i][val][]'", $field, (array) $val, ($field["null"] ? 0 : null))
|
||||
: enum_input("checkbox", " name='where[$i][val][]'", $field, (array) $val, lang('empty'))
|
||||
);
|
||||
echo "</div>\n";
|
||||
unset($columns[$name]);
|
||||
@@ -366,7 +369,13 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
if ($col != "" || is_numeric($val) || !preg_match(number_type(), $field["type"])) {
|
||||
$name = idf_escape($name);
|
||||
if ($col != "" && $field["type"] == "enum") {
|
||||
$conds[] = (in_array(0, $val) ? "$name IS NULL OR " : "") . "$name IN (" . implode(", ", array_map('Adminer\q', $val)) . ")";
|
||||
$in = array();
|
||||
foreach ($val as $val1) {
|
||||
if (preg_match('~val-~', $val1)) {
|
||||
$in[] = q(substr($val1, 4));
|
||||
}
|
||||
}
|
||||
$conds[] = (in_array("null", $val) ? "$name IS NULL OR " : "") . ($in ? "$name IN (" . implode(", ", $in) . ")" : "0");
|
||||
} else {
|
||||
$text_type = preg_match('~char|text|enum|set~', $field["type"]);
|
||||
$value = adminer()->processInput($field, (!$op && $text_type && preg_match('~^[^%]+$~', $val) ? "%$val%" : $val));
|
||||
@@ -456,8 +465,8 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
|
||||
function editInput($table, $field, $attrs, $value) {
|
||||
if ($field["type"] == "enum") {
|
||||
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
|
||||
. enum_input("radio", $attrs, $field, ($value || isset($_GET["select"]) ? $value : ""), ($field["null"] ? "" : null))
|
||||
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='orig' checked><i>" . lang('original') . "</i></label> " : "")
|
||||
. enum_input("radio", $attrs, $field, $value, lang('empty'))
|
||||
;
|
||||
}
|
||||
$options = $this->foreignKeyOptions($table, $field["field"], $value);
|
||||
|
2
externals/PhpShrink
vendored
2
externals/PhpShrink
vendored
Submodule externals/PhpShrink updated: 2b38322c9c...b3d92cdf76
2
externals/jush
vendored
2
externals/jush
vendored
Submodule externals/jush updated: c6ae413ff0...c6618a3016
@@ -116,7 +116,6 @@
|
||||
<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"/>
|
||||
|
||||
|
11
phpstan.neon
11
phpstan.neon
@@ -17,7 +17,8 @@ parameters:
|
||||
- "~^Constant LANG not found~" # defined in lang.inc.php
|
||||
- "~ an undefined \\w+ Adminer\\\\Db::~" # defined in that versions of Db
|
||||
- "~^Call to an undefined method Adminer\\\\Result::seek~" # defined in MS SQL
|
||||
- "~^Call to an undefined method Adminer\\\\Driver::setUserTypes~" # defined in PostgreSQL
|
||||
- "~^Call to an undefined method Adminer\\\\Driver::(setUserTypes|tableOid)~" # defined in PostgreSQL
|
||||
- "~^Access to an undefined property Adminer\\\\Driver::\\$nsOid~" # defined in PostgreSQL
|
||||
- "~expects int, float given~" # this will work
|
||||
- "~expects bool~" # truthy values
|
||||
- "~fread expects int<1, max>, 100000~" # 1e6
|
||||
@@ -39,11 +40,13 @@ parameters:
|
||||
- identifier: booleanAnd.leftAlwaysTrue
|
||||
- identifier: booleanAnd.rightAlwaysTrue
|
||||
- identifier: booleanAnd.rightAlwaysFalse
|
||||
- identifier: booleanOr.rightAlwaysTrue
|
||||
- identifier: ternary.alwaysTrue
|
||||
- identifier: if.alwaysTrue
|
||||
- identifier: while.alwaysTrue
|
||||
- identifier: isset.offset
|
||||
- identifier: deadCode.unreachable
|
||||
- "~Function Adminer\\\\get_driver\\(\\) never returns null~"
|
||||
- "~on array\\{}~"
|
||||
|
||||
paths:
|
||||
- adminer/drivers/mysql.inc.php # other drivers inherit the annotations so we take them from here
|
||||
@@ -61,8 +64,8 @@ parameters:
|
||||
max: 80499
|
||||
|
||||
typeAliases:
|
||||
TableStatus: "array{Name:string, Engine?:?string, Comment?:string, Oid?:numeric-string, Rows?:?numeric-string, Collation?:string, Auto_increment?:?numeric-string, Data_length?:numeric-string, Index_length?:numeric-string, Data_free?:numeric-string, Create_options?:string, inherited?:numeric-string, nspname?:string}"
|
||||
Field: "array{field?:string, full_type:string, type:string, length:numeric-string, unsigned:string, default?:string, null:bool, auto_increment:bool, collation:string, privileges:int[], comment:string, primary:bool, generated:string, orig?:string, on_update?:string, on_delete?:string, default_constraint?: string}"
|
||||
TableStatus: "array{Name:string, Engine?:?string, Comment?:string, Oid?:numeric-string, Rows?:?numeric-string, Collation?:string, Auto_increment?:?numeric-string, Data_length?:numeric-string, Index_length?:numeric-string, Data_free?:numeric-string, Create_options?:string, partition?:numeric-string, nspname?:string}"
|
||||
Field: "array{field?:string, full_type:string, type:string, length:?numeric-string, unsigned:string, default?:string, null:bool, auto_increment:bool, collation:string, privileges:int[], comment:string, primary:bool, generated:string, orig?:string, on_update?:string, on_delete?:string, default_constraint?: string}"
|
||||
FieldType: "array{type:string, length:numeric-string, unsigned:string, collation:string}" # subset of RoutineField and Field
|
||||
RoutineField: "array{field:string, type:string, length:numeric-string, unsigned:string, null:bool, full_type:string, collation:string, inout?:string}"
|
||||
Index: "array{type:string, columns:list<string>, lengths:list<numeric-string>, descs:list<?bool>, algorithm?:string, partial?:string}"
|
||||
|
@@ -11,15 +11,26 @@ class AdminerBackwardKeys extends Adminer\Plugin {
|
||||
|
||||
function backwardKeys($table, $tableName) {
|
||||
$return = array();
|
||||
// we couldn't use the same query in MySQL and PostgreSQL because unique_constraint_name is not table-specific in MySQL and referenced_table_name is not available in PostgreSQL
|
||||
foreach (
|
||||
Adminer\get_rows($q = "SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = " . Adminer\q(Adminer\DB) . "
|
||||
AND REFERENCED_TABLE_SCHEMA = " . Adminer\q(Adminer\DB) . "
|
||||
AND REFERENCED_TABLE_NAME = " . Adminer\q($table) . "
|
||||
ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
Adminer\get_rows("SELECT s.table_name table_name, s.constraint_name constraint_name, s.column_name column_name, " . (Adminer\JUSH == "sql" ? "referenced_column_name" : "t.column_name") . " referenced_column_name
|
||||
FROM information_schema.key_column_usage s" . (Adminer\JUSH == "sql" ? "
|
||||
WHERE table_schema = " . Adminer\q(Adminer\DB) . "
|
||||
AND referenced_table_schema = " . Adminer\q(Adminer\DB) . "
|
||||
AND referenced_table_name" : "
|
||||
JOIN information_schema.referential_constraints r USING (constraint_catalog, constraint_schema, constraint_name)
|
||||
JOIN information_schema.key_column_usage t ON r.unique_constraint_catalog = t.constraint_catalog
|
||||
AND r.unique_constraint_schema = t.constraint_schema
|
||||
AND r.unique_constraint_name = t.constraint_name
|
||||
AND r.constraint_catalog = t.constraint_catalog
|
||||
AND r.constraint_schema = t.constraint_schema
|
||||
AND r.unique_constraint_name = t.constraint_name
|
||||
AND s.position_in_unique_constraint = t.ordinal_position
|
||||
WHERE t.table_catalog = " . Adminer\q(Adminer\DB) . " AND t.table_schema = " . Adminer\q("$_GET[ns]") . "
|
||||
AND t.table_name") . " = " . Adminer\q($table) . "
|
||||
ORDER BY s.ordinal_position", null, "") as $row
|
||||
) {
|
||||
$return[$row["TABLE_NAME"]]["keys"][$row["CONSTRAINT_NAME"]][$row["COLUMN_NAME"]] = $row["REFERENCED_COLUMN_NAME"];
|
||||
$return[$row["table_name"]]["keys"][$row["constraint_name"]][$row["column_name"]] = $row["referenced_column_name"];
|
||||
}
|
||||
foreach ($return as $key => $val) {
|
||||
$name = Adminer\adminer()->tableName(Adminer\table_status1($key, true));
|
||||
@@ -40,9 +51,12 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
|
||||
$link = Adminer\ME . 'select=' . urlencode($table);
|
||||
$i = 0;
|
||||
foreach ($cols as $column => $val) {
|
||||
if (!isset($row[$val])) {
|
||||
continue 2;
|
||||
}
|
||||
$link .= Adminer\where_link($i++, $column, $row[$val]);
|
||||
}
|
||||
echo "<a href='" . Adminer\h($link) . "'>" . Adminer\h($backwardKey["name"]) . "</a>";
|
||||
echo "<a href='" . Adminer\h($link) . "'>" . Adminer\h(preg_replace('(^' . preg_quote($_GET["select"]) . (substr($_GET["select"], -1) == 's' ? '?' : '') . '_)', '_', $backwardKey["name"])) . "</a>";
|
||||
$link = Adminer\ME . 'edit=' . urlencode($table);
|
||||
foreach ($cols as $column => $val) {
|
||||
$link .= "&set" . urlencode("[" . Adminer\bracket_escape($column) . "]") . "=" . urlencode($row[$val]);
|
||||
|
@@ -1,3 +1,5 @@
|
||||
Using drivers: https://www.adminer.org/plugins/#use
|
||||
|
||||
Developing drivers: https://www.adminer.org/en/drivers/
|
||||
|
||||
The type declarations must be compatible both with source codes and the compiled version (where PHP5-incompatible types are stripped). It means:
|
||||
|
@@ -287,10 +287,6 @@ if (isset($_GET["elastic"])) {
|
||||
|
||||
return !!$this->conn->affected_rows;
|
||||
}
|
||||
|
||||
function convertOperator($operator): string {
|
||||
return $operator == "LIKE %%" ? "should" : $operator;
|
||||
}
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
@@ -412,6 +408,11 @@ if (isset($_GET["elastic"])) {
|
||||
return $table_status["Engine"] == "view";
|
||||
}
|
||||
|
||||
function view(string $name): array {
|
||||
$return = connection()->rootQuery("_alias/" . urlencode($name) . "");
|
||||
return array("select" => implode("\n", array_keys($return)));
|
||||
}
|
||||
|
||||
function error() {
|
||||
return h(connection()->error);
|
||||
}
|
||||
@@ -533,15 +534,18 @@ if (isset($_GET["elastic"])) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Drop types
|
||||
* @param list<string> $tables
|
||||
*/
|
||||
function drop_views(array $tables): bool {
|
||||
$return = connection()->rootQuery('_aliases', array('actions' => array_map(function ($table) {
|
||||
return array('remove' => array('index' => '*', 'alias' => $table));
|
||||
}, $tables)), 'POST');
|
||||
return $return && !$return['errors'];
|
||||
}
|
||||
|
||||
function drop_tables(array $tables): bool {
|
||||
$return = true;
|
||||
foreach ($tables as $table) { //! convert to bulk api
|
||||
$return = $return && connection()->rootQuery(urlencode($table), null, 'DELETE');
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,8 @@ if (isset($_GET["imap"])) {
|
||||
private $imap;
|
||||
|
||||
function attach($server, $username, $password): string {
|
||||
$this->mailbox = "{" . "$server:993/ssl}"; // Adminer disallows specifying privileged port in server name
|
||||
list($host, $port) = host_port($server);
|
||||
$this->mailbox = "{" . "$host:" . ($port ?: 993) . "/ssl}"; // Adminer disallows specifying privileged port in server name
|
||||
$this->imap = @imap_open($this->mailbox, $username, $password, OP_HALFOPEN, 1);
|
||||
return ($this->imap ? '' : imap_last_error());
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
class AdminerDumpDate extends Adminer\Plugin {
|
||||
|
||||
function dumpFilename($identifier) {
|
||||
return Adminer\friendly_url(($identifier != "" ? $identifier : (Adminer\SERVER != "" ? Adminer\SERVER : "localhost")) . "-" . Adminer\get_val("SELECT NOW()"));
|
||||
return Adminer\friendly_url(($identifier != "" ? $identifier : (Adminer\SERVER ?: "localhost")) . "-" . Adminer\get_val("SELECT NOW()"));
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
//! delete
|
||||
//! handle delete
|
||||
|
||||
/** Edit fields ending with "_path" by <input type="file"> and link to the uploaded files from select
|
||||
* @link https://www.adminer.org/plugins/#use
|
||||
@@ -30,13 +30,13 @@ class AdminerFileUpload extends Adminer\Plugin {
|
||||
function processInput($field, $value, $function = "") {
|
||||
if (preg_match('~(.*)_path$~', $field["field"], $regs)) {
|
||||
$table = ($_GET["edit"] != "" ? $_GET["edit"] : $_GET["select"]);
|
||||
$name = "fields-$field[field]";
|
||||
if ($_FILES[$name]["error"] || !preg_match("~(\\.($this->extensions))?\$~", $_FILES[$name]["name"], $regs2)) {
|
||||
$name = $field["field"];
|
||||
if ($_FILES["fields"]["error"][$name] || !preg_match("~(\\.($this->extensions))?\$~", $_FILES["fields"]["name"][$name], $regs2)) {
|
||||
return false;
|
||||
}
|
||||
//! unlink old
|
||||
$filename = (function_exists('random_bytes') ? bin2hex(random_bytes(8)) : uniqid("", true)) . $regs2[0];
|
||||
if (!move_uploaded_file($_FILES[$name]["tmp_name"], "$this->uploadPath$table/$regs[1]-$filename")) {
|
||||
if (!move_uploaded_file($_FILES["fields"]["tmp_name"][$name], $this->uploadPath . Adminer\friendly_url($table) . "/$regs[1]-$filename")) {
|
||||
return false;
|
||||
}
|
||||
return Adminer\q($filename);
|
||||
@@ -45,7 +45,7 @@ class AdminerFileUpload extends Adminer\Plugin {
|
||||
|
||||
function selectVal($val, &$link, $field, $original) {
|
||||
if ($val != "" && preg_match('~(.*)_path$~', $field["field"], $regs)) {
|
||||
$link = "$this->displayPath$_GET[select]/$regs[1]-$val";
|
||||
$link = $this->displayPath . Adminer\friendly_url($_GET["select"]) . "/$regs[1]-$val";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,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)
|
||||
*/
|
||||
class AdminerCodemirror extends Adminer\Plugin {
|
||||
class AdminerHighlightCodemirror extends Adminer\Plugin {
|
||||
private $root;
|
||||
private $minified;
|
||||
|
@@ -7,7 +7,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)
|
||||
*/
|
||||
class AdminerMonaco extends Adminer\Plugin {
|
||||
class AdminerHighlightMonaco extends Adminer\Plugin {
|
||||
private $root;
|
||||
|
||||
function __construct($root = "https://cdn.jsdelivr.net/npm/monaco-editor@0.52/min/vs") {
|
@@ -7,7 +7,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)
|
||||
*/
|
||||
class AdminerPrism extends Adminer\Plugin {
|
||||
class AdminerHighlightPrism extends Adminer\Plugin {
|
||||
private $editorRoot;
|
||||
private $minified;
|
||||
private $theme;
|
@@ -12,7 +12,7 @@ class AdminerLoginOtp extends Adminer\Plugin {
|
||||
/**
|
||||
* @param string $secret decoded secret, e.g. base64_decode("SECRET")
|
||||
*/
|
||||
function __construct(string $secret) {
|
||||
function __construct($secret) {
|
||||
$this->secret = $secret;
|
||||
if ($_POST["auth"]) {
|
||||
$_SESSION["otp"] = (string) $_POST["auth"]["otp"];
|
||||
|
@@ -12,7 +12,7 @@ class AdminerLoginPasswordLess extends Adminer\Plugin {
|
||||
/** Set allowed password
|
||||
* @param string $password_hash result of password_hash()
|
||||
*/
|
||||
function __construct(string $password_hash) {
|
||||
function __construct($password_hash) {
|
||||
$this->password_hash = $password_hash;
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ class AdminerLoginTable extends Adminer\Plugin {
|
||||
protected $database;
|
||||
|
||||
/** Set database of login table */
|
||||
function __construct(string $database) {
|
||||
function __construct($database) {
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
|
@@ -21,12 +21,12 @@ class AdminerMenuLinks extends Adminer\Plugin {
|
||||
'' => $this->lang('Both'),
|
||||
'auto' => $this->lang('Auto (select on select page, structure otherwise)'),
|
||||
);
|
||||
$menu = Adminer\get_setting("menu", "adminer_config") ?: $this->menu;
|
||||
$menu = Adminer\get_setting("menu", "adminer_config", $this->menu);
|
||||
return array($this->lang('Menu table links') => Adminer\html_radios('config[menu]', $options, $menu, "<br>"));
|
||||
}
|
||||
|
||||
function tablesPrint(array $tables) {
|
||||
$menu = Adminer\get_setting("menu", "adminer_config") ?: $this->menu;
|
||||
$menu = Adminer\get_setting("menu", "adminer_config", $this->menu);
|
||||
$titles = array(
|
||||
'select' => $this->lang('Select data'),
|
||||
'table' => $this->lang('Show structure'),
|
||||
@@ -36,7 +36,7 @@ class AdminerMenuLinks extends Adminer\Plugin {
|
||||
foreach ($tables as $table => $status) {
|
||||
$table = "$table"; // do not highlight "0" as active everywhere
|
||||
$name = Adminer\adminer()->tableName($status);
|
||||
if ($name != "" && !$status["inherited"]) {
|
||||
if ($name != "" && !$status["partition"]) {
|
||||
echo '<li>';
|
||||
if (!$menu) {
|
||||
echo '<a href="' . Adminer\h(Adminer\ME) . 'select=' . urlencode($table) . '"'
|
||||
|
@@ -26,7 +26,7 @@ class AdminerPrettyJsonColumn extends Adminer\Plugin {
|
||||
if ($function === '') {
|
||||
$json = $this->testJson($value);
|
||||
if ($json !== $value) {
|
||||
$value = json_encode($json);
|
||||
return Adminer\q(json_encode($json));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
plugins/row-numbers.php
Normal file
24
plugins/row-numbers.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/** Display row numbers in select
|
||||
* @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 AdminerRowNumbers extends Adminer\Plugin {
|
||||
|
||||
function backwardKeys($table, $tableName) {
|
||||
return array(1);
|
||||
}
|
||||
|
||||
function backwardKeysPrint($backwardKeys, $row) {
|
||||
static $n = $_GET["page"] * Adminer\adminer()->selectLimitProcess();
|
||||
$n++;
|
||||
echo "$n.\n";
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'cs' => array('' => 'Zobrazí čísla řádek ve výpisu'),
|
||||
);
|
||||
}
|
@@ -41,8 +41,8 @@ class AdminerSqlGemini extends Adminer\Plugin {
|
||||
echo "-- " . $response->error->message;
|
||||
} else {
|
||||
$text = $response->candidates[0]->content->parts[0]->text;
|
||||
$text = preg_replace('~(\n|^)```sql\n(.+)\n```(\n|$)~sU', "*/\n\n\\2\n\n/*", "/*\n$text*/\n");
|
||||
echo preg_replace('~/\*\s*\*/\n*~', '', $text);
|
||||
$text2 = preg_replace('~(\n|^)```sql\n(.+)\n```(\n|$)~sU', "*/\n\n\\2\n\n/*", "/*\n$text\n*/", -1, $count);
|
||||
echo ($count ? preg_replace('~/\*\s*\*/\n*~', '', $text2) : $text);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
@@ -64,15 +64,26 @@ sessionStorage && document.addEventListener('DOMContentLoaded', () => {
|
||||
sessionStorage.setItem('adminer_tables_filter_db', db);
|
||||
});
|
||||
</script>
|
||||
<p class="jsonly"><input id="filter-field" autocomplete="off" type="search"><?php echo Adminer\script("qs('#filter-field').oninput = tablesFilterInput;"); ?>
|
||||
<p class="jsonly"><?php echo $this->lang('Filter'); ?>: <input id="filter-field" autocomplete="off" type="search"><?php echo Adminer\script("qs('#filter-field').oninput = tablesFilterInput;"); ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'cs' => array('' => 'Filtruje názvy v seznamu tabulek'),
|
||||
'de' => array('' => 'Filtern Sie Namen in der Tabellenliste'),
|
||||
'pl' => array('' => 'Filtruj nazwy na liście tabel'),
|
||||
'ro' => array('' => 'Nume de filtre în lista de tabele'),
|
||||
'ja' => array('' => 'テーブル一覧をテーブル名でフィルタリング'),
|
||||
'cs' => array(
|
||||
'' => 'Filtruje názvy v seznamu tabulek',
|
||||
'Filter' => 'Filtr',
|
||||
),
|
||||
'de' => array(
|
||||
'' => 'Filtern Sie Namen in der Tabellenliste',
|
||||
),
|
||||
'pl' => array(
|
||||
'' => 'Filtruj nazwy na liście tabel',
|
||||
),
|
||||
'ro' => array(
|
||||
'' => 'Nume de filtre în lista de tabele',
|
||||
),
|
||||
'ja' => array(
|
||||
'' => 'テーブル一覧をテーブル名でフィルタリング',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
54
plugins/timeout.php
Normal file
54
plugins/timeout.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/** Specify timeout for running every query
|
||||
* @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 AdminerTimeout extends Adminer\Plugin {
|
||||
private $seconds;
|
||||
|
||||
/**
|
||||
* @param int $seconds
|
||||
*/
|
||||
function __construct($seconds = 5) {
|
||||
$this->seconds = $seconds;
|
||||
}
|
||||
|
||||
function afterConnect() {
|
||||
$seconds = Adminer\get_setting("timeout", "adminer_config", $this->seconds);
|
||||
if ($seconds != '') {
|
||||
$ms = $seconds * 1000;
|
||||
$conn = Adminer\connection();
|
||||
switch (Adminer\JUSH) {
|
||||
case 'sql':
|
||||
$conn->query("SET max_execution_time = $ms");
|
||||
break;
|
||||
case 'pgsql':
|
||||
$conn->query("SET statement_timeout = $ms");
|
||||
break;
|
||||
case 'mssql':
|
||||
$conn->query("SET LOCK_TIMEOUT $ms");
|
||||
break;
|
||||
default:
|
||||
if (method_exists($conn, 'timeout')) {
|
||||
$conn->timeout($ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function config() {
|
||||
$seconds = Adminer\get_setting("timeout", "adminer_config", $this->seconds);
|
||||
return array($this->lang('Queries timeout') => '<input type="number" name="config[timeout]" min="0" value="' . Adminer\h($seconds) . '" class="size"> ' . $this->lang('seconds'));
|
||||
}
|
||||
|
||||
protected $translations = array(
|
||||
'cs' => array(
|
||||
'' => 'Nastaví timeout pro spouštění každého dotazu',
|
||||
'Queries timeout' => 'Timeout dotazů',
|
||||
'seconds' => 'sekund',
|
||||
),
|
||||
);
|
||||
}
|
@@ -223,7 +223,7 @@
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Drop']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>cannot drop type</td><td></td></tr>
|
||||
<tr><td>open</td><td>/adminer/?pgsql=localhost:26257&username=ODBC&db=adminer_test&ns=public&edit=interprets&where%5Bid%5D=1</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@value='deceased']</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@value='val-deceased']</td><td></td></tr>
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>deceased</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
@@ -60,9 +60,8 @@
|
||||
<tr><td>type</td><td>indexes[3][partial]</td><td>surname IS NOT NULL</td></tr>
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>Indexes have been altered.</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>//tr[@title='interprets_surname']</td><td>INDEX (hash)</td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>//tr[@title='interprets_surname']</td><td>surname</td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>//tr[@title='interprets_surname']</td><td>WHERE surname IS NOT NULL</td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>INDEX (hash)</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>WHERE surname IS NOT NULL</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<table cellpadding="1" cellspacing="1" border="1">
|
||||
@@ -101,13 +100,13 @@
|
||||
<tbody>
|
||||
<tr><td>open</td><td>/adminer/?pgsql=&username=ODBC&db=adminer_test&ns=public&table=interprets</td><td></td></tr>
|
||||
<tr><td>clickAndWait</td><td>link=Alter table</td><td></td></tr>
|
||||
<tr><td>click</td><td>add[2]</td><td></td></tr>
|
||||
<tr><td>type</td><td>fields[3][field]</td><td>albums</td></tr>
|
||||
<tr><td>select</td><td>fields[3][type]</td><td>label=integer</td></tr>
|
||||
<tr><td>type</td><td>fields[3][length]</td><td></td></tr>
|
||||
<tr><td>click</td><td>add[3]</td><td></td></tr>
|
||||
<tr><td>type</td><td>fields[4][field]</td><td>albums</td></tr>
|
||||
<tr><td>select</td><td>fields[4][type]</td><td>label=integer</td></tr>
|
||||
<tr><td>type</td><td>fields[4][length]</td><td></td></tr>
|
||||
<tr><td>uncheck</td><td>name=defaults</td><td></td></tr>
|
||||
<tr><td>clickAndWait</td><td>name=defaults</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=fields[3][default]</td><td>0</td></tr>
|
||||
<tr><td>type</td><td>name=fields[4][default]</td><td>0</td></tr>
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>Table has been altered.</td><td></td></tr>
|
||||
</tbody></table>
|
||||
@@ -219,10 +218,10 @@
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=interprets</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=Alter table</td><td></td></tr>
|
||||
<tr><td>click</td><td>name=add[3]</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=fields[4][field]</td><td>alive</td></tr>
|
||||
<tr><td>select</td><td>name=fields[4][type]</td><td>label=alive</td></tr>
|
||||
<tr><td>click</td><td>name=fields[4][null]</td><td></td></tr>
|
||||
<tr><td>click</td><td>name=add[4]</td><td></td></tr>
|
||||
<tr><td>type</td><td>name=fields[5][field]</td><td>alive</td></tr>
|
||||
<tr><td>select</td><td>name=fields[5][type]</td><td>label=alive</td></tr>
|
||||
<tr><td>click</td><td>name=fields[5][null]</td><td></td></tr>
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>click</td><td>link=alive</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>'alive', 'deceased'</td><td></td></tr>
|
||||
@@ -230,7 +229,7 @@
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Drop']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>cannot drop type</td><td></td></tr>
|
||||
<tr><td>open</td><td>/adminer/?pgsql=&username=ODBC&db=adminer_test&ns=public&edit=interprets&where%5Bid%5D=1</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@value='deceased']</td><td></td></tr>
|
||||
<tr><td>click</td><td>//input[@value='val-deceased']</td><td></td></tr>
|
||||
<tr><td>clickAndWait</td><td>//input[@value='Save']</td><td></td></tr>
|
||||
<tr><td>verifyTextPresent</td><td>deceased</td><td></td></tr>
|
||||
</tbody></table>
|
||||
|
Reference in New Issue
Block a user