1
0
mirror of https://github.com/vrana/adminer.git synced 2025-09-10 22:30:53 +02:00

Compare commits

...

106 Commits

Author SHA1 Message Date
Jakub Vrana
187dd56b1c Release 4.4.0 2018-01-17 12:41:38 +01:00
Jakub Vrana
ba9099f084 Allow sending multiple CSP headers 2018-01-17 11:05:59 +01:00
Jakub Vrana
16e05167a4 Use __construct for constructor 2018-01-16 20:05:07 +01:00
Jakub Vrana
756e304c92 Set session cache limiter only without session.auto_start (bug #586) 2018-01-16 16:56:14 +01:00
Jakub Vrana
e762a6aa95 Add missing newline 2018-01-16 16:44:49 +01:00
Jakub Vrana
b3d5c9affe Require specifying credentials in login-sqlite plugin 2018-01-16 16:37:59 +01:00
Jakub Vrana
0268aba85a Avoid count(null) 2018-01-16 16:22:24 +01:00
Jakub Vrana
9ca92309a1 Disallow PHP 5.3 in Travis 2018-01-16 13:51:02 +01:00
Jakub Vrana
0fae40fb61 Disallow connecting to privileged ports (thanks to hyp3rlinx) 2018-01-16 11:18:32 +01:00
Jakub Vrana
0e5df34ea8 Rate limit password-less login attempts from the same IP address (thanks to hyp3rlinx) 2018-01-16 11:17:25 +01:00
Jakub Vrana
f3938c1a66 Use HTTPS 2018-01-14 11:03:54 +01:00
Jakub Vrana
07aa80048a Use HTTPS in doc_link() 2018-01-14 10:38:01 +01:00
Jakub Vrana
c57e7ac3e3 Do not set '' for empty enum 2018-01-14 10:19:56 +01:00
Jakub Vrana
6d14b47d02 Fix select function onchange 2018-01-14 10:18:38 +01:00
Jakub Vrana
ef3b468626 Clone all event handlers in cloneNode() 2018-01-14 10:04:53 +01:00
Jakub Vrana
4d38c09db5 Use border-collapse to prevent unnecessary wrapping in Chrome 2018-01-14 09:35:13 +01:00
Jakub Vrana
3ba99a1c2a Fix whitespace 2018-01-14 08:52:22 +01:00
Jakub Vrana
9cbdb6262b Fix selectCount() in information_schema 2018-01-14 08:36:10 +01:00
Jakub Vrana
cc268428b8 Fix SQL command toggle 2018-01-14 00:10:42 +01:00
Jakub Vrana
80d030f51a Disallow scripts without nonce 2018-01-13 22:19:16 +01:00
Jakub Vrana
e23da5da0e Fix wrapping in Create table 2018-01-13 17:40:21 +01:00
Jakub Vrana
9d532fc0a1 Use script_src for <script src> 2018-01-13 16:25:11 +01:00
Jakub Vrana
144c7de27f Fix typo in script() 2018-01-13 15:23:47 +01:00
Jakub Vrana
b7fcebfba8 Do not send empty CSP 2018-01-13 14:21:54 +01:00
Jakub Vrana
d39a6e59c7 Move inline event handlers to <script> 2018-01-13 09:34:01 +01:00
Jakub Vrana
fc559a1cf6 Move inline event handlers to <script> 2018-01-13 09:21:21 +01:00
Jakub Vrana
f457053d85 Use the fact that we handle oninput in whisper() 2018-01-13 09:07:35 +01:00
Jakub Vrana
e255ba9aa4 Move inline event handlers to <script> 2018-01-13 08:58:01 +01:00
Jakub Vrana
3fe0d88f98 Editor: Fix Search data in tables 2018-01-12 23:59:04 +01:00
Jakub Vrana
68c6b1c942 Move inline event handlers to <script> 2018-01-12 23:42:20 +01:00
Jakub Vrana
001c37e240 Use <script> instead of inline event handler for skipping original 2018-01-12 23:27:14 +01:00
Jakub Vrana
b6cc584f48 Move inline event handlers to <script> 2018-01-12 22:46:16 +01:00
Jakub Vrana
af1ad47a64 Return false from editingMoveRow() 2018-01-12 22:35:05 +01:00
Jakub Vrana
2eaac2e94e Move inline event handlers to <script> 2018-01-12 22:25:38 +01:00
Jakub Vrana
40abffe8de Use oninput instead of onchange 2018-01-12 22:18:54 +01:00
Jakub Vrana
259a465125 Move inline event handlers to <script> 2018-01-12 21:57:54 +01:00
Jakub Vrana
6c1fbf13c6 Fix fieldChange() after 6353a898 2018-01-12 21:49:45 +01:00
Jakub Vrana
6353a89816 Use oninput instead of onkeyup 2018-01-12 18:46:44 +01:00
Jakub Vrana
38aac7ada2 Move inline event handlers to <script> 2018-01-12 18:34:19 +01:00
Jakub Vrana
24245867d7 Use <script> instead of inline event handler in on_help() 2018-01-12 18:11:00 +01:00
Jakub Vrana
1459df56bc Move inline event handlers to <script> 2018-01-12 17:59:46 +01:00
Jakub Vrana
dc3a0e1a32 Clone onchange in cloneNode() 2018-01-12 17:33:23 +01:00
Jakub Vrana
0411495d20 Move inline event handlers to <script> 2018-01-12 17:19:47 +01:00
Jakub Vrana
3d69fbf5f7 Allow searching data in tables by Ctrl+Enter 2018-01-12 17:11:29 +01:00
Jakub Vrana
5e9df49fd1 Move inline event handlers to <script> 2018-01-12 17:11:29 +01:00
Jakub Vrana
565a5ca0eb Fix selectors in schema after 58b2904d 2018-01-12 17:11:29 +01:00
Jakub Vrana
9061583538 Rely on event always passed to handlers 2018-01-12 17:11:29 +01:00
Jakub Vrana
35b1db6974 Move inline event handlers to <script> 2018-01-12 17:11:29 +01:00
Jakub Vrana
068ee71bf7 Return false from editingRemoveRow 2018-01-12 17:11:29 +01:00
Jakub Vrana
efcf37d162 Move inline event handlers to <script> 2018-01-12 17:11:29 +01:00
Jakub Vrana
e645693147 Use script() for <script> 2018-01-12 17:10:33 +01:00
Jakub Vrana
12fbfc9847 Move inline event handlers to <script> 2018-01-12 17:09:41 +01:00
Jakub Vrana
6b2ba65084 Use <script> instead of inline event handler in print_fieldset() 2018-01-12 17:09:41 +01:00
Jakub Vrana
a5ee3451ac Use <script> instead of inline event handler in confirm() 2018-01-12 17:09:41 +01:00
Jakub Vrana
da671df728 Move inline event handlers to <script> 2018-01-12 17:09:41 +01:00
Jakub Vrana
650221357d Return false from ajaxSetHtml() 2018-01-12 17:09:41 +01:00
Jakub Vrana
d996b48cfa Move inline event handlers to <script> 2018-01-12 17:09:41 +01:00
Jakub Vrana
22b4322710 Revert using @this in formChecked 2018-01-12 17:09:41 +01:00
Jakub Vrana
36edd445a6 Move inline event handlers to <script> 2018-01-12 17:09:41 +01:00
Jakub Vrana
7305783c21 Return false from toggle() 2018-01-12 17:09:41 +01:00
Jakub Vrana
ee3a88d574 onchange='selectFieldChange 2018-01-12 17:09:41 +01:00
Jakub Vrana
e5c52589ec Use @this in selectFieldChange 2018-01-12 17:09:41 +01:00
Jakub Vrana
3b0e1cf289 Move inline event handlers to <script> 2018-01-12 17:09:41 +01:00
Jakub Vrana
767fc0e47e Fix indexesAddColumn after 14778165 2018-01-12 17:09:41 +01:00
Jakub Vrana
63581af0f6 Move inline event handlers to <script> 2018-01-12 17:09:35 +01:00
Jakub Vrana
813ada6661 Revert using @this in formChecked 2018-01-11 18:58:00 +01:00
Jakub Vrana
4be72a2a0d Allow customizing CSP 2018-01-11 18:39:49 +01:00
Jakub Vrana
541c3c1fed Allow img-src data: common in skins 2018-01-11 18:39:49 +01:00
Jakub Vrana
3408d4ad78 Use JSON.parse if available 2018-01-11 18:39:49 +01:00
Jakub Vrana
e614ae08c4 Add Content Security Policy 2018-01-11 18:39:49 +01:00
Jakub Vrana
552d2a6be4 Always send security headers in customization 2018-01-11 18:39:49 +01:00
Jakub Vrana
415253b1b1 Add nosniff header 2018-01-11 18:39:22 +01:00
Jakub Vrana
d07b7e3773 Use Referrer-Policy instead of <meta name="referrer">
To make securityheaders.io happy.

Also fix a typo in the value (https://lists.w3.org/Archives/Public/public-webappsec/2015May/0059.html).
2018-01-11 18:38:15 +01:00
Jakub Vrana
3de101dff4 Editor: Fix doubleclick on database page 2018-01-11 17:24:57 +01:00
Jakub Vrana
48dacd1e97 Fix a typo from 9cb28186 2018-01-11 17:05:37 +01:00
Jakub Vrana
14778165a8 Use @this in JavaScript (prepares for removing inline event handlers) 2018-01-11 17:01:29 +01:00
Jakub Vrana
72b199378a Prevent PHP 7.1 warning about non-numeric values 2018-01-11 16:22:29 +01:00
Jakub Vrana
329fa55af5 Unindent doc-comments 2018-01-11 15:14:05 +01:00
Jakub Vrana
ecf34769ad Delete type="text/css" from <style> as it is the default in HTML5 2018-01-11 14:14:15 +01:00
Jakub Vrana
dc85ba2d86 Delete type="text/javascript" from <script> as it is the default in HTML5 2018-01-11 14:13:43 +01:00
Jakub Vrana
741b76fbd4 Replace getElementsByTagName by shortcut for querySelectorAll 2018-01-11 14:00:04 +01:00
Jakub Vrana
58b2904d62 Use querySelector 2018-01-11 13:55:48 +01:00
Jakub Vrana
9cb281868f Replace getElementById by shortcut for querySelector (requires IE8) 2018-01-11 13:51:32 +01:00
Jakub Vrana
67f6aea77f Fix skin for Chrome 61 (thanks to Dominik Ulrich) 2017-10-28 15:05:07 +02:00
Jakub Vrana
7bcba262df Editor: Display field comment's text inside [] only in edit form 2017-10-01 08:45:17 -07:00
Itamar Schen
75c0786d2e Fix hebrew typos (#228) 2017-09-29 09:25:32 +02:00
Jakub Vrana
c4f6cbb32e Add new Hebrew translations 2017-09-11 13:25:49 +02:00
Jakub Vrana
b10e9e127e Add Hebrew translation 2017-09-09 12:06:14 +02:00
Lukas Tribus
32f1e856ad Editor: Don't set time zone from PHP
Current implementation checks the delta between the local time and
UTC, and applies the delta as time zone for MySQL.

This assumption is wrong if the current time is DST enabled, but the
time that is converted isn't - and vice versa.

For example, Europe/Prague is "CET-1CEST,M3.5.0,M10.5.0/3", when
the MySQL connections is setup now (September, DST enabled) and
we are reading a TIMESTAMP from November, then MySQL applies +0200
instead of +0100 to that timestamp even though November is supposed
to be DST disabled.

There is no reliable and portable way in PHP to understand the
time zone, especially since PHP >= 5.4.0 ignores environment
variable and OS settings [1].

MySQL needs to be properly setup (TZ data loaded [2] and default
TZ set [3]), then everything will work just fine.

The current implementation however causes wrong data 50% of the
time, even when OS/MySQL/PHP is properly setup. As a MySQL
connection will converte timestamps from both DST enabled and
DST disabled dates, a static UTC offset must never be set at
connection level (set time_zone = ...).

This change removes the current implementation, therefor maintaining
OS/MySQL defaults, fixing the DST issue in properly configured
environments.

[1] http://php.net/manual/en/function.date-default-timezone-get.php
[2] https://dev.mysql.com/doc/refman/5.5/en/mysql-tzinfo-to-sql.html
[3] https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html
2017-09-09 11:44:42 +02:00
Jonathan Vollebregt
17e45e9a9c Make sure all sidebar elements are pushed down, not just the form.
This was breaking the #logins block at the log in screen.
2017-09-09 11:39:47 +02:00
Jonathan Vollebregt
e1f43da8df Update AdminerTablesFilter to produce li as per c9801e2e24 2017-05-19 11:23:35 +02:00
Jakub Vrana
70aef8a55a MySQL: Remove dedicated view for replication status 2017-05-19 11:11:44 +02:00
Jakub Vrana
0b824dad29 Sort table names (bug #552) 2017-05-19 10:57:20 +02:00
Alfonso Montero
65fa4b4e31 Update es.inc.php 2017-04-22 10:07:55 +02:00
Jakub Vrana
c0a3f30060 Add a donate link 2017-04-16 10:42:27 +02:00
Jakub Vrana
7af1ee3702 Release 4.3.1 2017-04-14 09:48:11 +02:00
Jakub Vrana
3cbece1ec0 Fix SQL command autofocus 2017-04-09 12:30:34 +02:00
Jakub Vrana
0d73372c50 Add a todo 2017-04-09 12:13:18 +02:00
Jakub Vrana
fb7bd02713 Don't overwrite previous cookies (bug #539) 2017-04-09 11:04:57 +02:00
Jakub Vrana
fb71941daa PostgreSQL: Fix JSONB version support 2017-04-08 20:17:08 +02:00
Jakub Vrana
504c56216c PostgreSQL: Support JSON and JSONB data types (bug #542) 2017-04-08 19:59:13 +02:00
Jakub Vrana
88803c6d0e Update haeckel design (thanks to Klemens Haeckel) 2017-04-08 19:51:13 +02:00
Andre Polykanine A.K.A. Menelion Elensúlë
b585ee8261 Updating Russian translation 2017-04-08 19:41:36 +02:00
Deni
f4817e8568 Fix table dependency on export 2017-04-08 19:38:03 +02:00
Deni
105aca9b04 Fix PostgreSQL nullable fields in export 2017-04-08 19:37:56 +02:00
Jakub Vrana
f556f6acb1 PostgreSQL: Fix index size computation in PostgreSQL < 9.0 (reverts 4c78976c) 2017-04-08 19:33:46 +02:00
89 changed files with 1306 additions and 716 deletions

View File

@@ -1,5 +1,4 @@
language: php language: php
php: php:
- '5.3'
- '7.1' - '7.1'
script: git diff --name-only $TRAVIS_COMMIT_RANGE | grep '\.php$' | xargs -n1 -P8 php -l | grep -v 'No syntax errors'; test $? -eq 1 script: git diff --name-only $TRAVIS_COMMIT_RANGE | grep '\.php$' | xargs -n1 -P8 php -l | grep -v 'No syntax errors'; test $? -eq 1

View File

@@ -163,8 +163,8 @@ foreach ($engines as $engine) {
<p> <p>
<?php if (support("columns") || $TABLE == "") { ?> <?php if (support("columns") || $TABLE == "") { ?>
<?php echo lang('Table name'); ?>: <input name="name" maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off"> <?php echo lang('Table name'); ?>: <input name="name" maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php if ($TABLE == "" && !$_POST) { ?><script type='text/javascript'>focus(document.getElementById('form')['name']);</script><?php } ?> <?php if ($TABLE == "" && !$_POST) { echo script("focus(qs('#form')['name']);"); } ?>
<?php echo ($engines ? "<select name='Engine' onchange='helpClose();'" . on_help("getTarget(event).value", 1) . ">" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" : ""); ?> <?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?>
<?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?> <?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php } ?> <?php } ?>
@@ -187,9 +187,10 @@ edit_fields($row["fields"], $collations, "TABLE", $foreign_keys, $comments);
<p> <p>
<?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>"> <?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>">
<?php echo checkbox("defaults", 1, true, lang('Default values'), "columnShow(this.checked, 5)", "jsonly"); ?> <?php echo checkbox("defaults", 1, true, lang('Default values'), "columnShow(this.checked, 5)", "jsonly"); ?>
<?php if (!$_POST["defaults"]) { ?><script type="text/javascript">editingHideDefaults()</script><?php } ?> <?php if (!$_POST["defaults"]) { echo script("editingHideDefaults();"); } ?>
<?php echo (support("comment") <?php echo (support("comment")
? "<label><input type='checkbox' name='comments' value='1' class='jsonly' onclick=\"columnShow(this.checked, 6); toggle('Comment'); if (this.checked) this.form['Comment'].focus();\"" . ($comments ? " checked" : "") . ">" . lang('Comment') . "</label>" ? "<label><input type='checkbox' name='comments' value='1' class='jsonly'" . ($comments ? " checked" : "") . ">" . lang('Comment') . "</label>"
. script("qsl('input').onclick = function () { columnShow(this.checked, 6); toggle('Comment'); if (this.checked) this.form['Comment'].focus(); };")
. ' <input name="Comment" id="Comment" value="' . h($row["Comment"]) . '" maxlength="' . ($connection->server_info >= 5.5 ? 2048 : 60) . '"' . ($comments ? '' : ' class="hidden"') . '>' . ' <input name="Comment" id="Comment" value="' . h($row["Comment"]) . '" maxlength="' . ($connection->server_info >= 5.5 ? 2048 : 60) . '"' . ($comments ? '' : ' class="hidden"') . '>'
: '') : '')
; ?> ; ?>
@@ -197,14 +198,14 @@ edit_fields($row["fields"], $collations, "TABLE", $foreign_keys, $comments);
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php } ?> <?php } ?>
<?php if ($TABLE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if ($TABLE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<?php <?php
if (support("partitioning")) { if (support("partitioning")) {
$partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]); $partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]);
print_fieldset("partition", lang('Partition by'), $row["partition_by"]); print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
?> ?>
<p> <p>
<?php echo "<select name='partition_by' onchange='partitionByChange(this);'" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . ">" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>"; ?> <?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?>
(<input name="partition" value="<?php echo h($row["partition"]); ?>">) (<input name="partition" value="<?php echo h($row["partition"]); ?>">)
<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>"> <?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>">
<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>> <table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
@@ -212,7 +213,8 @@ if (support("partitioning")) {
<?php <?php
foreach ($row["partition_names"] as $key => $val) { foreach ($row["partition_names"] as $key => $val) {
echo '<tr>'; echo '<tr>';
echo '<td><input name="partition_names[]" value="' . h($val) . '"' . ($key == count($row["partition_names"]) - 1 ? ' onchange="partitionNameChange(this);"' : '') . ' autocapitalize="off">'; echo '<td><input name="partition_names[]" value="' . h($val) . '" autocapitalize="off">';
echo ($key == count($row["partition_names"]) - 1 ? script("qsl('input').oninput = partitionNameChange;") : '');
echo '<td><input name="partition_values[]" value="' . h($row["partition_values"][$key]) . '">'; echo '<td><input name="partition_values[]" value="' . h($row["partition_values"][$key]) . '">';
} }
?> ?>

View File

@@ -65,12 +65,12 @@ echo ($_POST["add_x"] || strpos($name, "\n")
'sql' => "charset-charsets.html", 'sql' => "charset-charsets.html",
'mssql' => "ms187963.aspx", 'mssql' => "ms187963.aspx",
)) : ""); )) : "");
echo script("focus(qs('#name'));");
?> ?>
<script type='text/javascript'>focus(document.getElementById('name'));</script>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php <?php
if (DB != "") { if (DB != "") {
echo "<input type='submit' name='drop' value='" . lang('Drop') . "'" . confirm() . ">\n"; echo "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . confirm() . "\n";
} elseif (!$_POST["add_x"] && $_GET["db"] == "") { } elseif (!$_POST["add_x"] && $_GET["db"] == "") {
echo "<input type='image' class='icon' name='add' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>\n"; echo "<input type='image' class='icon' name='add' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>\n";
} }

View File

@@ -4,7 +4,7 @@ $tables_views = array_merge((array) $_POST["tables"], (array) $_POST["views"]);
if ($tables_views && !$error && !$_POST["search"]) { if ($tables_views && !$error && !$_POST["search"]) {
$result = true; $result = true;
$message = ""; $message = "";
if ($jush == "sql" && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) { if ($jush == "sql" && $_POST["tables"] && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) {
queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once
} }
@@ -56,15 +56,19 @@ if ($adminer->homepage()) {
echo "<form action='' method='post'>\n"; echo "<form action='' method='post'>\n";
if (support("table")) { if (support("table")) {
echo "<fieldset><legend>" . lang('Search data in tables') . " <span id='selected2'></span></legend><div>"; echo "<fieldset><legend>" . lang('Search data in tables') . " <span id='selected2'></span></legend><div>";
echo "<input type='search' name='query' value='" . h($_POST["query"]) . "'> <input type='submit' name='search' value='" . lang('Search') . "'>\n"; 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"; echo "</div></fieldset>\n";
if ($_POST["search"] && $_POST["query"] != "") { if ($_POST["search"] && $_POST["query"] != "") {
search_tables(); search_tables();
} }
} }
$doc_link = doc_link(array('sql' => 'show-table-status.html')); $doc_link = doc_link(array('sql' => 'show-table-status.html'));
echo "<table cellspacing='0' class='nowrap checkable' onclick='tableClick(event);' ondblclick='tableClick(event, true);'>\n"; echo "<table cellspacing='0' class='nowrap checkable'>\n";
echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);" class="jsonly">'; echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo '<thead><tr class="wrap">';
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);", "");
echo '<th>' . lang('Table'); echo '<th>' . lang('Table');
echo '<td>' . lang('Engine') . doc_link(array('sql' => 'storage-engines.html')); echo '<td>' . lang('Engine') . doc_link(array('sql' => 'storage-engines.html'));
echo '<td>' . lang('Collation') . doc_link(array('sql' => 'charset-mysql.html')); echo '<td>' . lang('Collation') . doc_link(array('sql' => 'charset-mysql.html'));
@@ -115,17 +119,17 @@ if ($adminer->homepage()) {
echo "</table>\n"; echo "</table>\n";
if (!information_schema(DB)) { if (!information_schema(DB)) {
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'" . on_help("'VACUUM'") . "> "; $vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . on_help("'VACUUM'");
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'" . on_help($jush == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'") . "> "; $optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . on_help($jush == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'");
echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>" echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>"
. ($jush == "sqlite" ? $vacuum . ($jush == "sqlite" ? $vacuum
: ($jush == "pgsql" ? $vacuum . $optimize : ($jush == "pgsql" ? $vacuum . $optimize
: ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'" . on_help("'ANALYZE TABLE'") . "> " . $optimize : ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . on_help("'ANALYZE TABLE'") . $optimize
. "<input type='submit' name='check' value='" . lang('Check') . "'" . on_help("'CHECK TABLE'") . "> " . "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'CHECK TABLE'")
. "<input type='submit' name='repair' value='" . lang('Repair') . "'" . on_help("'REPAIR TABLE'") . "> " . "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . on_help("'REPAIR TABLE'")
: ""))) : "")))
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'" . confirm() . on_help($jush == "sqlite" ? "'DELETE'" : "'TRUNCATE" . ($jush == "pgsql" ? "'" : " TABLE'")) . "> " . "<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') . "'" . confirm() . on_help("'DROP TABLE'") . ">\n"; . "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . on_help("'DROP TABLE'") . confirm() . "\n";
$databases = (support("scheme") ? $adminer->schemas() : $adminer->databases()); $databases = (support("scheme") ? $adminer->schemas() : $adminer->databases());
if (count($databases) != 1 && $jush != "sqlite") { if (count($databases) != 1 && $jush != "sqlite") {
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB)); $db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
@@ -135,12 +139,13 @@ if ($adminer->homepage()) {
echo (support("copy") ? " <input type='submit' name='copy' value='" . lang('Copy') . "'>" : ""); echo (support("copy") ? " <input type='submit' name='copy' value='" . lang('Copy') . "'>" : "");
echo "\n"; echo "\n";
} }
echo "<input type='hidden' name='all' value='' onclick=\"selectCount('selected', formChecked(this, /^(tables|views)\[/));" . (support("table") ? " selectCount('selected2', formChecked(this, /^tables\[/) || $tables);" : "") . "\">\n"; // used by trCheck() 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 "<input type='hidden' name='token' value='$token'>\n"; echo "<input type='hidden' name='token' value='$token'>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
echo "</form>\n"; echo "</form>\n";
echo "<script type='text/javascript'>tableCheck();</script>\n"; echo script("tableCheck();");
} }
echo '<p class="links"><a href="' . h(ME) . 'create=">' . lang('Create table') . "</a>\n"; echo '<p class="links"><a href="' . h(ME) . 'create=">' . lang('Create table') . "</a>\n";
@@ -221,7 +226,7 @@ if ($adminer->homepage()) {
} }
if ($tables_list) { if ($tables_list) {
echo "<script type='text/javascript'>ajaxSetHtml('" . js_escape(ME) . "script=db');</script>\n"; echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');");
} }
} }
} }

View File

@@ -129,7 +129,7 @@ if (isset($_GET["mongo"])) {
return new Min_Result($this->_conn->_db->selectCollection($table) return new Min_Result($this->_conn->_db->selectCollection($table)
->find(array(), $select) ->find(array(), $select)
->sort($sort) ->sort($sort)
->limit(+$limit) ->limit($limit != "" ? +$limit : 0)
->skip($page * $limit) ->skip($page * $limit)
); );
} }

View File

@@ -977,14 +977,6 @@ if (!defined("DRIVER")) {
return get_key_vals("SHOW STATUS"); return get_key_vals("SHOW STATUS");
} }
/** Get replication status of master or slave
* @param string
* @return array ($name => $value)
*/
function replication_status($type) {
return get_rows("SHOW $type STATUS");
}
/** Convert field in select and edit /** Convert field in select and edit
* @param array one element from fields() * @param array one element from fields()
* @return string * @return string

View File

@@ -186,12 +186,20 @@ if (isset($_GET["pgsql"])) {
} }
function connect() { function connect() {
global $adminer; global $adminer, $types, $structured_types;
$connection = new Min_DB; $connection = new Min_DB;
$credentials = $adminer->credentials(); $credentials = $adminer->credentials();
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) { if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
if ($connection->server_info >= 9) { if ($connection->server_info >= 9) {
$connection->query("SET application_name = 'Adminer'"); $connection->query("SET application_name = 'Adminer'");
if ($connection->server_info >= 9.2) {
$structured_types[lang('Strings')][] = "json";
$types["json"] = 4294967295;
if ($connection->server_info >= 9.4) {
$structured_types[lang('Strings')][] = "jsonb";
$types["jsonb"] = 4294967295;
}
}
} }
return $connection; return $connection;
} }
@@ -244,7 +252,7 @@ ORDER BY 1";
function table_status($name = "") { function table_status($name = "") {
$return = array(); $return = array();
foreach (get_rows("SELECT c.relname AS \"Name\", CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\", pg_relation_size(c.oid) AS \"Data_length\", pg_indexes_size(c.oid) AS \"Index_length\", obj_description(c.oid, 'pg_class') AS \"Comment\", c.relhasoids::int AS \"Oid\", c.reltuples as \"Rows\", n.nspname foreach (get_rows("SELECT c.relname AS \"Name\", CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\", pg_relation_size(c.oid) AS \"Data_length\", pg_total_relation_size(c.oid) - pg_relation_size(c.oid) AS \"Index_length\", obj_description(c.oid, 'pg_class') AS \"Comment\", c.relhasoids::int AS \"Oid\", c.reltuples as \"Rows\", n.nspname
FROM pg_class c FROM pg_class c
JOIN pg_namespace n ON(n.nspname = current_schema() AND n.oid = c.relnamespace) JOIN pg_namespace n ON(n.nspname = current_schema() AND n.oid = c.relnamespace)
WHERE relkind IN ('r', 'm', 'v') WHERE relkind IN ('r', 'm', 'v')
@@ -638,7 +646,7 @@ AND typelem = 0"
foreach ($fields as $field_name => $field) { foreach ($fields as $field_name => $field) {
$part = idf_escape($field['field']) . ' ' . $field['full_type'] $part = idf_escape($field['field']) . ' ' . $field['full_type']
. (is_null($field['default']) ? "" : " DEFAULT $field[default]") . (is_null($field['default']) ? "" : " DEFAULT $field[default]")
. ($field['attnotnull'] ? "" : " NOT NULL"); . ($field['attnotnull'] ? " NOT NULL" : "");
$return_parts[] = $part; $return_parts[] = $part;
// sequences for fields // sequences for fields

View File

@@ -169,8 +169,8 @@ $prefixes = array();
if (DB != "") { if (DB != "") {
$checked = ($TABLE != "" ? "" : " checked"); $checked = ($TABLE != "" ? "" : " checked");
echo "<thead><tr>"; echo "<thead><tr>";
echo "<th style='text-align: left;'><label class='block'><input type='checkbox' id='check-tables'$checked onclick='formCheck(this, /^tables\\[/);'>" . lang('Tables') . "</label>"; echo "<th style='text-align: left;'><label class='block'><input type='checkbox' id='check-tables'$checked>" . lang('Tables') . "</label>" . script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);", "");
echo "<th style='text-align: right;'><label class='block'>" . lang('Data') . "<input type='checkbox' id='check-data'$checked onclick='formCheck(this, /^data\\[/);'></label>"; echo "<th style='text-align: right;'><label class='block'>" . lang('Data') . "<input type='checkbox' id='check-data'$checked></label>" . script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);", "");
echo "</thead>\n"; echo "</thead>\n";
$views = ""; $views = "";
@@ -178,22 +178,25 @@ if (DB != "") {
foreach ($tables_list as $name => $type) { foreach ($tables_list as $name => $type) {
$prefix = preg_replace('~_.*~', '', $name); $prefix = preg_replace('~_.*~', '', $name);
$checked = ($TABLE == "" || $TABLE == (substr($TABLE, -1) == "%" ? "$prefix%" : $name)); //! % may be part of table name $checked = ($TABLE == "" || $TABLE == (substr($TABLE, -1) == "%" ? "$prefix%" : $name)); //! % may be part of table name
$print = "<tr><td>" . checkbox("tables[]", $name, $checked, $name, "checkboxClick(event, this); formUncheck('check-tables');", "block"); $print = "<tr><td>" . checkbox("tables[]", $name, $checked, $name, "checkboxClick.call(this, event); formUncheck('check-tables');", "block");
if ($type !== null && !preg_match('~table~i', $type)) { if ($type !== null && !preg_match('~table~i', $type)) {
$views .= "$print\n"; $views .= "$print\n";
} else { } else {
echo "$print<td align='right'><label class='block'><span id='Rows-" . h($name) . "'></span>" . checkbox("data[]", $name, $checked, "", "checkboxClick(event, this); formUncheck('check-data');") . "</label>\n"; echo "$print<td align='right'><label class='block'><span id='Rows-" . h($name) . "'></span>" . checkbox("data[]", $name, $checked, "", "checkboxClick.call(this, event); formUncheck('check-data');") . "</label>\n";
} }
$prefixes[$prefix]++; $prefixes[$prefix]++;
} }
echo $views; echo $views;
if ($tables_list) { if ($tables_list) {
echo "<script type='text/javascript'>ajaxSetHtml('" . js_escape(ME) . "script=db');</script>\n"; echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');");
} }
} else { } else {
echo "<thead><tr><th style='text-align: left;'><label class='block'><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . " onclick='formCheck(this, /^databases\\[/);'>" . lang('Database') . "</label></thead>\n"; echo "<thead><tr><th style='text-align: left;'>";
echo "<label class='block'><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . ">" . lang('Database') . "</label>";
echo script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);", "");
echo "</thead>\n";
$databases = $adminer->databases(); $databases = $adminer->databases();
if ($databases) { if ($databases) {
foreach ($databases as $db) { foreach ($databases as $db) {

View File

@@ -1,7 +1,7 @@
<?php <?php
$TABLE = $_GET["edit"]; $TABLE = $_GET["edit"];
$fields = fields($TABLE); $fields = fields($TABLE);
$where = (isset($_GET["select"]) ? (count($_POST["check"]) == 1 ? where_check($_POST["check"][0], $fields) : "") : where($_GET, $fields)); $where = (isset($_GET["select"]) ? ($_POST["check"] && count($_POST["check"]) == 1 ? where_check($_POST["check"][0], $fields) : "") : where($_GET, $fields));
$update = (isset($_GET["select"]) ? $_POST["edit"] : $where); $update = (isset($_GET["select"]) ? $_POST["edit"] : $where);
foreach ($fields as $name => $field) { foreach ($fields as $name => $field) {
if (!isset($field["privileges"][$update ? "update" : "insert"]) || $adminer->fieldName($field) == "") { if (!isset($field["privileges"][$update ? "update" : "insert"]) || $adminer->fieldName($field) == "") {

View File

@@ -47,6 +47,6 @@ if (!$row && $EVENT != "") {
<p><?php textarea("EVENT_DEFINITION", $row["EVENT_DEFINITION"]); ?> <p><?php textarea("EVENT_DEFINITION", $row["EVENT_DEFINITION"]); ?>
<p> <p>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($EVENT != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if ($EVENT != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
</form> </form>

View File

@@ -67,7 +67,7 @@ $referencable = array_keys(array_filter(table_status('', true), 'fk_support'));
$j = 0; $j = 0;
foreach ($row["source"] as $key => $val) { foreach ($row["source"] as $key => $val) {
echo "<tr>"; echo "<tr>";
echo "<td>" . html_select("source[" . (+$key) . "]", array(-1 => "") + $source, $val, ($j == count($row["source"]) - 1 ? "foreignAddRow(this);" : 1), "label-source"); echo "<td>" . html_select("source[" . (+$key) . "]", array(-1 => "") + $source, $val, ($j == count($row["source"]) - 1 ? "foreignAddRow.call(this);" : 1), "label-source");
echo "<td>" . html_select("target[" . (+$key) . "]", $target, $row["target"][$key], 1, "label-target"); echo "<td>" . html_select("target[" . (+$key) . "]", $target, $row["target"][$key], 1, "label-target");
$j++; $j++;
} }
@@ -86,6 +86,6 @@ foreach ($row["source"] as $key => $val) {
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<noscript><p><input type="submit" name="add" value="<?php echo lang('Add column'); ?>"></noscript> <noscript><p><input type="submit" name="add" value="<?php echo lang('Add column'); ?>"></noscript>
<?php } ?> <?php } ?>
<?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
</form> </form>

View File

@@ -65,10 +65,16 @@ class Adminer {
} }
/** Headers to send before HTML output /** Headers to send before HTML output
* @return bool true to send security headers * @return null
*/ */
function headers() { function headers() {
return true; }
/** Get Content Security Policy headers
* @return array of arrays with directive name in key, allowed sources in value
*/
function csp() {
return csp();
} }
/** Print HTML code inside <head> /** Print HTML code inside <head>
@@ -88,16 +94,14 @@ class Adminer {
global $drivers; global $drivers;
?> ?>
<table cellspacing="0"> <table cellspacing="0">
<tr><th><?php echo lang('System'); ?><td><?php echo html_select("auth[driver]", $drivers, DRIVER); ?> <tr><th><?php echo lang('System'); ?><td><?php echo html_select("auth[driver]", $drivers, DRIVER) . "\n"; ?>
<tr><th><?php echo lang('Server'); ?><td><input name="auth[server]" value="<?php echo h(SERVER); ?>" title="hostname[:port]" placeholder="localhost" autocapitalize="off"> <tr><th><?php echo lang('Server'); ?><td><input name="auth[server]" value="<?php echo h(SERVER); ?>" title="hostname[:port]" placeholder="localhost" autocapitalize="off">
<tr><th><?php echo lang('Username'); ?><td><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Username'); ?><td><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off">
<tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]"> <tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]">
<tr><th><?php echo lang('Database'); ?><td><input name="auth[db]" value="<?php echo h($_GET["db"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Database'); ?><td><input name="auth[db]" value="<?php echo h($_GET["db"]); ?>" autocapitalize="off">
</table> </table>
<script type="text/javascript">
focus(document.getElementById('username'));
</script>
<?php <?php
echo script("focus(qs('#username'));");
echo "<p><input type='submit' value='" . lang('Login') . "'>\n"; echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n"; echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
} }
@@ -309,9 +313,16 @@ focus(document.getElementById('username'));
$select[""] = array(); $select[""] = array();
foreach ($select as $key => $val) { foreach ($select as $key => $val) {
$val = $_GET["columns"][$key]; $val = $_GET["columns"][$key];
$column = select_input(" name='columns[$i][col]' onchange='" . ($key !== "" ? "selectFieldChange(this.form)" : "selectAddRow(this)") . ";'", $columns, $val["col"]); $column = select_input(
echo "<div>" . ($functions || $grouping ? "<select name='columns[$i][fun]' onchange='helpClose();" . ($key !== "" ? "" : " this.nextSibling.nextSibling.onchange();") . "'" " name='columns[$i][col]'",
. on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1) . ">" . optionlist(array(-1 => "") + array_filter(array(lang('Functions') => $functions, lang('Aggregation') => $grouping)), $val["fun"]) . "</select>" $columns,
$val["col"],
($key !== "" ? "selectFieldChange" : "selectAddRow")
);
echo "<div>" . ($functions || $grouping ? "<select name='columns[$i][fun]'>"
. optionlist(array(-1 => "") + array_filter(array(lang('Functions') => $functions, lang('Aggregation') => $grouping)), $val["fun"]) . "</select>"
. on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1)
. script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "")
. "($column)" : $column) . "</div>\n"; . "($column)" : $column) . "</div>\n";
$i++; $i++;
} }
@@ -329,20 +340,29 @@ focus(document.getElementById('username'));
foreach ($indexes as $i => $index) { foreach ($indexes as $i => $index) {
if ($index["type"] == "FULLTEXT") { if ($index["type"] == "FULLTEXT") {
echo "(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST"; echo "(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST";
echo " <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "' onchange='selectFieldChange(this.form);'>"; echo " <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>";
echo script("qsl('input').oninput = selectFieldChange;", "");
echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL"); echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL");
echo "<br>\n"; echo "<br>\n";
} }
} }
$_GET["where"] = (array) $_GET["where"]; $_GET["where"] = (array) $_GET["where"];
reset($_GET["where"]); reset($_GET["where"]);
$change_next = "this.nextSibling.onchange();"; $change_next = "this.parentNode.firstChild.onchange();";
for ($i = 0; $i <= count($_GET["where"]); $i++) { for ($i = 0; $i <= count($_GET["where"]); $i++) {
list(, $val) = each($_GET["where"]); list(, $val) = each($_GET["where"]);
if (!$val || ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators))) { if (!$val || ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators))) {
echo "<div>" . select_input(" name='where[$i][col]' onchange='$change_next'", $columns, $val["col"], "(" . lang('anywhere') . ")"); echo "<div>" . select_input(
" name='where[$i][col]'",
$columns,
$val["col"],
($val ? "selectFieldChange" : "selectAddRow"),
"(" . lang('anywhere') . ")"
);
echo html_select("where[$i][op]", $this->operators, $val["op"], $change_next); echo html_select("where[$i][op]", $this->operators, $val["op"], $change_next);
echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "' onchange='" . ($val ? "selectFieldChange(this.form)" : "selectAddRow(this)") . ";' onkeydown='selectSearchKeydown(this, event);' onsearch='selectSearchSearch(this);'></div>\n"; echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>";
echo script("mixin(qsl('input'), {oninput: function () { $change_next }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", "");
echo "</div>\n";
} }
} }
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
@@ -359,12 +379,12 @@ focus(document.getElementById('username'));
$i = 0; $i = 0;
foreach ((array) $_GET["order"] as $key => $val) { foreach ((array) $_GET["order"] as $key => $val) {
if ($val != "") { if ($val != "") {
echo "<div>" . select_input(" name='order[$i]' onchange='selectFieldChange(this.form);'", $columns, $val); echo "<div>" . select_input(" name='order[$i]'", $columns, $val, "selectFieldChange");
echo checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')) . "</div>\n"; echo checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')) . "</div>\n";
$i++; $i++;
} }
} }
echo "<div>" . select_input(" name='order[$i]' onchange='selectAddRow(this);'", $columns); echo "<div>" . select_input(" name='order[$i]'", $columns, "", "selectAddRow");
echo checkbox("desc[$i]", 1, false, lang('descending')) . "</div>\n"; echo checkbox("desc[$i]", 1, false, lang('descending')) . "</div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -375,7 +395,8 @@ focus(document.getElementById('username'));
*/ */
function selectLimitPrint($limit) { function selectLimitPrint($limit) {
echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling
echo "<input type='number' name='limit' class='size' value='" . h($limit) . "' onchange='selectFieldChange(this.form);'>"; echo "<input type='number' name='limit' class='size' value='" . h($limit) . "'>";
echo script("qsl('input').oninput = selectFieldChange;", "");
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -399,7 +420,7 @@ focus(document.getElementById('username'));
echo "<fieldset><legend>" . lang('Action') . "</legend><div>"; echo "<fieldset><legend>" . lang('Action') . "</legend><div>";
echo "<input type='submit' value='" . lang('Select') . "'>"; echo "<input type='submit' value='" . lang('Select') . "'>";
echo " <span id='noindex' title='" . lang('Full table scan') . "'></span>"; echo " <span id='noindex' title='" . lang('Full table scan') . "'></span>";
echo "<script type='text/javascript'>\n"; echo "<script" . nonce() . ">\n";
echo "var indexColumns = "; echo "var indexColumns = ";
$columns = array(); $columns = array();
foreach ($indexes as $index) { foreach ($indexes as $index) {
@@ -413,7 +434,7 @@ focus(document.getElementById('username'));
json_row($key); json_row($key);
} }
echo ";\n"; echo ";\n";
echo "selectFieldChange(document.getElementById('form'));\n"; echo "selectFieldChange.call(qs('#form')['select']);\n";
echo "</script>\n"; echo "</script>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -571,12 +592,16 @@ focus(document.getElementById('username'));
global $jush; global $jush;
restart_session(); restart_session();
$history = &get_session("queries"); $history = &get_session("queries");
if (!$history[$_GET["db"]]) {
$history[$_GET["db"]] = array();
}
$id = "sql-" . count($history[$_GET["db"]]); $id = "sql-" . count($history[$_GET["db"]]);
if (strlen($query) > 1e6) { if (strlen($query) > 1e6) {
$query = preg_replace('~[\x80-\xFF]+$~', '', substr($query, 0, 1e6)) . "\n..."; // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment $query = preg_replace('~[\x80-\xFF]+$~', '', substr($query, 0, 1e6)) . "\n..."; // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
} }
$history[$_GET["db"]][] = array($query, time(), $time); // not DB - $_GET["db"] is changed in database.inc.php //! respect $_GET["ns"] $history[$_GET["db"]][] = array($query, time(), $time); // not DB - $_GET["db"] is changed in database.inc.php //! respect $_GET["ns"]
return " <span class='time'>" . @date("H:i:s") . "</span> <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a>" // @ - time zone may be not set return " <span class='time'>" . @date("H:i:s") . "</span>" // @ - time zone may be not set
. " <a href='#$id' class='toggle'>" . lang('SQL command') . "</a>"
. "<div id='$id' class='hidden'><pre><code class='jush-$jush'>" . shorten_utf8($query, 1000) . '</code></pre>' . "<div id='$id' class='hidden'><pre><code class='jush-$jush'>" . shorten_utf8($query, 1000) . '</code></pre>'
. ($time ? " <span class='time'>($time)</span>" : '') . ($time ? " <span class='time'>($time)</span>" : '')
. (support("sql") ? '<p><a href="' . h(str_replace("db=" . urlencode(DB), "db=" . urlencode($_GET["db"]), ME) . 'sql=&history=' . (count($history[$_GET["db"]]) - 1)) . '">' . lang('Edit') . '</a>' : '') . (support("sql") ? '<p><a href="' . h(str_replace("db=" . urlencode(DB), "db=" . urlencode($_GET["db"]), ME) . 'sql=&history=' . (count($history[$_GET["db"]]) - 1)) . '">' . lang('Edit') . '</a>' : '')
@@ -626,6 +651,16 @@ focus(document.getElementById('username'));
return ""; return "";
} }
/** Get hint for edit field
* @param string table name
* @param array single field from fields()
* @param string
* @return string
*/
function editHint($table, $field, $value) {
return "";
}
/** Process sent input /** Process sent input
* @param array single field from fields() * @param array single field from fields()
* @param string * @param string
@@ -645,7 +680,7 @@ focus(document.getElementById('username'));
} elseif (preg_match('~^([+-]|\\|\\|)$~', $function)) { } elseif (preg_match('~^([+-]|\\|\\|)$~', $function)) {
$return = idf_escape($name) . " $function $return"; $return = idf_escape($name) . " $function $return";
} elseif (preg_match('~^[+-] interval$~', $function)) { } 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) ? $value : $return);
} elseif (preg_match('~^(addtime|subtime|concat)$~', $function)) { } elseif (preg_match('~^(addtime|subtime|concat)$~', $function)) {
$return = "$function(" . idf_escape($name) . ", $return)"; $return = "$function(" . idf_escape($name) . ", $return)";
} elseif (preg_match('~^(md5|sha1|password|encrypt)$~', $function)) { } elseif (preg_match('~^(md5|sha1|password|encrypt)$~', $function)) {
@@ -842,7 +877,7 @@ focus(document.getElementById('username'));
foreach ($usernames as $username => $password) { foreach ($usernames as $username => $password) {
if ($password !== null) { if ($password !== null) {
if ($first) { if ($first) {
echo "<p id='logins' onmouseover='menuOver(this, event);' onmouseout='menuOut(this);'>\n"; echo "<p id='logins'>" . script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");
$first = false; $first = false;
} }
$dbs = $_SESSION["db"][$vendor][$server][$username]; $dbs = $_SESSION["db"][$vendor][$server][$username];
@@ -858,16 +893,14 @@ focus(document.getElementById('username'));
$connection->select_db(DB); $connection->select_db(DB);
$tables = table_status('', true); $tables = table_status('', true);
} }
?> echo script_src("../externals/jush/modules/jush.js");
<script type="text/javascript" src="../externals/jush/modules/jush.js"></script> echo script_src("../externals/jush/modules/jush-textarea.js");
<script type="text/javascript" src="../externals/jush/modules/jush-textarea.js"></script> echo script_src("../externals/jush/modules/jush-txt.js");
<script type="text/javascript" src="../externals/jush/modules/jush-txt.js"></script> echo script_src("../externals/jush/modules/jush-js.js");
<script type="text/javascript" src="../externals/jush/modules/jush-js.js"></script>
<?php
if (support("sql")) { if (support("sql")) {
echo script_src("../externals/jush/modules/jush-$jush.js");
?> ?>
<script type="text/javascript" src="../externals/jush/modules/jush-<?php echo $jush; ?>.js"></script> <script<?php echo nonce(); ?>>
<script type="text/javascript">
<?php <?php
if ($tables) { if ($tables) {
$links = array(); $links = array();
@@ -914,15 +947,15 @@ bodyLoad('<?php echo (is_object($connection) ? substr($connection->server_info,
<p id="dbs"> <p id="dbs">
<?php <?php
hidden_fields_get(); hidden_fields_get();
$db_events = " onmousedown='dbMouseDown(event, this);' onchange='dbChange(this);'"; $db_events = script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});", "");
echo "<span title='" . lang('database') . "'>DB</span>: " . ($databases echo "<span title='" . lang('database') . "'>DB</span>: " . ($databases
? "<select name='db'$db_events>" . optionlist(array("" => "") + $databases, DB) . "</select>" ? "<select name='db'>" . optionlist(array("" => "") + $databases, DB) . "</select>$db_events"
: '<input name="db" value="' . h(DB) . '" autocapitalize="off">' : '<input name="db" value="' . h(DB) . '" autocapitalize="off">'
); );
echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n"; echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n";
if ($missing != "db" && DB != "" && $connection->select_db(DB)) { if ($missing != "db" && DB != "" && $connection->select_db(DB)) {
if (support("scheme")) { if (support("scheme")) {
echo "<br>" . lang('Schema') . ": <select name='ns'$db_events>" . optionlist(array("" => "") + $adminer->schemas(), $_GET["ns"]) . "</select>"; echo "<br>" . lang('Schema') . ": <select name='ns'>" . optionlist(array("" => "") + $adminer->schemas(), $_GET["ns"]) . "</select>$db_events";
if ($_GET["ns"] != "") { if ($_GET["ns"] != "") {
set_schema($_GET["ns"]); set_schema($_GET["ns"]);
} }
@@ -941,7 +974,7 @@ bodyLoad('<?php echo (is_object($connection) ? substr($connection->server_info,
* @return null * @return null
*/ */
function tablesPrint($tables) { function tablesPrint($tables) {
echo "<ul id='tables' onmouseover='menuOver(this, event);' onmouseout='menuOut(this);'>\n"; echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $table => $status) { foreach ($tables as $table => $status) {
echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table || $_GET["edit"] == $table, "select") . ">" . lang('select') . "</a> "; echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table || $_GET["edit"] == $table, "select") . ">" . lang('select') . "</a> ";
$name = $this->tableName($status); $name = $this->tableName($status);

View File

@@ -48,14 +48,18 @@ function add_invalid_login() {
fclose($fp); fclose($fp);
} }
$auth = $_POST["auth"]; function check_invalid_login() {
if ($auth) { global $adminer;
$invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist $invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist
$invalid = $invalids[$adminer->bruteForceKey()]; $invalid = $invalids[$adminer->bruteForceKey()];
$next_attempt = ($invalid[1] > 30 ? $invalid[0] - time() : 0); // allow 30 invalid attempts $next_attempt = ($invalid[1] > 30 ? $invalid[0] - time() : 0); // allow 30 invalid attempts
if ($next_attempt > 0) { //! do the same with permanent login if ($next_attempt > 0) { //! do the same with permanent login
auth_error(lang('Too many unsuccessful logins, try again in %d minute(s).', ceil($next_attempt / 60))); auth_error(lang('Too many unsuccessful logins, try again in %d minute(s).', ceil($next_attempt / 60)));
} }
}
$auth = $_POST["auth"];
if ($auth) {
session_regenerate_id(); // defense against session fixation session_regenerate_id(); // defense against session fixation
$vendor = $auth["driver"]; $vendor = $auth["driver"];
$server = $auth["server"]; $server = $auth["server"];
@@ -89,7 +93,7 @@ if ($auth) {
set_session($key, null); set_session($key, null);
} }
unset_permanent(); unset_permanent();
redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1), lang('Logout successful.')); redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1), lang('Logout successful.') . ' ' . lang('Thanks for using Adminer, consider <a href="%s">donating</a>.', 'https://sourceforge.net/donate/index.php?group_id=264133'));
} }
} elseif ($permanent && !$_SESSION["pwds"]) { } elseif ($permanent && !$_SESSION["pwds"]) {
@@ -161,6 +165,11 @@ if (isset($_GET["username"])) {
page_footer("auth"); page_footer("auth");
exit; exit;
} }
list($host, $port) = explode(":", SERVER, 2);
if (is_numeric($port) && $port < 1024) {
auth_error('Connecting to privileged ports is not allowed.');
}
check_invalid_login();
$connection = connect(); $connection = connect();
} }

View File

@@ -36,8 +36,8 @@ if (!strpos($_SERVER["REQUEST_URI"], '?') && $_SERVER["QUERY_STRING"] != "") { /
$HTTPS = $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off"); $HTTPS = $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off");
@ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled @ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled
session_cache_limiter(""); // to allow restarting session and to not send Cache-Control: no-store
if (!defined("SID")) { if (!defined("SID")) {
session_cache_limiter(""); // to allow restarting session
session_name("adminer_sid"); // use specific session name to get own namespace session_name("adminer_sid"); // use specific session name to get own namespace
$params = array(0, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS); $params = array(0, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS);
if (version_compare(PHP_VERSION, '5.2.0') >= 0) { if (version_compare(PHP_VERSION, '5.2.0') >= 0) {

View File

@@ -17,7 +17,6 @@ function connect_error() {
'processlist' => lang('Process list'), 'processlist' => lang('Process list'),
'variables' => lang('Variables'), 'variables' => lang('Variables'),
'status' => lang('Status'), 'status' => lang('Status'),
'replication' => lang('Replication'),
) as $key => $val) { ) as $key => $val) {
if (support($key)) { if (support($key)) {
echo "<a href='" . h(ME) . "$key='>$val</a>\n"; echo "<a href='" . h(ME) . "$key='>$val</a>\n";
@@ -30,13 +29,14 @@ function connect_error() {
$scheme = support("scheme"); $scheme = support("scheme");
$collations = collations(); $collations = collations();
echo "<form action='' method='post'>\n"; echo "<form action='' method='post'>\n";
echo "<table cellspacing='0' class='checkable' onclick='tableClick(event);' ondblclick='tableClick(event, true);'>\n"; echo "<table cellspacing='0' class='checkable'>\n";
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo "<thead><tr>" echo "<thead><tr>"
. (support("database") ? "<td>&nbsp;" : "") . (support("database") ? "<td>&nbsp;" : "")
. "<th>" . lang('Database') . " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>" . "<th>" . lang('Database') . " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>"
. "<td>" . lang('Collation') . "<td>" . lang('Collation')
. "<td>" . lang('Tables') . "<td>" . lang('Tables')
. "<td>" . lang('Size') . " - <a href='" . h(ME) . "dbsize=1' onclick=\"return !ajaxSetHtml('" . h(js_escape(ME)) . "script=connect');\">" . lang('Compute') . "</a>" . "<td>" . lang('Size') . " - <a href='" . h(ME) . "dbsize=1'>" . lang('Compute') . "</a>" . script("qsl('a').onclick = partial(ajaxSetHtml, '" . js_escape(ME) . "script=connect');", "")
. "</thead>\n" . "</thead>\n"
; ;
@@ -57,12 +57,12 @@ function connect_error() {
echo "</table>\n"; echo "</table>\n";
echo (support("database") echo (support("database")
? "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>\n" ? "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>\n"
. "<input type='hidden' name='all' value='' onclick=\"selectCount('selected', formChecked(this, /^db/));\">\n" // used by trCheck() . "<input type='hidden' name='all' value=''>" . script("qsl('input').onclick = function () { selectCount('selected', formChecked(this, /^db/)); };") // used by trCheck()
. "<input type='submit' name='drop' value='" . lang('Drop') . "'" . confirm() . ">\n" . "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . confirm() . "\n"
. "</div></fieldset>\n" . "</div></fieldset>\n"
: "" : ""
); );
echo "<script type='text/javascript'>tableCheck();</script>\n"; echo script("tableCheck();");
echo "<input type='hidden' name='token' value='$token'>\n"; echo "<input type='hidden' name='token' value='$token'>\n";
echo "</form>\n"; echo "</form>\n";
} }
@@ -78,7 +78,7 @@ if (isset($_GET["import"])) {
$_GET["sql"] = $_GET["import"]; $_GET["sql"] = $_GET["import"];
} }
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["replication"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) { if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
if (DB != "" || $_GET["refresh"]) { if (DB != "" || $_GET["refresh"]) {
restart_session(); restart_session();
set_session("dbs", null); set_session("dbs", null);

View File

@@ -19,13 +19,11 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<?php echo $LANG; ?>" dir="<?php echo lang('ltr'); ?>"> <html lang="<?php echo $LANG; ?>" dir="<?php echo lang('ltr'); ?>">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
<meta name="referrer" content="origin-when-crossorigin">
<title><?php echo $title_page; ?></title> <title><?php echo $title_page; ?></title>
<link rel="stylesheet" type="text/css" href="../adminer/static/default.css"> <link rel="stylesheet" type="text/css" href="../adminer/static/default.css">
<script type="text/javascript" src="../adminer/static/functions.js"></script> <?php echo script_src("../adminer/static/functions.js"); ?>
<script type="text/javascript" src="static/editing.js"></script> <?php echo script_src("static/editing.js"); ?>
<?php if ($adminer->head()) { ?> <?php if ($adminer->head()) { ?>
<link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico"> <link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico">
<link rel="apple-touch-icon" href="../adminer/static/favicon.ico"> <link rel="apple-touch-icon" href="../adminer/static/favicon.ico">
@@ -34,13 +32,15 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
<?php } ?> <?php } ?>
<?php } ?> <?php } ?>
<body class="<?php echo lang('ltr'); ?> nojs" onkeydown="bodyKeydown(event);" onclick="bodyClick(event);"<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " onload=\"verifyVersion('$VERSION');\""); ?>> <body class="<?php echo lang('ltr'); ?> nojs">
<script type="text/javascript"> <script<?php echo nonce(); ?>>
mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick<?php echo (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '$VERSION')"); ?>});
document.body.className = document.body.className.replace(/ nojs/, ' js'); document.body.className = document.body.className.replace(/ nojs/, ' js');
var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>'; var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>';
</script> </script>
<div id="help" class="jush-<?php echo $jush; ?> jsonly hidden" onmouseover="helpOpen = 1;" onmouseout="helpMouseout(this, event);"></div> <div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div>
<?php echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"); ?>
<div id="content"> <div id="content">
<?php <?php
@@ -89,10 +89,46 @@ function page_headers() {
global $adminer; global $adminer;
header("Content-Type: text/html; charset=utf-8"); header("Content-Type: text/html; charset=utf-8");
header("Cache-Control: no-cache"); header("Cache-Control: no-cache");
if ($adminer->headers()) {
header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, Firefox 3.6.9 header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, Firefox 3.6.9
header("X-XSS-Protection: 0"); // prevents introducing XSS in IE8 by removing safe parts of the page header("X-XSS-Protection: 0"); // prevents introducing XSS in IE8 by removing safe parts of the page
header("X-Content-Type-Options: nosniff");
header("Referrer-Policy: origin-when-cross-origin");
foreach ($adminer->csp() as $csp) {
$header = array();
foreach ($csp as $key => $val) {
$header[] = "$key $val";
} }
header("Content-Security-Policy: " . implode("; ", $header));
}
$adminer->headers();
}
/** Get Content Security Policy headers
* @return array of arrays with directive name in key, allowed sources in value
*/
function csp() {
return array(
array(
"default-src" => "'none'",
"script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'", // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-'
"style-src" => "'self' 'unsafe-inline'",
"connect-src" => "'self'",
"img-src" => "'self' data:",
"frame-src" => "https://www.adminer.org",
"form-action" => "'self'",
),
);
}
/** Get a CSP nonce
* @return string Base64 value
*/
function get_nonce() {
static $nonce;
if (!$nonce) {
$nonce = base64_encode(rand_string());
}
return $nonce;
} }
/** Print flash and error messages /** Print flash and error messages
@@ -103,7 +139,7 @@ function page_messages($error) {
$uri = preg_replace('~^[^?]*~', '', $_SERVER["REQUEST_URI"]); $uri = preg_replace('~^[^?]*~', '', $_SERVER["REQUEST_URI"]);
$messages = $_SESSION["messages"][$uri]; $messages = $_SESSION["messages"][$uri];
if ($messages) { if ($messages) {
echo "<div class='message'>" . implode("</div>\n<div class='message'>", $messages) . "</div>\n"; echo "<div class='message'>" . implode("</div>\n<div class='message'>", $messages) . "</div>" . script("messagesPrint();");
unset($_SESSION["messages"][$uri]); unset($_SESSION["messages"][$uri]);
} }
if ($error) { if ($error) {
@@ -132,6 +168,6 @@ function page_footer($missing = "") {
<div id="menu"> <div id="menu">
<?php $adminer->navigation($missing); ?> <?php $adminer->navigation($missing); ?>
</div> </div>
<script type="text/javascript">setupSubmitHighlight(document);</script>
<?php <?php
echo script("setupSubmitHighlight(document);");
} }

View File

@@ -27,7 +27,7 @@
$query = $adminer->selectQueryBuild($select, $where, $group, $order, $limit, $page); $query = $adminer->selectQueryBuild($select, $where, $group, $order, $limit, $page);
if (!$query) { if (!$query) {
$query = "SELECT" . limit( $query = "SELECT" . limit(
($_GET["page"] != "last" && +$limit && $group && $is_group && $jush == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table), ($_GET["page"] != "last" && $limit != "" && $group && $is_group && $jush == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table),
($where ? "\nWHERE " . implode(" AND ", $where) : "") . ($group && $is_group ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : ""), ($where ? "\nWHERE " . implode(" AND ", $where) : "") . ($group && $is_group ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : ""),
($limit != "" ? +$limit : null), ($limit != "" ? +$limit : null),
($page ? $limit * $page : 0), ($page ? $limit * $page : 0),

View File

@@ -141,7 +141,7 @@ function edit_type($key, $field, $collations, $foreign_keys = array()) {
global $structured_types, $types, $unsigned, $on_actions; global $structured_types, $types, $unsigned, $on_actions;
$type = $field["type"]; $type = $field["type"];
?> ?>
<td><select name="<?php echo h($key); ?>[type]" class="type" onfocus="lastType = selectValue(this);" onchange="editingTypeChange(this);"<?php echo on_help("getTarget(event).value", 1); ?> aria-labelledby="label-type"><?php <td><select name="<?php echo h($key); ?>[type]" class="type" aria-labelledby="label-type"><?php
if ($type && !isset($types[$type]) && !isset($foreign_keys[$type])) { if ($type && !isset($types[$type]) && !isset($foreign_keys[$type])) {
array_unshift($structured_types, $type); array_unshift($structured_types, $type);
} }
@@ -150,7 +150,9 @@ if ($foreign_keys) {
} }
echo optionlist($structured_types, $type); echo optionlist($structured_types, $type);
?></select> ?></select>
<td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3" onfocus="editingLengthFocus(this);"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); ?> onchange="editingLengthChange(this);" onkeyup="this.onchange();" aria-labelledby="label-length"><td class="options"><?php //! type="number" with enabled JavaScript <?php echo on_help("getTarget(event).value", 1); ?>
<?php echo script("mixin(qsl('select'), {onfocus: function () { lastType = selectValue(this); }, onchange: editingTypeChange});", ""); ?>
<td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); ?> aria-labelledby="label-length"><?php echo script("mixin(qsl('input'), {onfocus: editingLengthFocus, oninput: editingLengthChange});", ""); ?><td class="options"><?php //! type="number" with enabled JavaScript
echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>'; echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>';
echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match('~((^|[^o])int|float|double|decimal)$~', $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : ''); echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match('~((^|[^o])int|float|double|decimal)$~', $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), $field["on_update"]) . '</select>' : ''); echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), $field["on_update"]) . '</select>' : '');
@@ -239,7 +241,7 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
<thead><tr class="wrap"> <thead><tr class="wrap">
<?php if ($type == "PROCEDURE") { ?><td>&nbsp;<?php } ?> <?php if ($type == "PROCEDURE") { ?><td>&nbsp;<?php } ?>
<th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?> <th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?>
<td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;" onblur="editingLengthBlur(this);"></textarea> <td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("qs('#enum-edit').onblur = editingLengthBlur;"); ?>
<td id="label-length"><?php echo lang('Length'); ?> <td id="label-length"><?php echo lang('Length'); ?>
<td><?php echo lang('Options'); /* no label required, options have their own label */ ?> <td><?php echo lang('Options'); /* no label required, options have their own label */ ?>
<?php if ($type == "TABLE") { ?> <?php if ($type == "TABLE") { ?>
@@ -253,10 +255,11 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
<td id="label-default"><?php echo lang('Default value'); ?> <td id="label-default"><?php echo lang('Default value'); ?>
<?php echo (support("comment") ? "<td id='label-comment'" . ($comments ? "" : " class='hidden'") . ">" . lang('Comment') : ""); ?> <?php echo (support("comment") ? "<td id='label-comment'" . ($comments ? "" : " class='hidden'") . ">" . lang('Comment') : ""); ?>
<?php } ?> <?php } ?>
<td><?php echo "<input type='image' class='icon' name='add[" . (support("move_col") ? 0 : count($fields)) . "]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>"; ?><script type="text/javascript">row_count = <?php echo count($fields); ?>;</script> <td><?php echo "<input type='image' class='icon' name='add[" . (support("move_col") ? 0 : count($fields)) . "]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>" . script("row_count = " . count($fields) . ";"); ?>
</thead> </thead>
<tbody onkeydown="return editingKeydown(event);"> <tbody>
<?php <?php
echo script("qsl('tbody').onkeydown = editingKeydown;");
foreach ($fields as $i => $field) { foreach ($fields as $i => $field) {
$i++; $i++;
$orig = $field[($_POST ? "orig" : "field")]; $orig = $field[($_POST ? "orig" : "field")];
@@ -264,24 +267,23 @@ function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = arra
?> ?>
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>> <tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $inout), $field["inout"]) : ""); ?> <?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $inout), $field["inout"]) : ""); ?>
<th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" onchange="editingNameChange(this);<?php echo ($field["field"] != "" || count($fields) > 1 ? '' : ' editingAddRow(this);" onkeyup="if (this.value) editingAddRow(this);'); ?>" maxlength="64" autocapitalize="off" aria-labelledby="label-name"><?php } ?> <th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" maxlength="64" autocapitalize="off" aria-labelledby="label-name"><?php echo script("qsl('input').oninput = function () { editingNameChange.call(this);" . ($field["field"] != "" || count($fields) > 1 ? "" : " editingAddRow.call(this);") . " };", ""); ?><?php } ?>
<input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($orig); ?>"> <input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($orig); ?>">
<?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?> <?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?>
<?php if ($type == "TABLE") { ?> <?php if ($type == "TABLE") { ?>
<td><?php echo checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"); ?> <td><?php echo checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"); ?>
<td><label class="block"><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?> onclick="var field = this.form['fields[' + this.value + '][field]']; if (!field.value) { field.value = 'id'; field.onchange(); }" aria-labelledby="label-ai"></label><td><?php <td><label class="block"><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?> aria-labelledby="label-ai"><?php echo script("qsl('input').onclick = function () { var field = this.form['fields[' + this.value + '][field]']; if (!field.value) { field.value = 'id'; field.oninput(); } }"); ?></label><td><?php
echo checkbox("fields[$i][has_default]", 1, $field["has_default"], "", "", "", "label-default"); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" onkeyup="keyupChange.call(this);" onchange="this.previousSibling.checked = true;" aria-labelledby="label-default"> echo checkbox("fields[$i][has_default]", 1, $field["has_default"], "", "", "", "label-default"); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" aria-labelledby="label-default"><?php echo script("qsl('input').oninput = function () { this.previousSibling.checked = true; }", ""); ?>
<?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . "><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' maxlength='" . ($connection->server_info >= 5.5 ? 1024 : 255) . "' aria-labelledby='label-comment'>" : ""); ?> <?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . "><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' maxlength='" . ($connection->server_info >= 5.5 ? 1024 : 255) . "' aria-labelledby='label-comment'>" : ""); ?>
<?php } ?> <?php } ?>
<?php <?php
echo "<td>"; echo "<td>";
echo (support("move_col") ? echo (support("move_col") ?
"<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "' onclick='return !editingAddRow(this, 1);'>&nbsp;" "<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>&nbsp;" . script("qsl('input').onclick = partial(editingAddRow, 1);", "")
. "<input type='image' class='icon' name='up[$i]' src='../adminer/static/up.gif' alt='^' title='" . lang('Move up') . "' onclick='return !editingMoveRow(this, 1);'>&nbsp;" . "<input type='image' class='icon' name='up[$i]' src='../adminer/static/up.gif' alt='^' title='" . lang('Move up') . "'>&nbsp;" . script("qsl('input').onclick = partial(editingMoveRow, 1);", "")
. "<input type='image' class='icon' name='down[$i]' src='../adminer/static/down.gif' alt='v' title='" . lang('Move down') . "' onclick='return !editingMoveRow(this, 0);'>&nbsp;" . "<input type='image' class='icon' name='down[$i]' src='../adminer/static/down.gif' alt='v' title='" . lang('Move down') . "'>&nbsp;" . script("qsl('input').onclick = partial(editingMoveRow, 0);", "")
: ""); : "");
echo ($orig == "" || support("drop_col") ? "<input type='image' class='icon' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "' onclick=\"return !editingRemoveRow(this, 'fields\$1[field]');\">" : ""); echo ($orig == "" || support("drop_col") ? "<input type='image' class='icon' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "'>" . script("qsl('input').onclick = partial(editingRemoveRow, 'fields\$1[field]');") : "");
echo "\n";
} }
} }
@@ -490,11 +492,11 @@ function ini_bytes($ini) {
function doc_link($paths) { function doc_link($paths) {
global $jush, $connection; global $jush, $connection;
$urls = array( $urls = array(
'sql' => "http://dev.mysql.com/doc/refman/" . substr($connection->server_info, 0, 3) . "/en/", 'sql' => "https://dev.mysql.com/doc/refman/" . substr($connection->server_info, 0, 3) . "/en/",
'sqlite' => "http://www.sqlite.org/", 'sqlite' => "https://www.sqlite.org/",
'pgsql' => "http://www.postgresql.org/docs/" . substr($connection->server_info, 0, 3) . "/static/", 'pgsql' => "https://www.postgresql.org/docs/" . substr($connection->server_info, 0, 3) . "/static/",
'mssql' => "http://msdn.microsoft.com/library/", 'mssql' => "https://msdn.microsoft.com/library/",
'oracle' => "http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/", 'oracle' => "https://download.oracle.com/docs/cd/B19306_01/server.102/b14200/",
); );
return ($paths[$jush] ? "<a href='$urls[$jush]$paths[$jush]' target='_blank' rel='noreferrer'><sup>?</sup></a>" : ""); return ($paths[$jush] ? "<a href='$urls[$jush]$paths[$jush]' target='_blank' rel='noreferrer'><sup>?</sup></a>" : "");
} }

View File

@@ -81,6 +81,30 @@ function charset($connection) {
return (version_compare($connection->server_info, "5.5.3") >= 0 ? "utf8mb4" : "utf8"); // SHOW CHARSET would require an extra query return (version_compare($connection->server_info, "5.5.3") >= 0 ? "utf8mb4" : "utf8"); // SHOW CHARSET would require an extra query
} }
/** Return <script> element
* @param string
* @param string
* @return string
*/
function script($source, $trailing = "\n") {
return "<script" . nonce() . ">$source</script>$trailing";
}
/** Return <script src> element
* @param string
* @return string
*/
function script_src($url) {
return "<script src='" . h($url) . "'" . nonce() . "></script>\n";
}
/** Get a nonce="" attribute with CSP nonce
* @return string
*/
function nonce() {
return ' nonce="' . get_nonce() . '"';
}
/** Escape for HTML /** Escape for HTML
* @param string * @param string
* @return string * @return string
@@ -119,8 +143,8 @@ function checkbox($name, $value, $checked, $label = "", $onclick = "", $class =
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'" $return = "<input type='checkbox' name='$name' value='" . h($value) . "'"
. ($checked ? " checked" : "") . ($checked ? " checked" : "")
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "") . ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
. ($onclick ? ' onclick="' . h($onclick) . '"' : '')
. ">" . ">"
. ($onclick ? script("qsl('input').onclick = function () { $onclick };", "") : "")
; ;
return ($label != "" || $class ? "<label" . ($class ? " class='$class'" : "") . ">$return" . h($label) . "</label>" : $return); return ($label != "" || $class ? "<label" . ($class ? " class='$class'" : "") . ">$return" . h($label) . "</label>" : $return);
} }
@@ -160,9 +184,10 @@ function optionlist($options, $selected = null, $use_keys = false) {
function html_select($name, $options, $value = "", $onchange = true, $labelled_by = "") { function html_select($name, $options, $value = "", $onchange = true, $labelled_by = "") {
if ($onchange) { if ($onchange) {
return "<select name='" . h($name) . "'" return "<select name='" . h($name) . "'"
. (is_string($onchange) ? ' onchange="' . h($onchange) . '"' : "")
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "") . ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
. ">" . optionlist($options, $value) . "</select>"; . ">" . optionlist($options, $value) . "</select>"
. (is_string($onchange) ? script("qsl('select').onchange = function () { $onchange };", "") : "")
;
} }
$return = ""; $return = "";
foreach ($options as $key => $val) { foreach ($options as $key => $val) {
@@ -172,35 +197,41 @@ function html_select($name, $options, $value = "", $onchange = true, $labelled_b
} }
/** Generate HTML <select> or <input> if $options are empty /** Generate HTML <select> or <input> if $options are empty
* @param string * @param string
* @param array * @param array
* @param string * @param string
* @param string * @param string
* @return string * @param string
*/ * @return string
function select_input($attrs, $options, $value = "", $placeholder = "") { */
return ($options function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") {
? "<select$attrs><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>" $tag = ($options ? "select" : "input");
: "<input$attrs size='10' value='" . h($value) . "' placeholder='$placeholder'>" return "<$tag$attrs" . ($options
); ? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
: " size='10' value='" . h($value) . "' placeholder='$placeholder'>"
) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input
} }
/** Get onclick confirmation /** Get onclick confirmation
* @param string
* @return string * @return string
*/ */
function confirm() { function confirm($selector = "qsl('input')") {
return " onclick=\"return confirm('" . lang('Are you sure?') . "');\""; return script("$selector.onclick = function () { return confirm('" . lang('Are you sure?') . "'); };", "");
} }
/** Print header for hidden fieldset (close by </div></fieldset>) /** Print header for hidden fieldset (close by </div></fieldset>)
* @param string * @param string
* @param string * @param string
* @param bool * @param bool
* @param string
* @return null * @return null
*/ */
function print_fieldset($id, $legend, $visible = false, $onclick = "") { function print_fieldset($id, $legend, $visible = false) {
echo "<fieldset><legend><a href='#fieldset-$id' onclick=\"" . h($onclick) . "return !toggle('fieldset-$id');\">$legend</a></legend><div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n"; echo "<fieldset><legend>";
echo "<a href='#fieldset-$id'>$legend</a>";
echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", "");
echo "</legend>";
echo "<div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
} }
/** Return class='active' if $bold is true /** Return class='active' if $bold is true
@@ -481,8 +512,8 @@ function cookie($name, $value, $lifetime = 2592000) { // 2592000 - 30 days
. ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "") . ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "")
. "; path=" . preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]) . "; path=" . preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"])
. ($HTTPS ? "; secure" : "") . ($HTTPS ? "; secure" : "")
. "; HttpOnly; SameSite=lax" . "; HttpOnly; SameSite=lax",
); false);
} }
/** Restart stopped session /** Restart stopped session
@@ -587,7 +618,7 @@ function query_redirect($query, $location, $message, $redirect = true, $execute
$sql = $adminer->messageQuery($query, $time); $sql = $adminer->messageQuery($query, $time);
} }
if ($failed) { if ($failed) {
$error = error() . $sql; $error = error() . $sql . script("messagesPrint();");
return false; return false;
} }
if ($redirect) { if ($redirect) {
@@ -867,18 +898,11 @@ function input($field, $value, $function) {
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
echo nbsp($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value); echo nbsp($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
} else { } else {
$first = 0;
foreach ($functions as $key => $val) {
if ($key === "" || !$val) {
break;
}
$first++;
}
$onchange = ($first ? " onchange=\"var f = this.form['function[" . h(js_escape(bracket_escape($field["field"]))) . "]']; if ($first > f.selectedIndex) f.selectedIndex = $first;\" onkeyup='keyupChange.call(this);'" : "");
$attrs .= $onchange;
$has_function = (in_array($function, $functions) || isset($functions[$function])); $has_function = (in_array($function, $functions) || isset($functions[$function]));
echo (count($functions) > 1 echo (count($functions) > 1
? "<select name='function[$name]' onchange='functionChange(this);'" . on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1) . ">" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>" ? "<select name='function[$name]'>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
. script("qsl('select').onchange = functionChange;", "")
: nbsp(reset($functions)) : nbsp(reset($functions))
) . '<td>'; ) . '<td>';
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table $input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
@@ -892,10 +916,10 @@ function input($field, $value, $function) {
foreach ($matches[1] as $i => $val) { foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val)); $val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_int($value) ? ($value >> $i) & 1 : in_array($val, explode(",", $value), true)); $checked = (is_int($value) ? ($value >> $i) & 1 : in_array($val, explode(",", $value), true));
echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . (1 << $i) . "'" . ($checked ? ' checked' : '') . "$onchange>" . h($adminer->editVal($val, $field)) . '</label>'; echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . (1 << $i) . "'" . ($checked ? ' checked' : '') . ">" . h($adminer->editVal($val, $field)) . '</label>';
} }
} elseif (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) { } elseif (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
echo "<input type='file' name='fields-$name'$onchange>"; echo "<input type='file' name='fields-$name'>";
} elseif (($text = preg_match('~text|lob~', $field["type"])) || preg_match("~\n~", $value)) { } elseif (($text = preg_match('~text|lob~', $field["type"])) || preg_match("~\n~", $value)) {
if ($text && $jush != "sqlite") { if ($text && $jush != "sqlite") {
$attrs .= " cols='50' rows='12'"; $attrs .= " cols='50' rows='12'";
@@ -920,6 +944,18 @@ function input($field, $value, $function) {
. "$attrs>" . "$attrs>"
; ;
} }
echo $adminer->editHint($_GET["edit"], $field, $value);
// skip 'original'
$first = 0;
foreach ($functions as $key => $val) {
if ($key === "" || !$val) {
break;
}
$first++;
}
if ($first) {
echo script("mixin(qsl('td'), {onchange: partial(skipOriginal, $first), oninput: function () { this.onchange(); }});");
}
} }
} }
@@ -1003,7 +1039,6 @@ function fields_from_edit() {
*/ */
function search_tables() { function search_tables() {
global $adminer, $connection; global $adminer, $connection;
$_GET["where"][0]["op"] = "LIKE %%";
$_GET["where"][0]["val"] = $_POST["query"]; $_GET["where"][0]["val"] = $_POST["query"];
$found = false; $found = false;
foreach (table_status('', true) as $table => $table_status) { foreach (table_status('', true) as $table => $table_status) {
@@ -1214,7 +1249,7 @@ function slow_query($query) {
if (support("kill") && is_object($connection2 = connect()) && ($db == "" || $connection2->select_db($db))) { if (support("kill") && is_object($connection2 = connect()) && ($db == "" || $connection2->select_db($db))) {
$kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL $kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
?> ?>
<script type="text/javascript"> <script<?php echo nonce(); ?>>
var timeout = setTimeout(function () { var timeout = setTimeout(function () {
ajax('<?php echo js_escape(ME); ?>script=kill', function () { ajax('<?php echo js_escape(ME); ?>script=kill', function () {
}, 'token=<?php echo $token; ?>&kill=<?php echo $kill; ?>'); }, 'token=<?php echo $token; ?>&kill=<?php echo $kill; ?>');
@@ -1228,7 +1263,7 @@ var timeout = setTimeout(function () {
flush(); flush();
$return = @get_key_vals($query, $connection2, $timeout); // @ - may be killed $return = @get_key_vals($query, $connection2, $timeout); // @ - may be killed
if ($connection2) { if ($connection2) {
echo "<script type='text/javascript'>clearTimeout(timeout);</script>\n"; echo script("clearTimeout(timeout);");
ob_flush(); ob_flush();
flush(); flush();
} }
@@ -1295,7 +1330,7 @@ function lzw_decompress($binary) {
* @return string * @return string
*/ */
function on_help($command, $side = 0) { function on_help($command, $side = 0) {
return " onmouseover='helpMouseover(this, event, " . h($command) . ", $side);' onmouseout='helpMouseout(this, event);'"; return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", "");
} }
/** Print edit data form /** Print edit data form
@@ -1323,7 +1358,7 @@ function edit_form($TABLE, $fields, $row, $update) {
if (!$fields) { if (!$fields) {
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n"; echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
} else { } else {
echo "<table cellspacing='0' onkeydown='return editingKeydown(event);'>\n"; echo "<table cellspacing='0'>" . script("qsl('table').onkeydown = editingKeydown;");
foreach ($fields as $name => $field) { foreach ($fields as $name => $field) {
echo "<tr><th>" . $adminer->fieldName($field); echo "<tr><th>" . $adminer->fieldName($field);
@@ -1363,7 +1398,8 @@ function edit_form($TABLE, $fields, $row, $update) {
} }
if (!support("table")) { if (!support("table")) {
echo "<tr>" echo "<tr>"
. "<th><input name='field_keys[]' onkeyup='keyupChange.call(this);' onchange='fieldChange(this);' value=''>" // needs empty value for keyupChange() . "<th><input name='field_keys[]'>"
. script("qsl('input').oninput = fieldChange;")
. "<td class='function'>" . html_select("field_funs[]", $adminer->editFunctions(array("null" => isset($_GET["select"])))) . "<td class='function'>" . html_select("field_funs[]", $adminer->editFunctions(array("null" => isset($_GET["select"]))))
. "<td><input name='field_vals[]'>" . "<td><input name='field_vals[]'>"
. "\n" . "\n"
@@ -1376,13 +1412,14 @@ function edit_form($TABLE, $fields, $row, $update) {
echo "<input type='submit' value='" . lang('Save') . "'>\n"; echo "<input type='submit' value='" . lang('Save') . "'>\n";
if (!isset($_GET["select"])) { if (!isset($_GET["select"])) {
echo "<input type='submit' name='insert' value='" . ($update echo "<input type='submit' name='insert' value='" . ($update
? lang('Save and continue edit') . "' onclick='return !ajaxForm(this.form, \"" . lang('Saving') . '...", this)' ? lang('Save and continue edit')
: lang('Save and insert next') : lang('Save and insert next')
) . "' title='Ctrl+Shift+Enter'>\n"; ) . "' title='Ctrl+Shift+Enter'>\n";
echo ($update ? script("qsl('input').onclick = function () { return !ajaxForm(this.form, '" . lang('Saving') . "...', this); };") : "");
} }
} }
echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'" . confirm() . ">\n" echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n"
: ($_POST || !$fields ? "" : "<script type='text/javascript'>focus(document.getElementById('form').getElementsByTagName('td')[1].firstChild);</script>\n") : ($_POST || !$fields ? "" : script("focus(qsa('td', qs('#form'))[1].firstChild);"))
); );
if (isset($_GET["select"])) { if (isset($_GET["select"])) {
hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"])); hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"]));

View File

@@ -2,13 +2,13 @@
// not used in a single language version // not used in a single language version
$langs = array( $langs = array(
'en' => 'English', // Jakub Vrána - http://www.vrana.cz 'en' => 'English', // Jakub Vrána - https://www.vrana.cz
'ar' => 'العربية', // Y.M Amine - Algeria - nbr7@live.fr 'ar' => 'العربية', // Y.M Amine - Algeria - nbr7@live.fr
'bg' => 'Български', // Deyan Delchev 'bg' => 'Български', // Deyan Delchev
'bn' => 'বাংলা', // Dipak Kumar - dipak.ndc@gmail.com 'bn' => 'বাংলা', // Dipak Kumar - dipak.ndc@gmail.com
'bs' => 'Bosanski', // Emir Kurtovic 'bs' => 'Bosanski', // Emir Kurtovic
'ca' => 'Català', // Joan Llosas 'ca' => 'Català', // Joan Llosas
'cs' => 'Čeština', // Jakub Vrána - http://www.vrana.cz 'cs' => 'Čeština', // Jakub Vrána - https://www.vrana.cz
'da' => 'Dansk', // Jarne W. Beutnagel - jarne@beutnagel.dk 'da' => 'Dansk', // Jarne W. Beutnagel - jarne@beutnagel.dk
'de' => 'Deutsch', // Klemens Häckel - http://clickdimension.wordpress.com 'de' => 'Deutsch', // Klemens Häckel - http://clickdimension.wordpress.com
'el' => 'Ελληνικά', // Dimitrios T. Tanis - jtanis@tanisfood.gr 'el' => 'Ελληνικά', // Dimitrios T. Tanis - jtanis@tanisfood.gr
@@ -18,6 +18,7 @@ $langs = array(
'fi' => 'Suomi', // Finnish - Kari Eveli - http://www.lexitec.fi/ 'fi' => 'Suomi', // Finnish - Kari Eveli - http://www.lexitec.fi/
'fr' => 'Français', // Francis Gagné, Aurélien Royer 'fr' => 'Français', // Francis Gagné, Aurélien Royer
'gl' => 'Galego', // Eduardo Penabad Ramos 'gl' => 'Galego', // Eduardo Penabad Ramos
'he' => 'עברית', // Binyamin Yawitz - https://stuff-group.com/
'hu' => 'Magyar', // Borsos Szilárd (Borsosfi) - http://www.borsosfi.hu, info@borsosfi.hu 'hu' => 'Magyar', // Borsos Szilárd (Borsosfi) - http://www.borsosfi.hu, info@borsosfi.hu
'id' => 'Bahasa Indonesia', // Ivan Lanin - http://ivan.lanin.org 'id' => 'Bahasa Indonesia', // Ivan Lanin - http://ivan.lanin.org
'it' => 'Italiano', // Alessandro Fiorotto, Paolo Asperti 'it' => 'Italiano', // Alessandro Fiorotto, Paolo Asperti
@@ -30,7 +31,7 @@ $langs = array(
'pt' => 'Português', // André Dias 'pt' => 'Português', // André Dias
'pt-br' => 'Português (Brazil)', // Gian Live - gian@live.com, Davi Alexandre davi@davialexandre.com.br, RobertoPC - http://www.robertopc.com.br 'pt-br' => 'Português (Brazil)', // Gian Live - gian@live.com, Davi Alexandre davi@davialexandre.com.br, RobertoPC - http://www.robertopc.com.br
'ro' => 'Limba Română', // .nick .messing - dot.nick.dot.messing@gmail.com 'ro' => 'Limba Română', // .nick .messing - dot.nick.dot.messing@gmail.com
'ru' => 'Русский язык', // Maksim Izmaylov 'ru' => 'Русский', // Maksim Izmaylov; Andre Polykanine - https://github.com/Oire/
'sk' => 'Slovenčina', // Ivan Suchy - http://www.ivansuchy.com, Juraj Krivda - http://www.jstudio.cz 'sk' => 'Slovenčina', // Ivan Suchy - http://www.ivansuchy.com, Juraj Krivda - http://www.jstudio.cz
'sl' => 'Slovenski', // Matej Ferlan - www.itdinamik.com, matej.ferlan@itdinamik.com 'sl' => 'Slovenski', // Matej Ferlan - www.itdinamik.com, matej.ferlan@itdinamik.com
'sr' => 'Српски', // Nikola Radovanović - cobisimo@gmail.com 'sr' => 'Српски', // Nikola Radovanović - cobisimo@gmail.com

View File

@@ -1,2 +1,2 @@
<?php <?php
$VERSION = "4.3.0"; $VERSION = "4.4.0";

View File

@@ -3,8 +3,8 @@
* @link https://www.adminer.org/ * @link https://www.adminer.org/
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @copyright 2007 Jakub Vrana * @copyright 2007 Jakub Vrana
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
include "./include/bootstrap.inc.php"; include "./include/bootstrap.inc.php";
@@ -65,8 +65,6 @@ if (isset($_GET["download"])) {
include "./user.inc.php"; include "./user.inc.php";
} elseif (isset($_GET["processlist"])) { } elseif (isset($_GET["processlist"])) {
include "./processlist.inc.php"; include "./processlist.inc.php";
} elseif (isset($_GET["replication"])) {
include "./replication.inc.php";
} elseif (isset($_GET["select"])) { } elseif (isset($_GET["select"])) {
include "./select.inc.php"; include "./select.inc.php";
} elseif (isset($_GET["variables"])) { } elseif (isset($_GET["variables"])) {

View File

@@ -113,16 +113,17 @@ if ($primary) {
$j = 1; $j = 1;
foreach ($row["indexes"] as $index) { foreach ($row["indexes"] as $index) {
if (!$_POST["drop_col"] || $j != key($_POST["drop_col"])) { if (!$_POST["drop_col"] || $j != key($_POST["drop_col"])) {
echo "<tr><td>" . html_select("indexes[$j][type]", array(-1 => "") + $index_types, $index["type"], ($j == count($row["indexes"]) ? "indexesAddRow(this);" : 1), "label-type"); echo "<tr><td>" . html_select("indexes[$j][type]", array(-1 => "") + $index_types, $index["type"], ($j == count($row["indexes"]) ? "indexesAddRow.call(this);" : 1), "label-type");
echo "<td>"; echo "<td>";
ksort($index["columns"]); ksort($index["columns"]);
$i = 1; $i = 1;
foreach ($index["columns"] as $key => $column) { foreach ($index["columns"] as $key => $column) {
echo "<span>" . select_input( echo "<span>" . select_input(
" name='indexes[$j][columns][$i]' onchange=\"" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . "(this, '" . h(js_escape($jush == "sql" ? "" : $_GET["indexes"] . "_")) . "');\" title='" . lang('Column') . "'", " name='indexes[$j][columns][$i]' title='" . lang('Column') . "'",
($fields ? array_combine($fields, $fields) : $fields), ($fields ? array_combine($fields, $fields) : $fields),
$column $column,
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape($jush == "sql" ? "" : $_GET["indexes"] . "_") . "')"
); );
echo ($jush == "sql" || $jush == "mssql" ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h($index["lengths"][$key]) . "' title='" . lang('Length') . "'>" : ""); echo ($jush == "sql" || $jush == "mssql" ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h($index["lengths"][$key]) . "' title='" . lang('Length') . "'>" : "");
echo ($jush != "sql" ? checkbox("indexes[$j][descs][$i]", 1, $index["descs"][$key], lang('descending')) : ""); echo ($jush != "sql" ? checkbox("indexes[$j][descs][$i]", 1, $index["descs"][$key], lang('descending')) : "");
@@ -131,7 +132,7 @@ foreach ($row["indexes"] as $index) {
} }
echo "<td><input name='indexes[$j][name]' value='" . h($index["name"]) . "' autocapitalize='off' aria-labelledby='label-name'>\n"; echo "<td><input name='indexes[$j][name]' value='" . h($index["name"]) . "' autocapitalize='off' aria-labelledby='label-name'>\n";
echo "<td><input type='image' class='icon' name='drop_col[$j]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "' onclick=\"return !editingRemoveRow(this, 'indexes\$1[type]');\">\n"; echo "<td><input type='image' class='icon' name='drop_col[$j]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "'>" . script("qsl('input').onclick = partial(editingRemoveRow, 'indexes\$1[type]');");
} }
$j++; $j++;
} }

View File

@@ -10,6 +10,7 @@ $translations = array(
'Logout' => 'Odhlásit', 'Logout' => 'Odhlásit',
'Logged as: %s' => 'Přihlášen jako: %s', 'Logged as: %s' => 'Přihlášen jako: %s',
'Logout successful.' => 'Odhlášení proběhlo v pořádku.', 'Logout successful.' => 'Odhlášení proběhlo v pořádku.',
'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Díky za použití Admineru, zvažte <a href="%s">příspěvek</a>.',
'Invalid credentials.' => 'Neplatné přihlašovací údaje.', 'Invalid credentials.' => 'Neplatné přihlašovací údaje.',
'<a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to use SQLite.' => 'Pro přihlášení k SQLite <a href="https://www.adminer.org/cs/extension/" target="_blank">implementujte</a> metodu %s.', '<a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to use SQLite.' => 'Pro přihlášení k SQLite <a href="https://www.adminer.org/cs/extension/" target="_blank">implementujte</a> metodu %s.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minutu.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minuty.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minut.'), 'Too many unsuccessful logins, try again in %d minute(s).' => array('Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minutu.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minuty.', 'Příliš mnoho pokusů o přihlášení, zkuste to znovu za %d minut.'),
@@ -19,6 +20,7 @@ $translations = array(
'If you did not send this request from Adminer then close this page.' => 'Pokud jste tento požadavek neposlali z Adminera, tak tuto stránku zavřete.', 'If you did not send this request from Adminer then close this page.' => 'Pokud jste tento požadavek neposlali z Adminera, tak tuto stránku zavřete.',
'No extension' => 'Žádné rozšíření', 'No extension' => 'Žádné rozšíření',
'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).',
'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
'Session support must be enabled.' => 'Session proměnné musí být povolené.', '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řihlašte se prosím znovu.',
'%s version: %s through PHP extension %s' => 'Verze %s: %s přes PHP rozšíření %s', '%s version: %s through PHP extension %s' => 'Verze %s: %s přes PHP rozšíření %s',
@@ -45,10 +47,6 @@ $translations = array(
'Variables' => 'Proměnné', 'Variables' => 'Proměnné',
'Status' => 'Stav', 'Status' => 'Stav',
'Replication' => 'Replikace',
'Master status' => 'Master status',
'Slave status' => 'Slave status',
'SQL command' => 'SQL příkaz', 'SQL command' => 'SQL příkaz',
'%d query(s) executed OK.' => array('%d příkaz proběhl v pořádku.', '%d příkazy proběhly v pořádku.', '%d příkazů proběhlo v pořádku.'), '%d query(s) executed OK.' => array('%d příkaz proběhl v pořádku.', '%d příkazy proběhly v pořádku.', '%d příkazů proběhlo v pořádku.'),
'Query executed OK, %d row(s) affected.' => array('Příkaz proběhl v pořádku, byl změněn %d záznam.', 'Příkaz proběhl v pořádku, byly změněny %d záznamy.', 'Příkaz proběhl v pořádku, bylo změněno %d záznamů.'), 'Query executed OK, %d row(s) affected.' => array('Příkaz proběhl v pořádku, byl změněn %d záznam.', 'Příkaz proběhl v pořádku, byly změněny %d záznamy.', 'Příkaz proběhl v pořádku, bylo změněno %d záznamů.'),
@@ -339,8 +337,4 @@ $translations = array(
'Type has been dropped.' => 'Typ byl odstraněn.', 'Type has been dropped.' => 'Typ byl odstraněn.',
'Type has been created.' => 'Typ byl vytvořen.', 'Type has been created.' => 'Typ byl vytvořen.',
'Alter type' => 'Pozměnit typ', 'Alter type' => 'Pozměnit typ',
'Replication' => null,
'Master status' => null,
'Slave status' => null,
); );

View File

@@ -44,9 +44,9 @@ $translations = array(
'Delete' => 'Eliminar', 'Delete' => 'Eliminar',
'Database' => 'Base de datos', 'Database' => 'Base de datos',
'Routines' => 'Procedimientos', 'Routines' => 'Procedimientos',
'Indexes have been altered.' => 'Indices actualizados.', 'Indexes have been altered.' => 'Índices actualizados.',
'Indexes' => 'Indices', 'Indexes' => 'Índices',
'Alter indexes' => 'Modificar indices', 'Alter indexes' => 'Modificar índices',
'Add next' => 'Agregar', 'Add next' => 'Agregar',
'Language' => 'Idioma', 'Language' => 'Idioma',
'Select' => 'Mostrar', 'Select' => 'Mostrar',
@@ -77,7 +77,7 @@ $translations = array(
'File uploads are disabled.' => 'Importación de archivos deshablilitada.', 'File uploads are disabled.' => 'Importación de archivos deshablilitada.',
'Routine has been called, %d row(s) affected.' => array('Consulta ejecutada, %d registro afectado.', 'Consulta ejecutada, %d registros afectados.'), 'Routine has been called, %d row(s) affected.' => array('Consulta ejecutada, %d registro afectado.', 'Consulta ejecutada, %d registros afectados.'),
'Call' => 'Llamar', 'Call' => 'Llamar',
'No extension' => 'No hay extension', 'No extension' => 'No hay extensión',
'None of the supported PHP extensions (%s) are available.' => 'Ninguna de las extensiones PHP soportadas (%s) está disponible.', 'None of the supported PHP extensions (%s) are available.' => 'Ninguna de las extensiones PHP soportadas (%s) está disponible.',
'Session support must be enabled.' => 'Deben estar habilitadas las sesiones.', 'Session support must be enabled.' => 'Deben estar habilitadas las sesiones.',
'Session expired, please login again.' => 'Sesión caducada, por favor escriba su clave de nuevo.', 'Session expired, please login again.' => 'Sesión caducada, por favor escriba su clave de nuevo.',
@@ -113,7 +113,7 @@ $translations = array(
'Routine has been dropped.' => 'Procedimiento eliminado.', 'Routine has been dropped.' => 'Procedimiento eliminado.',
'Routine has been altered.' => 'Procedimiento modificado.', 'Routine has been altered.' => 'Procedimiento modificado.',
'Routine has been created.' => 'Procedimiento creado.', 'Routine has been created.' => 'Procedimiento creado.',
'Alter function' => 'Modificar Función', 'Alter function' => 'Modificar función',
'Alter procedure' => 'Modificar procedimiento', 'Alter procedure' => 'Modificar procedimiento',
'Return type' => 'Tipo de valor de vuelta', 'Return type' => 'Tipo de valor de vuelta',
'Add trigger' => 'Agregar disparador', 'Add trigger' => 'Agregar disparador',
@@ -127,7 +127,7 @@ $translations = array(
'%s version: %s through PHP extension %s' => 'Versión %s: %s a través de la extensión de PHP %s', '%s version: %s through PHP extension %s' => 'Versión %s: %s a través de la extensión de PHP %s',
'%d row(s)' => array('%d registro', '%d registros'), '%d row(s)' => array('%d registro', '%d registros'),
'Remove' => 'Eliminar', 'Remove' => 'Eliminar',
'Are you sure?' => 'Está seguro?', 'Are you sure?' => '¿Está seguro?',
'Privileges' => 'Privilegios', 'Privileges' => 'Privilegios',
'Create user' => 'Crear Usuario', 'Create user' => 'Crear Usuario',
'User has been dropped.' => 'Usuario eliminado.', 'User has been dropped.' => 'Usuario eliminado.',
@@ -139,7 +139,7 @@ $translations = array(
'Grant' => 'Conceder', 'Grant' => 'Conceder',
'Revoke' => 'Impedir', 'Revoke' => 'Impedir',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST data demasiado grande. Reduzca el tamaño o aumente la directiva de configuración %s.', 'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST data demasiado grande. Reduzca el tamaño o aumente la directiva de configuración %s.',
'Logged as: %s' => 'Logeado como: %s', 'Logged as: %s' => 'Logueado como: %s',
'Move up' => 'Mover arriba', 'Move up' => 'Mover arriba',
'Move down' => 'Mover abajo', 'Move down' => 'Mover abajo',
'Functions' => 'Funciones', 'Functions' => 'Funciones',
@@ -191,7 +191,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Excedida la cantidad máxima de campos permitidos. Por favor aumente %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Excedida la cantidad máxima de campos permitidos. Por favor aumente %s.',
'Partition by' => 'Particionar por', 'Partition by' => 'Particionar por',
'Partitions' => 'Particiones', 'Partitions' => 'Particiones',
'Partition name' => 'Nombre de Partición', 'Partition name' => 'Nombre de partición',
'Values' => 'Valores', 'Values' => 'Valores',
'%d row(s) have been imported.' => array('%d registro importado.', '%d registros importados.'), '%d row(s) have been imported.' => array('%d registro importado.', '%d registros importados.'),
'anywhere' => 'donde sea', 'anywhere' => 'donde sea',
@@ -248,16 +248,16 @@ $translations = array(
'System' => 'Motor de base de datos', 'System' => 'Motor de base de datos',
'Select data' => 'Visualizar contenido', 'Select data' => 'Visualizar contenido',
'Show structure' => 'Mostrar estructura', 'Show structure' => 'Mostrar estructura',
'empty' => 'ningúno', 'empty' => 'ninguno',
'Network' => 'Red', 'Network' => 'Red',
'Geometry' => 'Geometría', 'Geometry' => 'Geometría',
'File exists.' => 'Ese archivo ya existe.', 'File exists.' => 'Ese archivo ya existe.',
'Attachments' => 'Adjuntos', 'Attachments' => 'Adjuntos',
'%d query(s) executed OK.' => array('%d sentencia sql ejecutada correctamente.', '%d sentencias sql ejecutadas correctamente.'), '%d query(s) executed OK.' => array('%d sentencia SQL ejecutada correctamente.', '%d sentencias SQL ejecutadas correctamente.'),
'Show only errors' => 'Mostrar solamente errores', 'Show only errors' => 'Mostrar solamente errores',
'Refresh' => 'Refrescar', 'Refresh' => 'Refrescar',
'Invalid schema.' => 'Esquema inválido.', 'Invalid schema.' => 'Esquema inválido.',
'Please use one of the extensions %s.' => 'Por favor use una de las extensiones %s.', 'Please use one of the extensions %s.' => 'Por favor, use una de las extensiones %s.',
'now' => 'ahora', 'now' => 'ahora',
'ltr' => 'ltr', 'ltr' => 'ltr',
'Tables have been copied.' => 'Tablas copiadas.', 'Tables have been copied.' => 'Tablas copiadas.',

294
adminer/lang/he.inc.php Normal file
View File

@@ -0,0 +1,294 @@
<?php
$translations = array(
'Login' => 'התחברות',
'Logout successful.' => 'ההתחברות הצליחה',
'Invalid credentials.' => 'פרטי התחברות שגויים',
'Server' => 'שרת',
'Username' => 'שם משתמש',
'Password' => 'סיסמה',
'Select database' => 'בחר מסד נתונים',
'Invalid database.' => 'מסד נתונים שגוי',
'Table has been dropped.' => 'הטבלה הושלכה',
'Table has been altered.' => 'הטבלה שונתה',
'Table has been created.' => 'הטבלה נוצרה',
'Alter table' => 'שנה טבלה',
'Create table' => 'צור טבלה',
'Table name' => 'שם הטבלה',
'engine' => 'מנוע',
'collation' => 'קולקציה',
'Column name' => 'שם עמודה',
'Type' => 'סוג',
'Length' => 'אורך',
'Auto Increment' => 'הגדלה אוטומטית',
'Options' => 'אפשרויות',
'Save' => 'שמור',
'Drop' => 'השלך',
'Database has been created.' => 'מסד הנתונים נוצר',
'Database has been renamed.' => 'שם מסד הנתונים שונה',
'Database has been altered.' => 'מסד הנתונים שונה',
'Alter database' => 'שנה מסד נתונים',
'Create database' => 'צור מסד נתונים',
'SQL command' => 'שאילתת SQL',
'Logout' => 'התנתק',
'database' => 'מסד נתונים',
'Use' => 'השתמש',
'No tables.' => 'אין טבלאות',
'select' => 'בחר',
'Item has been deleted.' => 'הפריט נמחק',
'Item has been updated.' => 'הפריט עודכן',
'Edit' => 'ערוך',
'Insert' => 'הכנס',
'Save and insert next' => 'שמור והמשך להכניס',
'Delete' => 'מחק',
'Database' => 'מסד נתונים',
'Routines' => 'רוטינות',
'Indexes have been altered.' => 'האינדקסים שונו',
'Indexes' => 'אינדקסים',
'Alter indexes' => 'שנה אינדקסים',
'Add next' => 'הוסף הבא',
'Language' => 'שפה',
'Select' => 'בחר',
'New item' => 'פריט חדש',
'Search' => 'חפש',
'Sort' => 'מיין',
'descending' => 'סדר הפוך',
'Limit' => 'הגבל',
'No rows.' => 'אין שורות',
'Action' => 'פעולות',
'edit' => 'ערוך',
'Page' => 'עמוד',
'Query executed OK, %d row(s) affected.' => 'השאילתה בוצעה כהלכה, %d שורות הושפעו',
'Error in query' => 'שגיאה בשאילתה',
'Execute' => 'הרץ',
'Table' => 'טבלה',
'Foreign keys' => 'מפתחות זרים',
'Triggers' => 'מפעילים',
'View' => 'הצג',
'Unable to select the table' => 'בחירת הטבלה נכשלה',
'Invalid CSRF token. Send the form again.' => 'כשל באבטחת נתונים, שלח טופס שוב',
'Comment' => 'הערה',
'Default values' => 'ערכי ברירת מחדל',
'%d byte(s)' => '%d בתים',
'No commands to execute.' => 'לא נמצאו פקודות להרצה',
'Unable to upload a file.' => 'העלאת הקובץ נכשלה',
'File upload' => 'העלה קובץ',
'File uploads are disabled.' => 'העלאת קבצים מבוטלת',
'Routine has been called, %d row(s) affected.' => 'הרוטינה נקראה, %d שורות הושפעו',
'Call' => 'קרא',
'No extension' => 'אין תוסף',
'None of the supported PHP extensions (%s) are available.' => 'שום תוסף PHP (%s) זמין',
'Session support must be enabled.' => 'חובה להפעיל תמיכה בסשן',
'Session expired, please login again.' => 'תם זמן ההפעלה, אנא התחבר שוב',
'Text length' => 'אורך הטקסט',
'Foreign key has been dropped.' => 'המפתח הזר הושלך',
'Foreign key has been altered.' => 'המפתח הזר שונה',
'Foreign key has been created.' => 'המפתח הזר נוצר',
'Foreign key' => 'מפתח זר',
'Target table' => 'טבלת יעד',
'Change' => 'שנה',
'Source' => 'מקור',
'Target' => 'יעד',
'Add column' => 'הוסף עמודה',
'Alter' => 'שנה',
'Add foreign key' => 'הוסף מפתח זר',
'ON DELETE' => 'בעת מחיקה',
'ON UPDATE' => 'בעת עידכון',
'Index Type' => 'סוג אינדקס',
'Column (length)' => 'עמודה (אורך)',
'View has been dropped.' => 'התצוגה הושלכה',
'View has been altered.' => 'התצוגה שונתה',
'View has been created.' => 'התצוגה נוצרה',
'Alter view' => 'שנה תצוגה',
'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.' => 'הרוטינה הושלכה',
'Routine has been altered.' => 'הרוטינה שונתה',
'Routine has been created.' => 'הרוטינה נוצרה',
'Alter function' => 'שנה פונקציה',
'Alter procedure' => 'שנה פרוצדורה',
'Return type' => 'סוג ערך מוחזר',
'Add trigger' => 'הוסף טריגר',
'Trigger has been dropped.' => 'הטריגר הושלך',
'Trigger has been altered.' => 'הטריגר שונה',
'Trigger has been created.' => 'הטריגר נוצר',
'Alter trigger' => 'שנה טריגר',
'Create trigger' => 'צור טריגר',
'Time' => 'זמן',
'Event' => 'אירוע',
'%d row(s)' => '%d שורות',
'Remove' => 'הסר',
'Are you sure?' => 'האם אתה בטוח?',
'Privileges' => 'פריווילגיות',
'Create user' => 'צור משתמש',
'User has been dropped.' => 'המשתמש הושלך',
'User has been altered.' => 'המשתמש שונה',
'User has been created.' => 'המשתמש נוצר',
'Hashed' => 'הצפנה',
'Column' => 'עמודה',
'Routine' => 'רוטינה',
'Grant' => 'הענק',
'Revoke' => 'שלול',
'%s version: %s through PHP extension %s' => '%s גרסה: %s דרך תוסף PHP %s',
'Logged as: %s' => 'מחובר כ: %s',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'מידע גדול מידי נשלח ב-POST. הקטן את את המידע הוא הגדלת את הגדרות ה-%s',
'Move up' => 'הזז למעלה',
'Move down' => 'הזז למטה',
'Export' => 'יצא',
'Tables' => 'טבלאות',
'Data' => 'נתונים',
'Output' => 'פלט',
'open' => 'פתח',
'save' => 'שמור',
'Format' => 'פורמט',
'Functions' => 'פונקציות',
'Aggregation' => 'צבירה',
'Event has been dropped.' => 'האירוע הושלך',
'Event has been altered.' => 'האירוע שונה',
'Event has been created.' => 'האירוע נוצר',
'Alter event' => 'שנה אירוע',
'Create event' => 'צור אירוע',
'Start' => 'התחלה',
'End' => 'סיום',
'Every' => 'כל',
'Status' => 'סטטוס',
'On completion preserve' => 'בעת סיום שמור',
'Events' => 'אירועים',
'Schedule' => 'תזמן',
'At given time' => 'לפי זמן נתון',
'Save and continue edit' => 'שמור והמשך לערוך',
'original' => 'מקורי',
'Tables have been truncated.' => 'הטבלה קוצרה',
'Tables have been moved.' => 'הטבלה הועברה',
'Tables have been dropped.' => 'הטבלה הושלכה',
'Tables and views' => 'טבלאות ותצוגות',
'Engine' => 'מנוע',
'Collation' => 'קולקציה',
'Data Length' => 'אורך נתונים',
'Index Length' => 'אורך אינדקס',
'Data Free' => 'נתונים משוחררים',
'Rows' => 'שורות',
',' => ',',
'0123456789' => '0123456789',
'Analyze' => 'נתח',
'Optimize' => 'יעל',
'Check' => 'בדוק',
'Repair' => 'תקן',
'Truncate' => 'קצר',
'Move to other database' => 'העבר למסד נתונים אחר',
'Move' => 'העבר',
'%d item(s) have been affected.' => '%d פריטים הושפעו',
'whole result' => 'כל התוצאות',
'Clone' => 'שכפל',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'הגעת למספר השדות המרבי. בבקשה הגדל את %s',
'Partition by' => 'מחיצות ע"י',
'Partitions' => 'מחיצות',
'Partition name' => 'שם מחיצה',
'Values' => 'ערכים',
'%d row(s) have been imported.' => '%d שורות יובאו',
'anywhere' => 'בכל מקום',
'Import' => 'יבא',
'Stop on error' => 'עצור בעת שגיאה',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$1-$3-$5',
'[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.' => 'על עמודות המקור והיעד להיות מאותו טיפוס נתונים, חובה שיהיה אינדקס בעמודת היעד ושהמידע המתאים יהיה קיים',
'Relations' => 'הקשרים',
'Run file' => 'הרץ קובץ',
'Clear' => 'נקה',
'Maximum allowed file size is %sB.' => 'גודל מקסימלאי להעלאה: %sB',
'Numbers' => 'מספרים',
'Date and time' => 'תאריך ושעה',
'Strings' => 'מחרוזות',
'Binary' => 'בינארי',
'Lists' => 'רשימות',
'Editor' => 'עורך',
'E-mail' => 'דוא"ל',
'From' => 'מ:',
'Subject' => 'נושא',
'Send' => 'שלח',
'%d e-mail(s) have been sent.' => '%d הודעות דוא"ל נשלחו',
'Webserver file %s' => 'קובץ השרת %s',
'File does not exist.' => 'הקובץ אינו קיים',
'%d in total' => '%d בסך הכל',
'Permanent login' => 'התחבר לצמיתות',
'Databases have been dropped.' => 'מסד הנתונים הושלך',
'Database has been dropped.' => 'מסד הנתונים הושלך',
'Search data in tables' => 'חפש מידע בטבלאות',
'Schema' => 'סכמה',
'Alter schema' => 'שנה סכמה',
'Create schema' => 'צור סכמה',
'Schema has been dropped.' => 'הסכמה הושלכה',
'Schema has been created.' => 'הסכמה נוצרה',
'Schema has been altered.' => 'הסכמה שונתה',
'Sequences' => 'סדרות',
'Create sequence' => 'צור סדרה',
'Alter sequence' => 'שנה סדרה',
'Sequence has been dropped.' => 'הסדרה הושלכה',
'Sequence has been created.' => 'הסדרה נוצרה',
'Sequence has been altered.' => 'הסדרה שונתה',
'User types' => 'סוגי משתמשים',
'Create type' => 'צור סוג',
'Alter type' => 'שנה סוג',
'Type has been dropped.' => 'הסוג הושלך',
'Type has been created.' => 'הסוג נוצר',
'Use edit link to modify this value.' => 'השתמש בקישור העריכה בשביל לשנות את הערך',
'last' => 'אחרון',
'From server' => 'משרת',
'System' => 'מערכת',
'Select data' => 'בחר נתונים',
'Show structure' => 'הראה מבנה',
'empty' => 'ריק',
'Network' => 'רשת',
'Geometry' => 'גיאומטריה',
'File exists.' => 'קובץ קיים',
'Attachments' => 'קבצים מצורפים',
'Item%s has been inserted.' => 'הפריט %s הוזן בהצלחה',
'now' => 'כעת',
'%d query(s) executed OK.' => '%d שאילתות בוצעו בהצלחה',
'Show only errors' => 'הראה שגיאות בלבד',
'Refresh' => 'רענן',
'Invalid schema.' => 'סכמה שגויה',
'Please use one of the extensions %s.' => 'בבקשה השתמש באחד מהתוספים %s',
'ltr' => 'rtl',
'Tables have been copied.' => 'הטבלה הועתקה',
'Copy' => 'העתק',
'Permanent link' => 'קישור סופי',
'Edit all' => 'ערוך הכל',
'HH:MM:SS' => 'HH:MM:SS',
'Tables have been optimized.' => 'הטבלאות עברו אופטימיזציה',
'Materialized view' => 'תצוגת מימוש ',
'Vacuum' => 'וואקום',
'Selected' => 'נבחרים',
'Ctrl+click on a value to modify it.' => 'לחץ ctrl + לחיצת עכבר לערוך ערך זה',
'File must be in UTF-8 encoding.' => 'על הקובץ להיות בקידוד utf-8',
'Modify' => 'ערוך',
'Loading' => 'טוען',
'Load more data' => 'טען נתונים נוספים',
'ATTACH queries are not supported.' => 'שאילתת ATTACH אינה נתמכת',
'%d / ' => '%d / ',
'Limit rows' => 'הגבל שורות',
'<a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/en/extension/" target="_blank">התקן</a> את תוסף SQLite בשביל להתחבר',
'Default value' => 'ערך ברירת מחדל',
'Full table scan' => 'סריקה טבלה מלאה',
'Too many unsuccessful logins, try again in %d minute(s).' => 'יותר מידי נסיונות כניסה נכשלו, אנא נסה עוד %d דקות',
'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'תודה שהשתמש ב-adminer אנא שקול <a href="%s">לתרום</a>.',
'Master password expired. <a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to make it permanent.' => 'סיסמת המאסטר פגה <a href="https://www.adminer.org/en/extension/" target="_blank">התקן תוסף</a> על מנת להפוך את זה לתמידי',
'If you did not send this request from Adminer then close this page.' => 'אם לא אתה שלחת בקשה ל-Adminer הינך יכול לסגור חלון זה',
'You can upload a big SQL file via FTP and import it from server.' => 'ניתן לעלות קבצים ב-FTP ואז למשוך אותם מהשרת',
'Size' => 'גודל',
'Compute' => 'חישוב',
'You are offline.' => 'הינך לא מקוון',
'You have no privileges to update this table.' => 'אין לך ההרשאות המתאימות לעדכן טבלה זו',
'Saving' => 'שומר',
'yes' => 'כן',
'no' => 'לא',
);

View File

@@ -7,14 +7,14 @@ $translations = array(
'Username' => 'Имя пользователя', 'Username' => 'Имя пользователя',
'Password' => 'Пароль', 'Password' => 'Пароль',
'Select database' => 'Выбрать базу данных', 'Select database' => 'Выбрать базу данных',
'Invalid database.' => 'Плохая база данных.', 'Invalid database.' => 'Неверная база данных.',
'Table has been dropped.' => 'Таблица была удалена.', 'Table has been dropped.' => 'Таблица была удалена.',
'Table has been altered.' => 'Таблица была изменена.', 'Table has been altered.' => 'Таблица была изменена.',
'Table has been created.' => 'Таблица была создана.', 'Table has been created.' => 'Таблица была создана.',
'Alter table' => 'Изменить таблицу', 'Alter table' => 'Изменить таблицу',
'Create table' => 'Создать таблицу', 'Create table' => 'Создать таблицу',
'Table name' => 'Название таблицы', 'Table name' => 'Название таблицы',
'engine' => 'тип', 'engine' => 'Тип таблицы',
'collation' => 'режим сопоставления', 'collation' => 'режим сопоставления',
'Column name' => 'Название поля', 'Column name' => 'Название поля',
'Type' => 'Тип', 'Type' => 'Тип',
@@ -29,7 +29,7 @@ $translations = array(
'Database has been altered.' => 'База данных была изменена.', 'Database has been altered.' => 'База данных была изменена.',
'Alter database' => 'Изменить базу данных', 'Alter database' => 'Изменить базу данных',
'Create database' => 'Создать базу данных', 'Create database' => 'Создать базу данных',
'SQL command' => 'SQL запрос', 'SQL command' => 'SQL-запрос',
'Logout' => 'Выйти', 'Logout' => 'Выйти',
'database' => 'база данных', 'database' => 'база данных',
'Use' => 'Выбрать', 'Use' => 'Выбрать',
@@ -67,7 +67,7 @@ $translations = array(
'Triggers' => 'Триггеры', 'Triggers' => 'Триггеры',
'View' => 'Представление', 'View' => 'Представление',
'Unable to select the table' => 'Не удалось получить данные из таблицы', 'Unable to select the table' => 'Не удалось получить данные из таблицы',
'Invalid CSRF token. Send the form again.' => 'Недействительный CSRF токен. Отправите форму ещё раз.', 'Invalid CSRF token. Send the form again.' => 'Недействительный CSRF-токен. Отправите форму ещё раз.',
'Comment' => 'Комментарий', 'Comment' => 'Комментарий',
'Default values' => 'Значения по умолчанию', 'Default values' => 'Значения по умолчанию',
'%d byte(s)' => array('%d байт', '%d байта', '%d байтов'), '%d byte(s)' => array('%d байт', '%d байта', '%d байтов'),
@@ -90,13 +90,13 @@ $translations = array(
'Change' => 'Изменить', 'Change' => 'Изменить',
'Source' => 'Источник', 'Source' => 'Источник',
'Target' => 'Цель', 'Target' => 'Цель',
'Add column' => 'Добавить колонку', 'Add column' => 'Добавить поле',
'Alter' => 'Изменить', 'Alter' => 'Изменить',
'Add foreign key' => 'Добавить внешний ключ', 'Add foreign key' => 'Добавить внешний ключ',
'ON DELETE' => 'При стирании', 'ON DELETE' => 'При стирании',
'ON UPDATE' => 'При обновлении', 'ON UPDATE' => 'При обновлении',
'Index Type' => 'Тип индекса', 'Index Type' => 'Тип индекса',
'Column (length)' => 'Колонка (длина)', 'Column (length)' => 'Поле (длина)',
'View has been dropped.' => 'Представление было удалено.', 'View has been dropped.' => 'Представление было удалено.',
'View has been altered.' => 'Представление было изменено.', 'View has been altered.' => 'Представление было изменено.',
'View has been created.' => 'Представление было создано.', 'View has been created.' => 'Представление было создано.',
@@ -134,11 +134,11 @@ $translations = array(
'User has been altered.' => 'Пользователь был изменён.', 'User has been altered.' => 'Пользователь был изменён.',
'User has been created.' => 'Пользователь был создан.', 'User has been created.' => 'Пользователь был создан.',
'Hashed' => 'Хешировано', 'Hashed' => 'Хешировано',
'Column' => 'Колонка', 'Column' => 'поле',
'Routine' => 'Процедура', 'Routine' => 'Процедура',
'Grant' => 'Позволить', 'Grant' => 'Позволить',
'Revoke' => 'Запретить', 'Revoke' => 'Запретить',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'Слишком большой объем POST-данных. Пошлите меньший объем данных или увеличьте параметр конфигурационной директивы %s.', 'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'Слишком большой объем POST-данных. Пошлите меньший объём данных или увеличьте параметр конфигурационной директивы %s.',
'Logged as: %s' => 'Вы вошли как: %s', 'Logged as: %s' => 'Вы вошли как: %s',
'Move up' => 'Переместить вверх', 'Move up' => 'Переместить вверх',
'Move down' => 'Переместить вниз', 'Move down' => 'Переместить вниз',
@@ -181,7 +181,7 @@ $translations = array(
'Tables have been moved.' => 'Таблицы были перемещены.', 'Tables have been moved.' => 'Таблицы были перемещены.',
'Move to other database' => 'Переместить в другую базу данных', 'Move to other database' => 'Переместить в другую базу данных',
'Move' => 'Переместить', 'Move' => 'Переместить',
'Engine' => 'Тип', 'Engine' => 'Тип таблиц',
'Save and continue edit' => 'Сохранить и продолжить редактирование', 'Save and continue edit' => 'Сохранить и продолжить редактирование',
'original' => 'исходный', 'original' => 'исходный',
'%d item(s) have been affected.' => array('Была изменена %d запись.', 'Были изменены %d записи.', 'Было изменено %d записей.'), '%d item(s) have been affected.' => array('Была изменена %d запись.', 'Были изменены %d записи.', 'Было изменено %d записей.'),
@@ -202,20 +202,20 @@ $translations = array(
'[yyyy]-mm-dd' => 'дд.мм.[гггг]', '[yyyy]-mm-dd' => 'дд.мм.[гггг]',
'History' => 'История', 'History' => 'История',
'Variables' => 'Переменные', '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' => 'Реляции', 'Relations' => 'Отношения',
'Run file' => 'Запустить файл', 'Run file' => 'Запустить файл',
'Clear' => 'Очистить', 'Clear' => 'Очистить',
'Maximum allowed file size is %sB.' => 'Максимальный разрешённый размер файла - %sB.', 'Maximum allowed file size is %sB.' => 'Максимальный разрешённый размер файла %sB.',
'Numbers' => 'Число', 'Numbers' => 'Числа',
'Date and time' => 'Дата и время', 'Date and time' => 'Дата и время',
'Strings' => 'Строки', 'Strings' => 'Строки',
'Binary' => 'Двоичный тип', 'Binary' => 'Двоичный тип',
'Lists' => 'Списки', 'Lists' => 'Списки',
'Editor' => 'Редактор', 'Editor' => 'Редактор',
'E-mail' => 'Электропочта', 'E-mail' => 'Эл. почта',
'From' => 'От', 'From' => 'От',
'Subject' => 'Кому', 'Subject' => 'Тема',
'Send' => 'Послать', 'Send' => 'Послать',
'%d e-mail(s) have been sent.' => array('Было отправлено %d письмо.', 'Было отправлено %d письма.', 'Было отправлено %d писем.'), '%d e-mail(s) have been sent.' => array('Было отправлено %d письмо.', 'Было отправлено %d письма.', 'Было отправлено %d писем.'),
'Webserver file %s' => 'Файл %s на вебсервере', 'Webserver file %s' => 'Файл %s на вебсервере',
@@ -241,7 +241,7 @@ $translations = array(
'Alter type' => 'Изменить тип', 'Alter type' => 'Изменить тип',
'Type has been dropped.' => 'Тип удален.', 'Type has been dropped.' => 'Тип удален.',
'Type has been created.' => 'Создан новый тип.', 'Type has been created.' => 'Создан новый тип.',
'Ctrl+click on a value to modify it.' => 'Ctrl+кликни по значению, чтобы его изменить.', 'Ctrl+click on a value to modify it.' => 'Выполните Ctrl+Щелчок мышью по значению, чтобы его изменить.',
'Use edit link to modify this value.' => 'Изменить это значение можно с помощью ссылки «изменить».', 'Use edit link to modify this value.' => 'Изменить это значение можно с помощью ссылки «изменить».',
'last' => 'последняя', 'last' => 'последняя',
'From server' => 'С сервера', 'From server' => 'С сервера',
@@ -265,4 +265,29 @@ $translations = array(
'Permanent link' => 'Постоянная ссылка', 'Permanent link' => 'Постоянная ссылка',
'Edit all' => 'Редактировать всё', 'Edit all' => 'Редактировать всё',
'HH:MM:SS' => 'ЧЧ:ММ:СС', 'HH:MM:SS' => 'ЧЧ:ММ:СС',
'Tables have been optimized.' => 'Таблицы оптимизированы.',
'Materialized view' => 'Материализованное представление',
'Vacuum' => 'Вакуум',
'Selected' => 'Выбранные',
'File must be in UTF-8 encoding.' => 'Файл должен быть в кодировке UTF-8.',
'Modify' => 'Изменить',
'Loading' => 'Загрузка',
'Load more data' => 'Загрузить ещё данные',
'ATTACH queries are not supported.' => 'ATTACH-запросы не поддерживаются.',
'%d / ' => '%d / ',
'Limit rows' => 'Лимит строк',
'<a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to use SQLite.' => '<a href="https://www.adminer.org/en/extension/" target="_blank">Реализуйте</a> метод %s, чтобы использовать SQLite.',
'Default value' => 'Значение по умолчанию',
'Full table scan' => 'Анализ полной таблицы',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Слишком много неудачных попыток входа. Попробуйте снова через %d минуту.', 'Слишком много неудачных попыток входа. Попробуйте снова через %d минуты.', 'Слишком много неудачных попыток входа. Попробуйте снова через %d минут.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to make it permanent.' => 'Мастер-пароль истёк. <a href="https://www.adminer.org/en/extension/" target="_blank">Реализуйте</a> метод %s, чтобы сделать его постоянным.',
'If you did not send this request from Adminer then close this page.' => 'Если вы не посылали этот запрос из Adminer, закройте эту страницу.',
'You can upload a big SQL file via FTP and import it from server.' => 'Вы можете закачать большой SQL-файл по FTP и затем импортировать его с сервера.',
'Size' => 'Размер',
'Compute' => 'Вычислить',
'You are offline.' => 'Вы не выполнили вход.',
'You have no privileges to update this table.' => 'У вас нет прав на обновление этой таблицы.',
'Saving' => 'Сохранение',
'yes' => 'Да',
'no' => 'Нет',
); );

View File

@@ -10,6 +10,7 @@ $translations = array(
'Logout' => 'Xx', 'Logout' => 'Xx',
'Logged as: %s' => 'Xx', 'Logged as: %s' => 'Xx',
'Logout successful.' => 'Xx.', 'Logout successful.' => 'Xx.',
'Thanks for using Adminer, consider <a href="%s">donating</a>.' => 'Xx.',
'Invalid credentials.' => 'Xx.', 'Invalid credentials.' => 'Xx.',
'<a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to use SQLite.' => 'Xx.', '<a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to use SQLite.' => 'Xx.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Xx.', 'Xx.'), 'Too many unsuccessful logins, try again in %d minute(s).' => array('Xx.', 'Xx.'),
@@ -45,10 +46,6 @@ $translations = array(
'Variables' => 'Xx', 'Variables' => 'Xx',
'Status' => 'Xx', 'Status' => 'Xx',
'Replication' => 'Xx',
'Master status' => 'Xx',
'Slave status' => 'Xx',
'SQL command' => 'Xx', 'SQL command' => 'Xx',
'%d query(s) executed OK.' => array('Xx.', 'Xx.'), '%d query(s) executed OK.' => array('Xx.', 'Xx.'),
'Query executed OK, %d row(s) affected.' => array('Xx.', 'Xx.'), 'Query executed OK, %d row(s) affected.' => array('Xx.', 'Xx.'),

View File

@@ -17,7 +17,7 @@ function adminer_object() {
new AdminerDumpXml, new AdminerDumpXml,
new AdminerDumpAlter, new AdminerDumpAlter,
//~ new AdminerSqlLog("past-" . rtrim(`git describe --tags --abbrev=0`) . ".sql"), //~ new AdminerSqlLog("past-" . rtrim(`git describe --tags --abbrev=0`) . ".sql"),
//~ new AdminerEditCalendar("<script type='text/javascript' src='../externals/jquery-ui/jquery-1.4.4.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.core.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.widget.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.datepicker.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.mouse.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.slider.js'></script>\n<script type='text/javascript' src='../externals/jquery-timepicker/jquery-ui-timepicker-addon.js'></script>\n<link rel='stylesheet' href='../externals/jquery-ui/themes/base/jquery.ui.all.css'>\n<style type='text/css'>\n.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }\n.ui-timepicker-div dl { text-align: left; }\n.ui-timepicker-div dl dt { height: 25px; }\n.ui-timepicker-div dl dd { margin: -25px 0 10px 65px; }\n.ui-timepicker-div td { font-size: 90%; }\n</style>\n", "../externals/jquery-ui/ui/i18n/jquery.ui.datepicker-%s.js"), //~ new AdminerEditCalendar(script_src("../externals/jquery-ui/jquery-1.4.4.js") . script_src("../externals/jquery-ui/ui/jquery.ui.core.js") . script_src("../externals/jquery-ui/ui/jquery.ui.widget.js") . script_src("../externals/jquery-ui/ui/jquery.ui.datepicker.js") . script_src("../externals/jquery-ui/ui/jquery.ui.mouse.js") . script_src("../externals/jquery-ui/ui/jquery.ui.slider.js") . script_src("../externals/jquery-timepicker/jquery-ui-timepicker-addon.js") . "<link rel='stylesheet' href='../externals/jquery-ui/themes/base/jquery.ui.all.css'>\n<style>\n.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }\n.ui-timepicker-div dl { text-align: left; }\n.ui-timepicker-div dl dt { height: 25px; }\n.ui-timepicker-div dl dd { margin: -25px 0 10px 65px; }\n.ui-timepicker-div td { font-size: 90%; }\n</style>\n", "../externals/jquery-ui/ui/i18n/jquery.ui.datepicker-%s.js"),
//~ new AdminerTinymce("../externals/tinymce/jscripts/tiny_mce/tiny_mce_dev.js"), //~ new AdminerTinymce("../externals/tinymce/jscripts/tiny_mce/tiny_mce_dev.js"),
//~ new AdminerWymeditor(array("../externals/wymeditor/src/jquery/jquery.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.explorer.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.mozilla.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.opera.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.safari.js")), //~ new AdminerWymeditor(array("../externals/wymeditor/src/jquery/jquery.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.explorer.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.mozilla.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.opera.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.safari.js")),
new AdminerFileUpload(""), new AdminerFileUpload(""),

View File

@@ -49,6 +49,6 @@ if (isset($_GET["function"])) {
<p><?php textarea("definition", $row["definition"]); ?> <p><?php textarea("definition", $row["definition"]); ?>
<p> <p>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($PROCEDURE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if ($PROCEDURE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
</form> </form>

View File

@@ -13,8 +13,9 @@ page_header(lang('Process list'), $error);
?> ?>
<form action="" method="post"> <form action="" method="post">
<table cellspacing="0" onclick="tableClick(event);" ondblclick="tableClick(event, true);" class="nowrap checkable"> <table cellspacing="0" class="nowrap checkable">
<?php <?php
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
// HTML valid because there is always at least one process // HTML valid because there is always at least one process
$i = -1; $i = -1;
foreach (process_list() as $i => $row) { foreach (process_list() as $i => $row) {
@@ -44,7 +45,7 @@ foreach (process_list() as $i => $row) {
} }
?> ?>
</table> </table>
<script type='text/javascript'>tableCheck();</script> <?php echo script("tableCheck();"); ?>
<p> <p>
<?php <?php
if (support("kill")) { if (support("kill")) {

View File

@@ -1,30 +0,0 @@
<?php
page_header(lang('Replication'));
echo "<h3>" . lang('Master status') . doc_link(array("sql" => "show-master-status.html")) . "</h3>\n";
$master_replication_status = replication_status("MASTER");
if (!$master_replication_status) {
echo "<p class='message'>" . lang('No rows.') . "\n";
} else {
echo "<table cellspacing='0'>\n";
foreach ($master_replication_status[0] as $key => $val) {
echo "<tr>";
echo "<th>" . h($key);
echo "<td>" . nbsp($val);
}
echo "</table>\n";
}
$slave_replication_status = replication_status("SLAVE");
if ($slave_replication_status) {
echo "<h3>" . lang('Slave status') . doc_link(array("sql" => "show-slave-status.html")) . "</h3>\n";
foreach ($slave_replication_status[0] as $slave) {
echo "<table cellspacing='0'>\n";
foreach ($slave as $key => $val) {
echo "<tr>";
echo "<th>" . h($key);
echo "<td>" . nbsp($val);
}
echo "</table>\n";
}
}

View File

@@ -48,19 +48,19 @@ foreach (table_status('', true) as $table => $table_status) {
} }
?> ?>
<div id="schema" style="height: <?php echo $top; ?>em;" onselectstart="return false;"> <div id="schema" style="height: <?php echo $top; ?>em;">
<script type="text/javascript"> <script<?php echo nonce(); ?>>
qs('#schema').onselectstart = function () { return false; };
var tablePos = {<?php echo implode(",", $table_pos_js) . "\n"; ?>}; var tablePos = {<?php echo implode(",", $table_pos_js) . "\n"; ?>};
var em = document.getElementById('schema').offsetHeight / <?php echo $top; ?>; var em = qs('#schema').offsetHeight / <?php echo $top; ?>;
document.onmousemove = schemaMousemove; document.onmousemove = schemaMousemove;
document.onmouseup = function (ev) { document.onmouseup = partialArg(schemaMouseup, '<?php echo js_escape(DB); ?>');
schemaMouseup(ev, '<?php echo js_escape(DB); ?>');
};
</script> </script>
<?php <?php
foreach ($schema as $name => $table) { foreach ($schema as $name => $table) {
echo "<div class='table' style='top: " . $table["pos"][0] . "em; left: " . $table["pos"][1] . "em;' onmousedown='schemaMousedown(this, event);'>"; echo "<div class='table' style='top: " . $table["pos"][0] . "em; left: " . $table["pos"][1] . "em;'>";
echo '<a href="' . h(ME) . 'table=' . urlencode($name) . '"><b>' . h($name) . "</b></a>"; echo '<a href="' . h(ME) . 'table=' . urlencode($name) . '"><b>' . h($name) . "</b></a>";
echo script("qsl('div').onmousedown = schemaMousedown;");
foreach ($table["fields"] as $field) { foreach ($table["fields"] as $field) {
$val = '<span' . type_class($field["type"]) . ' title="' . h($field["full_type"] . ($field["null"] ? " NULL" : '')) . '">' . h($field["field"]) . '</span>'; $val = '<span' . type_class($field["type"]) . ' title="' . h($field["full_type"] . ($field["null"] ? " NULL" : '')) . '">' . h($field["field"]) . '</span>';

View File

@@ -27,11 +27,11 @@ if (!$row) {
<form action="" method="post"> <form action="" method="post">
<p><input name="name" id="name" value="<?php echo h($row["name"]); ?>" autocapitalize="off"> <p><input name="name" id="name" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<script type='text/javascript'>focus(document.getElementById('name'));</script> <?php echo script("focus(qs('#name'));"); ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php <?php
if ($_GET["ns"] != "") { if ($_GET["ns"] != "") {
echo "<input type='submit' name='drop' value='" . lang('Drop') . "'" . confirm() . ">\n"; echo "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . confirm() . "\n";
} }
?> ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">

View File

@@ -226,7 +226,7 @@ $set = null;
if (isset($rights["insert"]) || !support("table")) { if (isset($rights["insert"]) || !support("table")) {
$set = ""; $set = "";
foreach ((array) $_GET["where"] as $val) { foreach ((array) $_GET["where"] as $val) {
if (count($foreign_keys[$val["col"]]) == 1 && ($val["op"] == "=" if ($foreign_keys[$val["col"]] && count($foreign_keys[$val["col"]]) == 1 && ($val["op"] == "="
|| (!$val["op"] && !preg_match('~[_%]~', $val["val"])) // LIKE in Editor || (!$val["op"] && !preg_match('~[_%]~', $val["val"])) // LIKE in Editor
)) { )) {
$set .= "&set" . urlencode("[" . bracket_escape($val["col"]) . "]") . "=" . urlencode($val["val"]); $set .= "&set" . urlencode("[" . bracket_escape($val["col"]) . "]") . "=" . urlencode($val["val"]);
@@ -288,7 +288,7 @@ if (!$columns && support("table")) {
} }
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest) // use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
if ($_GET["page"] != "last" && +$limit && $group && $is_group && $jush == "sql") { if ($_GET["page"] != "last" && $limit != "" && $group && $is_group && $jush == "sql") {
$found_rows = $connection->result(" SELECT FOUND_ROWS()"); // space to allow mysql.trace_mode $found_rows = $connection->result(" SELECT FOUND_ROWS()"); // space to allow mysql.trace_mode
} }
@@ -297,8 +297,12 @@ if (!$columns && support("table")) {
} else { } else {
$backward_keys = $adminer->backwardKeys($TABLE, $table_name); $backward_keys = $adminer->backwardKeys($TABLE, $table_name);
echo "<table id='table' cellspacing='0' class='nowrap checkable' onclick='tableClick(event);' ondblclick='tableClick(event, true);' onkeydown='return editingKeydown(event);'>\n"; echo "<table id='table' cellspacing='0' class='nowrap checkable'>";
echo "<thead><tr>" . (!$group && $select ? "" : "<td><input type='checkbox' id='all-page' onclick='formCheck(this, /check/);' class='jsonly'> <a href='" . h($_GET["modify"] ? remove_from_uri("modify") : $_SERVER["REQUEST_URI"] . "&modify=1") . "'>" . lang('Modify') . "</a>"); echo script("mixin(qs('#table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});");
echo "<thead><tr>" . (!$group && $select
? ""
: "<td><input type='checkbox' id='all-page' class='jsonly'>" . script("qs('#all-page').onclick = partial(formCheck, /check/);", "")
. " <a href='" . h($_GET["modify"] ? remove_from_uri("modify") : $_SERVER["REQUEST_URI"] . "&modify=1") . "'>" . lang('Modify') . "</a>");
$names = array(); $names = array();
$functions = array(); $functions = array();
reset($select); reset($select);
@@ -314,13 +318,14 @@ if (!$columns && support("table")) {
$column = idf_escape($key); $column = idf_escape($key);
$href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($key); $href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($key);
$desc = "&desc%5B0%5D=1"; $desc = "&desc%5B0%5D=1";
echo '<th onmouseover="columnMouse(this);" onmouseout="columnMouse(this, \' hidden\');">'; echo "<th>" . script("mixin(qsl('th'), {onmouseover: partial(columnMouse), onmouseout: partial(columnMouse, ' hidden')});", "");
echo '<a href="' . h($href . ($order[0] == $column || $order[0] == $key || (!$order && $is_group && $group[0] == $column) ? $desc : '')) . '">'; // $order[0] == $key - COUNT(*) echo '<a href="' . h($href . ($order[0] == $column || $order[0] == $key || (!$order && $is_group && $group[0] == $column) ? $desc : '')) . '">'; // $order[0] == $key - COUNT(*)
echo apply_sql_function($val["fun"], $name) . "</a>"; //! columns looking like functions echo apply_sql_function($val["fun"], $name) . "</a>"; //! columns looking like functions
echo "<span class='column hidden'>"; echo "<span class='column hidden'>";
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>"; echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
if (!$val["fun"]) { if (!$val["fun"]) {
echo '<a href="#fieldset-search" onclick="selectSearch(\'' . h(js_escape($key)) . '\'); return false;" title="' . lang('Search') . '" class="text jsonly"> =</a>'; echo '<a href="#fieldset-search" title="' . lang('Search') . '" class="text jsonly"> =</a>';
echo script("qsl('a').onclick = partial(selectSearch, '" . js_escape($key) . "');");
} }
echo "</span>"; echo "</span>";
} }
@@ -419,7 +424,8 @@ if (!$columns && support("table")) {
echo "<td>" . ($text ? "<textarea name='$id' cols='30' rows='" . (substr_count($row[$key], "\n") + 1) . "'>$h_value</textarea>" : "<input name='$id' value='$h_value' size='$lengths[$key]'>"); echo "<td>" . ($text ? "<textarea name='$id' cols='30' rows='" . (substr_count($row[$key], "\n") + 1) . "'>$h_value</textarea>" : "<input name='$id' value='$h_value' size='$lengths[$key]'>");
} else { } else {
$long = strpos($val, "<i>...</i>"); $long = strpos($val, "<i>...</i>");
echo "<td id='$id' onclick=\"selectClick(this, event, " . ($long ? 2 : ($text ? 1 : 0)) . ($editable ? "" : ", '" . h(lang('Use edit link to modify this value.')) . "'") . ");\">$val"; echo "<td id='$id'>$val</td>";
echo script("qsl('td').onclick = partialArg(selectClick, " . ($long ? 2 : ($text ? 1 : 0)) . ($editable ? "" : ", '" . h(lang('Use edit link to modify this value.')) . "'") . ");", "");
} }
} }
} }
@@ -440,7 +446,7 @@ if (!$columns && support("table")) {
if (($rows || $page) && !is_ajax()) { if (($rows || $page) && !is_ajax()) {
$exact_count = true; $exact_count = true;
if ($_GET["page"] != "last") { if ($_GET["page"] != "last") {
if (!+$limit) { if ($limit == "") {
$found_rows = count($rows); $found_rows = count($rows);
} elseif ($jush != "sql" || !$is_group) { } elseif ($jush != "sql" || !$is_group) {
$found_rows = ($is_group ? false : found_rows($table_status, $where)); $found_rows = ($is_group ? false : found_rows($table_status, $where));
@@ -453,7 +459,7 @@ if (!$columns && support("table")) {
} }
} }
if (+$limit && ($found_rows === false || $found_rows > $limit || $page)) { if ($limit != "" && ($found_rows === false || $found_rows > $limit || $page)) {
echo "<p class='pages'>"; echo "<p class='pages'>";
// display first, previous 4, next 4 and last page // display first, previous 4, next 4 and last page
$max_page = ($found_rows === false $max_page = ($found_rows === false
@@ -461,7 +467,8 @@ if (!$columns && support("table")) {
: floor(($found_rows - 1) / $limit) : floor(($found_rows - 1) / $limit)
); );
if ($jush != "simpledb") { if ($jush != "simpledb") {
echo '<a href="' . h(remove_from_uri("page")) . "\" onclick=\"pageClick(this.href, +prompt('" . lang('Page') . "', '" . ($page + 1) . "'), event); return false;\">" . lang('Page') . "</a>:"; echo '<a href="' . h(remove_from_uri("page")) . '">' . lang('Page') . "</a>:";
echo script("qsl('a').onclick = function () { pageClick(this.href, +prompt('" . lang('Page') . "', '" . ($page + 1) . "')); return false; };");
echo pagination(0, $page) . ($page > 5 ? " ..." : ""); echo pagination(0, $page) . ($page > 5 ? " ..." : "");
for ($i = max(1, $page - 4); $i < min($max_page, $page + 5); $i++) { for ($i = max(1, $page - 4); $i < min($max_page, $page + 5); $i++) {
echo pagination($i, $page); echo pagination($i, $page);
@@ -474,7 +481,8 @@ if (!$columns && support("table")) {
); );
} }
echo (($found_rows === false ? count($rows) + 1 : $found_rows - $page * $limit) > $limit echo (($found_rows === false ? count($rows) + 1 : $found_rows - $page * $limit) > $limit
? ' <a href="' . h(remove_from_uri("page") . "&page=" . ($page + 1)) . '" onclick="return !selectLoadMore(this, ' . (+$limit) . ', \'' . lang('Loading') . '...\');" class="loadmore">' . lang('Load more data') . '</a>' ? ' <a href="' . h(remove_from_uri("page") . "&page=" . ($page + 1)) . '" class="loadmore">' . lang('Load more data') . '</a>'
. script("qsl('a').onclick = partial(selectLoadMore, " . (+$limit) . ", '" . lang('Loading') . "...');", "")
: '' : ''
); );
} else { } else {
@@ -498,7 +506,7 @@ if (!$columns && support("table")) {
<fieldset><legend><?php echo lang('Selected'); ?> <span id="selected"></span></legend><div> <fieldset><legend><?php echo lang('Selected'); ?> <span id="selected"></span></legend><div>
<input type="submit" name="edit" value="<?php echo lang('Edit'); ?>"> <input type="submit" name="edit" value="<?php echo lang('Edit'); ?>">
<input type="submit" name="clone" value="<?php echo lang('Clone'); ?>"> <input type="submit" name="clone" value="<?php echo lang('Clone'); ?>">
<input type="submit" name="delete" value="<?php echo lang('Delete'); ?>"<?php echo confirm(); ?>> <input type="submit" name="delete" value="<?php echo lang('Delete'); ?>"><?php echo confirm(); ?>
</div></fieldset> </div></fieldset>
<?php <?php
} }
@@ -519,7 +527,7 @@ if (!$columns && support("table")) {
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
echo (!$group && $select ? "" : "<script type='text/javascript'>tableCheck();</script>\n"); echo (!$group && $select ? "" : script("tableCheck();"));
} }
if ($adminer->selectImportPrint()) { if ($adminer->selectImportPrint()) {

View File

@@ -28,7 +28,7 @@ if (!$row) {
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php <?php
if ($SEQUENCE != "") { if ($SEQUENCE != "") {
echo "<input type='submit' name='drop' value='" . lang('Drop') . "'" . confirm() . ">\n"; echo "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . confirm() . "\n";
} }
?> ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">

View File

@@ -137,7 +137,7 @@ if (!$error && $_POST) {
echo "<p>" . ($num_rows ? ($limit && $num_rows > $limit ? lang('%d / ', $limit) : "") . lang('%d row(s)', $num_rows) : ""); echo "<p>" . ($num_rows ? ($limit && $num_rows > $limit ? lang('%d / ', $limit) : "") . lang('%d row(s)', $num_rows) : "");
echo $time; echo $time;
$id = "export-$commands"; $id = "export-$commands";
$export = ", <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('Export') . "</a><span id='$id' class='hidden'>: " $export = ", <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("output", $adminer->dumpOutput(), $adminer_export["output"]) . " "
. html_select("format", $dump_format, $adminer_export["format"]) . html_select("format", $dump_format, $adminer_export["format"])
. "<input type='hidden' name='query' value='" . h($q) . "'>" . "<input type='hidden' name='query' value='" . h($q) . "'>"
@@ -145,7 +145,7 @@ if (!$error && $_POST) {
; ;
if ($connection2 && preg_match("~^($space|\\()*+SELECT\\b~i", $q) && ($explain = explain($connection2, $q))) { if ($connection2 && preg_match("~^($space|\\()*+SELECT\\b~i", $q) && ($explain = explain($connection2, $q))) {
$id = "explain-$commands"; $id = "explain-$commands";
echo ", <a href='#$id' onclick=\"return !toggle('$id');\">EXPLAIN</a>$export"; echo ", <a href='#$id'>EXPLAIN</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "") . $export;
echo "<div id='$id' class='hidden'>\n"; echo "<div id='$id' class='hidden'>\n";
select($explain, $connection2, $orgtables); select($explain, $connection2, $orgtables);
echo "</div>\n"; echo "</div>\n";
@@ -208,7 +208,7 @@ if (!isset($_GET["import"])) {
} }
echo "<p>"; echo "<p>";
textarea("query", $q, 20); textarea("query", $q, 20);
echo ($_POST ? "" : "<script type='text/javascript'>focus(document.getElementsByTagName('textarea')[0]);</script>\n"); echo ($_POST ? "" : script("qs('textarea').focus();"));
echo "<p>$execute\n"; echo "<p>$execute\n";
echo lang('Limit rows') . ": <input type='number' name='limit' class='size' value='" . h($_POST ? $_POST["limit"] : $_GET["limit"]) . "'>\n"; echo lang('Limit rows') . ": <input type='number' name='limit' class='size' value='" . h($_POST ? $_POST["limit"] : $_GET["limit"]) . "'>\n";

View File

@@ -2,7 +2,7 @@
function adminer_object() { function adminer_object() {
include_once "../plugins/plugin.php"; include_once "../plugins/plugin.php";
include_once "../plugins/login-sqlite.php"; include_once "../plugins/login-sqlite.php";
return new AdminerPlugin(array(new AdminerLoginSqlite)); return new AdminerPlugin(array(new AdminerLoginSqlite("admin", password_hash("", PASSWORD_DEFAULT))));
} }
include "./index.php"; include "./index.php";

View File

@@ -10,8 +10,8 @@ h2 { font-size: 150%; margin: 0 0 20px -18px; padding: .8em 1em; border-bottom:
h3 { font-weight: normal; font-size: 130%; margin: 1em 0 0; } h3 { font-weight: normal; font-size: 130%; margin: 1em 0 0; }
form { margin: 0; } form { margin: 0; }
td table { width: 100%; margin: 0; } td table { width: 100%; margin: 0; }
table { margin: 1em 20px 0 0; border: 0; border-top: 1px solid #999; border-left: 1px solid #999; font-size: 90%; } table { margin: 1em 20px 0 0; border-collapse: collapse; font-size: 90%; }
td, th { border: 0; border-right: 1px solid #999; border-bottom: 1px solid #999; padding: .2em .3em; } td, th { border: 1px solid #999; padding: .2em .3em; }
th { background: #eee; text-align: left; } th { background: #eee; text-align: left; }
thead th { text-align: center; padding: .2em .5em; } thead th { text-align: center; padding: .2em .5em; }
thead td, thead th { background: #ddf; } thead td, thead th { background: #ddf; }

View File

@@ -23,7 +23,7 @@ function bodyLoad(version) {
jush.custom_links = jushLinks; jush.custom_links = jushLinks;
} }
jush.highlight_tag('code', 0); jush.highlight_tag('code', 0);
var tags = document.getElementsByTagName('textarea'); var tags = qsa('textarea', document);
for (var i = 0; i < tags.length; i++) { for (var i = 0; i < tags.length; i++) {
if (/(^|\s)jush-/.test(tags[i].className)) { if (/(^|\s)jush-/.test(tags[i].className)) {
var pre = jush.textarea(tags[i]); var pre = jush.textarea(tags[i]);
@@ -60,6 +60,15 @@ function typePassword(el, disable) {
} }
} }
/** Install toggle handler
*/
function messagesPrint() {
var els = qsa('.toggle', document);
for (var i = 0; i < els.length; i++) {
els[i].onclick = partial(toggle, els[i].getAttribute('href').substr(1));
}
}
var dbCtrl; var dbCtrl;
@@ -67,45 +76,46 @@ var dbPrevious = {};
/** Check if database should be opened to a new window /** Check if database should be opened to a new window
* @param MouseEvent * @param MouseEvent
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function dbMouseDown(event, el) { function dbMouseDown(event) {
dbCtrl = isCtrl(event); dbCtrl = isCtrl(event);
if (dbPrevious[el.name] == undefined) { if (dbPrevious[this.name] == undefined) {
dbPrevious[el.name] = el.value; dbPrevious[this.name] = this.value;
} }
} }
/** Load database after selecting it /** Load database after selecting it
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function dbChange(el) { function dbChange() {
if (dbCtrl) { if (dbCtrl) {
el.form.target = '_blank'; this.form.target = '_blank';
} }
el.form.submit(); this.form.submit();
el.form.target = ''; this.form.target = '';
if (dbCtrl && dbPrevious[el.name] != undefined) { if (dbCtrl && dbPrevious[this.name] != undefined) {
el.value = dbPrevious[el.name]; this.value = dbPrevious[this.name];
dbPrevious[el.name] = undefined; dbPrevious[this.name] = undefined;
} }
} }
/** Check whether the query will be executed with index /** Check whether the query will be executed with index
* @param HTMLFormElement * @this HTMLElement
*/ */
function selectFieldChange(form) { function selectFieldChange() {
var form = this.form;
var ok = (function () { var ok = (function () {
var inputs = form.getElementsByTagName('input'); var inputs = qsa('input', form);
for (var i=0; i < inputs.length; i++) { for (var i=0; i < inputs.length; i++) {
if (inputs[i].value && /^fulltext/.test(inputs[i].name)) { if (inputs[i].value && /^fulltext/.test(inputs[i].name)) {
return true; return true;
} }
} }
var ok = form.limit.value; var ok = form.limit.value;
var selects = form.getElementsByTagName('select'); var selects = qsa('select', form);
var group = false; var group = false;
var columns = {}; var columns = {};
for (var i=0; i < selects.length; i++) { for (var i=0; i < selects.length; i++) {
@@ -172,14 +182,14 @@ function idfEscape(s) {
} }
/** Detect foreign key /** Detect foreign key
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function editingNameChange(field) { function editingNameChange() {
var name = field.name.substr(0, field.name.length - 7); var name = this.name.substr(0, this.name.length - 7);
var type = formField(field.form, name + '[type]'); var type = formField(this.form, name + '[type]');
var opts = type.options; var opts = type.options;
var candidate; // don't select anything with ambiguous match (like column `id`) var candidate; // don't select anything with ambiguous match (like column `id`)
var val = field.value; var val = this.value;
for (var i = opts.length; i--; ) { for (var i = opts.length; i--; ) {
var match = /(.+)`(.+)/.exec(opts[i].value); var match = /(.+)`(.+)/.exec(opts[i].value);
if (!match) { // common type if (!match) { // common type
@@ -209,23 +219,23 @@ function editingNameChange(field) {
} }
/** Add table row for next field /** Add table row for next field
* @param HTMLInputElement
* @param boolean * @param boolean
* @return boolean * @return boolean false
* @this HTMLInputElement
*/ */
function editingAddRow(button, focus) { function editingAddRow(focus) {
var match = /(\d+)(\.\d+)?/.exec(button.name); var match = /(\d+)(\.\d+)?/.exec(this.name);
var x = match[0] + (match[2] ? added.substr(match[2].length) : added) + '1'; var x = match[0] + (match[2] ? added.substr(match[2].length) : added) + '1';
var row = parentTag(button, 'tr'); var row = parentTag(this, 'tr');
var row2 = cloneNode(row); var row2 = cloneNode(row);
var tags = row.getElementsByTagName('select'); var tags = qsa('select', row);
var tags2 = row2.getElementsByTagName('select'); var tags2 = qsa('select', row2);
for (var i=0; i < tags.length; i++) { for (var i=0; i < tags.length; i++) {
tags2[i].name = tags[i].name.replace(/[0-9.]+/, x); tags2[i].name = tags[i].name.replace(/[0-9.]+/, x);
tags2[i].selectedIndex = tags[i].selectedIndex; tags2[i].selectedIndex = tags[i].selectedIndex;
} }
tags = row.getElementsByTagName('input'); tags = qsa('input', row);
tags2 = row2.getElementsByTagName('input'); tags2 = qsa('input', row2);
var input = tags2[0]; // IE loose tags2 after insertBefore() var input = tags2[0]; // IE loose tags2 after insertBefore()
for (var i=0; i < tags.length; i++) { for (var i=0; i < tags.length; i++) {
if (tags[i].name == 'auto_increment_col') { if (tags[i].name == 'auto_increment_col') {
@@ -240,59 +250,52 @@ function editingAddRow(button, focus) {
tags2[i].checked = false; tags2[i].checked = false;
} }
} }
tags[0].onchange = function () { tags[0].oninput = editingNameChange;
editingNameChange(tags[0]);
};
tags[0].onkeyup = function () {
};
row.parentNode.insertBefore(row2, row.nextSibling); row.parentNode.insertBefore(row2, row.nextSibling);
if (focus) { if (focus) {
input.onchange = function () { input.oninput = editingNameChange;
editingNameChange(input);
};
input.onkeyup = function () {
};
input.focus(); input.focus();
} }
added += '0'; added += '0';
rowCount++; rowCount++;
return true; return false;
} }
/** Remove table row for field /** Remove table row for field
* @param HTMLInputElement
* @param string * @param string
* @return boolean * @return boolean false
* @this HTMLInputElement
*/ */
function editingRemoveRow(button, name) { function editingRemoveRow(name) {
var field = formField(button.form, button.name.replace(/[^\[]+(.+)/, name)); var field = formField(this.form, this.name.replace(/[^\[]+(.+)/, name));
field.parentNode.removeChild(field); field.parentNode.removeChild(field);
parentTag(button, 'tr').style.display = 'none'; parentTag(this, 'tr').style.display = 'none';
return true; return false;
} }
/** Move table row for field /** Move table row for field
* @param HTMLInputElement
* @param boolean direction to move row, true for up or false for down * @param boolean direction to move row, true for up or false for down
* @return boolean * @return boolean false for success
* @this HTMLInputElement
*/ */
function editingMoveRow(button, dir){ function editingMoveRow(dir){
var row = parentTag(button, 'tr'); var row = parentTag(this, 'tr');
if (!('nextElementSibling' in row)) { if (!('nextElementSibling' in row)) {
return false; return true;
} }
row.parentNode.insertBefore(row, dir row.parentNode.insertBefore(row, dir
? row.previousElementSibling ? row.previousElementSibling
: row.nextElementSibling ? row.nextElementSibling.nextElementSibling : row.parentNode.firstChild); : row.nextElementSibling ? row.nextElementSibling.nextElementSibling : row.parentNode.firstChild);
return true; return false;
} }
var lastType = ''; var lastType = '';
/** Clear length and hide collation or unsigned /** Clear length and hide collation or unsigned
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function editingTypeChange(type) { function editingTypeChange() {
var type = this;
var name = type.name.substr(0, type.name.length - 6); var name = type.name.substr(0, type.name.length - 6);
var text = selectValue(type); var text = selectValue(type);
for (var i=0; i < type.form.elements.length; i++) { for (var i=0; i < type.form.elements.length; i++) {
@@ -304,7 +307,7 @@ function editingTypeChange(type) {
)) { )) {
el.value = ''; el.value = '';
} }
el.onchange.apply(el); el.oninput.apply(el);
} }
if (lastType == 'timestamp' && el.name == name + '[has_default]' && /timestamp/i.test(formField(type.form, name + '[default]').value)) { if (lastType == 'timestamp' && el.name == name + '[has_default]' && /timestamp/i.test(formField(type.form, name + '[default]').value)) {
el.checked = false; el.checked = false;
@@ -326,37 +329,37 @@ function editingTypeChange(type) {
} }
/** Mark length as required /** Mark length as required
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function editingLengthChange(el) { function editingLengthChange() {
alterClass(el, 'required', !el.value.length && /var(char|binary)$/.test(selectValue(el.parentNode.previousSibling.firstChild))); alterClass(this, 'required', !this.value.length && /var(char|binary)$/.test(selectValue(this.parentNode.previousSibling.firstChild)));
} }
/** Edit enum or set /** Edit enum or set
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function editingLengthFocus(field) { function editingLengthFocus() {
var td = field.parentNode; var td = this.parentNode;
if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) { if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) {
var edit = document.getElementById('enum-edit'); var edit = qs('#enum-edit');
var val = field.value; var val = this.value;
edit.value = (/^'.+'$/.test(val) ? val.substr(1, val.length - 2).replace(/','/g, "\n").replace(/''/g, "'") : val); //! doesn't handle 'a'',''b' correctly edit.value = (/^'.+'$/.test(val) ? val.substr(1, val.length - 2).replace(/','/g, "\n").replace(/''/g, "'") : val); //! doesn't handle 'a'',''b' correctly
td.appendChild(edit); td.appendChild(edit);
field.style.display = 'none'; this.style.display = 'none';
edit.style.display = 'inline'; edit.style.display = 'inline';
edit.focus(); edit.focus();
} }
} }
/** Finish editing of enum or set /** Finish editing of enum or set
* @param HTMLTextAreaElement * @this HTMLTextAreaElement
*/ */
function editingLengthBlur(edit) { function editingLengthBlur() {
var field = edit.parentNode.firstChild; var field = this.parentNode.firstChild;
var val = edit.value; var val = this.value;
field.value = (/^'[^\n]+'$/.test(val) ? val : "'" + val.replace(/\n+$/, '').replace(/'/g, "''").replace(/\n/g, "','") + "'"); field.value = (/^'[^\n]+'$/.test(val) ? val : val && "'" + val.replace(/\n+$/, '').replace(/'/g, "''").replace(/\n/g, "','") + "'");
field.style.display = 'inline'; field.style.display = 'inline';
edit.style.display = 'none'; this.style.display = 'none';
} }
/** Show or hide selected table column /** Show or hide selected table column
@@ -364,9 +367,9 @@ function editingLengthBlur(edit) {
* @param number * @param number
*/ */
function columnShow(checked, column) { function columnShow(checked, column) {
var trs = document.getElementById('edit-fields').getElementsByTagName('tr'); var trs = qsa('tr', qs('#edit-fields'));
for (var i=0; i < trs.length; i++) { for (var i=0; i < trs.length; i++) {
alterClass(trs[i].getElementsByTagName('td')[column], 'hidden', !checked); alterClass(qsa('td', trs[i])[column], 'hidden', !checked);
} }
} }
@@ -374,76 +377,76 @@ function columnShow(checked, column) {
*/ */
function editingHideDefaults() { function editingHideDefaults() {
if (innerWidth < document.documentElement.scrollWidth) { if (innerWidth < document.documentElement.scrollWidth) {
document.getElementById('form')['defaults'].checked = false; qs('#form')['defaults'].checked = false;
columnShow(false, 5); columnShow(false, 5);
} }
} }
/** Display partition options /** Display partition options
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function partitionByChange(el) { function partitionByChange() {
var partitionTable = /RANGE|LIST/.test(selectValue(el)); var partitionTable = /RANGE|LIST/.test(selectValue(this));
alterClass(el.form['partitions'], 'hidden', partitionTable || !el.selectedIndex); alterClass(this.form['partitions'], 'hidden', partitionTable || !this.selectedIndex);
alterClass(document.getElementById('partition-table'), 'hidden', !partitionTable); alterClass(qs('#partition-table'), 'hidden', !partitionTable);
helpClose(); helpClose();
} }
/** Add next partition row /** Add next partition row
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function partitionNameChange(el) { function partitionNameChange() {
var row = cloneNode(parentTag(el, 'tr')); var row = cloneNode(parentTag(this, 'tr'));
row.firstChild.firstChild.value = ''; row.firstChild.firstChild.value = '';
parentTag(el, 'table').appendChild(row); parentTag(this, 'table').appendChild(row);
el.onchange = function () {}; this.oninput = function () {};
} }
/** Add row for foreign key /** Add row for foreign key
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function foreignAddRow(field) { function foreignAddRow() {
field.onchange = function () { }; this.onchange = function () { };
var row = cloneNode(parentTag(field, 'tr')); var row = cloneNode(parentTag(this, 'tr'));
var selects = row.getElementsByTagName('select'); var selects = qsa('select', row);
for (var i=0; i < selects.length; i++) { for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/\]/, '1$&'); selects[i].name = selects[i].name.replace(/\]/, '1$&');
selects[i].selectedIndex = 0; selects[i].selectedIndex = 0;
} }
parentTag(field, 'table').appendChild(row); parentTag(this, 'table').appendChild(row);
} }
/** Add row for indexes /** Add row for indexes
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function indexesAddRow(field) { function indexesAddRow() {
field.onchange = function () { }; this.onchange = function () { };
var row = cloneNode(parentTag(field, 'tr')); var row = cloneNode(parentTag(this, 'tr'));
var selects = row.getElementsByTagName('select'); var selects = qsa('select', row);
for (var i=0; i < selects.length; i++) { for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/indexes\[\d+/, '$&1'); selects[i].name = selects[i].name.replace(/indexes\[\d+/, '$&1');
selects[i].selectedIndex = 0; selects[i].selectedIndex = 0;
} }
var inputs = row.getElementsByTagName('input'); var inputs = qsa('input', row);
for (var i=0; i < inputs.length; i++) { for (var i=0; i < inputs.length; i++) {
inputs[i].name = inputs[i].name.replace(/indexes\[\d+/, '$&1'); inputs[i].name = inputs[i].name.replace(/indexes\[\d+/, '$&1');
inputs[i].value = ''; inputs[i].value = '';
} }
parentTag(field, 'table').appendChild(row); parentTag(this, 'table').appendChild(row);
} }
/** Change column in index /** Change column in index
* @param HTMLSelectElement
* @param string name prefix * @param string name prefix
* @this HTMLSelectElement
*/ */
function indexesChangeColumn(field, prefix) { function indexesChangeColumn(prefix) {
var names = []; var names = [];
for (var tag in { 'select': 1, 'input': 1 }) { for (var tag in { 'select': 1, 'input': 1 }) {
var columns = parentTag(field, 'td').getElementsByTagName(tag); var columns = qsa(tag, parentTag(this, 'td'));
for (var i=0; i < columns.length; i++) { for (var i=0; i < columns.length; i++) {
if (/\[columns\]/.test(columns[i].name)) { if (/\[columns\]/.test(columns[i].name)) {
var value = selectValue(columns[i]); var value = selectValue(columns[i]);
@@ -453,17 +456,15 @@ function indexesChangeColumn(field, prefix) {
} }
} }
} }
field.form[field.name.replace(/\].*/, '][name]')].value = prefix + names.join('_'); this.form[this.name.replace(/\].*/, '][name]')].value = prefix + names.join('_');
} }
/** Add column for index /** Add column for index
* @param HTMLSelectElement
* @param string name prefix * @param string name prefix
* @this HTMLSelectElement
*/ */
function indexesAddColumn(field, prefix) { function indexesAddColumn(prefix) {
field.onchange = function () { var field = this;
indexesChangeColumn(field, prefix);
};
var select = field.form[field.name.replace(/\].*/, '][type]')]; var select = field.form[field.name.replace(/\].*/, '][type]')];
if (!select.selectedIndex) { if (!select.selectedIndex) {
while (selectValue(select) != "INDEX" && select.selectedIndex < select.options.length) { while (selectValue(select) != "INDEX" && select.selectedIndex < select.options.length) {
@@ -472,13 +473,14 @@ function indexesAddColumn(field, prefix) {
select.onchange(); select.onchange();
} }
var column = cloneNode(field.parentNode); var column = cloneNode(field.parentNode);
var selects = column.getElementsByTagName('select'); var selects = qsa('select', column);
for (var i = 0; i < selects.length; i++) { for (var i = 0; i < selects.length; i++) {
select = selects[i]; select = selects[i];
select.name = select.name.replace(/\]\[\d+/, '$&1'); select.name = select.name.replace(/\]\[\d+/, '$&1');
select.selectedIndex = 0; select.selectedIndex = 0;
} }
var inputs = column.getElementsByTagName('input'); field.onchange = partial(indexesChangeColumn, prefix);
var inputs = qsa('input', column);
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
var input = inputs[i]; var input = inputs[i];
input.name = input.name.replace(/\]\[\d+/, '$&1'); input.name = input.name.replace(/\]\[\d+/, '$&1');
@@ -510,48 +512,47 @@ function triggerChange(tableRe, table, form) {
var that, x, y; // em and tablePos defined in schema.inc.php var that, x, y; // em and tablePos defined in schema.inc.php
/** Get mouse position /** Get mouse position
* @param HTMLElement
* @param MouseEvent * @param MouseEvent
* @this HTMLElement
*/ */
function schemaMousedown(el, event) { function schemaMousedown(event) {
if ((event.which ? event.which : event.button) == 1) { if ((event.which ? event.which : event.button) == 1) {
that = el; that = this;
x = event.clientX - el.offsetLeft; x = event.clientX - this.offsetLeft;
y = event.clientY - el.offsetTop; y = event.clientY - this.offsetTop;
} }
} }
/** Move object /** Move object
* @param MouseEvent * @param MouseEvent
*/ */
function schemaMousemove(ev) { function schemaMousemove(event) {
if (that !== undefined) { if (that !== undefined) {
ev = ev || event; var left = (event.clientX - x) / em;
var left = (ev.clientX - x) / em; var top = (event.clientY - y) / em;
var top = (ev.clientY - y) / em; var divs = qsa('div', that);
var divs = that.getElementsByTagName('div');
var lineSet = { }; var lineSet = { };
for (var i=0; i < divs.length; i++) { for (var i=0; i < divs.length; i++) {
if (divs[i].className == 'references') { if (divs[i].className == 'references') {
var div2 = document.getElementById((/^refs/.test(divs[i].id) ? 'refd' : 'refs') + divs[i].id.substr(4)); var div2 = qs('[id="' + (/^refs/.test(divs[i].id) ? 'refd' : 'refs') + divs[i].id.substr(4) + '"]');
var ref = (tablePos[divs[i].title] ? tablePos[divs[i].title] : [ div2.parentNode.offsetTop / em, 0 ]); var ref = (tablePos[divs[i].title] ? tablePos[divs[i].title] : [ div2.parentNode.offsetTop / em, 0 ]);
var left1 = -1; var left1 = -1;
var id = divs[i].id.replace(/^ref.(.+)-.+/, '$1'); var id = divs[i].id.replace(/^ref.(.+)-.+/, '$1');
if (divs[i].parentNode != div2.parentNode) { if (divs[i].parentNode != div2.parentNode) {
left1 = Math.min(0, ref[1] - left) - 1; left1 = Math.min(0, ref[1] - left) - 1;
divs[i].style.left = left1 + 'em'; divs[i].style.left = left1 + 'em';
divs[i].getElementsByTagName('div')[0].style.width = -left1 + 'em'; divs[i].querySelector('div').style.width = -left1 + 'em';
var left2 = Math.min(0, left - ref[1]) - 1; var left2 = Math.min(0, left - ref[1]) - 1;
div2.style.left = left2 + 'em'; div2.style.left = left2 + 'em';
div2.getElementsByTagName('div')[0].style.width = -left2 + 'em'; div2.querySelector('div').style.width = -left2 + 'em';
} }
if (!lineSet[id]) { if (!lineSet[id]) {
var line = document.getElementById(divs[i].id.replace(/^....(.+)-.+$/, 'refl$1')); var line = qs('[id="' + divs[i].id.replace(/^....(.+)-.+$/, 'refl$1') + '"]');
var top1 = top + divs[i].offsetTop / em; var top1 = top + divs[i].offsetTop / em;
var top2 = top + div2.offsetTop / em; var top2 = top + div2.offsetTop / em;
if (divs[i].parentNode != div2.parentNode) { if (divs[i].parentNode != div2.parentNode) {
top2 += ref[0] - top; top2 += ref[0] - top;
line.getElementsByTagName('div')[0].style.height = Math.abs(top1 - top2) + 'em'; line.querySelector('div').style.height = Math.abs(top1 - top2) + 'em';
} }
line.style.left = (left + left1) + 'em'; line.style.left = (left + left1) + 'em';
line.style.top = Math.min(top1, top2) + 'em'; line.style.top = Math.min(top1, top2) + 'em';
@@ -568,17 +569,16 @@ function schemaMousemove(ev) {
* @param MouseEvent * @param MouseEvent
* @param string * @param string
*/ */
function schemaMouseup(ev, db) { function schemaMouseup(event, db) {
if (that !== undefined) { if (that !== undefined) {
ev = ev || event; tablePos[that.firstChild.firstChild.firstChild.data] = [ (event.clientY - y) / em, (event.clientX - x) / em ];
tablePos[that.firstChild.firstChild.firstChild.data] = [ (ev.clientY - y) / em, (ev.clientX - x) / em ];
that = undefined; that = undefined;
var s = ''; var s = '';
for (var key in tablePos) { for (var key in tablePos) {
s += '_' + key + ':' + Math.round(tablePos[key][0] * 10000) / 10000 + 'x' + Math.round(tablePos[key][1] * 10000) / 10000; s += '_' + key + ':' + Math.round(tablePos[key][0] * 10000) / 10000 + 'x' + Math.round(tablePos[key][1] * 10000) / 10000;
} }
s = encodeURIComponent(s.substr(1)); s = encodeURIComponent(s.substr(1));
var link = document.getElementById('schema-link'); var link = qs('#schema-link');
link.href = link.href.replace(/[^=]+$/, '') + s; link.href = link.href.replace(/[^=]+$/, '') + s;
cookie('adminer_schema-' + db + '=' + s, 30); //! special chars in db cookie('adminer_schema-' + db + '=' + s, 30); //! special chars in db
} }
@@ -589,18 +589,18 @@ function schemaMouseup(ev, db) {
var helpOpen, helpIgnore; // when mouse outs <option> then it mouse overs border of <select> - ignore it var helpOpen, helpIgnore; // when mouse outs <option> then it mouse overs border of <select> - ignore it
/** Display help /** Display help
* @param HTMLElement
* @param MouseEvent * @param MouseEvent
* @param string * @param string
* @param bool display on left side (otherwise on top) * @param bool display on left side (otherwise on top)
* @this HTMLElement
*/ */
function helpMouseover(el, event, text, side) { function helpMouseover(event, text, side) {
var target = getTarget(event); var target = getTarget(event);
if (!text) { if (!text) {
helpClose(); helpClose();
} else if (window.jush && (!helpIgnore || el != target)) { } else if (window.jush && (!helpIgnore || this != target)) {
helpOpen = 1; helpOpen = 1;
var help = document.getElementById('help'); var help = qs('#help');
help.innerHTML = text; help.innerHTML = text;
jush.highlight_tag([ help ]); jush.highlight_tag([ help ]);
alterClass(help, 'hidden'); alterClass(help, 'hidden');
@@ -612,12 +612,12 @@ function helpMouseover(el, event, text, side) {
} }
/** Close help after timeout /** Close help after timeout
* @param HTMLElement
* @param MouseEvent * @param MouseEvent
* @this HTMLElement
*/ */
function helpMouseout(el, event) { function helpMouseout(event) {
helpOpen = 0; helpOpen = 0;
helpIgnore = (el != getTarget(event)); helpIgnore = (this != getTarget(event));
setTimeout(function () { setTimeout(function () {
if (!helpOpen) { if (!helpOpen) {
helpClose(); helpClose();
@@ -628,5 +628,5 @@ function helpMouseout(el, event) {
/** Close help /** Close help
*/ */
function helpClose() { function helpClose() {
alterClass(document.getElementById('help'), 'hidden', true); alterClass(qs('#help'), 'hidden', true);
} }

View File

@@ -1,4 +1,66 @@
/** Get first element by selector
* @param string
* @return HTMLElement
*/
function qs(selector) {
return document.querySelector(selector);
}
/** Get last element by selector
* @param string
* @param [HTMLElement] defaults to document
* @return HTMLElement
*/
function qsl(selector, context) {
var els = qsa(selector, context || document);
return els[els.length - 1];
}
/** Get all elements by selector
* @param string
* @param HTMLElement
* @return NodeList
*/
function qsa(selector, context) {
return context.querySelectorAll(selector);
}
/** Return a function calling fn with the next arguments
* @param function
* @param ...
* @return function with preserved this
*/
function partial(fn) {
var args = Array.apply(null, arguments).slice(1);
return function () {
return fn.apply(this, args);
};
}
/** Return a function calling fn with the first parameter and then the next arguments
* @param function
* @param ...
* @return function with preserved this
*/
function partialArg(fn) {
var args = Array.apply(null, arguments);
return function (arg) {
args[0] = arg;
return fn.apply(this, args);
};
}
/** Assign values from source to target
* @param Object
* @param Object
*/
function mixin(target, source) {
for (var key in source) {
target[key] = source[key];
}
}
/** Add or remove CSS class /** Add or remove CSS class
* @param HTMLElement * @param HTMLElement
* @param string * @param string
@@ -12,12 +74,12 @@ function alterClass(el, className, enable) {
/** Toggle visibility /** Toggle visibility
* @param string * @param string
* @return boolean * @return boolean false
*/ */
function toggle(id) { function toggle(id) {
var el = document.getElementById(id); var el = qs('#' + id);
el.className = (el.className == 'hidden' ? '' : 'hidden'); el.className = (el.className == 'hidden' ? '' : 'hidden');
return true; return false;
} }
/** Set permanent cookie /** Set permanent cookie
@@ -54,7 +116,7 @@ function verifyVersion(current) {
} }
}, false); }, false);
} }
document.getElementById('version').appendChild(iframe); qs('#version').appendChild(iframe);
} }
/** Get value of select /** Get value of select
@@ -70,20 +132,20 @@ function selectValue(select) {
} }
/** Verify if element has a specified tag name /** Verify if element has a specified tag name
* @param HTMLElement * @param HTMLElement
* @param string regular expression * @param string regular expression
* @return bool * @return bool
*/ */
function isTag(el, tag) { function isTag(el, tag) {
var re = new RegExp('^(' + tag + ')$', 'i'); var re = new RegExp('^(' + tag + ')$', 'i');
return re.test(el.tagName); return re.test(el.tagName);
} }
/** Get parent node with specified tag name /** Get parent node with specified tag name
* @param HTMLElement * @param HTMLElement
* @param string regular expression * @param string regular expression
* @return HTMLElement * @return HTMLElement
*/ */
function parentTag(el, tag) { function parentTag(el, tag) {
while (el && !isTag(el, tag)) { while (el && !isTag(el, tag)) {
el = el.parentNode; el = el.parentNode;
@@ -108,24 +170,27 @@ function trCheck(el) {
*/ */
function selectCount(id, count) { function selectCount(id, count) {
setHtml(id, (count === '' ? '' : '(' + (count + '').replace(/\B(?=(\d{3})+$)/g, ' ') + ')')); setHtml(id, (count === '' ? '' : '(' + (count + '').replace(/\B(?=(\d{3})+$)/g, ' ') + ')'));
var inputs = document.getElementById(id).parentNode.parentNode.getElementsByTagName('input'); var el = qs('#' + id);
if (el) {
var inputs = qsa('input', el.parentNode.parentNode);
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
var input = inputs[i]; var input = inputs[i];
if (input.type == 'submit') { if (input.type == 'submit') {
input.disabled = (count == '0'); input.disabled = (count == '0');
} }
} }
}
} }
/** Check all elements matching given name /** Check all elements matching given name
* @param HTMLInputElement
* @param RegExp * @param RegExp
* @this HTMLInputElement
*/ */
function formCheck(el, name) { function formCheck(name) {
var elems = el.form.elements; var elems = this.form.elements;
for (var i=0; i < elems.length; i++) { for (var i=0; i < elems.length; i++) {
if (name.test(elems[i].name)) { if (name.test(elems[i].name)) {
elems[i].checked = el.checked; elems[i].checked = this.checked;
trCheck(elems[i]); trCheck(elems[i]);
} }
} }
@@ -134,10 +199,10 @@ function formCheck(el, name) {
/** Check all rows in <table class="checkable"> /** Check all rows in <table class="checkable">
*/ */
function tableCheck() { function tableCheck() {
var tables = document.getElementsByTagName('table'); var tables = qsa('table', document);
for (var i=0; i < tables.length; i++) { for (var i=0; i < tables.length; i++) {
if (/(^|\s)checkable(\s|$)/.test(tables[i].className)) { if (/(^|\s)checkable(\s|$)/.test(tables[i].className)) {
var trs = tables[i].getElementsByTagName('tr'); var trs = qsa('tr', tables[i]);
for (var j=0; j < trs.length; j++) { for (var j=0; j < trs.length; j++) {
trCheck(trs[j].firstChild.firstChild); trCheck(trs[j].firstChild.firstChild);
} }
@@ -149,7 +214,7 @@ function tableCheck() {
* @param string * @param string
*/ */
function formUncheck(id) { function formUncheck(id) {
var el = document.getElementById(id); var el = qs('#' + id);
el.checked = false; el.checked = false;
trCheck(el); trCheck(el);
} }
@@ -182,7 +247,7 @@ function tableClick(event, click) {
if (el.type != 'checkbox') { if (el.type != 'checkbox') {
return; return;
} }
checkboxClick(event, el); checkboxClick.call(el, event);
click = false; click = false;
} }
el = el.parentNode; el = el.parentNode;
@@ -201,25 +266,25 @@ function tableClick(event, click) {
var lastChecked; var lastChecked;
/** Shift-click on checkbox for multiple selection. /** Shift-click on checkbox for multiple selection.
* @param MouseEvent * @param MouseEvent
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function checkboxClick(event, el) { function checkboxClick(event) {
if (!el.name) { if (!this.name) {
return; return;
} }
if (event.shiftKey && (!lastChecked || lastChecked.name == el.name)) { if (event.shiftKey && (!lastChecked || lastChecked.name == this.name)) {
var checked = (lastChecked ? lastChecked.checked : true); var checked = (lastChecked ? lastChecked.checked : true);
var inputs = parentTag(el, 'table').getElementsByTagName('input'); var inputs = qsa('input', parentTag(this, 'table'));
var checking = !lastChecked; var checking = !lastChecked;
for (var i=0; i < inputs.length; i++) { for (var i=0; i < inputs.length; i++) {
var input = inputs[i]; var input = inputs[i];
if (input.name === el.name) { if (input.name === this.name) {
if (checking) { if (checking) {
input.checked = checked; input.checked = checked;
trCheck(input); trCheck(input);
} }
if (input === el || input === lastChecked) { if (input === this || input === lastChecked) {
if (checking) { if (checking) {
break; break;
} }
@@ -228,7 +293,7 @@ function checkboxClick(event, el) {
} }
} }
} else { } else {
lastChecked = el; lastChecked = this;
} }
} }
@@ -237,7 +302,7 @@ function checkboxClick(event, el) {
* @param string undefined to set parentNode to &nbsp; * @param string undefined to set parentNode to &nbsp;
*/ */
function setHtml(id, html) { function setHtml(id, html) {
var el = document.getElementById(id); var el = qs('#' + id);
if (el) { if (el) {
if (html == null) { if (html == null) {
el.parentNode.innerHTML = '&nbsp;'; el.parentNode.innerHTML = '&nbsp;';
@@ -262,52 +327,49 @@ function nodePosition(el) {
/** Go to the specified page /** Go to the specified page
* @param string * @param string
* @param string * @param string
* @param [MouseEvent]
*/ */
function pageClick(href, page, event) { function pageClick(href, page) {
if (!isNaN(page) && page) { if (!isNaN(page) && page) {
href += (page != 1 ? '&page=' + (page - 1) : ''); location.href = href + (page != 1 ? '&page=' + (page - 1) : '');
location.href = href;
} }
} }
/** Display items in menu /** Display items in menu
* @param HTMLElement
* @param MouseEvent * @param MouseEvent
* @this HTMLElement
*/ */
function menuOver(el, event) { function menuOver(event) {
var a = getTarget(event); var a = getTarget(event);
if (isTag(a, 'a|span') && a.offsetLeft + a.offsetWidth > a.parentNode.offsetWidth - 15) { // 15 - ellipsis if (isTag(a, 'a|span') && a.offsetLeft + a.offsetWidth > a.parentNode.offsetWidth - 15) { // 15 - ellipsis
el.style.overflow = 'visible'; this.style.overflow = 'visible';
} }
} }
/** Hide items in menu /** Hide items in menu
* @param HTMLElement * @this HTMLElement
*/ */
function menuOut(el) { function menuOut() {
el.style.overflow = 'auto'; this.style.overflow = 'auto';
} }
/** Add row in select fieldset /** Add row in select fieldset
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function selectAddRow(field) { function selectAddRow() {
field.onchange = function () { var field = this;
selectFieldChange(field.form);
};
field.onchange();
var row = cloneNode(field.parentNode); var row = cloneNode(field.parentNode);
var selects = row.getElementsByTagName('select'); field.onchange = selectFieldChange;
field.onchange();
var selects = qsa('select', row);
for (var i=0; i < selects.length; i++) { for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/[a-z]\[\d+/, '$&1'); selects[i].name = selects[i].name.replace(/[a-z]\[\d+/, '$&1');
selects[i].selectedIndex = 0; selects[i].selectedIndex = 0;
} }
var inputs = row.getElementsByTagName('input'); var inputs = qsa('input', row);
for (var i=0; i < inputs.length; i++) { for (var i=0; i < inputs.length; i++) {
inputs[i].name = inputs[i].name.replace(/[a-z]\[\d+/, '$&1'); inputs[i].name = inputs[i].name.replace(/[a-z]\[\d+/, '$&1');
inputs[i].className = ''; inputs[i].className = '';
@@ -321,33 +383,33 @@ function selectAddRow(field) {
} }
/** Prevent onsearch handler on Enter /** Prevent onsearch handler on Enter
* @param HTMLInputElement
* @param KeyboardEvent * @param KeyboardEvent
* @this HTMLInputElement
*/ */
function selectSearchKeydown(el, event) { function selectSearchKeydown(event) {
if (event.keyCode == 13 || event.keyCode == 10) { if (event.keyCode == 13 || event.keyCode == 10) {
el.onsearch = function () { this.onsearch = function () {
}; };
} }
} }
/** Clear column name after resetting search /** Clear column name after resetting search
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function selectSearchSearch(el) { function selectSearchSearch() {
if (!el.value) { if (!this.value) {
el.parentNode.firstChild.selectedIndex = 0; this.parentNode.firstChild.selectedIndex = 0;
} }
} }
/** Toggles column context menu /** Toggles column context menu
* @param HTMLElement * @param [string] extra class name
* @param [string] extra class name * @this HTMLElement
*/ */
function columnMouse(el, className) { function columnMouse(className) {
var spans = el.getElementsByTagName('span'); var spans = qsa('span', this);
for (var i=0; i < spans.length; i++) { for (var i=0; i < spans.length; i++) {
if (/column/.test(spans[i].className)) { if (/column/.test(spans[i].className)) {
spans[i].className = 'column' + (className || ''); spans[i].className = 'column' + (className || '');
@@ -358,12 +420,13 @@ function columnMouse(el, className) {
/** Fill column in search field /** Fill column in search field
* @param string * @param string
*/ * @return boolean false
*/
function selectSearch(name) { function selectSearch(name) {
var el = document.getElementById('fieldset-search'); var el = qs('#fieldset-search');
el.className = ''; el.className = '';
var divs = el.getElementsByTagName('div'); var divs = qsa('div', el);
for (var i=0; i < divs.length; i++) { for (var i=0; i < divs.length; i++) {
var div = divs[i]; var div = divs[i];
if (isTag(div.firstChild, 'select') && selectValue(div.firstChild) == name) { if (isTag(div.firstChild, 'select') && selectValue(div.firstChild) == name) {
@@ -375,6 +438,7 @@ function selectSearch(name) {
div.firstChild.onchange(); div.firstChild.onchange();
} }
div.lastChild.focus(); div.lastChild.focus();
return false;
} }
@@ -402,6 +466,7 @@ function getTarget(event) {
* @return boolean * @return boolean
*/ */
function bodyKeydown(event, button) { function bodyKeydown(event, button) {
eventStop(event);
var target = getTarget(event); var target = getTarget(event);
if (target.jushTextarea) { if (target.jushTextarea) {
target = target.jushTextarea; target = target.jushTextarea;
@@ -450,18 +515,17 @@ function editingKeydown(event) {
return false; return false;
} }
if (event.shiftKey && !bodyKeydown(event, 'insert')) { if (event.shiftKey && !bodyKeydown(event, 'insert')) {
eventStop(event);
return false; return false;
} }
return true; return true;
} }
/** Disable maxlength for functions /** Disable maxlength for functions
* @param HTMLSelectElement * @this HTMLSelectElement
*/ */
function functionChange(select) { function functionChange() {
var input = select.form[select.name.replace(/^function/, 'fields')]; var input = this.form[this.name.replace(/^function/, 'fields')];
if (selectValue(select)) { if (selectValue(this)) {
if (input.origType === undefined) { if (input.origType === undefined) {
input.origType = input.type; input.origType = input.type;
input.origMaxLength = input.getAttribute('data-maxlength'); input.origMaxLength = input.getAttribute('data-maxlength');
@@ -478,28 +542,29 @@ function functionChange(select) {
helpClose(); helpClose();
} }
/** Call this.onchange() if value changes /** Skip 'original' when typing
* @this HTMLInputElement * @param number
* @this HTMLTableCellElement
*/ */
function keyupChange() { function skipOriginal(first) {
if (this.value != this.getAttribute('value')) { var fnSelect = this.previousSibling.firstChild;
this.onchange(); if (fnSelect.selectedIndex < first) {
this.setAttribute('value', this.value); fnSelect.selectedIndex = first;
} }
} }
/** Add new field in schema-less edit /** Add new field in schema-less edit
* @param HTMLInputElement * @this HTMLInputElement
*/ */
function fieldChange(field) { function fieldChange() {
var row = cloneNode(parentTag(field, 'tr')); var row = cloneNode(parentTag(this, 'tr'));
var inputs = row.getElementsByTagName('input'); var inputs = qsa('input', row);
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
inputs[i].value = ''; inputs[i].value = '';
} }
// keep value in <select> (function) // keep value in <select> (function)
parentTag(field, 'table').appendChild(row); parentTag(this, 'table').appendChild(row);
field.onchange = function () { }; this.oninput = function () { };
} }
@@ -514,7 +579,7 @@ function fieldChange(field) {
function ajax(url, callback, data, message) { function ajax(url, callback, data, message) {
var request = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false)); var request = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false));
if (request) { if (request) {
var ajaxStatus = document.getElementById('ajaxstatus'); var ajaxStatus = qs('#ajaxstatus');
if (message) { if (message) {
ajaxStatus.innerHTML = '<div class="message">' + message + '</div>'; ajaxStatus.innerHTML = '<div class="message">' + message + '</div>';
ajaxStatus.className = ajaxStatus.className.replace(/ hidden/g, ''); ajaxStatus.className = ajaxStatus.className.replace(/ hidden/g, '');
@@ -543,11 +608,11 @@ function ajax(url, callback, data, message) {
/** Use setHtml(key, value) for JSON response /** Use setHtml(key, value) for JSON response
* @param string * @param string
* @return XMLHttpRequest or false in case of an error * @return boolean false for success
*/ */
function ajaxSetHtml(url) { function ajaxSetHtml(url) {
return ajax(url, function (request) { return !ajax(url, function (request) {
var data = eval('(' + request.responseText + ')'); var data = window.JSON ? JSON.parse(request.responseText) : eval('(' + request.responseText + ')');
for (var key in data) { for (var key in data) {
setHtml(key, data[key]); setHtml(key, data[key]);
} }
@@ -584,7 +649,7 @@ function ajaxForm(form, message, button) {
return ajax(url, function (request) { return ajax(url, function (request) {
setHtml('ajaxstatus', request.responseText); setHtml('ajaxstatus', request.responseText);
if (window.jush) { if (window.jush) {
jush.highlight_tag(document.getElementById('ajaxstatus').getElementsByTagName('code'), 0); jush.highlight_tag(qsa('code', qs('#ajaxstatus')), 0);
} }
}, data, message); }, data, message);
} }
@@ -592,12 +657,13 @@ function ajaxForm(form, message, button) {
/** Display edit field /** Display edit field
* @param HTMLElement
* @param MouseEvent * @param MouseEvent
* @param number display textarea instead of input, 2 - load long text * @param number display textarea instead of input, 2 - load long text
* @param string warning to display * @param string warning to display
* @this HTMLElement
*/ */
function selectClick(td, event, text, warning) { function selectClick(event, text, warning) {
var td = this;
var target = getTarget(event); var target = getTarget(event);
if (!isCtrl(event) || isTag(td.firstChild, 'input|textarea') || isTag(target, 'a')) { if (!isCtrl(event) || isTag(td.firstChild, 'input|textarea') || isTag(target, 'a')) {
return; return;
@@ -627,7 +693,7 @@ function selectClick(td, event, text, warning) {
}); });
input.rows = rows; input.rows = rows;
} }
if (value == '\u00A0' || td.getElementsByTagName('i').length) { // &nbsp; or i - NULL if (value == '\u00A0' || qsa('i', td).length) { // &nbsp; or i - NULL
value = ''; value = '';
} }
if (document.selection) { if (document.selection) {
@@ -664,21 +730,22 @@ function selectClick(td, event, text, warning) {
/** Load and display next page in select /** Load and display next page in select
* @param HTMLLinkElement
* @param number * @param number
* @param string * @param string
* @return boolean * @return boolean false for success
* @this HTMLLinkElement
*/ */
function selectLoadMore(a, limit, loading) { function selectLoadMore(limit, loading) {
var a = this;
var title = a.innerHTML; var title = a.innerHTML;
var href = a.href; var href = a.href;
a.innerHTML = loading; a.innerHTML = loading;
if (href) { if (href) {
a.removeAttribute('href'); a.removeAttribute('href');
return ajax(href, function (request) { return !ajax(href, function (request) {
var tbody = document.createElement('tbody'); var tbody = document.createElement('tbody');
tbody.innerHTML = request.responseText; tbody.innerHTML = request.responseText;
document.getElementById('table').appendChild(tbody); qs('#table').appendChild(tbody);
if (tbody.children.length < limit) { if (tbody.children.length < limit) {
a.parentNode.removeChild(a); a.parentNode.removeChild(a);
} else { } else {
@@ -711,7 +778,7 @@ function eventStop(event) {
*/ */
function setupSubmitHighlight(parent) { function setupSubmitHighlight(parent) {
for (var key in { input: 1, select: 1, textarea: 1 }) { for (var key in { input: 1, select: 1, textarea: 1 }) {
var inputs = parent.getElementsByTagName(key); var inputs = qsa(key, parent);
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
setupSubmitHighlightInput(inputs[i]) setupSubmitHighlightInput(inputs[i])
} }
@@ -756,7 +823,7 @@ function findDefaultSubmit(el) {
if (el.jushTextarea) { if (el.jushTextarea) {
el = el.jushTextarea; el = el.jushTextarea;
} }
var inputs = el.form.getElementsByTagName('input'); var inputs = qsa('input', el.form);
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
var input = inputs[i]; var input = inputs[i];
if (input.type == 'submit' && !input.style.zIndex) { if (input.type == 'submit' && !input.style.zIndex) {
@@ -795,6 +862,17 @@ function focus(el) {
*/ */
function cloneNode(el) { function cloneNode(el) {
var el2 = el.cloneNode(true); var el2 = el.cloneNode(true);
var selector = 'input, select';
var origEls = qsa(selector, el);
var cloneEls = qsa(selector, el2);
for (var i=0; i < origEls.length; i++) {
var origEl = origEls[i];
for (var key in origEl) {
if (/^on/.test(key) && origEl[key]) {
cloneEls[i][key] = origEl[key];
}
}
}
setupSubmitHighlight(el2); setupSubmitHighlight(el2);
return el2; return el2;
} }

View File

@@ -40,10 +40,10 @@ page_header(($name != "" ? lang('Alter trigger') . ": " . h($name) : lang('Creat
<tr><th><?php echo lang('Type'); ?><td><?php echo html_select("Type", $trigger_options["Type"], $row["Type"]); ?> <tr><th><?php echo lang('Type'); ?><td><?php echo html_select("Type", $trigger_options["Type"], $row["Type"]); ?>
</table> </table>
<p><?php echo lang('Name'); ?>: <input name="Trigger" value="<?php echo h($row["Trigger"]); ?>" maxlength="64" autocapitalize="off"> <p><?php echo lang('Name'); ?>: <input name="Trigger" value="<?php echo h($row["Trigger"]); ?>" maxlength="64" autocapitalize="off">
<script type="text/javascript">document.getElementById('form')['Timing'].onchange();</script> <?php echo script("qs('#form')['Timing'].onchange();"); ?>
<p><?php textarea("Statement", $row["Statement"]); ?> <p><?php textarea("Statement", $row["Statement"]); ?>
<p> <p>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
</form> </form>

View File

@@ -22,7 +22,7 @@ if (!$row) {
<p> <p>
<?php <?php
if ($TYPE != "") { if ($TYPE != "") {
echo "<input type='submit' name='drop' value='" . lang('Drop') . "'" . confirm() . ">\n"; echo "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . confirm() . "\n";
} else { } else {
echo "<input name='name' value='" . h($row['name']) . "' autocapitalize='off'>\n"; echo "<input name='name' value='" . h($row['name']) . "' autocapitalize='off'>\n";
textarea("as", $row["as"]); textarea("as", $row["as"]);

View File

@@ -135,7 +135,7 @@ if ($_POST) {
<tr><th><?php echo lang('Server'); ?><td><input name="host" maxlength="60" value="<?php echo h($row["host"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Server'); ?><td><input name="host" maxlength="60" value="<?php echo h($row["host"]); ?>" autocapitalize="off">
<tr><th><?php echo lang('Username'); ?><td><input name="user" maxlength="16" value="<?php echo h($row["user"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Username'); ?><td><input name="user" maxlength="16" value="<?php echo h($row["user"]); ?>" autocapitalize="off">
<tr><th><?php echo lang('Password'); ?><td><input name="pass" id="pass" value="<?php echo h($row["pass"]); ?>"> <tr><th><?php echo lang('Password'); ?><td><input name="pass" id="pass" value="<?php echo h($row["pass"]); ?>">
<?php if (!$row["hashed"]) { ?><script type="text/javascript">typePassword(document.getElementById('pass'));</script><?php } ?> <?php if (!$row["hashed"]) { echo script("typePassword(qs('#pass'));"); } ?>
<?php echo checkbox("hashed", 1, $row["hashed"], lang('Hashed'), "typePassword(this.form['pass'], this.checked);"); ?> <?php echo checkbox("hashed", 1, $row["hashed"], lang('Hashed'), "typePassword(this.form['pass'], this.checked);"); ?>
</table> </table>
@@ -169,7 +169,11 @@ foreach (array(
} elseif (isset($_GET["grant"])) { } elseif (isset($_GET["grant"])) {
echo "<td><select name=$name><option><option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</select>"; echo "<td><select name=$name><option><option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</select>";
} else { } else {
echo "<td align='center'><label class='block'><input type='checkbox' name=$name value='1'" . ($value ? " checked" : "") . ($privilege == "All privileges" ? " id='grants-$i-all'" : ($privilege == "Grant option" ? "" : " onclick=\"if (this.checked) formUncheck('grants-$i-all');\"")) . "></label>"; //! uncheck all except grant if all is checked echo "<td align='center'><label class='block'>";
echo "<input type='checkbox' name=$name value='1'" . ($value ? " checked" : "") . ($privilege == "All privileges"
? " id='grants-$i-all'>" //! uncheck all except grant if all is checked
: ">" . ($privilege == "Grant option" ? "" : script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };")));
echo "</label>";
} }
$i++; $i++;
} }
@@ -180,6 +184,6 @@ echo "</table>\n";
?> ?>
<p> <p>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php if (isset($_GET["host"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if (isset($_GET["host"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
</form> </form>

View File

@@ -53,6 +53,6 @@ page_header(($TABLE != "" ? lang('Alter view') : lang('Create view')), $error, a
<p><?php textarea("select", $row["select"]); ?> <p><?php textarea("select", $row["select"]); ?>
<p> <p>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($_GET["view"] != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo confirm(); ?>><?php } ?> <?php if ($_GET["view"] != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(); ?><?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
</form> </form>

View File

@@ -1,3 +1,27 @@
Adminer 4.4.0 (released 2018-01-17):
Add Content Security Policy
Disallow scripts without nonce
Rate limit password-less login attempts from the same IP address
Disallow connecting to privileged ports
Add nosniff header
PHP 7.1: Prevent warning when using empty limit
PHP 7.2: Prevent warning when searching in select
MySQL: Remove dedicated view for replication status (added in 4.3.0)
PostgreSQL: Sort table names (regression from 4.3.1)
Editor: Don't set time zone from PHP, fixes DST
Editor: Display field comment's text inside [] only in edit form
Editor: Fix doubleclick on database page
Editor: Fix Search data in tables
Customization: Always send security headers
Hebrew translation
Adminer 4.3.1 (released 2017-04-14):
Fix permanent login after logout (bug #539)
Fix SQL command autofocus (regression from 4.0.0)
PostgreSQL: Support JSON and JSONB data types
PostgreSQL: Fix index size computation in PostgreSQL < 9.0 (regression from 4.3.0)
PostgreSQL: Fix nullable fields in export
Adminer 4.3.0 (released 2017-03-15): Adminer 4.3.0 (released 2017-03-15):
Make maxlength in edit fields a soft limit Make maxlength in edit fields a soft limit
Add accessibility labels Add accessibility labels

View File

@@ -344,7 +344,7 @@ foreach (glob(dirname(__FILE__) . "/adminer/drivers/" . ($driver ? $driver : "*"
include dirname(__FILE__) . "/adminer/include/pdo.inc.php"; include dirname(__FILE__) . "/adminer/include/pdo.inc.php";
include dirname(__FILE__) . "/adminer/include/driver.inc.php"; include dirname(__FILE__) . "/adminer/include/driver.inc.php";
$features = array("call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "replication", "variables", "view"); $features = array("call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view");
$lang_ids = array(); // global variable simplifies usage in a callback function $lang_ids = array(); // global variable simplifies usage in a callback function
$file = file_get_contents(dirname(__FILE__) . "/$project/index.php"); $file = file_get_contents(dirname(__FILE__) . "/$project/index.php");
if ($driver) { if ($driver) {
@@ -393,17 +393,15 @@ if ($_SESSION["lang"]) {
$file = str_replace("<?php switch_lang(); ?>\n", "", $file); $file = str_replace("<?php switch_lang(); ?>\n", "", $file);
$file = str_replace('<?php echo $LANG; ?>', $_SESSION["lang"], $file); $file = str_replace('<?php echo $LANG; ?>', $_SESSION["lang"], $file);
} }
$file = str_replace('<script type="text/javascript" src="static/editing.js"></script>' . "\n", "", $file); $file = str_replace('<?php echo script_src("static/editing.js"); ?>' . "\n", "", $file);
$file = str_replace('<script type="text/javascript" src="../externals/jush/modules/jush-textarea.js"></script>' . "\n", "", $file); $file = preg_replace('~\\s+echo script_src\\("\\.\\./externals/jush/modules/jush-(textarea|txt|js|\\$jush)\\.js"\\);~', '', $file);
$file = str_replace('<script type="text/javascript" src="../externals/jush/modules/jush-txt.js"></script>' . "\n", "", $file);
$file = str_replace('<script type="text/javascript" src="../externals/jush/modules/jush-js.js"></script>' . "\n", "", $file);
$file = str_replace('<script type="text/javascript" src="../externals/jush/modules/jush-<?php echo $jush; ?>.js"></script>' . "\n", "", $file);
$file = str_replace('<link rel="stylesheet" type="text/css" href="../externals/jush/jush.css">' . "\n", "", $file); $file = str_replace('<link rel="stylesheet" type="text/css" href="../externals/jush/jush.css">' . "\n", "", $file);
$file = preg_replace_callback("~compile_file\\('([^']+)'(?:, '([^']*)')?\\)~", 'compile_file', $file); // integrate static files $file = preg_replace_callback("~compile_file\\('([^']+)'(?:, '([^']*)')?\\)~", 'compile_file', $file); // integrate static files
$replace = 'h(preg_replace("~\\\\\\\\?.*~", "", ME)) . "?file=\\1&amp;version=' . $VERSION . ($driver ? '&amp;driver=' . $driver : ''); $replace = 'preg_replace("~\\\\\\\\?.*~", "", ME) . "?file=\\1&version=' . $VERSION . ($driver ? '&driver=' . $driver : '') . '"';
$file = preg_replace('~\\.\\./adminer/static/(default\\.css|functions\\.js|favicon\\.ico)~', '<?php echo ' . $replace . '"; ?>', $file); $file = preg_replace('~\\.\\./adminer/static/(default\\.css|favicon\\.ico)~', '<?php echo h(' . $replace . '); ?>', $file);
$file = preg_replace('~\\.\\./adminer/static/([^\'"]*)~', '" . ' . $replace, $file); $file = preg_replace('~"\\.\\./adminer/static/(functions\\.js)"~', $replace, $file);
$file = preg_replace('~\\.\\./externals/jush/modules/(jush\\.js)~', '<?php echo ' . $replace . '"; ?>', $file); $file = preg_replace('~\\.\\./adminer/static/([^\'"]*)~', '" . h(' . $replace . ') . "', $file);
$file = preg_replace('~"\\.\\./externals/jush/modules/(jush\\.js)"~', $replace, $file);
$file = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $file); $file = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $file);
$file = php_shrink($file); $file = php_shrink($file);

View File

@@ -3,7 +3,8 @@
* *
* Klemens Häckel [http://clickdimension.wordpress.com/] * Klemens Häckel [http://clickdimension.wordpress.com/]
* *
* update 2014-01 * update 2017-03
* adapted for adminer 4.3.0
* *
* new remaster based on style for WT-NMP 13.12 * new remaster based on style for WT-NMP 13.12
* *
@@ -77,7 +78,7 @@ html>/**/body input[name="logout"], #logout {
right: 8px; right: 8px;
text-indent: 8px; text-indent: 8px;
top: 6px; top: 6px;
width: 80px; width: 120px;
position:fixed; position:fixed;
z-index: 10; z-index: 10;
} }
@@ -154,10 +155,10 @@ html>/**/body form>table a[href*="&edit="][href*="&where"] {
} }
/* Select data */ /* Select data */
html>/**/body #tables li a[href*="&select="], html>/**/body .links a[href*="&select="] { html>/**/body #menu li a[href*="&select="], html>/**/body .links a[href*="&select="] {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdVJREFUeNqck8tO21AQhn8bB8ehRe0SUEBOlIsSVFGqqlK3oey6K+9A96wTKU/RFU/AG7CrKhAg7gmKiJKIplFWqItWIQEfuzOT2LmsSo408j+2/5lvjo+1rULhM4AFTLfahuu6i3vF4rdp3F/y+W3DVUrzKNk8BTzPC4IKS3h8Hc0Hz49zr8BeXSml8wu8PsU1uW7EhjpHOmd7wX1fs4e9hnIcTUkBDfs1DzGjS5N1pPOGRR3bLjR6ztoNNJm9ebDXcBxnjMD99YCdzGvJT25v8T6ZFH1QLuNjNiv6++UlESyDvSMEEIKcCZzX6zLvXDiMo0pFZn5hWfhxfS2aF3sCAkUvDwmA1ZUVyS9qNawnEn0aKvQhkxF9WCqBPUIgBSYISnd3QmCZJs6qVekaYZqbmzGCfoGnp2AEnyAdjUpeajTwJh4XfU778S6d7tNQISlA3rFN9AkqzaYQmLOzuKIxuGuYaE4H++F/RvbqVEVXE+cgsbSEFFH0Hh+RtW2sxmLo9npYoy/yNpUajkBeo9ftzkwSVFstIeBVpjH8rhc0xigBe43f9/dmKBTCburv4ISb//VvsYe9mmXbX/VIZHman8ntdH7y0BbFSwrjmX6H4s8/AQYAQChL+KIinhAAAAAASUVORK5CYII=") no-repeat left bottom background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdVJREFUeNqck8tO21AQhn8bB8ehRe0SUEBOlIsSVFGqqlK3oey6K+9A96wTKU/RFU/AG7CrKhAg7gmKiJKIplFWqItWIQEfuzOT2LmsSo408j+2/5lvjo+1rULhM4AFTLfahuu6i3vF4rdp3F/y+W3DVUrzKNk8BTzPC4IKS3h8Hc0Hz49zr8BeXSml8wu8PsU1uW7EhjpHOmd7wX1fs4e9hnIcTUkBDfs1DzGjS5N1pPOGRR3bLjR6ztoNNJm9ebDXcBxnjMD99YCdzGvJT25v8T6ZFH1QLuNjNiv6++UlESyDvSMEEIKcCZzX6zLvXDiMo0pFZn5hWfhxfS2aF3sCAkUvDwmA1ZUVyS9qNawnEn0aKvQhkxF9WCqBPUIgBSYISnd3QmCZJs6qVekaYZqbmzGCfoGnp2AEnyAdjUpeajTwJh4XfU778S6d7tNQISlA3rFN9AkqzaYQmLOzuKIxuGuYaE4H++F/RvbqVEVXE+cgsbSEFFH0Hh+RtW2sxmLo9npYoy/yNpUajkBeo9ftzkwSVFstIeBVpjH8rhc0xigBe43f9/dmKBTCburv4ISb//VvsYe9mmXbX/VIZHman8ntdH7y0BbFSwrjmX6H4s8/AQYAQChL+KIinhAAAAAASUVORK5CYII=") no-repeat left bottom
} }
html>/**/body #tables li a[href*="&select="] { html>/**/body #menu li a[href*="&select="] {
clear: left; clear: left;
display: block; display: block;
float: left; float: left;
@@ -305,8 +306,12 @@ a, a:visited {
box-shadow: 0px 0px 3px rgba(0,0,0,0.30) !important; box-shadow: 0px 0px 3px rgba(0,0,0,0.30) !important;
margin: 0; margin: 0;
padding-bottom: 0; padding-bottom: 0;
padding-top: 30px;
top: 0; top: 0;
} }
#menu > h1:first-child {
margin-top: -30px;
}
/*** Forms ***/ /*** Forms ***/
fieldset { fieldset {
border-radius: 1px !important border-radius: 1px !important
@@ -316,7 +321,7 @@ fieldset {
background: transparent; background: transparent;
font-size: .9em; font-size: .9em;
left: auto; left: auto;
right: 90px; right: 120px;
position:fixed; position:fixed;
z-index: 10; z-index: 10;
padding-top: 2px; padding-top: 2px;
@@ -333,10 +338,6 @@ p {
margin: 0.8em 0 0 0 margin: 0.8em 0 0 0
} }
#menu form {
padding-top: 30px;
}
.view { .view {
background-color: #FFFFAA !important; background-color: #FFFFAA !important;
} }

View File

@@ -29,8 +29,8 @@ html/*\*/>/*/*/body a[href$="dump="] {background:url("data:image/png;base64,iVBO
html/*\*/>/*/*/body select[name="db"] {background:white url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC") no-repeat scroll left bottom; padding-left:16px;} html/*\*/>/*/*/body select[name="db"] {background:white url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEYSURBVBgZBcHPio5hGAfg6/2+R980k6wmJgsJ5U/ZOAqbSc2GnXOwUg7BESgLUeIQ1GSjLFnMwsKGGg1qxJRmPM97/1zXFAAAAEADdlfZzr26miup2svnelq7d2aYgt3rebl585wN6+K3I1/9fJe7O/uIePP2SypJkiRJ0vMhr55FLCA3zgIAOK9uQ4MS361ZOSX+OrTvkgINSjS/HIvhjxNNFGgQsbSmabohKDNoUGLohsls6BaiQIMSs2FYmnXdUsygQYmumy3Nhi6igwalDEOJEjPKP7CA2aFNK8Bkyy3fdNCg7r9/fW3jgpVJbDmy5+PB2IYp4MXFelQ7izPrhkPHB+P5/PjhD5gCgCenx+VR/dODEwD+A3T7nqbxwf1HAAAAAElFTkSuQmCC") no-repeat scroll left bottom; padding-left:16px;}
html/*\*/>/*/*/body select[name="db"] option {padding-left:18px;} html/*\*/>/*/*/body select[name="db"] option {padding-left:18px;}
html/*\*/>/*/*/body a[href$="&create="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIpSURBVDjLpZNPSFRRFMZ/749/Kt3IqFTSRoSMmrGIYTTbpEJtjBCCok1Em9JVG1dRC8FFEES5aGFEgRRZWq1iLKKxBiNqLDcltQgmHR9hY6LOu+feFm+YGVsZXbh8nHO53/nud8+xjDH8z3IB7r5avGgMZ8XoBq01okFpjYhGtEGJLtmCKINo/XbgVFPUBdDG9PVEq0P/UvnSvdlwQYFoHQIY/3obpRVKFL5W+OIXUVThrL91AN+XihKCwIeTu85sqPryqsJXUvRARAMwkshsiKB7fw25UgKVJwA40V7H/cl5jh+oL+RGk/P0xIqxl11dr8AXjTYG14HRNxkcx+ZhMoNlg52/ND6VAWMoc6F5+2Zy/l9PMIDrWByL1jI+tcDRaN06BaXxbDqLUnq9AqPBteHpuwUcJ0AIcgBXH93h+/wEyyuLrPk5cmv7gNY8gdIYYyhz4PDeWuIpj85IsS2ujQ2zJAk6DkZpqGnixcwYyU+PifUOX7Eh6DoAx7aIpzwA4imPeMrj+bTH+88PaNkZQWwhsrULsXxie9oAzgcESgUe2NAZCeE6AXZGQhwKh/Cyc5RZVXQ39wFwoeMmjXVhgMqiB8awe0cVP36u0Fi/iW9zvwuzkF3+xUz6Nal0gv6uWww+O02lUwGwmv8FM3l55EtLTvQWXwm+EkRpfNEoUZRXHCE5PUFbuJ0nH4cot1wSH14C3LA2Os6x3m2DwDmgGlgChpLX0/1/AIu8MA7WsWBMAAAAAElFTkSuQmCC") no-repeat scroll left bottom; padding-left:22px;} html/*\*/>/*/*/body a[href$="&create="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIpSURBVDjLpZNPSFRRFMZ/749/Kt3IqFTSRoSMmrGIYTTbpEJtjBCCok1Em9JVG1dRC8FFEES5aGFEgRRZWq1iLKKxBiNqLDcltQgmHR9hY6LOu+feFm+YGVsZXbh8nHO53/nud8+xjDH8z3IB7r5avGgMZ8XoBq01okFpjYhGtEGJLtmCKINo/XbgVFPUBdDG9PVEq0P/UvnSvdlwQYFoHQIY/3obpRVKFL5W+OIXUVThrL91AN+XihKCwIeTu85sqPryqsJXUvRARAMwkshsiKB7fw25UgKVJwA40V7H/cl5jh+oL+RGk/P0xIqxl11dr8AXjTYG14HRNxkcx+ZhMoNlg52/ND6VAWMoc6F5+2Zy/l9PMIDrWByL1jI+tcDRaN06BaXxbDqLUnq9AqPBteHpuwUcJ0AIcgBXH93h+/wEyyuLrPk5cmv7gNY8gdIYYyhz4PDeWuIpj85IsS2ujQ2zJAk6DkZpqGnixcwYyU+PifUOX7Eh6DoAx7aIpzwA4imPeMrj+bTH+88PaNkZQWwhsrULsXxie9oAzgcESgUe2NAZCeE6AXZGQhwKh/Cyc5RZVXQ39wFwoeMmjXVhgMqiB8awe0cVP36u0Fi/iW9zvwuzkF3+xUz6Nal0gv6uWww+O02lUwGwmv8FM3l55EtLTvQWXwm+EkRpfNEoUZRXHCE5PUFbuJ0nH4cot1wSH14C3LA2Os6x3m2DwDmgGlgChpLX0/1/AIu8MA7WsWBMAAAAAElFTkSuQmCC") no-repeat scroll left bottom; padding-left:22px;}
html/*\*/>/*/*/body #tables a[href*="&select="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHISURBVDjLpVPNK0RRFP+9D98syMwUspHkm9I0YkFZWBFKkZ0s7a3Ewh+ilChK7FgoZCJFKYlYKB8zk2+Z5t0P577He29kQU7dd+6575zf+d1zztWklPiPmOozt/U4SThjXIoyIQS4AJjSXO0lGGlvcXAm6Vzsz4xUhm0AIeX4QLig+C+ZpxbOG1wGhGYHr1zMUmZGWRgs0ha3PE1nX/8mWmdgWTzLB+DUYbhm9FfZ35IEyrhXA3VXJfPbsV8B9LQUIeUHYJ8ASobag1jcucNgW8g9W4reYSDi2YnnZDoDiwCokDANct6NwTB0LEdj0HRA/wxa2SN25JNBEdWluUhZ366gqmAaGvrCAXKOozccTGPgt8+vn8GYSGcgyTYp3dpBnBg42nbQPRBTo5bTvqYkmxL6AQhNTWQGBXY3B7BxlEBXozcW64dxRKoKUZBju+P06gl5WaaviMJBM3TNDlbypemIZgHYOnlwASsCmW7nHADGnBoQ3c76YmweJ9BR5zFYjsbRHwm4tmJg6PhWA7pCXXk+bu7fURHKweXtq/sWaksz7SC/CCGFrwtyZ3r+rCnFRZ7qr1qc6mLZj4f9OEyPL8lVpbX/PucPv5QPKHB1TdEAAAAASUVORK5CYII=") no-repeat scroll left bottom; clear:left; display:block; float:left; height:16px; margin-right:8px; padding:1px 0 0 16px; overflow:hidden; width:0; text-decoration:none; } html/*\*/>/*/*/body #menu p a[href*="&select="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHISURBVDjLpVPNK0RRFP+9D98syMwUspHkm9I0YkFZWBFKkZ0s7a3Ewh+ilChK7FgoZCJFKYlYKB8zk2+Z5t0P577He29kQU7dd+6575zf+d1zztWklPiPmOozt/U4SThjXIoyIQS4AJjSXO0lGGlvcXAm6Vzsz4xUhm0AIeX4QLig+C+ZpxbOG1wGhGYHr1zMUmZGWRgs0ha3PE1nX/8mWmdgWTzLB+DUYbhm9FfZ35IEyrhXA3VXJfPbsV8B9LQUIeUHYJ8ASobag1jcucNgW8g9W4reYSDi2YnnZDoDiwCokDANct6NwTB0LEdj0HRA/wxa2SN25JNBEdWluUhZ366gqmAaGvrCAXKOozccTGPgt8+vn8GYSGcgyTYp3dpBnBg42nbQPRBTo5bTvqYkmxL6AQhNTWQGBXY3B7BxlEBXozcW64dxRKoKUZBju+P06gl5WaaviMJBM3TNDlbypemIZgHYOnlwASsCmW7nHADGnBoQ3c76YmweJ9BR5zFYjsbRHwm4tmJg6PhWA7pCXXk+bu7fURHKweXtq/sWaksz7SC/CCGFrwtyZ3r+rCnFRZ7qr1qc6mLZj4f9OEyPL8lVpbX/PucPv5QPKHB1TdEAAAAASUVORK5CYII=") no-repeat scroll left bottom; clear:left; display:block; float:left; height:16px; margin-right:8px; padding:1px 0 0 16px; overflow:hidden; width:0; text-decoration:none; }
html/*\*/>/*/*/body #tables a[href*="&table="], html/*\*/>/*/*/body #tables a[href*="&view="] {margin:0; line-height:18px; padding-bottom:1px; text-decoration:none;} html/*\*/>/*/*/body #menu p a[href*="&table="], html/*\*/>/*/*/body #menu p a[href*="&view="] {margin:0; line-height:18px; padding-bottom:1px; text-decoration:none;}
html/*\*/>/*/*/body #content p a[href*="&create="] {padding-left:22px;} html/*\*/>/*/*/body #content p a[href*="&create="] {padding-left:22px;}
html/*\*/>/*/*/body #content p a[href$="?database="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIkSURBVDjLpVNNiFJRFP7eU1E0KSLTMpAwYSxyaidDtChm0WYQ3NSutv2s2kwwm2igNgMtooUQEQhhA9GqhSDTQsZZFDbNDBgVg5bSw9J8rzFF33udc+HGg0ladOHj3nPe+b7zc99VbNvG/yy30yiVSl4SnCNcsixrivYEgY7WJu0faX9EKGUyGVNyFFkBkY/T+WkoFEpFIhEEAgH4/X7w916vB8Mw0Gg00G63y+S7mM1mm4LIAYxisbhSr9c5nT1pjUYju1qt2oVC4YnkqbIUMk6Ew+F/9hyNRkFJLuyaATmFoqZp8Pl88Hq98Hg8wtfv99HpdNBsNhGPx0XsRAG3241ut4vBYCDs8XgMXdcxHA7FN/b9VUD25HK5RAUczKC+hYgcNpNN05xcAQdLkqIoIlj6VFWdXIEUkAQGV8M2k2vaG3z6sYGfVR39XzsHlm/dX3h5d31xlwAHM5goBd5+LuO75z3OnU3jyP4EVrZeKGub2p309cP7VKcAQ2Znoiz3deMVTk1Nw1RNTB+ahamMkD45w7RrfwSYwFdFf6K4Quf6pmvwKHswl7wh7Jvnc4gfTPHR52zhcqVSeZZMJgOxWEyI8BC5CmOnh63WKtZbZczPPsa94hX4XCLJQHG+xnw+f5SEFghZmvhefgvcTqn2HN3gBmZSZ5CInMaHr1Wsvivjy3ZvSZn0nHO5XJDIxwgWDbW2vL10m9xXCUGCQXi49qA1/xvyq6BCh7yZeQAAAABJRU5ErkJggg==") no-repeat scroll 2px bottom; padding-left:22px;} html/*\*/>/*/*/body #content p a[href$="?database="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIkSURBVDjLpVNNiFJRFP7eU1E0KSLTMpAwYSxyaidDtChm0WYQ3NSutv2s2kwwm2igNgMtooUQEQhhA9GqhSDTQsZZFDbNDBgVg5bSw9J8rzFF33udc+HGg0ladOHj3nPe+b7zc99VbNvG/yy30yiVSl4SnCNcsixrivYEgY7WJu0faX9EKGUyGVNyFFkBkY/T+WkoFEpFIhEEAgH4/X7w916vB8Mw0Gg00G63y+S7mM1mm4LIAYxisbhSr9c5nT1pjUYju1qt2oVC4YnkqbIUMk6Ew+F/9hyNRkFJLuyaATmFoqZp8Pl88Hq98Hg8wtfv99HpdNBsNhGPx0XsRAG3241ut4vBYCDs8XgMXdcxHA7FN/b9VUD25HK5RAUczKC+hYgcNpNN05xcAQdLkqIoIlj6VFWdXIEUkAQGV8M2k2vaG3z6sYGfVR39XzsHlm/dX3h5d31xlwAHM5goBd5+LuO75z3OnU3jyP4EVrZeKGub2p309cP7VKcAQ2Znoiz3deMVTk1Nw1RNTB+ahamMkD45w7RrfwSYwFdFf6K4Quf6pmvwKHswl7wh7Jvnc4gfTPHR52zhcqVSeZZMJgOxWEyI8BC5CmOnh63WKtZbZczPPsa94hX4XCLJQHG+xnw+f5SEFghZmvhefgvcTqn2HN3gBmZSZ5CInMaHr1Wsvivjy3ZvSZn0nHO5XJDIxwgWDbW2vL10m9xXCUGCQXi49qA1/xvyq6BCh7yZeQAAAABJRU5ErkJggg==") no-repeat scroll 2px bottom; padding-left:22px;}
html/*\*/>/*/*/body #content a[href*="&database="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKRSURBVDjLhVNLTBNRFD3TTju1FCcBaxuaQEr94ydiZIHGpcFISBOi0YREZWHCVoyRxKUxxq0LXcACQyLsjO6KjSEiDfHDz0S0CLSxlFKd2g7MTDudGd+bMAQCxJucuXfuu+fcO/PeYwzDALVoNMqRuI3guq7rR4g/SEBC/Svxc8T3EUTD4bCGTcZQAUI+RvxLr9d70u/3o6KiAm63G3Qtn89DFEUkk0lks9lRkrvW3t6e2lCgRZFI5F0ikaDtjN1MVVVjYmLCGBoa6qccC7Z1kQafz4f/WSAQAGlyaXOOpQ+SNNUymQxcLhc4joPD4TBzkiRBEASkUimEQiGzdlcBlmWRy+WgKIr5Xi6XUSgUUCwWzTVN+IAzeOOde71orP0eAaOkbrDWf6Cw2+3mBLSYgny3KULXPOUY2BUB/hMd4IOn8XfhMGYjvU+2TECLLRLDMNA0zYw5JYa6Ghke/hyEn9/gZEqo3OuHp7qW3yJgESjoNPSdlb8gWCOCr29BMT0Ip5tBYnIWqlL6o8irzVsEaHcKSqQCen4cweok+FAblNRz2JxlODx1cEkzGWmVbTl7Z/jHhgCF1Z3GYjIKf+U8+ANhQn4Gm6OMUiGI9MhHg5Gl1sbu8UnKNc8B7Ui3ipxEcwvlpVFw6hz2N1xGabkXdqeBYqEOmfefEZWac4e6xz9Z22hbn+BmLBZbi8fjEBdG4NF/QdUDSM88hQ4FawKJR6cxLDZl86qzZdtdoDYwMBAkQg/2LL/ovNLVh++Dd7G0OAau9hTkrKgnnE39GW3f/Z6enpUdBSx7ePu4eq+zi4VNw+TbV0gsxFd5b9X5i4+mpnY63tsErl6okhvrfWzT0SAMR3FMXsnean08Pb/b/fgHqpjCspi90kkAAAAASUVORK5CYII=") no-repeat scroll 2px bottom; padding-left:22px;} html/*\*/>/*/*/body #content a[href*="&database="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKRSURBVDjLhVNLTBNRFD3TTju1FCcBaxuaQEr94ydiZIHGpcFISBOi0YREZWHCVoyRxKUxxq0LXcACQyLsjO6KjSEiDfHDz0S0CLSxlFKd2g7MTDudGd+bMAQCxJucuXfuu+fcO/PeYwzDALVoNMqRuI3guq7rR4g/SEBC/Svxc8T3EUTD4bCGTcZQAUI+RvxLr9d70u/3o6KiAm63G3Qtn89DFEUkk0lks9lRkrvW3t6e2lCgRZFI5F0ikaDtjN1MVVVjYmLCGBoa6qccC7Z1kQafz4f/WSAQAGlyaXOOpQ+SNNUymQxcLhc4joPD4TBzkiRBEASkUimEQiGzdlcBlmWRy+WgKIr5Xi6XUSgUUCwWzTVN+IAzeOOde71orP0eAaOkbrDWf6Cw2+3mBLSYgny3KULXPOUY2BUB/hMd4IOn8XfhMGYjvU+2TECLLRLDMNA0zYw5JYa6Ghke/hyEn9/gZEqo3OuHp7qW3yJgESjoNPSdlb8gWCOCr29BMT0Ip5tBYnIWqlL6o8irzVsEaHcKSqQCen4cweok+FAblNRz2JxlODx1cEkzGWmVbTl7Z/jHhgCF1Z3GYjIKf+U8+ANhQn4Gm6OMUiGI9MhHg5Gl1sbu8UnKNc8B7Ui3ipxEcwvlpVFw6hz2N1xGabkXdqeBYqEOmfefEZWac4e6xz9Z22hbn+BmLBZbi8fjEBdG4NF/QdUDSM88hQ4FawKJR6cxLDZl86qzZdtdoDYwMBAkQg/2LL/ovNLVh++Dd7G0OAau9hTkrKgnnE39GW3f/Z6enpUdBSx7ePu4eq+zi4VNw+TbV0gsxFd5b9X5i4+mpnY63tsErl6okhvrfWzT0SAMR3FMXsnean08Pb/b/fgHqpjCspi90kkAAAAASUVORK5CYII=") no-repeat scroll 2px bottom; padding-left:22px;}
@@ -46,7 +46,7 @@ html/*\*/>/*/*/body input[name="delete"], html/*\*/>/*/*/body input[name="drop"]
html/*\*/>/*/*/body input[name="delete"]:hover, html/*\*/>/*/*/body input[name="drop"]:hover {color:red; background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJdSURBVDjLpZP7S1NhGMf9W7YfogSJboSEUVCY8zJ31trcps6zTI9bLGJpjp1hmkGNxVz4Q6ildtXKXzJNbJRaRmrXoeWx8tJOTWptnrNryre5YCYuI3rh+8vL+/m8PA/PkwIg5X+y5mJWrxfOUBXm91QZM6UluUmthntHqplxUml2lciF6wrmdHriI0Wx3xw2hAediLwZRWRkCPzdDswaSvGqkGCfq8VEUsEyPF1O8Qu3O7A09RbRvjuIttsRbT6HHzebsDjcB4/JgFFlNv9MnkmsEszodIIY7Oaut2OJcSF68Qx8dgv8tmqEL1gQaaARtp5A+N4NzB0lMXxon/uxbI8gIYjB9HytGYuusfiPIQcN71kjgnW6VeFOkgh3XcHLvAwMSDPohOADdYQJdF1FtLMZPmslvhZJk2ahkgRvq4HHUoWHRDqTEDDl2mDkfheiDgt8pw340/EocuClCuFvboQzb0cwIZgki4KhzlaE6w0InipbVzBfqoK/qRH94i0rgokSFeO11iBkp8EdV8cfJo0yD75aE2ZNRvSJ0lZKcBXLaUYmQrCzDT6tDN5SyRqYlWeDLZAg0H4JQ+Jt6M3atNLE10VSwQsN4Z6r0CBwqzXesHmV+BeoyAUri8EyMfi2FowXS5dhd7doo2DVII0V5BAjigP89GEVAtda8b2ehodU4rNaAW+dGfzlFkyo89GTlcrHYCLpKD+V7yeeHNzLjkp24Uu1Ed6G8/F8qjqGRzlbl2H2dzjpMg1KdwsHxOlmJ7GTeZC/nesXbeZ6c9OYnuxUc3fmBuFft/Ff8xMd0s65SXIb/gAAAABJRU5ErkJggg==")} html/*\*/>/*/*/body input[name="delete"]:hover, html/*\*/>/*/*/body input[name="drop"]:hover {color:red; background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJdSURBVDjLpZP7S1NhGMf9W7YfogSJboSEUVCY8zJ31trcps6zTI9bLGJpjp1hmkGNxVz4Q6ildtXKXzJNbJRaRmrXoeWx8tJOTWptnrNryre5YCYuI3rh+8vL+/m8PA/PkwIg5X+y5mJWrxfOUBXm91QZM6UluUmthntHqplxUml2lciF6wrmdHriI0Wx3xw2hAediLwZRWRkCPzdDswaSvGqkGCfq8VEUsEyPF1O8Qu3O7A09RbRvjuIttsRbT6HHzebsDjcB4/JgFFlNv9MnkmsEszodIIY7Oaut2OJcSF68Qx8dgv8tmqEL1gQaaARtp5A+N4NzB0lMXxon/uxbI8gIYjB9HytGYuusfiPIQcN71kjgnW6VeFOkgh3XcHLvAwMSDPohOADdYQJdF1FtLMZPmslvhZJk2ahkgRvq4HHUoWHRDqTEDDl2mDkfheiDgt8pw340/EocuClCuFvboQzb0cwIZgki4KhzlaE6w0InipbVzBfqoK/qRH94i0rgokSFeO11iBkp8EdV8cfJo0yD75aE2ZNRvSJ0lZKcBXLaUYmQrCzDT6tDN5SyRqYlWeDLZAg0H4JQ+Jt6M3atNLE10VSwQsN4Z6r0CBwqzXesHmV+BeoyAUri8EyMfi2FowXS5dhd7doo2DVII0V5BAjigP89GEVAtda8b2ehodU4rNaAW+dGfzlFkyo89GTlcrHYCLpKD+V7yeeHNzLjkp24Uu1Ed6G8/F8qjqGRzlbl2H2dzjpMg1KdwsHxOlmJ7GTeZC/nesXbeZ6c9OYnuxUc3fmBuFft/Ff8xMd0s65SXIb/gAAAABJRU5ErkJggg==")}
body{background-color:#eee} body{background-color:#eee}
form{margin:0;overflow:auto} form{margin:0;overflow:auto}
#breadcrumb{position:absolute;top:0;left:0;height:2.6em;margin:0;padding:5px 5px 0 22em;width:-moz-available!important;width:100%;line-height:1.6em;border:1px solid #444;white-space:nowrap;color:#fff;background:#7abcff;background:-moz-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#7abcff),color-stop(44%,#60abf8),color-stop(100%,#4096ee));background:-webkit-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:-o-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:-ms-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:linear-gradient(to bottom,#7abcff 0,#60abf8 44%,#4096ee 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#7abcff',endColorstr='#4096ee',GradientType=0)} #breadcrumb{position:absolute;top:0;left:0;height:2.6em;margin:0;padding:5px 5px 0 22em;width:-moz-available!important;width: -webkit-fill-available !important;width:100%;line-height:1.6em;border:1px solid #444;white-space:nowrap;color:#fff;background:#7abcff;background:-moz-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#7abcff),color-stop(44%,#60abf8),color-stop(100%,#4096ee));background:-webkit-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:-o-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:-ms-linear-gradient(top,#7abcff 0,#60abf8 44%,#4096ee 100%);background:linear-gradient(to bottom,#7abcff 0,#60abf8 44%,#4096ee 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#7abcff',endColorstr='#4096ee',GradientType=0)}
#menu,#content{background-color:#fff;border-radius:10px;border:1px solid #444;box-shadow:0 0 5px #999;margin:5em 1em 2em 0} #menu,#content{background-color:#fff;border-radius:10px;border:1px solid #444;box-shadow:0 0 5px #999;margin:5em 1em 2em 0}
#menu{position:absolute;top:0;left:0;margin-left:1em;padding:0 0 30px;width:19em} #menu{position:absolute;top:0;left:0;margin-left:1em;padding:0 0 30px;width:19em}
#content{border:1px solid #444;margin-left:21.5em;padding:10px 10px 30px 30px} #content{border:1px solid #444;margin-left:21.5em;padding:10px 10px 30px 30px}

View File

@@ -7,8 +7,13 @@ if ($adminer->homepage()) {
if ($_POST["query"] != "") { if ($_POST["query"] != "") {
search_tables(); search_tables();
} }
echo "<table cellspacing='0' class='nowrap checkable' onclick='tableClick(event);'>\n"; echo "<table cellspacing='0' class='nowrap checkable'>\n";
echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^tables\[/);" class="jsonly"><th>' . lang('Table') . '<td>' . lang('Rows') . "</thead>\n"; echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo '<thead><tr class="wrap">';
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("qs('#check-all').onclick = partial(formCheck, /^tables\[/);", "");
echo '<th>' . lang('Table');
echo '<td>' . lang('Rows');
echo "</thead>\n";
foreach (table_status() as $table => $row) { foreach (table_status() as $table => $row) {
$name = $adminer->tableName($row); $name = $adminer->tableName($row);
@@ -21,6 +26,6 @@ if ($adminer->homepage()) {
} }
echo "</table>\n"; echo "</table>\n";
echo "<script type='text/javascript'>tableCheck();</script>\n"; echo script("tableCheck();");
echo "</form>\n"; echo "</form>\n";
} }

View File

@@ -45,7 +45,10 @@ class Adminer {
} }
function headers() { function headers() {
return true; }
function csp() {
return csp();
} }
function head() { function head() {
@@ -58,17 +61,13 @@ class Adminer {
<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="auth[driver]" value="server"><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="auth[driver]" value="server"><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off">
<tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]"> <tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]">
</table> </table>
<script type="text/javascript">
focus(document.getElementById('username'));
</script>
<?php <?php
echo script("focus(qs('#username'));");
echo "<p><input type='submit' value='" . lang('Login') . "'>\n"; echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n"; echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
} }
function login($login, $password) { function login($login, $password) {
global $connection;
$connection->query("SET time_zone = " . q(substr_replace(@date("O"), ":", -2, 0))); // date("P") available since PHP 5.1.3, @ - requires date.timezone since PHP 5.3.0
return true; return true;
} }
@@ -77,7 +76,7 @@ focus(document.getElementById('username'));
} }
function fieldName($field, $order = 0) { function fieldName($field, $order = 0) {
return h($field["comment"] != "" ? $field["comment"] : $field["field"]); return h(preg_replace('~\s+\[.*\]$~', '', ($field["comment"] != "" ? $field["comment"] : $field["field"])));
} }
function selectLinks($tableStatus, $set = "") { function selectLinks($tableStatus, $set = "") {
@@ -244,13 +243,15 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
if (($val["col"] == "" || $columns[$val["col"]]) && "$val[col]$val[val]" != "") { if (($val["col"] == "" || $columns[$val["col"]]) && "$val[col]$val[val]" != "") {
echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>"; echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>";
echo html_select("where[$i][op]", array(-1 => "") + $this->operators, $val["op"]); echo html_select("where[$i][op]", array(-1 => "") + $this->operators, $val["op"]);
echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "' onkeydown='selectSearchKeydown(this, event);' onsearch='selectSearchSearch(this);'></div>\n"; echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>" . script("mixin(qsl('input'), {onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", "") . "</div>\n";
$i++; $i++;
} }
} }
echo "<div><select name='where[$i][col]' onchange='this.nextSibling.nextSibling.onchange();'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>"; echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
echo script("qsl('select').onchange = selectAddRow;", "");
echo html_select("where[$i][op]", array(-1 => "") + $this->operators); echo html_select("where[$i][op]", array(-1 => "") + $this->operators);
echo "<input type='search' name='where[$i][val]' onchange='selectAddRow(this);' onsearch='selectSearch(this);'></div>\n"; echo "<input type='search' name='where[$i][val]'></div>";
echo script("mixin(qsl('input'), {onchange: function () { this.parentNode.firstChild.onchange(); }, onsearch: selectSearchSearch});");
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -305,14 +306,15 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
function selectEmailPrint($emailFields, $columns) { function selectEmailPrint($emailFields, $columns) {
if ($emailFields) { if ($emailFields) {
print_fieldset("email", lang('E-mail'), $_POST["email_append"]); print_fieldset("email", lang('E-mail'), $_POST["email_append"]);
echo "<div onkeydown=\"eventStop(event); return bodyKeydown(event, 'email');\">\n"; echo "<div>";
echo script("qsl('div').onkeydown = partialArg(bodyKeydown, 'email');");
echo "<p>" . lang('From') . ": <input name='email_from' value='" . h($_POST ? $_POST["email_from"] : $_COOKIE["adminer_email"]) . "'>\n"; echo "<p>" . lang('From') . ": <input name='email_from' value='" . h($_POST ? $_POST["email_from"] : $_COOKIE["adminer_email"]) . "'>\n";
echo lang('Subject') . ": <input name='email_subject' value='" . h($_POST["email_subject"]) . "'>\n"; echo lang('Subject') . ": <input name='email_subject' value='" . h($_POST["email_subject"]) . "'>\n";
echo "<p><textarea name='email_message' rows='15' cols='75'>" . h($_POST["email_message"] . ($_POST["email_append"] ? '{$' . "$_POST[email_addition]}" : "")) . "</textarea>\n"; echo "<p><textarea name='email_message' rows='15' cols='75'>" . h($_POST["email_message"] . ($_POST["email_append"] ? '{$' . "$_POST[email_addition]}" : "")) . "</textarea>\n";
echo "<p onkeydown=\"eventStop(event); return bodyKeydown(event, 'email_append');\">" . html_select("email_addition", $columns, $_POST["email_addition"]) . "<input type='submit' name='email_append' value='" . lang('Insert') . "'>\n"; //! JavaScript echo "<p>" . script("qsl('p').onkeydown = partialArg(bodyKeydown, 'email_append');", "") . html_select("email_addition", $columns, $_POST["email_addition"]) . "<input type='submit' name='email_append' value='" . lang('Insert') . "'>\n"; //! JavaScript
echo "<p>" . lang('Attachments') . ": <input type='file' name='email_files[]' onchange=\"this.onchange = function () { }; var el = this.cloneNode(true); el.value = ''; this.parentNode.appendChild(el);\">"; echo "<p>" . lang('Attachments') . ": <input type='file' name='email_files[]'>" . script("qsl('input').onchange = emailFileChange;");
echo "<p>" . (count($emailFields) == 1 ? '<input type="hidden" name="email_field" value="' . h(key($emailFields)) . '">' : html_select("email_field", $emailFields)); echo "<p>" . (count($emailFields) == 1 ? '<input type="hidden" name="email_field" value="' . h(key($emailFields)) . '">' : html_select("email_field", $emailFields));
echo "<input type='submit' name='email' value='" . lang('Send') . "' onclick=\"return this.form['delete'].onclick();\">\n"; echo "<input type='submit' name='email' value='" . lang('Send') . "'>" . confirm();
echo "</div>\n"; echo "</div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -459,7 +461,11 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
if ($options !== null) { if ($options !== null) {
return (is_array($options) return (is_array($options)
? "<select$attrs>" . optionlist($options, $value, true) . "</select>" ? "<select$attrs>" . optionlist($options, $value, true) . "</select>"
: "<input value='" . h($value) . "'$attrs class='hidden'><input value='" . h($options) . "' class='jsonly' onkeyup=\"whisper('" . h(ME . "script=complete&source=" . urlencode($table) . "&field=" . urlencode($field["field"])) . "&value=', this);\"><div onclick='return whisperClick(event, this.previousSibling);'></div>" : "<input value='" . h($value) . "'$attrs class='hidden'>"
. "<input value='" . h($options) . "' class='jsonly'>"
. "<div></div>"
. script("qsl('input').oninput = partial(whisper, '" . ME . "script=complete&source=" . urlencode($table) . "&field=" . urlencode($field["field"]) . "&value=');
qsl('div').onclick = whisperClick;", "")
); );
} }
if (like_bool($field)) { if (like_bool($field)) {
@@ -481,6 +487,10 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
return ''; return '';
} }
function editHint($table, $field, $value) {
return (preg_match('~\s+(\[.*\])$~', ($field["comment"] != "" ? $field["comment"] : $field["field"]), $match) ? h(" $match[1]") : '');
}
function processInput($field, $value, $function = "") { function processInput($field, $value, $function = "") {
if ($function == "now") { if ($function == "now") {
return "$function()"; return "$function()";
@@ -557,7 +567,8 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
foreach ($servers[""] as $username => $password) { foreach ($servers[""] as $username => $password) {
if ($password !== null) { if ($password !== null) {
if ($first) { if ($first) {
echo "<p id='logins' onmouseover='menuOver(this, event);' onmouseout='menuOut(this);'>\n"; echo "<p id='logins'>";
echo script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");
$first = false; $first = false;
} }
echo "<a href='" . h(auth_url($vendor, "", $username)) . "'>" . ($username != "" ? h($username) : "<i>" . lang('empty') . "</i>") . "</a><br>\n"; echo "<a href='" . h(auth_url($vendor, "", $username)) . "'>" . ($username != "" ? h($username) : "<i>" . lang('empty') . "</i>") . "</a><br>\n";
@@ -581,7 +592,8 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
} }
function tablesPrint($tables) { function tablesPrint($tables) {
echo "<p id='tables' onmouseover='menuOver(this, event);' onmouseout='menuOut(this);'>\n"; echo "<p id='tables'>";
echo script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $row) { foreach ($tables as $row) {
$name = $this->tableName($row); $name = $this->tableName($row);
if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name

View File

@@ -3,8 +3,8 @@
* @link https://www.adminer.org/ * @link https://www.adminer.org/
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @copyright 2009 Jakub Vrana * @copyright 2009 Jakub Vrana
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
include "../adminer/include/bootstrap.inc.php"; include "../adminer/include/bootstrap.inc.php";

View File

@@ -1,5 +1,8 @@
// Editor specific functions // Editor specific functions
function messagesPrint() {
}
function selectFieldChange() { function selectFieldChange() {
} }
@@ -11,18 +14,12 @@ function helpMouseover() {
function helpMouseout() { function helpMouseout() {
} }
function whisperClick(event, field) { /** Display typeahead
var el = getTarget(event); * @param string
if (isTag(el, 'a') && !(event.button || event.shiftKey || event.altKey || isCtrl(event))) { * @this HTMLInputElement
field.value = el.firstChild.data; */
field.previousSibling.value = decodeURIComponent(el.href.replace(/.*=/, '')); function whisper(url) {
field.nextSibling.style.display = 'none'; var field = this;
return false;
}
}
function whisper(url, field) {
if (field.orig != field.value) { // ignore arrows, Shift, ...
field.orig = field.value; field.orig = field.value;
field.previousSibling.value = field.value; // accept number, reject string field.previousSibling.value = field.value; // accept number, reject string
return ajax(url + encodeURIComponent(field.value), function (xmlhttp) { return ajax(url + encodeURIComponent(field.value), function (xmlhttp) {
@@ -36,5 +33,30 @@ function whisper(url, field) {
} }
} }
}); });
}
/** Select typeahead value
* @param MouseEvent
* @return boolean false for success
* @this HTMLDivElement
*/
function whisperClick(event) {
var field = this.previousSibling;
var el = getTarget(event);
if (isTag(el, 'a') && !(event.button || event.shiftKey || event.altKey || isCtrl(event))) {
field.value = el.firstChild.data;
field.previousSibling.value = decodeURIComponent(el.href.replace(/.*=/, ''));
field.nextSibling.style.display = 'none';
return false;
} }
} }
/** Add new attachment field
* @this HTMLInputElement
*/
function emailFileChange() {
this.onchange = function () { };
var el = this.cloneNode(true);
el.value = '';
this.parentNode.appendChild(el);
}

2
externals/jush vendored

View File

@@ -3,8 +3,8 @@
/** Hide some databases from the interface - just to improve design, not a security plugin /** Hide some databases from the interface - just to improve design, not a security plugin
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDatabaseHide { class AdminerDatabaseHide {
protected $disabled; protected $disabled;

View File

@@ -3,8 +3,8 @@
/** Exports one database (e.g. development) so that it can be synced with other database (e.g. production) /** Exports one database (e.g. development) so that it can be synced with other database (e.g. production)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpAlter { class AdminerDumpAlter {

View File

@@ -4,8 +4,8 @@
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @uses bzopen(), tempnam("") * @uses bzopen(), tempnam("")
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpBz2 { class AdminerDumpBz2 {
/** @access protected */ /** @access protected */

View File

@@ -3,8 +3,8 @@
/** Include current date and time in export filename /** Include current date and time in export filename
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpDate { class AdminerDumpDate {

View File

@@ -3,8 +3,8 @@
/** Dump to JSON format /** Dump to JSON format
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpJson { class AdminerDumpJson {
/** @access protected */ /** @access protected */

View File

@@ -2,8 +2,8 @@
/** Dump to PHP format /** Dump to PHP format
* @author Martin Zeman (Zemistr), http://www.zemistr.eu/ * @author Martin Zeman (Zemistr), http://www.zemistr.eu/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpPhp { class AdminerDumpPhp {
var $output = array(); var $output = array();

View File

@@ -3,8 +3,8 @@
/** Dump to XML format in structure <database name=""><table name=""><column name="">value /** Dump to XML format in structure <database name=""><table name=""><column name="">value
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpXml { class AdminerDumpXml {
/** @access protected */ /** @access protected */

View File

@@ -4,8 +4,8 @@
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @uses ZipArchive, tempnam("") * @uses ZipArchive, tempnam("")
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerDumpZip { class AdminerDumpZip {
/** @access protected */ /** @access protected */

View File

@@ -5,8 +5,8 @@
* @uses jQuery-Timepicker, http://trentrichardson.com/examples/timepicker/ * @uses jQuery-Timepicker, http://trentrichardson.com/examples/timepicker/
* @uses jQuery UI: core, widget, mouse, slider, datepicker * @uses jQuery UI: core, widget, mouse, slider, datepicker
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerEditCalendar { class AdminerEditCalendar {
/** @access protected */ /** @access protected */
@@ -16,7 +16,14 @@ class AdminerEditCalendar {
* @param string text to append before first calendar usage * @param string text to append before first calendar usage
* @param string path to language file, %s stands for language code * @param string path to language file, %s stands for language code
*/ */
function __construct($prepend = "<script type='text/javascript' src='jquery-ui/jquery.js'></script>\n<script type='text/javascript' src='jquery-ui/jquery-ui.js'></script>\n<script type='text/javascript' src='jquery-ui/jquery-ui-timepicker-addon.js'></script>\n<link rel='stylesheet' type='text/css' href='jquery-ui/jquery-ui.css'>\n", $langPath = "jquery-ui/i18n/jquery.ui.datepicker-%s.js") { function __construct($prepend = null, $langPath = "jquery-ui/i18n/jquery.ui.datepicker-%s.js") {
if ($prepend === null) {
$prepend = "<link rel='stylesheet' type='text/css' href='jquery-ui/jquery-ui.css'>\n"
. script_src("jquery-ui/jquery.js")
. script_src("jquery-ui/jquery-ui.js")
. script_src("jquery-ui/jquery-ui-timepicker-addon.js")
;
}
$this->prepend = $prepend; $this->prepend = $prepend;
$this->langPath = $langPath; $this->langPath = $langPath;
} }
@@ -27,8 +34,8 @@ class AdminerEditCalendar {
$lang = get_lang(); $lang = get_lang();
$lang = ($lang == "zh" ? "zh-CN" : ($lang == "zh-tw" ? "zh-TW" : $lang)); $lang = ($lang == "zh" ? "zh-CN" : ($lang == "zh-tw" ? "zh-TW" : $lang));
if ($lang != "en" && file_exists(sprintf($this->langPath, $lang))) { if ($lang != "en" && file_exists(sprintf($this->langPath, $lang))) {
printf("<script type='text/javascript' src='$this->langPath'></script>\n", $lang); echo script_src(sprintf($this->langPath, $lang));
echo "<script type='text/javascript'>jQuery(function () { jQuery.timepicker.setDefaults(jQuery.datepicker.regional['$lang']); });</script>\n"; echo script("jQuery(function () { jQuery.timepicker.setDefaults(jQuery.datepicker.regional['$lang']); });");
} }
} }
} }
@@ -37,11 +44,12 @@ class AdminerEditCalendar {
if (preg_match("~date|time~", $field["type"])) { if (preg_match("~date|time~", $field["type"])) {
$dateFormat = "changeYear: true, dateFormat: 'yy-mm-dd'"; //! yy-mm-dd regional $dateFormat = "changeYear: true, dateFormat: 'yy-mm-dd'"; //! yy-mm-dd regional
$timeFormat = "showSecond: true, timeFormat: 'HH:mm:ss.lcZ', timeInput: true"; $timeFormat = "showSecond: true, timeFormat: 'HH:mm:ss.lcZ', timeInput: true";
return "<input id='fields-" . h($field["field"]) . "' value='" . h($value) . "'" . (@+$field["length"] ? " maxlength='" . (+$field["length"]) . "'" : "") . "$attrs><script type='text/javascript'>jQuery('#fields-" . js_escape($field["field"]) . "')." return "<input id='fields-" . h($field["field"]) . "' value='" . h($value) . "'" . (@+$field["length"] ? " maxlength='" . (+$field["length"]) . "'" : "") . "$attrs>" . script(
"jQuery('#fields-" . js_escape($field["field"]) . "')."
. ($field["type"] == "time" ? "timepicker({ $timeFormat })" . ($field["type"] == "time" ? "timepicker({ $timeFormat })"
: (preg_match("~time~", $field["type"]) ? "datetimepicker({ $dateFormat, $timeFormat })" : (preg_match("~time~", $field["type"]) ? "datetimepicker({ $dateFormat, $timeFormat })"
: "datepicker({ $dateFormat })" : "datepicker({ $dateFormat })"
)) . ";</script>"; )) . ";");
} }
} }

View File

@@ -3,8 +3,8 @@
/** Select foreign key in edit form /** Select foreign key in edit form
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerEditForeign { class AdminerEditForeign {
var $_limit; var $_limit;

View File

@@ -3,8 +3,8 @@
/** Use <textarea> for char and varchar /** Use <textarea> for char and varchar
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerEditTextarea { class AdminerEditTextarea {

View File

@@ -3,8 +3,8 @@
/** Get e-mail subject and message from database (Adminer Editor) /** Get e-mail subject and message from database (Adminer Editor)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerEmailTable { class AdminerEmailTable {
/** @access protected */ /** @access protected */
@@ -28,12 +28,19 @@ class AdminerEmailTable {
function selectEmailPrint($emailFields, $columns) { function selectEmailPrint($emailFields, $columns) {
if ($emailFields) { if ($emailFields) {
print_fieldset("email", ('E-mail')); print_fieldset("email", ('E-mail'));
echo "<div onkeydown=\"eventStop(event); return bodyKeydown(event, 'email');\">\n"; echo "<div>\n";
echo script("qsl('div').onkeydown = partial(bodyKeydown, 'email');");
echo "<p>" . ('From') . ": <input name='email_from' value='" . h($_POST ? $_POST["email_from"] : $_COOKIE["adminer_email"]) . "'>\n"; echo "<p>" . ('From') . ": <input name='email_from' value='" . h($_POST ? $_POST["email_from"] : $_COOKIE["adminer_email"]) . "'>\n";
echo ('Subject') . ": <select name='email_id'><option>" . optionlist(get_key_vals("SELECT $this->id, $this->title FROM $this->table ORDER BY $this->title"), $_POST["email_id"], true) . "</select>\n"; echo ('Subject') . ": <select name='email_id'><option>" . optionlist(get_key_vals("SELECT $this->id, $this->title FROM $this->table ORDER BY $this->title"), $_POST["email_id"], true) . "</select>\n";
echo "<p>" . ('Attachments') . ": <input type='file' name='email_files[]' onchange=\"this.onchange = function () { }; var el = this.cloneNode(true); el.value = ''; this.parentNode.appendChild(el);\">"; echo "<p>" . ('Attachments') . ": <input type='file' name='email_files[]'>";
echo script("qsl('input').onchange = function () {
this.onchange = function () { };
var el = this.cloneNode(true);
el.value = '';
this.parentNode.appendChild(el);
};");
echo "<p>" . (count($emailFields) == 1 ? '<input type="hidden" name="email_field" value="' . h(key($emailFields)) . '">' : html_select("email_field", $emailFields)); echo "<p>" . (count($emailFields) == 1 ? '<input type="hidden" name="email_field" value="' . h(key($emailFields)) . '">' : html_select("email_field", $emailFields));
echo "<input type='submit' name='email' value='" . ('Send') . "' onclick=\"return this.form['delete'].onclick();\">\n"; echo "<input type='submit' name='email' value='" . ('Send') . "'>" . confirm();
echo "</div>\n"; echo "</div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
return true; return true;

View File

@@ -3,8 +3,8 @@
/** Use <select><option> for enum edit instead of <input type="radio"> /** Use <select><option> for enum edit instead of <input type="radio">
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerEnumOption { class AdminerEnumOption {

View File

@@ -3,8 +3,8 @@
/** Use <select><option> for enum edit instead of regular input text on enum type in PostgreSQL /** Use <select><option> for enum edit instead of regular input text on enum type in PostgreSQL
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Adam Kuśmierz, http://kusmierz.be/ * @author Adam Kuśmierz, http://kusmierz.be/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerEnumTypes { class AdminerEnumTypes {
var $_types = null; var $_types = null;

View File

@@ -4,8 +4,8 @@
/** Edit fields ending with "_path" by <input type="file"> and link to the uploaded files from select /** Edit fields ending with "_path" by <input type="file"> and link to the uploaded files from select
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerFileUpload { class AdminerFileUpload {
/** @access protected */ /** @access protected */

View File

@@ -3,8 +3,8 @@
/** Link system tables (in mysql and information_schema databases) by foreign keys /** Link system tables (in mysql and information_schema databases) by foreign keys
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerForeignSystem { class AdminerForeignSystem {

View File

@@ -3,8 +3,8 @@
/** Allow using Adminer inside a frame (disables ClickJacking protection) /** Allow using Adminer inside a frame (disables ClickJacking protection)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerFrames { class AdminerFrames {
/** @access protected */ /** @access protected */
@@ -20,9 +20,9 @@ class AdminerFrames {
function headers() { function headers() {
if ($this->sameOrigin) { if ($this->sameOrigin) {
header("X-Frame-Options: SameOrigin"); header("X-Frame-Options: SameOrigin");
} elseif (function_exists('header_remove')) {
header_remove("X-Frame-Options");
} }
header("X-XSS-Protection: 0");
return false;
} }
} }

View File

@@ -4,8 +4,8 @@
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @author Martin Zeman (Zemistr), http://www.zemistr.eu/ * @author Martin Zeman (Zemistr), http://www.zemistr.eu/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerJsonColumn { class AdminerJsonColumn {
private function _testJson($value) { private function _testJson($value) {

View File

@@ -3,8 +3,8 @@
/** Avoid redirecting of external links through adminer.org and disclose the URL of installed Adminer to visited links /** Avoid redirecting of external links through adminer.org and disclose the URL of installed Adminer to visited links
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerLinksDirect { class AdminerLinksDirect {

View File

@@ -3,8 +3,8 @@
/** Display constant list of servers in login form /** Display constant list of servers in login form
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerLoginServers { class AdminerLoginServers {
/** @access protected */ /** @access protected */

View File

@@ -1,36 +1,29 @@
<?php <?php
/** Enable auto-login for SQLite /** Enable login for SQLite
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerLoginSqlite { class AdminerLoginSqlite {
/** @access protected */
var $login, $password_hash;
/** Set allowed credentials
* @param string
* @param string result of password_hash
*/
function __construct($login, $password_hash) {
$this->login = $login;
$this->password_hash = $password_hash;
}
function login($login, $password) { function login($login, $password) {
if (DRIVER != "sqlite" && DRIVER != "sqlite2") {
return true; return true;
} }
return $this->login == $login && password_verify($password, $this->password_hash);
function loginForm() {
?>
<script type="text/javascript">
addEventListener('load', function () {
var driver = document.getElementsByName('auth[driver]')[0];
if (isTag(driver, 'select')) {
driver.onchange = function () {
var trs = parentTag(driver, 'table').rows;
for (var i=1; i < trs.length - 1; i++) {
var disabled = /sqlite/.test(driver.value);
alterClass(trs[i], 'hidden', disabled);
trs[i].getElementsByTagName('input')[0].disabled = disabled;
}
};
}
driver.onchange();
});
</script>
<?php
} }
} }

View File

@@ -12,8 +12,8 @@ CREATE TABLE login (
/** Authenticate a user from the login table /** Authenticate a user from the login table
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerLoginTable { class AdminerLoginTable {
/** @access protected */ /** @access protected */

View File

@@ -3,8 +3,8 @@
/** Execute writes on master and reads on slave /** Execute writes on master and reads on slave
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerMasterSlave { class AdminerMasterSlave {
private $masters = array(); private $masters = array();

View File

@@ -3,8 +3,8 @@
/** Adminer customization allowing usage of plugins /** Adminer customization allowing usage of plugins
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerPlugin extends Adminer { class AdminerPlugin extends Adminer {
/** @access protected */ /** @access protected */
@@ -127,6 +127,11 @@ class AdminerPlugin extends Adminer {
return $this->_applyPlugin(__FUNCTION__, $args); return $this->_applyPlugin(__FUNCTION__, $args);
} }
function csp() {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
}
function head() { function head() {
$args = func_get_args(); $args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args); return $this->_applyPlugin(__FUNCTION__, $args);
@@ -307,6 +312,11 @@ class AdminerPlugin extends Adminer {
return $this->_applyPlugin(__FUNCTION__, $args); return $this->_applyPlugin(__FUNCTION__, $args);
} }
function editHint($table, $field, $value) {
$args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args);
}
function processInput($field, $value, $function = "") { function processInput($field, $value, $function = "") {
$args = func_get_args(); $args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args); return $this->_applyPlugin(__FUNCTION__, $args);

View File

@@ -3,8 +3,8 @@
/** Prefill field containing "_slug" with slugified value of a previous field (JavaScript) /** Prefill field containing "_slug" with slugified value of a previous field (JavaScript)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerSlugify { class AdminerSlugify {
/** @access protected */ /** @access protected */
@@ -34,7 +34,16 @@ class AdminerSlugify {
} }
$slug = $slugify[$field["field"]]; $slug = $slugify[$field["field"]];
if ($slug !== null) { if ($slug !== null) {
return "<input value='" . h($value) . "' maxlength='$field[length]' size='40'$attrs onchange=\"var find = '$this->from'; var repl = '$this->to'; this.form['fields[$slug]'].value = this.value.toLowerCase().replace(new RegExp('[' + find + ']', 'g'), function (str) { return repl[find.indexOf(str)]; }).replace(/[^a-z0-9_]+/g, '-').replace(/^-|-\$/g, '').substr(0, $field[length]);\">"; return "<input value='" . h($value) . "' maxlength='$field[length]' size='40'$attrs>"
. script("qsl('input').onchange = function () {
var find = '$this->from';
var repl = '$this->to';
this.form['fields[$slug]'].value = this.value.toLowerCase()
.replace(new RegExp('[' + find + ']', 'g'), function (str) { return repl[find.indexOf(str)]; })
.replace(/[^a-z0-9_]+/g, '-')
.replace(/^-|-\$/g, '')
.substr(0, $field[length]);
};");
} }
} }
} }

View File

@@ -3,8 +3,8 @@
/** Log all queries to SQL file (manual queries through SQL command are not logged) /** Log all queries to SQL file (manual queries through SQL command are not logged)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerSqlLog { class AdminerSqlLog {
/** @access protected */ /** @access protected */

View File

@@ -3,8 +3,8 @@
/** Show comments of sql structure in more places (mainly where you edit things) /** Show comments of sql structure in more places (mainly where you edit things)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Adam Kuśmierz, http://kusmierz.be/ * @author Adam Kuśmierz, http://kusmierz.be/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerStructComments { class AdminerStructComments {

View File

@@ -3,8 +3,8 @@
/** Expanded table indexes structure output /** Expanded table indexes structure output
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Matthew Gamble, https://www.matthewgamble.net/ * @author Matthew Gamble, https://www.matthewgamble.net/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerTableIndexesStructure { class AdminerTableIndexesStructure {

View File

@@ -3,8 +3,8 @@
/** Expanded table structure output /** Expanded table structure output
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Matthew Gamble, https://www.matthewgamble.net/ * @author Matthew Gamble, https://www.matthewgamble.net/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerTableStructure { class AdminerTableStructure {

View File

@@ -3,25 +3,33 @@
/** Use filter in tables list /** Use filter in tables list
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerTablesFilter { class AdminerTablesFilter {
function tablesPrint($tables) { ?> function tablesPrint($tables) { ?>
<p class="jsonly"><input id="filter-field" onkeyup="tablesFilterInput();" autocomplete="off"> <p class="jsonly"><input id="filter-field" autocomplete="off"><?php echo script("qs('#filter-field').oninput = tablesFilterInput;"); ?>
<p id='tables' onmouseover='menuOver(this, event);' onmouseout='menuOut(this);'> <ul id='tables'>
<?php <?php
foreach ($tables as $table => $type) { echo script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
echo '<span data-table-name="'.h($table).'"><a href="'.h(ME).'select='.urlencode($table).'"'.bold($_GET["select"] == $table).">".lang('select')."</a> "; foreach ($tables as $table => $status) {
echo '<a href="'.h(ME).'table='.urlencode($table).'"'.bold($_GET["table"] == $table).">".h($table)."</a><br></span>\n"; echo '<li data-table-name="' . h($table) . '"><a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table || $_GET["edit"] == $table, "select") . ">" . lang('select') . "</a> ";
$name = h($status["Name"]);
echo (support("table") || support("indexes")
? '<a href="' . h(ME) . 'table=' . urlencode($table) . '"'
. bold(in_array($table, array($_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"])), (is_view($status) ? "view" : "structure"))
. " title='" . lang('Show structure') . "'>$name</a>"
: "<span>$name</span>"
) . "\n";
} }
?> ?>
<script type="text/javascript"> </ul>
<script<?php echo nonce(); ?>>
var tablesFilterTimeout = null; var tablesFilterTimeout = null;
var tablesFilterValue = ''; var tablesFilterValue = '';
function tablesFilter(){ function tablesFilter(){
var value = document.getElementById('filter-field').value.toLowerCase(); var value = qs('#filter-field').value.toLowerCase();
if (value == tablesFilterValue) { if (value == tablesFilterValue) {
return; return;
} }
@@ -33,9 +41,9 @@ function tablesFilter(){
if (sessionStorage) { if (sessionStorage) {
sessionStorage.setItem('adminer_tables_filter', value); sessionStorage.setItem('adminer_tables_filter', value);
} }
var tables = document.getElementById('tables').getElementsByTagName('span'); var tables = qsa('li', qs('#tables'));
for (var i = 0; i < tables.length; i++) { for (var i = 0; i < tables.length; i++) {
var a = tables[i].getElementsByTagName('a')[1]; var a = qsa('a', tables[i])[1];
var text = tables[i].getAttribute('data-table-name'); var text = tables[i].getAttribute('data-table-name');
if (value == '') { if (value == '') {
tables[i].className = ''; tables[i].className = '';
@@ -53,10 +61,10 @@ function tablesFilterInput() {
} }
if (sessionStorage){ if (sessionStorage){
var db = document.getElementById('dbs').getElementsByTagName('select')[0]; var db = qs('#dbs').querySelector('select');
db = db.options[db.selectedIndex].text; db = db.options[db.selectedIndex].text;
if (db == sessionStorage.getItem('adminer_tables_filter_db') && sessionStorage.getItem('adminer_tables_filter')){ if (db == sessionStorage.getItem('adminer_tables_filter_db') && sessionStorage.getItem('adminer_tables_filter')){
document.getElementById('filter-field').value = sessionStorage.getItem('adminer_tables_filter'); qs('#filter-field').value = sessionStorage.getItem('adminer_tables_filter');
tablesFilter(); tablesFilter();
} }
sessionStorage.setItem('adminer_tables_filter_db', db); sessionStorage.setItem('adminer_tables_filter_db', db);

View File

@@ -4,8 +4,8 @@
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @uses TinyMCE, http://tinymce.moxiecode.com/ * @uses TinyMCE, http://tinymce.moxiecode.com/
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerTinymce { class AdminerTinymce {
/** @access protected */ /** @access protected */
@@ -27,9 +27,9 @@ class AdminerTinymce {
$lang = "en"; $lang = "en";
} }
} }
echo script_src($this->path);
?> ?>
<script type="text/javascript" src="<?php echo h($this->path); ?>"></script> <script<?php echo nonce(); ?>>
<script type="text/javascript">
tinyMCE.init({ tinyMCE.init({
mode: 'none', mode: 'none',
theme: 'advanced', theme: 'advanced',
@@ -68,15 +68,15 @@ tinyMCE.init({
function editInput($table, $field, $attrs, $value) { function editInput($table, $field, $attrs, $value) {
if (preg_match("~text~", $field["type"]) && preg_match("~_html~", $field["field"])) { if (preg_match("~text~", $field["type"]) && preg_match("~_html~", $field["field"])) {
return "<textarea$attrs id='fields-" . h($field["field"]) . "' rows='12' cols='50'>" . h($value) . "</textarea><script type='text/javascript'> return "<textarea$attrs id='fields-" . h($field["field"]) . "' rows='12' cols='50'>" . h($value) . "</textarea>" . script("
tinyMCE.remove(tinyMCE.get('fields-" . js_escape($field["field"]) . "') || { }); tinyMCE.remove(tinyMCE.get('fields-" . js_escape($field["field"]) . "') || { });
tinyMCE.execCommand('mceAddControl', true, 'fields-" . js_escape($field["field"]) . "'); tinyMCE.execCommand('mceAddControl', true, 'fields-" . js_escape($field["field"]) . "');
document.getElementById('form').onsubmit = function () { qs('#form').onsubmit = function () {
tinyMCE.each(tinyMCE.editors, function (ed) { tinyMCE.each(tinyMCE.editors, function (ed) {
ed.remove(); ed.remove();
}); });
}; };
</script>"; ");
} }
} }

View File

@@ -13,8 +13,8 @@ CREATE TABLE translation (
/** Translate all table and field comments, enum and set values from the translation table (inserts new translations) /** Translate all table and field comments, enum and set values from the translation table (inserts new translations)
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerTranslation { class AdminerTranslation {

View File

@@ -3,18 +3,13 @@
/** Disable version checker /** Disable version checker
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerVersionNoverify { class AdminerVersionNoverify {
function navigation($missing) { function navigation($missing) {
?> echo script("verifyVersion = function () {};");
<script type="text/javascript">
verifyVersion = function () {
};
</script>
<?php
} }
} }

View File

@@ -4,8 +4,8 @@
* @link https://www.adminer.org/plugins/#use * @link https://www.adminer.org/plugins/#use
* @uses WYMeditor, http://www.wymeditor.org/ * @uses WYMeditor, http://www.wymeditor.org/
* @author Jakub Vrana, https://www.vrana.cz/ * @author Jakub Vrana, https://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/ */
class AdminerWymeditor { class AdminerWymeditor {
/** @access protected */ /** @access protected */
@@ -22,7 +22,7 @@ class AdminerWymeditor {
function head() { function head() {
foreach ($this->scripts as $script) { foreach ($this->scripts as $script) {
echo "<script type='text/javascript' src='" . h($script) . "'></script>\n"; echo script_src($script);
} }
} }
@@ -55,9 +55,9 @@ class AdminerWymeditor {
$lang = get_lang(); $lang = get_lang();
$lang = ($lang == "zh" || $lang == "zh-tw" ? "zh_cn" : $lang); $lang = ($lang == "zh" || $lang == "zh-tw" ? "zh_cn" : $lang);
} }
return "<textarea$attrs id='fields-" . h($field["field"]) . "' rows='12' cols='50'>" . h($value) . "</textarea><script type='text/javascript'> return "<textarea$attrs id='fields-" . h($field["field"]) . "' rows='12' cols='50'>" . h($value) . "</textarea>" . script("
jQuery('#fields-" . js_escape($field["field"]) . "').wymeditor({ updateSelector: '#form [type=\"submit\"]', lang: '$lang'" . ($this->options ? ", $this->options" : "") . " }); jQuery('#fields-" . js_escape($field["field"]) . "').wymeditor({ updateSelector: '#form [type=\"submit\"]', lang: '$lang'" . ($this->options ? ", $this->options" : "") . " });
</script>"; ");
} }
} }

View File

@@ -20,6 +20,7 @@ Joining tables - PRIMARY KEY (table, joining)
Rank, Tree structure Rank, Tree structure
MySQL: MySQL:
Generated columns (MySQL >= 5.7.6)
Data longer than max_allowed_packet can be sent by mysqli_stmt_send_long_data() Data longer than max_allowed_packet can be sent by mysqli_stmt_send_long_data()
SQLite: SQLite: