[adminer-svn] SF.net SVN: adminer:[1366] branches/sqlite
Database management in a single PHP file
Brought to you by:
jakubvrana
From: <jak...@us...> - 2010-04-02 22:31:03
|
Revision: 1366 http://adminer.svn.sourceforge.net/adminer/?rev=1366&view=rev Author: jakubvrana Date: 2010-04-02 22:30:57 +0000 (Fri, 02 Apr 2010) Log Message: ----------- Allow concurrent logins on the same server (pass username in URL) Modified Paths: -------------- branches/sqlite/adminer/database.inc.php branches/sqlite/adminer/drivers/mssql.inc.php branches/sqlite/adminer/drivers/mysql.inc.php branches/sqlite/adminer/drivers/pgsql.inc.php branches/sqlite/adminer/include/adminer.inc.php branches/sqlite/adminer/include/auth.inc.php branches/sqlite/adminer/include/bootstrap.inc.php branches/sqlite/adminer/include/connect.inc.php branches/sqlite/adminer/include/design.inc.php branches/sqlite/adminer/include/functions.inc.php branches/sqlite/adminer/sql.inc.php branches/sqlite/changes.txt branches/sqlite/editor/include/adminer.inc.php Modified: branches/sqlite/adminer/database.inc.php =================================================================== --- branches/sqlite/adminer/database.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/database.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -2,11 +2,11 @@ if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x restart_session(); if ($_POST["drop"]) { - unset($_SESSION["databases"][$_GET["server"]]); + set_session("databases", null); query_redirect("DROP DATABASE " . idf_escape(DB), remove_from_uri("db|database"), lang('Database has been dropped.')); } elseif (DB !== $_POST["name"]) { // create or rename database - unset($_SESSION["databases"][$_GET["server"]]); // clear cache + set_session("databases", null); // clear cache if (DB != "") { queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), rename_database($_POST["name"], $_POST["collation"])); } else { Modified: branches/sqlite/adminer/drivers/mssql.inc.php =================================================================== --- branches/sqlite/adminer/drivers/mssql.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/drivers/mssql.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -227,7 +227,7 @@ } function get_databases($flush = true) { - $return = &$_SESSION["databases"][$_GET["server"]]; + $return = &get_session("databases"); if (!isset($return)) { $return = get_vals("EXEC sp_databases"); if ($flush) { Modified: branches/sqlite/adminer/drivers/mysql.inc.php =================================================================== --- branches/sqlite/adminer/drivers/mysql.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/drivers/mysql.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -239,7 +239,7 @@ */ function get_databases($flush = true) { // SHOW DATABASES can take a very long time so it is cached - $return = &$_SESSION["databases"][$_GET["server"]]; + $return = &get_session("databases"); if (!isset($return)) { restart_session(); $return = get_vals("SHOW DATABASES"); Modified: branches/sqlite/adminer/drivers/pgsql.inc.php =================================================================== --- branches/sqlite/adminer/drivers/pgsql.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/drivers/pgsql.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -125,7 +125,7 @@ } function get_databases($flush = true) { - $return = &$_SESSION["databases"][$_GET["server"]]; + $return = &get_session("databases"); if (!isset($return)) { $return = get_vals("SELECT datname FROM pg_database"); if ($flush) { Modified: branches/sqlite/adminer/include/adminer.inc.php =================================================================== --- branches/sqlite/adminer/include/adminer.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/include/adminer.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -20,7 +20,7 @@ * @return array ($server, $username, $password) */ function credentials() { - return array($_GET["server"], $_SESSION["usernames"][$_GET["server"]], $_SESSION["passwords"][$_GET["server"]]); + return array($_GET["server"], $_GET["username"], get_session("passwords")); } /** Get key used for permanent login @@ -39,16 +39,15 @@ } /** Print login form - * @param string * @return null */ - function loginForm($username) { + function loginForm() { global $drivers; ?> <table cellspacing="0"> <tr><th><?php echo lang('Driver'); ?><td><?php echo (count($drivers) > 1 ? html_select("driver", $drivers, $_GET["driver"]) : "<input type='hidden' name='driver' value='" . key($drivers) . "'>" . reset($drivers)); ?></tr> <tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h($_GET["server"]); ?>"> -<tr><th><?php echo lang('Username'); ?><td><input name="username" value="<?php echo h($username); ?>"> +<tr><th><?php echo lang('Username'); ?><td><input name="username" value="<?php echo h($_GET["username"]); ?>"> <tr><th><?php echo lang('Password'); ?><td><input type="password" name="password"> </table> <?php @@ -383,8 +382,9 @@ global $driver; restart_session(); $id = "sql-" . count($_SESSION["messages"]); - $_SESSION["history"][$_GET["server"]][DB][] = (strlen($query) > 1e6 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." : $query); // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment - return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-$driver'>" . shorten_utf8($query, 1000) . '</pre><a href="' . h(ME . 'sql=&history=' . (count($_SESSION["history"][$_GET["server"]][DB]) - 1)) . '">' . lang('Edit') . '</a></div>'; + $history = &get_session("history"); + $history[DB][] = (strlen($query) > 1e6 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." : $query); // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment + return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-$driver'>" . shorten_utf8($query, 1000) . '</pre><a href="' . h(ME . 'sql=&history=' . (count($history[DB]) - 1)) . '">' . lang('Edit') . '</a></div>'; } /** Functions displayed in edit form @@ -503,7 +503,7 @@ <p class="logout"> <a href="<?php echo h(ME); ?>sql="><?php echo bold(lang('SQL command'), isset($_GET["sql"])); ?></a> <a href="<?php echo h(ME); ?>dump=<?php echo urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]); ?>"><?php echo bold(lang('Dump'), isset($_GET["dump"])); ?></a> -<input type="hidden" name="token" value="<?php echo $_SESSION["tokens"][$_GET["server"]]; ?>"> +<input type="hidden" name="token" value="<?php echo $_SESSION["token"]; ?>"> <input type="submit" name="logout" value="<?php echo lang('Logout'); ?>"> </p> </form> Modified: branches/sqlite/adminer/include/auth.inc.php =================================================================== --- branches/sqlite/adminer/include/auth.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/include/auth.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -7,49 +7,46 @@ if (isset($_POST["server"])) { session_regenerate_id(); // defense against session fixation - $_SESSION["usernames"][$_POST["server"]] = $_POST["username"]; - $_SESSION["passwords"][$_POST["server"]] = $_POST["password"]; + $_SESSION["passwords"][$_POST["server"]][$_POST["username"]] = $_POST["password"]; if ($_POST["permanent"]) { - cookie("adminer_permanent", + cookie("adminer_permanent", //! store separately for each driver, server and username to allow several permanent logins base64_encode($_POST["server"]) . ":" . base64_encode($_POST["username"]) . ":" . base64_encode(encrypt_string($_POST["password"], $adminer->permanentLogin())) ); } - $same_driver = (string) $_GET["driver"] === $_POST["driver"]; - if (count($_POST) == ($_POST["permanent"] ? 5 : 4) || !$same_driver) { // 4 - driver, server, username, password - $location = ((string) $_GET["server"] === $_POST["server"] && $same_driver ? remove_from_uri("login|" . session_name()) : substr(preg_replace('~\\?.*~', '', ME) . "?" . ($_POST["driver"] ? "driver=" . urlencode($_POST["driver"]) . "&" : "") . ($_POST["server"] != "" ? "server=" . urlencode($_POST["server"]) . "&" : ""), 0, -1)); + $same_connection = ((string) $_GET["driver"] === $_POST["driver"] && (string) $_GET["server"] === $_POST["server"] && $_GET["username"] === $_POST["username"]); + if (count($_POST) == ($_POST["permanent"] ? 5 : 4) || !$same_connection) { // 4 - driver, server, username, password + $location = ($same_connection ? remove_from_uri(session_name()) : preg_replace('~\\?.*~', '', ME) . "?" . ($_POST["driver"] ? "driver=" . urlencode($_POST["driver"]) . "&" : "") . ($_POST["server"] != "" ? "server=" . urlencode($_POST["server"]) . "&" : "") . "username=" . urlencode($_POST["username"])); if (SID_FORM) { - $pos = strpos($location, '?'); - $location = ($pos ? substr_replace($location, SID . "&", $pos + 1, 0) : "$location?" . SID); + $location = substr_replace($location, SID . "&", strpos($location, '?') + 1, 0); } redirect($location); } - $_GET["server"] = $_POST["server"]; //! used also in ME } elseif ($_POST["logout"]) { - $token = $_SESSION["tokens"][$_GET["server"]]; + $token = $_SESSION["token"]; if ($token && $_POST["token"] != $token) { page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.')); page_footer("db"); exit; } else { - foreach (array("usernames", "passwords", "databases", "tokens", "history") as $val) { - unset($_SESSION[$val][$_GET["server"]]); + foreach (array("passwords", "databases", "history") as $key) { + set_session($key, null); } - if (!isset($_SESSION["passwords"])) { // don't require login to logout + if (!$_SESSION["passwords"]) { // don't require login to logout $_SESSION["passwords"] = array(); } cookie("adminer_permanent", ""); - redirect(substr(ME, 0, -1), lang('Logout successful.')); + redirect(substr(preg_replace('~username=[^&]*&~', '', ME), 0, -1), lang('Logout successful.')); } -} elseif ($_COOKIE["adminer_permanent"] && !isset($_SESSION["usernames"][$_GET["server"]])) { +} elseif ($_COOKIE["adminer_permanent"]) { list($server, $username, $cipher) = array_map('base64_decode', explode(":", $_COOKIE["adminer_permanent"])); - if (($_GET["server"] == "" && !$_POST) || $server == $_GET["server"]) { + if (!isset($_GET["username"]) || ($server == $_GET["server"] && $username == $_GET["username"])) { session_regenerate_id(); // defense against session fixation - $_SESSION["usernames"][$server] = $username; - $_SESSION["passwords"][$server] = decrypt_string($cipher, $adminer->permanentLogin()); - if ($server != $_GET["server"]) { - redirect(preg_replace('~^([^?]*).*~', '\\1', ME) . '?server=' . urlencode($server)); //! store and respect driver + $_SESSION["passwords"][$server][$username] = decrypt_string($cipher, $adminer->permanentLogin()); + if (!isset($_GET["username"])) { + // cookies are allowed - no need to pass SID in URL + redirect(preg_replace('~\\?.*~', '', ME) . '?server=' . urlencode($server) . '&username=' . urlencode($server)); //! respect driver } } } @@ -57,41 +54,32 @@ function auth_error($exception = null) { global $connection, $adminer; $session_name = session_name(); - $username = $_SESSION["usernames"][$_GET["server"]]; - if (!$_GET["login"]) { - unset($_SESSION["usernames"][$_GET["server"]]); - } - page_header(lang('Login'), (isset($username) ? h($exception ? $exception->getMessage() : (is_string($connection) ? $connection : lang('Invalid credentials.'))) + page_header(lang('Login'), (isset($_GET["username"]) ? h($exception ? $exception->getMessage() : (is_string($connection) ? $connection : lang('Invalid credentials.'))) : (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_get("session.use_only_cookies") ? lang('Session support must be enabled.') : (($_COOKIE[$session_name] || $_GET[$session_name]) && !isset($_SESSION["passwords"]) ? lang('Session expired, please login again.') : ""))), null); echo "<form action='' method='post'>\n"; - $adminer->loginForm($username); + $adminer->loginForm(); echo "<div>"; - hidden_fields($_POST, array("driver", "server", "username", "password")); // expired session + hidden_fields($_POST, array("driver", "server", "username", "password", "permanent")); // expired session echo "</div>\n"; echo "</form>\n"; page_footer("auth"); } -$username = &$_SESSION["usernames"][$_GET["server"]]; -if (!isset($username)) { - $username = $_GET["username"]; // default username can be passed in URL -} -$connection = (!$_GET["login"] && isset($username) ? connect() : ''); -if (is_string($connection) || !$adminer->login($username, $_SESSION["passwords"][$_GET["server"]])) { +$connection = (isset($_GET["username"]) ? connect() : ''); +if (is_string($connection) || !$adminer->login($_GET["username"], $_SESSION["passwords"][$_GET["server"]])) { auth_error(); exit; } -unset($username); -if (!$_SESSION["tokens"][$_GET["server"]]) { - $_SESSION["tokens"][$_GET["server"]] = rand(1, 1e6); // defense against cross-site request forgery +if (!$_SESSION["token"]) { + $_SESSION["token"] = rand(1, 1e6); // defense against cross-site request forgery } if (isset($_POST["server"]) && $_POST["token"]) { - $_POST["token"] = $_SESSION["tokens"][$_GET["server"]]; + $_POST["token"] = $_SESSION["token"]; // reset token after explicit login } -$token = $_SESSION["tokens"][$_GET["server"]]; ///< @var string CSRF protection +$token = $_SESSION["token"]; ///< @var string CSRF protection $error = ($_POST ///< @var string ? ($_POST["token"] == $token ? "" : lang('Invalid CSRF token. Send the form again.')) : ($_SERVER["REQUEST_METHOD"] != "POST" ? "" : lang('Too big POST data. Reduce the data or increase the %s configuration directive.', '"post_max_size"')) // posted form with no data means that post_max_size exceeded because Adminer always sends token at least Modified: branches/sqlite/adminer/include/bootstrap.inc.php =================================================================== --- branches/sqlite/adminer/include/bootstrap.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/include/bootstrap.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -79,7 +79,7 @@ define("DB", $_GET["db"]); // for the sake of speed and size define("SID_FORM", SID && !ini_get("session.use_only_cookies") ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : ''); -define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\\1', $_SERVER["REQUEST_URI"]) . '?' . (SID_FORM ? SID . '&' : '') . ($_GET["driver"] ? "driver=" . urlencode($_GET["driver"]) . '&' : '') . ($_GET["server"] != "" ? "server=" . urlencode($_GET["server"]) . '&' : '') . (DB != "" ? 'db=' . urlencode(DB) . '&' : '')); +define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\\1', $_SERVER["REQUEST_URI"]) . '?' . (SID_FORM ? SID . '&' : '') . ($_GET["driver"] ? "driver=" . urlencode($_GET["driver"]) . '&' : '') . ($_GET["server"] != "" ? "server=" . urlencode($_GET["server"]) . '&' : '') . (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '') . (DB != "" ? 'db=' . urlencode(DB) . '&' : '')); include "../adminer/include/lang.inc.php"; include "../adminer/lang/$LANG.inc.php"; Modified: branches/sqlite/adminer/include/connect.inc.php =================================================================== --- branches/sqlite/adminer/include/connect.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/include/connect.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -6,7 +6,7 @@ page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), true); } else { if ($_POST["db"] && !$error) { - unset($_SESSION["databases"][$_GET["server"]]); + set_session("databases", null); foreach ($_POST["db"] as $db) { if (!queries("DROP DATABASE " . idf_escape($db))) { break; @@ -50,7 +50,7 @@ } 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"]))) { if (DB != "") { - unset($_SESSION["databases"][$_GET["server"]]); + set_session("databases", null); } connect_error(); // separate function to catch SQLite error exit; Modified: branches/sqlite/adminer/include/design.inc.php =================================================================== --- branches/sqlite/adminer/include/design.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/include/design.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -31,13 +31,14 @@ <div id="content"> <?php if (isset($breadcrumb)) { + $link = substr(preg_replace('~(driver|server|username|db)=[^&]*&~', '', ME), 0, -1); + echo '<p id="breadcrumb"><a href="' . ($link ? h($link) : ".") . '">' . $drivers[$_GET["driver"]] . '</a> » '; //! hide in Editor $link = substr(preg_replace('~db=[^&]*&~', '', ME), 0, -1); - echo '<p id="breadcrumb"><a href="' . h(preg_replace('~(driver|server|db)=[^&]*&~', '', ME)) . 'login=1">' . $drivers[$_GET["driver"]] . '</a> » '; //! hide in Editor $server = (isset($_GET["server"]) ? h($_GET["server"]) : lang('Server')); if ($breadcrumb === false) { echo "$server\n"; } else { - echo "<a href='" . ($link != "" ? h($link) : ".") . "'>$server</a> » "; + echo "<a href='" . ($link ? h($link) : ".") . "'>$server</a> » "; if (is_array($breadcrumb)) { if (DB != "") { echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</a> » '; @@ -61,7 +62,7 @@ if (!$_POST && !isset($_SESSION["passwords"])) { // used in auth $_SESSION["passwords"] = array(); } - $databases = &$_SESSION["databases"][$_GET["server"]]; + $databases = &get_session("databases"); if (DB != "" && $databases && !in_array(DB, $databases, true)) { $databases = null; } Modified: branches/sqlite/adminer/include/functions.inc.php =================================================================== --- branches/sqlite/adminer/include/functions.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/include/functions.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -223,6 +223,23 @@ } } +/** Get session variable for current server +* @param string +* @return mixed +*/ +function &get_session($key) { + return $_SESSION[$key][$_GET["server"]][$_GET["username"]]; +} + +/** Set session variable for current server +* @param string +* @param mixed +* @return mixed +*/ +function set_session($key, $val) { + $_SESSION[$key][$_GET["server"]][$_GET["username"]] = $val; +} + /** Send Location header and exit * @param string * @param string Modified: branches/sqlite/adminer/sql.inc.php =================================================================== --- branches/sqlite/adminer/sql.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/adminer/sql.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -1,6 +1,7 @@ <?php restart_session(); -$history = &$_SESSION["history"][$_GET["server"]][DB]; +$history_all = &get_session("history"); +$history = &$history_all[DB]; if (!$error && $_POST["clear"]) { $history = array(); redirect(remove_from_uri("history")); @@ -88,7 +89,7 @@ } else { if (preg_match("~^$space*$alter_database", $query)) { restart_session(); - $_SESSION["databases"][$_GET["server"]] = null; // clear cache + set_session("databases", null); // clear cache session_write_close(); } echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $connection->affected_rows) . "\n"; Modified: branches/sqlite/changes.txt =================================================================== --- branches/sqlite/changes.txt 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/changes.txt 2010-04-02 22:30:57 UTC (rev 1366) @@ -1,6 +1,7 @@ Adminer 3.0.0-dev: Drivers for MS SQL, SQLite, PostgreSQL Show number of tables in server overview +Allow concurrent logins on the same server Defer table information in database overview to JavaScript (performance) Adminer 2.3.1-dev: Modified: branches/sqlite/editor/include/adminer.inc.php =================================================================== --- branches/sqlite/editor/include/adminer.inc.php 2010-04-02 21:11:44 UTC (rev 1365) +++ branches/sqlite/editor/include/adminer.inc.php 2010-04-02 22:30:57 UTC (rev 1366) @@ -7,6 +7,8 @@ return lang('Editor'); } + //! driver + function credentials() { return array(); // default INI settings } @@ -24,10 +26,10 @@ ); } - function loginForm($username) { + function loginForm() { ?> <table cellspacing="0"> -<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="driver" value=""><input type="hidden" name="server" value=""><input name="username" value="<?php echo h($username); //! driver ?>"> +<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="driver" value=""><input type="hidden" name="server" value=""><input name="username" value="<?php echo h($_GET["username"]); ?>"> <tr><th><?php echo lang('Password'); ?><td><input type="password" name="password"> </table> <?php @@ -454,7 +456,7 @@ ?> <form action="" method="post"> <p class="logout"> -<input type="hidden" name="token" value="<?php echo $_SESSION["tokens"][$_GET["server"]]; ?>"> +<input type="hidden" name="token" value="<?php echo $_SESSION["token"]; ?>"> <input type="submit" name="logout" value="<?php echo lang('Logout'); ?>"> </p> </form> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |