diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index dce1433e..e02f8189 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -268,15 +268,18 @@ if (!defined("DRIVER")) { function get_databases($flush) { global $connection; // SHOW DATABASES can take a very long time so it is cached - $return = &get_session("dbs"); + $return = get_session("dbs"); if ($return === null) { + $kill = ($flush ? kill_timeout() : 0); + $return = @get_vals("/* Adminer $kill */ " . ($connection->server_info >= 5 // @ - may be killed + ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA" + : "SHOW DATABASES" + )); // SHOW DATABASES can be disabled by skip_show_database if ($flush) { - ob_flush(); - flush(); + cancel_kill_timeout(); } - $databases = get_vals($connection->server_info >= 5 ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA" : "SHOW DATABASES"); // SHOW DATABASES can be disabled by skip_show_database restart_session(); - $return = $databases; + set_session("dbs", $return); stop_session(); } return $return; @@ -932,10 +935,11 @@ if (!defined("DRIVER")) { } /** Get process list + * @param bool * @return array ($row) */ - function process_list() { - return get_rows("SHOW FULL PROCESSLIST"); + function process_list($full = true) { + return get_rows("SHOW" . ($full ? " FULL" : "") . " PROCESSLIST"); } /** Get status variables diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index 6b4f1cd0..6bebe422 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -42,6 +42,13 @@ class Adminer { return get_databases($flush); } + /** Specify limit for waiting on some slow queries like DB list + * @return float number of seconds + */ + function queryTimeout() { + return 5; + } + /** Headers to send before HTML output * @return bool true to send security headers */ diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index 48a36dd1..85cb9038 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -22,6 +22,7 @@ if (isset($_GET["file"])) { include "../adminer/include/functions.inc.php"; global $adminer, $connection, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $structured_types, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function + if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"]; } @@ -73,12 +74,13 @@ include "./include/adminer.inc.php"; include "../adminer/include/design.inc.php"; include "../adminer/include/xxtea.inc.php"; include "../adminer/include/auth.inc.php"; -include "./include/connect.inc.php"; -include "./include/editing.inc.php"; if (!ini_bool("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled session_cache_limiter(""); // to allow restarting session session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later } +include "./include/connect.inc.php"; +include "./include/editing.inc.php"; + $on_actions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys() diff --git a/adminer/include/connect.inc.php b/adminer/include/connect.inc.php index 90d8f063..c0ce43d9 100644 --- a/adminer/include/connect.inc.php +++ b/adminer/include/connect.inc.php @@ -23,9 +23,6 @@ function connect_error() { } echo "

" . lang('%s version: %s through PHP extension %s', $drivers[DRIVER], "$connection->server_info", "$connection->extension") . "\n"; echo "

" . lang('Logged as: %s', "" . h(logged_user()) . "") . "\n"; - if ($_GET["refresh"]) { - set_session("dbs", null); - } $refresh = "" . lang('Refresh') . "\n"; $databases = $adminer->databases(); if ($databases) { @@ -61,8 +58,9 @@ function connect_error() { if (isset($_GET["status"])) { $_GET["variables"] = $_GET["status"]; } -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")) { - if (DB != "") { +if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) { + if (DB != "" || $_GET["refresh"]) { + restart_session(); set_session("dbs", null); } connect_error(); // separate function to catch SQLite error diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 6f7004d2..8030b8ec 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -898,3 +898,38 @@ function is_url($string) { $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN return (preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string, $match) ? strtolower($match[1]) : ""); //! restrict path, query and fragment characters } + +/** Launch timeout after which the query will be killed +* @return int kill token +*/ +function kill_timeout() { + global $adminer, $token; + $kill = mt_rand(); + ?> + +clearTimeout(timeout);\n"; + ob_flush(); + flush(); + if ($connection->errno == 2006) { // 2006 - CR_SERVER_GONE_ERROR + $connection2 = connect(); + if (is_object($connection2)) { + $connection = $connection2; + } + } +} diff --git a/adminer/script.inc.php b/adminer/script.inc.php index 39ede5bf..ed9c09d7 100644 --- a/adminer/script.inc.php +++ b/adminer/script.inc.php @@ -31,6 +31,14 @@ if ($_GET["script"] == "db") { json_row("sum-$key", number_format($val, 0, '.', lang(','))); } json_row(""); + +} elseif ($_GET["script"] == "kill") { + foreach (process_list(false) as $process) { + if (ereg('^/\* Adminer ' . (+$_POST["kill"]) . ' \*/', $process["Info"])) { + $connection->query("KILL $process[Id]"); + } + } + } else { // connect foreach (count_tables($adminer->databases()) as $db => $val) { json_row("tables-" . js_escape($db), $val); diff --git a/changes.txt b/changes.txt index 5b5f4835..34761b55 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,6 @@ Adminer 3.5.2-dev: Edit strings with \n in textarea +Time out long running database list Use VALUES() in INSERT+UPDATE export Style logout button as link