Compare commits

...

6 Commits

Author SHA1 Message Date
Jakub Vrana
53dfafd2ea Release 4.2.5 2016-06-01 10:09:29 -07:00
Jakub Vrana
7a33661b72 SQLite: Require credentials to use (thanks to Vincent Waart) 2016-06-01 09:59:20 -07:00
Jakub Vrana
a5b65fba5b Fix remote execution in SQLite query (thanks to Vincent Waart) 2016-06-01 09:56:40 -07:00
Jakub Vrana
63f2a041ed Remove global variable 2016-02-28 12:30:52 -08:00
Bernhard J. M. Gruen
3289eca040 improved kill command support for MySQL and initial support for PgSQL 2016-02-28 12:27:45 -08:00
Petr Sedlacek
c5a7174a2a Fix http:// links in stylesheets to protocol-independent ones (//)
The http links do not load on https pages due to mixed content restriction
of modern browsers
2016-02-28 11:34:10 -08:00
15 changed files with 50 additions and 36 deletions

View File

@@ -1015,6 +1015,15 @@ if (!defined("DRIVER")) {
return !preg_match("~scheme|sequence|type|view_trigger" . ($connection->server_info < 5.1 ? "|event|partitioning" . ($connection->server_info < 5 ? "|routine|trigger|view" : "") : "") . "~", $feature); return !preg_match("~scheme|sequence|type|view_trigger" . ($connection->server_info < 5.1 ? "|event|partitioning" . ($connection->server_info < 5 ? "|routine|trigger|view" : "") : "") . "~", $feature);
} }
function kill_process($val) {
return queries("KILL " . number($val));
}
function max_connections() {
global $connection;
return $connection->result("SELECT @@max_connections");
}
$jush = "sql"; ///< @var string JUSH identifier $jush = "sql"; ///< @var string JUSH identifier
$types = array(); ///< @var array ($type => $maximum_unsigned_length, ...) $types = array(); ///< @var array ($type => $maximum_unsigned_length, ...)
$structured_types = array(); ///< @var array ($description => array($type, ...), ...) $structured_types = array(); ///< @var array ($description => array($type, ...), ...)

View File

@@ -631,7 +631,16 @@ AND typelem = 0"
function support($feature) { function support($feature) {
global $connection; global $connection;
return preg_match('~^(database|table|columns|sql|indexes|comment|view|' . ($connection->server_info >= 9.3 ? 'materializedview|' : '') . 'scheme|processlist|sequence|trigger|type|variables|drop_col)$~', $feature); //! routine| return preg_match('~^(database|table|columns|sql|indexes|comment|view|' . ($connection->server_info >= 9.3 ? 'materializedview|' : '') . 'scheme|processlist|sequence|trigger|type|variables|drop_col|kill)$~', $feature); //! routine|
}
function kill_process($val) {
return queries("SELECT pg_terminate_backend(" . number($val).")");
}
function max_connections() {
global $connection;
return $connection->result("SHOW max_connections");
} }
$jush = "pgsql"; $jush = "pgsql";

View File

@@ -88,16 +88,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, "loginDriver(this);"); ?> <tr><th><?php echo lang('System'); ?><td><?php echo html_select("auth[driver]", $drivers, DRIVER); ?>
<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"> <script type="text/javascript">
var username = document.getElementById('username'); focus(document.getElementById('username'));
focus(username);
username.form['auth[driver]'].onchange();
</script> </script>
<?php <?php
echo "<p><input type='submit' value='" . lang('Login') . "'>\n"; echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
@@ -107,9 +105,13 @@ username.form['auth[driver]'].onchange();
/** Authorize the user /** Authorize the user
* @param string * @param string
* @param string * @param string
* @return bool * @return mixed true for success, string for error message, false for unknown error
*/ */
function login($login, $password) { function login($login, $password) {
global $jush;
if ($jush == "sqlite") {
return lang('Implement %s method to use SQLite.', 'login()');
}
return true; return true;
} }

View File

@@ -167,8 +167,8 @@ if (isset($_GET["username"])) {
$driver = new Min_Driver($connection); $driver = new Min_Driver($connection);
if (!is_object($connection) || !$adminer->login($_GET["username"], get_password())) { if (!is_object($connection) || ($login = $adminer->login($_GET["username"], get_password())) !== true) {
auth_error((is_string($connection) ? $connection : lang('Invalid credentials.'))); auth_error((is_string($connection) ? $connection : (is_string($login) ? $login : lang('Invalid credentials.'))));
} }
if ($auth && $_POST["token"]) { if ($auth && $_POST["token"]) {

View File

@@ -1,2 +1,2 @@
<?php <?php
$VERSION = "4.2.4"; $VERSION = "4.2.5";

View File

@@ -11,6 +11,7 @@ $translations = array(
'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.',
'Invalid credentials.' => 'Neplatné přihlašovací údaje.', 'Invalid credentials.' => 'Neplatné přihlašovací údaje.',
'Implement %s method to use SQLite.' => 'Pro přihlášení k SQLite implementujte 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.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to make it permanent.' => 'Platnost hlavního hesla vypršela. <a href="https://www.adminer.org/cs/extension/" target="_blank">Implementujte</a> metodu %s, aby platilo stále.', 'Master password expired. <a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to make it permanent.' => 'Platnost hlavního hesla vypršela. <a href="https://www.adminer.org/cs/extension/" target="_blank">Implementujte</a> metodu %s, aby platilo stále.',
'Language' => 'Jazyk', 'Language' => 'Jazyk',

View File

@@ -11,6 +11,7 @@ $translations = array(
'Logged as: %s' => 'Xx', 'Logged as: %s' => 'Xx',
'Logout successful.' => 'Xx.', 'Logout successful.' => 'Xx.',
'Invalid credentials.' => 'Xx.', 'Invalid credentials.' => 'Xx.',
'Implement %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.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to make it permanent.' => 'Xx.', 'Master password expired. <a href="https://www.adminer.org/en/extension/" target="_blank">Implement</a> %s method to make it permanent.' => 'Xx.',
'Language' => 'Xx', 'Language' => 'Xx',

View File

@@ -2,7 +2,7 @@
if (support("kill") && $_POST && !$error) { if (support("kill") && $_POST && !$error) {
$killed = 0; $killed = 0;
foreach ((array) $_POST["kill"] as $val) { foreach ((array) $_POST["kill"] as $val) {
if (queries("KILL " . number($val))) { if (kill_process($val)) {
$killed++; $killed++;
} }
} }
@@ -30,8 +30,7 @@ foreach (process_list() as $i => $row) {
} }
echo "</thead>\n"; echo "</thead>\n";
} }
echo "<tr" . odd() . ">" . (support("kill") ? "<td>" . checkbox("kill[]", $row[$jush == "sql" ? "Id" : "pid"], 0) : "");
echo "<tr" . odd() . ">" . (support("kill") ? "<td>" . checkbox("kill[]", $row["Id"], 0) : "");
foreach ($row as $key => $val) { foreach ($row as $key => $val) {
echo "<td>" . ( echo "<td>" . (
($jush == "sql" && $key == "Info" && preg_match("~Query|Killed~", $row["Command"]) && $val != "") || ($jush == "sql" && $key == "Info" && preg_match("~Query|Killed~", $row["Command"]) && $val != "") ||
@@ -49,7 +48,7 @@ foreach (process_list() as $i => $row) {
<p> <p>
<?php <?php
if (support("kill")) { if (support("kill")) {
echo ($i + 1) . "/" . lang('%d in total', $connection->result("SELECT @@max_connections")); echo ($i + 1) . "/" . lang('%d in total', max_connections());
echo "<p><input type='submit' value='" . lang('Kill') . "'>\n"; echo "<p><input type='submit' value='" . lang('Kill') . "'>\n";
} }
?> ?>

View File

@@ -45,7 +45,7 @@ if (!$error && $_POST) {
} }
} }
$space = "(?:\\s|/\\*.*\\*/|(?:#|-- )[^\n]*\n|--\r?\n)"; $space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
$delimiter = ";"; $delimiter = ";";
$offset = 0; $offset = 0;
$empty = true; $empty = true;
@@ -62,7 +62,7 @@ if (!$error && $_POST) {
unset($dump_format["sql"]); unset($dump_format["sql"]);
while ($query != "") { while ($query != "") {
if (!$offset && preg_match("~^$space*DELIMITER\\s+(\\S+)~i", $query, $match)) { if (!$offset && preg_match("~^$space*+DELIMITER\\s+(\\S+)~i", $query, $match)) {
$delimiter = $match[1]; $delimiter = $match[1];
$query = substr($query, strlen($match[0])); $query = substr($query, strlen($match[0]));
} else { } else {
@@ -94,7 +94,7 @@ if (!$error && $_POST) {
$q = substr($query, 0, $pos); $q = substr($query, 0, $pos);
$commands++; $commands++;
$print = "<pre id='sql-$commands'><code class='jush-$jush'>" . shorten_utf8(trim($q), 1000) . "</code></pre>\n"; $print = "<pre id='sql-$commands'><code class='jush-$jush'>" . shorten_utf8(trim($q), 1000) . "</code></pre>\n";
if ($jush == "sqlite" && preg_match("~^$space*ATTACH\b~i", $q, $match)) { if ($jush == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) {
// PHP doesn't support setting SQLITE_LIMIT_ATTACHED // PHP doesn't support setting SQLITE_LIMIT_ATTACHED
echo $print; echo $print;
echo "<p class='error'>" . lang('ATTACH queries are not supported.') . "\n"; echo "<p class='error'>" . lang('ATTACH queries are not supported.') . "\n";
@@ -110,7 +110,7 @@ if (!$error && $_POST) {
} }
$start = microtime(true); $start = microtime(true);
//! don't allow changing of character_set_results, convert encoding of displayed query //! don't allow changing of character_set_results, convert encoding of displayed query
if ($connection->multi_query($q) && is_object($connection2) && preg_match("~^$space*USE\\b~isU", $q)) { if ($connection->multi_query($q) && is_object($connection2) && preg_match("~^$space*+USE\\b~i", $q)) {
$connection2->query($q); $connection2->query($q);
} }
@@ -143,7 +143,7 @@ if (!$error && $_POST) {
. "<input type='hidden' name='query' value='" . h($q) . "'>" . "<input type='hidden' name='query' value='" . h($q) . "'>"
. " <input type='submit' name='export' value='" . lang('Export') . "'><input type='hidden' name='token' value='$token'></span>\n" . " <input type='submit' name='export' value='" . lang('Export') . "'><input type='hidden' name='token' value='$token'></span>\n"
; ;
if ($connection2 && preg_match("~^($space|\\()*SELECT\\b~isU", $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' onclick=\"return !toggle('$id');\">EXPLAIN</a>$export";
echo "<div id='$id' class='hidden'>\n"; echo "<div id='$id' class='hidden'>\n";
@@ -156,7 +156,7 @@ if (!$error && $_POST) {
} }
} else { } else {
if (preg_match("~^$space*(CREATE|DROP|ALTER)$space+(DATABASE|SCHEMA)\\b~isU", $q)) { if (preg_match("~^$space*+(CREATE|DROP|ALTER)$space++(DATABASE|SCHEMA)\\b~i", $q)) {
restart_session(); restart_session();
set_session("dbs", null); // clear cache set_session("dbs", null); // clear cache
stop_session(); stop_session();

View File

@@ -60,18 +60,6 @@ function typePassword(el, disable) {
} }
} }
/** Hide or show some login rows for selected driver
* @param HTMLSelectElement
*/
function loginDriver(driver) {
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;
}
}
var dbCtrl; var dbCtrl;

View File

@@ -1,3 +1,8 @@
Adminer 4.2.5 (released 2016-06-01):
Fix remote execution in SQLite query
SQLite: Require credentials to use
PostgreSQL: Support KILL
Adminer 4.2.4 (released 2016-02-06): Adminer 4.2.4 (released 2016-02-06):
Fix remote execution in SQLite query Fix remote execution in SQLite query
MySQL: Support PHP 7 MySQL: Support PHP 7

View File

@@ -45,7 +45,7 @@ border:5px solid #ccc;margin:0}
#menu a{color:#333;margin-right:4px} #menu a{color:#333;margin-right:4px}
#menu a:hover{background:#333;color:#fff;border-color:#333} #menu a:hover{background:#333;color:#fff;border-color:#333}
#menu a.h1,#menu a.h1:hover{display:block;height:0;width:175px;padding:40px 0 0 0;overflow:hidden;float:left;border:0;margin:0; #menu a.h1,#menu a.h1:hover{display:block;height:0;width:175px;padding:40px 0 0 0;overflow:hidden;float:left;border:0;margin:0;
outline:0;background:url(http://www.bradezone.com/random/adminer_logo.gif) no-repeat;line-height:32px} outline:0;background:url(//www.bradezone.com/random/adminer_logo.gif) no-repeat;line-height:32px}
#menu p{white-space:nowrap;border:0;padding:0 0 4px 0;margin:0 0 4px 0} #menu p{white-space:nowrap;border:0;padding:0 0 4px 0;margin:0 0 4px 0}
#breadcrumb{background:#333;color:#fff;position:fixed;top:0;left:320px;width:100%;line-height:40px;padding:0;z-index:1;margin:0} #breadcrumb{background:#333;color:#fff;position:fixed;top:0;left:320px;width:100%;line-height:40px;padding:0;z-index:1;margin:0}
#breadcrumb a{color:#ff9} #breadcrumb a{color:#ff9}

View File

@@ -1,6 +1,6 @@
/** theme "easy on the eyes" for Adminer by p.galkaev@miraidenshi-tech.jp */ /** theme "easy on the eyes" for Adminer by p.galkaev@miraidenshi-tech.jp */
@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,900); @import url(//fonts.googleapis.com/css?family=Source+Sans+Pro:400,900);
/* reset /* reset
----------------------------------------------------------------------- */ ----------------------------------------------------------------------- */

View File

@@ -1,5 +1,5 @@
/* CSS by Nicu I. - www.nicu.me */ /* CSS by Nicu I. - www.nicu.me */
@import url('http://fonts.googleapis.com/css?family=Roboto:400,700,300'); @import url('//fonts.googleapis.com/css?family=Roboto:400,700,300');
body { body {
font: 16px/1.25 'Roboto', Verdana, Arial, Helvetica, sans-serif; font: 16px/1.25 'Roboto', Verdana, Arial, Helvetica, sans-serif;
margin: 0; margin: 0;

View File

@@ -6,8 +6,8 @@
*/ */
/*** Fonts ***/ /*** Fonts ***/
@import url(http://fonts.googleapis.com/css?family=Ubuntu:300&subset=latin,latin-ext); @import url(//fonts.googleapis.com/css?family=Ubuntu:300&subset=latin,latin-ext);
@import url(http://fonts.googleapis.com/css?family=Ubuntu+Mono&subset=latin,latin-ext); @import url(//fonts.googleapis.com/css?family=Ubuntu+Mono&subset=latin,latin-ext);
* { * {
font-family: 'Ubuntu', sans-serif font-family: 'Ubuntu', sans-serif
} }