Reintegrate sqlite branch

git-svn-id: https://adminer.svn.sourceforge.net/svnroot/adminer/trunk@1466 7c3ca157-0c34-0410-bff1-cbf682f78f5c
This commit is contained in:
jakubvrana 2010-04-21 12:01:32 +00:00
parent 2df25baa3c
commit 3f5b683456
84 changed files with 3010 additions and 1095 deletions

View file

@ -28,7 +28,9 @@ if (!$error && $_POST) {
} }
$call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val); $call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val);
} }
if (!$connection->multi_query((isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . idf_escape($PROCEDURE) . "(" . implode(", ", $call) . ")")) { $query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . idf_escape($PROCEDURE) . "(" . implode(", ", $call) . ")";
echo "<p><code class='jush-$driver'>" . h($query) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
if (!$connection->multi_query($query)) {
echo "<p class='error'>" . error() . "\n"; echo "<p class='error'>" . error() . "\n";
} else { } else {
do { do {
@ -52,8 +54,9 @@ if ($in) {
echo "<table cellspacing='0'>\n"; echo "<table cellspacing='0'>\n";
foreach ($in as $key) { foreach ($in as $key) {
$field = $routine["fields"][$key]; $field = $routine["fields"][$key];
echo "<tr><th>" . h($field["field"]); $name = $field["field"];
$value = $_POST["fields"][$key]; echo "<tr><th>" . h($name);
$value = $_POST["fields"][$name];
if ($value != "" && ereg("enum|set", $field["type"])) { if ($value != "" && ereg("enum|set", $field["type"])) {
$value = intval($value); $value = intval($value);
} }

View file

@ -19,20 +19,8 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
if ($_POST["drop"]) { if ($_POST["drop"]) {
query_redirect("DROP TABLE " . idf_escape($_GET["create"]), substr(ME, 0, -1), lang('Table has been dropped.')); query_redirect("DROP TABLE " . idf_escape($_GET["create"]), substr(ME, 0, -1), lang('Table has been dropped.'));
} else { } else {
$auto_increment_index = " PRIMARY KEY"; $fields = array();
// don't overwrite primary key by auto_increment $foreign = array();
if ($TABLE != "" && $_POST["auto_increment_col"]) {
foreach (indexes($TABLE) as $index) {
if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
$auto_increment_index = "";
break;
}
if ($index["type"] == "PRIMARY") {
$auto_increment_index = " UNIQUE";
}
}
}
$fields = "";
ksort($_POST["fields"]); ksort($_POST["fields"]);
$orig_field = reset($orig_fields); $orig_field = reset($orig_fields);
$after = "FIRST"; $after = "FIRST";
@ -48,33 +36,26 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
$field["on_update"] = "CURRENT_TIMESTAMP"; $field["on_update"] = "CURRENT_TIMESTAMP";
$field["default"] = $default; $field["default"] = $default;
} }
if ($key == $_POST["auto_increment_col"]) {
$field["auto_increment"] = true;
}
$process_field = process_field($field, $type_field); $process_field = process_field($field, $type_field);
$auto_increment = ($key == $_POST["auto_increment_col"]); if ($process_field != process_field($orig_field, $orig_field)) {
if ($process_field != process_field($orig_field, $orig_field) || $orig_field["auto_increment"] != $auto_increment) { $fields[] = array($field["orig"], $process_field, $after);
$fields .= "\n" . ($TABLE != "" ? ($field["orig"] != "" ? "CHANGE " . idf_escape($field["orig"]) : "ADD") : " ")
. " $process_field"
. ($auto_increment ? " AUTO_INCREMENT$auto_increment_index" : "")
. ($TABLE != "" ? " $after" : "") . ","
;
} }
if (!isset($types[$field["type"]])) { if (!isset($types[$field["type"]])) {
$fields .= ($TABLE != "" ? "\nADD" : "") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . "),"; $foreign[] = ($TABLE != "" ? "ADD " : " ") . "FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")";
} }
} }
$after = "AFTER " . idf_escape($field["field"]); $after = "AFTER " . idf_escape($field["field"]);
//! drop and create foreign keys with renamed columns
} elseif ($field["orig"] != "") { } elseif ($field["orig"] != "") {
$fields .= "\nDROP " . idf_escape($field["orig"]) . ","; $fields[] = array($field["orig"]);
} }
if ($field["orig"] != "") { if ($field["orig"] != "") {
$orig_field = next($orig_fields); $orig_field = next($orig_fields);
} }
} }
$status = "COMMENT=" . $connection->quote($_POST["Comment"]) $partitioning = "";
. ($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? " ENGINE=" . $connection->quote($_POST["Engine"]) : "")
. ($_POST["Collation"] && $_POST["Collation"] != $orig_status["Collation"] ? " COLLATE " . $connection->quote($_POST["Collation"]) : "")
. ($_POST["Auto_increment"] != "" ? " AUTO_INCREMENT=" . preg_replace('~[^0-9]+~', '', $_POST["Auto_increment"]) : "")
;
if (in_array($_POST["partition_by"], $partition_by)) { if (in_array($_POST["partition_by"], $partition_by)) {
$partitions = array(); $partitions = array();
if ($_POST["partition_by"] == 'RANGE' || $_POST["partition_by"] == 'LIST') { if ($_POST["partition_by"] == 'RANGE' || $_POST["partition_by"] == 'LIST') {
@ -83,20 +64,29 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
$partitions[] = "\nPARTITION " . idf_escape($val) . " VALUES " . ($_POST["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection $partitions[] = "\nPARTITION " . idf_escape($val) . " VALUES " . ($_POST["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
} }
} }
$status .= "\nPARTITION BY $_POST[partition_by]($_POST[partition])" . ($partitions // $_POST["partition"] can be expression, not only column $partitioning .= "\nPARTITION BY $_POST[partition_by]($_POST[partition])" . ($partitions // $_POST["partition"] can be expression, not only column
? " (" . implode(",", $partitions) . "\n)" ? " (" . implode(",", $partitions) . "\n)"
: ($_POST["partitions"] ? " PARTITIONS " . intval($_POST["partitions"]) : "") : ($_POST["partitions"] ? " PARTITIONS " . intval($_POST["partitions"]) : "")
); );
} elseif ($connection->server_info >= 5.1 && $TABLE != "") { } elseif ($TABLE != "") {
$status .= "\nREMOVE PARTITIONING"; $partitioning .= "\nREMOVE PARTITIONING";
} }
$location = ME . "table=" . urlencode($_POST["name"]); $message = lang('Table has been altered.');
if ($TABLE != "") { if ($TABLE == "") {
query_redirect("ALTER TABLE " . idf_escape($TABLE) . "$fields\nRENAME TO " . idf_escape($_POST["name"]) . ",\n$status", $location, lang('Table has been altered.'));
} else {
cookie("adminer_engine", $_POST["Engine"]); cookie("adminer_engine", $_POST["Engine"]);
query_redirect("CREATE TABLE " . idf_escape($_POST["name"]) . " (" . substr($fields, 0, -1) . "\n) $status", $location, lang('Table has been created.')); $message = lang('Table has been created.');
} }
queries_redirect(ME . "table=" . urlencode($_POST["name"]), $message, alter_table(
$TABLE,
$_POST["name"],
$fields,
$foreign,
$_POST["Comment"],
($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? $_POST["Engine"] : ""),
($_POST["Collation"] && $_POST["Collation"] != $orig_status["Collation"] ? $_POST["Collation"] : ""),
($_POST["Auto_increment"] != "" ? preg_replace('~[^0-9]+~', '', $_POST["Auto_increment"]) : ""),
$partitioning
));
} }
} }
@ -127,9 +117,9 @@ if ($_POST) {
} }
$row["fields"][] = $field; $row["fields"][] = $field;
} }
if ($connection->server_info >= 5.1) { if (support("partitioning")) {
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . $connection->quote(DB) . " AND TABLE_NAME = " . $connection->quote($TABLE); $from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . $connection->quote(DB) . " AND TABLE_NAME = " . $connection->quote($TABLE);
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); $result = $connection->query("SELECT" . limit("PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION", 1));
list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row(); list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row();
$row["partition_names"] = array(); $row["partition_names"] = array();
$row["partition_values"] = array(); $row["partition_values"] = array();
@ -162,24 +152,23 @@ foreach ($engines as $engine) {
<p> <p>
<?php echo lang('Table name'); ?>: <input name="name" maxlength="64" value="<?php echo h($row["name"]); ?>"> <?php echo lang('Table name'); ?>: <input name="name" maxlength="64" value="<?php echo h($row["name"]); ?>">
<?php echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) : ""); ?> <?php echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) : ""); ?>
<?php echo html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]); ?> <?php echo ($collations ? 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'); ?>">
<table cellspacing="0" id="edit-fields" class="nowrap"> <table cellspacing="0" id="edit-fields" class="nowrap">
<?php $column_comments = edit_fields($row["fields"], $collations, "TABLE", $suhosin, $foreign_keys); ?> <?php $comments = edit_fields($row["fields"], $collations, "TABLE", $suhosin, $foreign_keys, $row["Comment"] != ""); ?>
</table> </table>
<p> <p>
<?php echo lang('Auto Increment'); ?>: <input name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>"> <?php echo lang('Auto Increment'); ?>: <input name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>">
<?php echo lang('Comment'); ?>: <input name="Comment" value="<?php echo h($row["Comment"]); ?>" maxlength="60">
<script type="text/javascript"> <script type="text/javascript">
document.write('<label><input type="checkbox" onclick="columnShow(this.checked, 5);"><?php echo lang('Default values'); ?><\/label>'); document.write('<label><input type="checkbox" onclick="columnShow(this.checked, 5);"><?php echo lang('Default values'); ?><\/label>');
document.write('<label><input type="checkbox"<?php if ($column_comments) { ?> checked<?php } ?> onclick="columnShow(this.checked, 6);"><?php echo lang('Show column comments'); ?><\/label>');
</script> </script>
<?php echo (support("comment") ? checkbox("", "", $comments, lang('Comment'), "columnShow(this.checked, 6); toggle('Comment');") . ' <input id="Comment" name="Comment" value="' . h($row["Comment"]) . '" maxlength="60"' . ($comments ? '' : ' class="hidden"') . '>' : ''); ?>
<p> <p>
<input type="hidden" name="token" value="<?php echo $token; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php if (strlen($_GET["create"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo $confirm; ?>><?php } ?> <?php if (strlen($_GET["create"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo $confirm; ?>><?php } ?>
<?php <?php
if ($connection->server_info >= 5.1) { if (support("partitioning")) {
$partition_table = ereg('RANGE|LIST', $row["partition_by"]); $partition_table = ereg('RANGE|LIST', $row["partition_by"]);
print_fieldset("partition", lang('Partition by'), $row["partition_by"]); print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
?> ?>

View file

@ -2,35 +2,26 @@
if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x
restart_session(); restart_session();
if ($_POST["drop"]) { 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.')); query_redirect("DROP DATABASE " . idf_escape(DB), remove_from_uri("db|database"), lang('Database has been dropped.'));
} elseif (DB !== $_POST["name"]) { } elseif (DB !== $_POST["name"]) {
// create or rename database // create or rename database
unset($_SESSION["databases"][$_GET["server"]]); // clear cache set_session("databases", null); // clear cache
$dbs = explode("\n", str_replace("\r", "", $_POST["name"])); if (DB != "") {
$failed = false; queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), rename_database($_POST["name"], $_POST["collation"]));
$last = ""; } else {
foreach ($dbs as $db) { $dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database $success = true;
if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) { $last = "";
$failed = true; foreach ($dbs as $db) {
} if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
$last = $db; if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
} $success = false;
} }
if (query_redirect(queries(), ME . "db=" . urlencode($last), lang('Database has been created.'), DB == "", false, $failed)) { $last = $db;
//! move triggers
$result = $connection->query("SHOW TABLES");
while ($row = $result->fetch_row()) {
if (!queries("RENAME TABLE " . idf_escape($row[0]) . " TO " . idf_escape($_POST["name"]) . "." . idf_escape($row[0]))) {
break;
} }
} }
if (!$row) { queries_redirect(ME . "db=" . urlencode($last), lang('Database has been created.'), $success);
queries("DROP DATABASE " . idf_escape(DB));
//! saved to history of removed database
}
queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), !$row);
} }
} else { } else {
// alter database // alter database
@ -49,17 +40,16 @@ $collate = null;
if ($_POST) { if ($_POST) {
$name = $_POST["name"]; $name = $_POST["name"];
$collate = $_POST["collation"]; $collate = $_POST["collation"];
} elseif (DB == "") { } elseif (DB != "") {
$collate = db_collation(DB, $collations);
} elseif ($driver == "sql") {
// propose database name with limited privileges // propose database name with limited privileges
$result = $connection->query("SHOW GRANTS"); foreach (get_vals("SHOW GRANTS") as $grant) {
while ($row = $result->fetch_row()) { if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $grant, $match) && $match[1]) {
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $row[0], $match) && $match[1]) { $name = stripcslashes(idf_unescape("`$match[2]`"));
$name = stripcslashes(idf_unescape($match[2]));
break; break;
} }
} }
} else {
$collate = db_collation(DB, $collations);
} }
?> ?>

View file

@ -4,18 +4,15 @@ $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 (count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"])) { if ($driver == "sql" && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"])) {
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
} }
if (isset($_POST["truncate"])) { if ($_POST["truncate"]) {
foreach ((array) $_POST["tables"] as $table) { if ($_POST["tables"]) {
if (!queries("TRUNCATE " . idf_escape($table))) { $result = truncate_tables($_POST["tables"]);
$result = false;
break;
}
} }
$message = lang('Tables have been truncated.'); $message = lang('Tables have been truncated.');
} elseif (isset($_POST["move"])) { } elseif ($_POST["move"]) {
$rename = array(); $rename = array();
foreach ($tables_views as $table) { foreach ($tables_views as $table) {
$rename[] = idf_escape($table) . " TO " . idf_escape($_POST["target"]) . "." . idf_escape($table); $rename[] = idf_escape($table) . " TO " . idf_escape($_POST["target"]) . "." . idf_escape($table);
@ -23,66 +20,65 @@ if ($tables_views && !$error && !$_POST["search"]) {
$result = queries("RENAME TABLE " . implode(", ", $rename)); $result = queries("RENAME TABLE " . implode(", ", $rename));
//! move triggers //! move triggers
$message = lang('Tables have been moved.'); $message = lang('Tables have been moved.');
} elseif ((!isset($_POST["drop"]) || !$_POST["views"] || queries("DROP VIEW " . implode(", ", array_map('idf_escape', $_POST["views"])))) } elseif ($_POST["drop"]) {
&& (!$_POST["tables"] || ($result = queries((isset($_POST["optimize"]) ? "OPTIMIZE" : (isset($_POST["check"]) ? "CHECK" : (isset($_POST["repair"]) ? "REPAIR" : (isset($_POST["drop"]) ? "DROP" : "ANALYZE")))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"]))))) if ($_POST["views"]) {
) { $result = drop_views($_POST["views"]);
if (isset($_POST["drop"])) { }
$message = lang('Tables have been dropped.'); if ($result && $_POST["tables"]) {
} else { $result = drop_tables($_POST["tables"]);
while ($row = $result->fetch_assoc()) { }
$message .= h("$row[Table]: $row[Msg_text]") . "<br>"; $message = lang('Tables have been dropped.');
} } elseif ($_POST["tables"] && ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"]))))) {
while ($row = $result->fetch_assoc()) {
$message .= h("$row[Table]: $row[Msg_text]") . "<br>";
} }
} }
queries_redirect(substr(ME, 0, -1), $message, $result); queries_redirect(substr(ME, 0, -1), $message, $result);
} }
page_header(lang('Database') . ": " . h(DB), $error, false); page_header(lang('Database') . ": " . h(DB), $error, true);
echo '<p><a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n"; echo '<p><a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n";
echo '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n"; echo '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n";
$sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
echo "<h3>" . lang('Tables and views') . "</h3>\n"; echo "<h3>" . lang('Tables and views') . "</h3>\n";
$table_status = table_status(); $tables_list = tables_list();
if (!$table_status) { if (!$tables_list) {
echo "<p class='message'>" . lang('No tables.') . "\n"; echo "<p class='message'>" . lang('No tables.') . "\n";
} else { } else {
echo "<form action='' method='post'>\n"; echo "<form action='' method='post'>\n";
echo "<p><input name='query' value='" . h($_POST["query"]) . "'> <input type='submit' name='search' value='" . lang('Search') . "'>\n"; echo "<p><input name='query' value='" . h($_POST["query"]) . "'> <input type='submit' name='search' value='" . lang('Search') . "'>\n";
if ($_POST["search"] && $_POST["query"] != "") { if ($_POST["search"] && $_POST["query"] != "") {
$_GET["where"][0]["op"] = "LIKE"; $_GET["where"][0]["op"] = "LIKE %%";
$_GET["where"][0]["val"] = "%$_POST[query]%"; $_GET["where"][0]["val"] = $_POST["query"];
search_tables(); search_tables();
} }
echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n"; echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n";
echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);"><th>' . lang('Table') . '<td>' . lang('Engine') . '<td>' . lang('Collation') . '<td>' . lang('Data Length') . '<td>' . lang('Index Length') . '<td>' . lang('Data Free') . '<td>' . lang('Auto Increment') . '<td>' . lang('Rows') . '<td>' . lang('Comment') . "</thead>\n"; echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);"><th>' . lang('Table') . '<td>' . lang('Engine') . '<td>' . lang('Collation') . '<td>' . lang('Data Length') . '<td>' . lang('Index Length') . '<td>' . lang('Data Free') . '<td>' . lang('Auto Increment') . '<td>' . lang('Rows') . (support("comment") ? '<td>' . lang('Comment') : '') . "</thead>\n";
$sums = array(); foreach ($tables_list as $name => $type) {
foreach ($table_status as $row) { $view = (isset($type) && !eregi("table", $type));
$name = $row["Name"]; echo '<tr' . odd() . '><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
echo '<tr' . odd() . '><td>' . checkbox((isset($row["Rows"]) ? "tables[]" : "views[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
echo '<th><a href="' . h(ME) . 'table=' . urlencode($name) . '">' . h($name) . '</a>'; echo '<th><a href="' . h(ME) . 'table=' . urlencode($name) . '">' . h($name) . '</a>';
if (isset($row["Rows"])) { if ($view) {
echo "<td>$row[Engine]<td>$row[Collation]";
foreach (array("Data_length" => "create", "Index_length" => "indexes", "Data_free" => "edit", "Auto_increment" => "auto_increment=1&create", "Rows" => "select") as $key => $link) {
$val = number_format($row[$key], 0, '.', lang(','));
echo '<td align="right">' . ($row[$key] != "" ? '<a href="' . h(ME . "$link=") . urlencode($name) . '">' . str_replace(" ", "&nbsp;", ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? lang('~ %s', $val) : $val)) . '</a>' : '&nbsp;');
$sums[$link] += ($row["Engine"] != "InnoDB" || $link != "edit" ? $row[$key] : 0);
}
echo "<td>" . nbsp($row["Comment"]);
} else {
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '">' . lang('View') . '</a>'; echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '">' . lang('View') . '</a>';
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '">?</a>'; echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '">?</a>';
echo '<td>&nbsp;'; } else {
echo "<td id='Engine-" . h($name) . "'>&nbsp;<td id='Collation-" . h($name) . "'>&nbsp;";
foreach (array("Data_length" => "create", "Index_length" => "indexes", "Data_free" => "edit", "Auto_increment" => "auto_increment=1&create", "Rows" => "select") as $key => $link) {
echo "<td align='right'><a href='" . h(ME . "$link=") . urlencode($name) . "' id='$key-" . h($name) . "'>?</a>";
}
} }
echo (support("comment") ? "<td id='Comment-" . h($name) . "'>&nbsp;" : "");
} }
echo "<tr><td>&nbsp;<th>" . lang('%d in total', count($table_status)); echo "<tr><td>&nbsp;<th>" . lang('%d in total', count($tables_list));
echo "<td>" . $connection->result($connection->query("SELECT @@storage_engine")); echo "<td>" . $connection->result("SELECT @@storage_engine");
echo "<td>" . db_collation(DB, collations()); echo "<td>" . db_collation(DB, collations());
foreach (array("create", "indexes", "edit") as $val) { foreach ($sums as $key => $val) {
echo "<td align='right'>" . number_format($sums[$val], 0, '.', lang(',')); echo "<td align='right' id='sum-$key'>&nbsp;";
} }
echo "</table>\n"; echo "</table>\n";
if (!information_schema(DB)) { if (!information_schema(DB)) {
echo "<p><input type='hidden' name='token' value='$token'><input type='submit' value='" . lang('Analyze') . "'> <input type='submit' name='optimize' value='" . lang('Optimize') . "'> <input type='submit' name='check' value='" . lang('Check') . "'> <input type='submit' name='repair' value='" . lang('Repair') . "'> <input type='submit' name='truncate' value='" . lang('Truncate') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables/) + ')');\"> <input type='submit' name='drop' value='" . lang('Drop') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables|views/) + ')');\">\n"; echo "<p><input type='hidden' name='token' value='$token'>" . ($driver == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> <input type='submit' name='optimize' value='" . lang('Optimize') . "'> <input type='submit' name='check' value='" . lang('Check') . "'> <input type='submit' name='repair' value='" . lang('Repair') . "'> " : "") . "<input type='submit' name='truncate' value='" . lang('Truncate') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables/) + ')');\"> <input type='submit' name='drop' value='" . lang('Drop') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables|views/) + ')');\">\n";
$dbs = get_databases(); $dbs = get_databases();
if (count($dbs) != 1) { if (count($dbs) != 1) {
$db = (isset($_POST["target"]) ? $_POST["target"] : DB); $db = (isset($_POST["target"]) ? $_POST["target"] : DB);
@ -93,8 +89,10 @@ if (!$table_status) {
} }
echo '<p><a href="' . h(ME) . 'create=">' . lang('Create table') . "</a>\n"; echo '<p><a href="' . h(ME) . 'create=">' . lang('Create table') . "</a>\n";
if ($connection->server_info >= 5) { if (support("view")) {
echo '<a href="' . h(ME) . 'view=">' . lang('Create view') . "</a>\n"; echo '<a href="' . h(ME) . 'view=">' . lang('Create view') . "</a>\n";
}
if (support("routine")) {
echo "<h3>" . lang('Routines') . "</h3>\n"; echo "<h3>" . lang('Routines') . "</h3>\n";
$result = $connection->query("SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . $connection->quote(DB)); $result = $connection->query("SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . $connection->quote(DB));
if ($result->num_rows) { if ($result->num_rows) {
@ -110,9 +108,10 @@ if ($connection->server_info >= 5) {
echo '<p><a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a> <a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n"; echo '<p><a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a> <a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n";
} }
if ($connection->server_info >= 5.1 && ($result = $connection->query("SHOW EVENTS"))) { if (support("event")) {
echo "<h3>" . lang('Events') . "</h3>\n"; echo "<h3>" . lang('Events') . "</h3>\n";
if ($result->num_rows) { $result = $connection->query("SHOW EVENTS");
if ($result && $result->num_rows) {
echo "<table cellspacing='0'>\n"; echo "<table cellspacing='0'>\n";
echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "</thead>\n"; echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "</thead>\n";
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
@ -125,3 +124,34 @@ if ($connection->server_info >= 5.1 && ($result = $connection->query("SHOW EVENT
} }
echo '<p><a href="' . h(ME) . 'event=">' . lang('Create event') . "</a>\n"; echo '<p><a href="' . h(ME) . 'event=">' . lang('Create event') . "</a>\n";
} }
page_footer();
$table_status = table_status();
if ($table_status) {
echo "<script type='text/javascript'>\n";
foreach ($table_status as $row) {
$id = addcslashes($row["Name"], "\\'/");
echo "setHtml('Comment-$id', '" . nbsp($row["Comment"]) . "');\n";
if (!eregi("view", $row["Engine"])) {
foreach (array("Engine", "Collation") as $key) {
echo "setHtml('$key-$id', '" . nbsp($row[$key]) . "');\n";
}
foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
if ($row[$key] != "") {
$val = number_format($row[$key], 0, '.', lang(','));
echo "setHtml('$key-$id', '" . ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? "~ $val" : $val) . "');\n";
if (isset($sums[$key])) {
$sums[$key] += ($row["Engine"] != "InnoDB" || $key != "Data_free" ? $row[$key] : 0);
}
} elseif (array_key_exists($key, $row)) {
echo "setHtml('$key-$id');\n";
}
}
}
}
foreach ($sums as $key => $val) {
echo "setHtml('sum-$key', '" . number_format($val, 0, '.', lang(',')) . "');\n";
}
echo "</script>\n";
}
exit; // page_footer() already called

View file

@ -2,5 +2,5 @@
$TABLE = $_GET["download"]; $TABLE = $_GET["download"];
header("Content-Type: application/octet-stream"); header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=" . friendly_url("$TABLE-" . implode("_", $_GET["where"])) . "." . friendly_url($_GET["field"])); header("Content-Disposition: attachment; filename=" . friendly_url("$TABLE-" . implode("_", $_GET["where"])) . "." . friendly_url($_GET["field"]));
echo $connection->result($connection->query("SELECT " . idf_escape($_GET["field"]) . " FROM " . idf_escape($TABLE) . " WHERE " . where($_GET) . " LIMIT 1")); echo $connection->result("SELECT" . limit(idf_escape($_GET["field"]) . " FROM " . idf_escape($TABLE) . " WHERE " . where($_GET), 1));
exit; // don't output footer exit; // don't output footer

View file

@ -0,0 +1,406 @@
<?php
/**
* @author Jakub Cernohuby
* @author Vladimir Stastka
* @author Jakub Vrana
*/
$possible_drivers[] = "SQLSRV";
$possible_drivers[] = "MSSQL";
if (extension_loaded("sqlsrv") || extension_loaded("mssql")) {
$drivers["mssql"] = "MS SQL";
}
if (isset($_GET["mssql"])) {
define("DRIVER", "mssql");
if (extension_loaded("sqlsrv")) {
class Min_DB {
var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $error;
function _get_error() {
$this->error = "";
foreach (sqlsrv_errors() as $error) {
$this->error .= "$error[message]\n";
}
$this->error = rtrim($this->error);
}
function connect($server, $username, $password) {
$this->_link = @sqlsrv_connect($server, array("UID" => $username, "PWD" => $password));
if ($this->_link) {
$info = sqlsrv_server_info($this->_link);
$this->server_info = $info['SQLServerVersion'];
} else {
$this->_get_error();
}
return (bool) $this->_link;
}
function quote($string) {
return "'" . str_replace("'", "''", $string) . "'";
}
function select_db($database) {
return $this->query("USE $database");
}
function query($query, $unbuffered = false) {
$result = sqlsrv_query($this->_link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
if (!$result) {
$this->_get_error();
return false;
}
return $this->store_result($result);
}
function multi_query($query) {
$this->_result = sqlsrv_query($this->_link, $query);
if (!$this->_result) {
$this->_get_error();
return false;
}
return true;
}
function store_result($result = null) {
if (!$result) {
$result = $this->_result;
}
if (sqlsrv_field_metadata($result)) {
return new Min_Result($result);
}
$this->affected_rows = sqlsrv_rows_affected($result);
return true;
}
function next_result() {
return sqlsrv_next_result($this->_result);
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!is_object($result)) {
return false;
}
$row = $result->fetch_row();
return $row[$field];
}
}
class Min_Result {
var $_result, $_offset = 0, $_fields, $num_rows;
function Min_Result($result) {
$this->_result = $result;
$this->num_rows = sqlsrv_has_rows($result); //! sqlsrv_num_rows($result)
}
function _convert($row) {
foreach ((array) $row as $key => $val) {
if (is_a($val, 'DateTime')) {
$row[$key] = $val->format("Y-m-d H:i:s");
}
//! stream
}
return $row;
}
function fetch_assoc() {
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_ASSOC, SQLSRV_SCROLL_NEXT));
}
function fetch_row() {
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_NUMERIC, SQLSRV_SCROLL_NEXT));
}
function fetch_field() {
if (!$this->_fields) {
$this->_fields = sqlsrv_field_metadata($this->_result);
}
$field = $this->_fields[$this->_offset++];
$return = new stdClass;
$return->name = $field["Name"];
$return->orgname = $field["Name"];
$return->type = ($field["Type"] == 1 ? 254 : 0);
return $return;
}
function __destruct() {
sqlsrv_free_stmt($this->_result);
}
}
} elseif (extension_loaded("mssql")) {
class Min_DB {
var $extension = "MSSQL", $_link, $_result, $server_info, $affected_rows, $error;
function connect($server, $username, $password) {
$this->_link = @mssql_connect($server, $username, $password);
if ($this->_link) {
$result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
$row = $result->fetch_row();
$this->server_info = $this->result("sp_server_info 2", 2)." [$row[0]] $row[1]";
} else {
$this->error = mssql_get_last_message();
}
return (bool) $this->_link;
}
function quote($string) {
return "'" . str_replace("'", "''", $string) . "'";
}
function select_db($database) {
return mssql_select_db($database);
}
function query($query, $unbuffered = false) {
$result = mssql_query($query, $this->_link); //! $unbuffered
if (!$result) {
$this->error = mssql_get_last_message();
return false;
}
if ($result === true) {
$this->affected_rows = mssql_rows_affected($this->_link);
return true;
}
return new Min_Result($result);
}
function multi_query($query) {
return $this->_result = $this->query($query);
}
function store_result() {
return $this->_result;
}
function next_result() {
return mssql_next_result($this->_result);
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!is_object($result)) {
return false;
}
return mssql_result($result->_result, 0, $field);
}
}
class Min_Result {
var $_result, $_offset = 0, $_fields, $num_rows;
function Min_Result($result) {
$this->_result = $result;
$this->num_rows = mssql_num_rows($result);
}
function fetch_assoc() {
return mssql_fetch_assoc($this->_result);
}
function fetch_row() {
return mssql_fetch_row($this->_result);
}
function num_rows() {
return mssql_num_rows($this->_result);
}
function fetch_field() {
$return = mssql_fetch_field($this->_result);
$return->orgtable = $return->table;
$return->orgname = $return->name;
return $return;
}
function __destruct() {
mssql_free_result($this->_result);
}
}
}
function idf_escape($idf) {
return "[" . str_replace("]", "]]", $idf) . "]";
}
function connect() {
global $adminer;
$connection = new Min_DB;
$credentials = $adminer->credentials();
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection;
}
return $connection->error;
}
function get_databases() {
return get_vals("EXEC sp_databases");
}
function limit($query, $limit, $offset = 0) {
return (isset($limit) ? " TOP ($limit)" : "") . " $query"; //! offset
}
function limit1($query, $limit, $offset = 0) {
return limit($query, 1);
}
function db_collation($db, $collations) {
global $connection;
return $connection->result("SELECT collation_name FROM sys.databases WHERE name = " . $connection->quote($db));
}
function engines() {
return array();
}
function logged_user() {
global $connection;
return $connection->result("SELECT SUSER_NAME()");
}
function tables_list() {
return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES");
}
function count_tables($databases) {
global $connection;
$return = array();
foreach ($databases as $db) {
$connection->select_db($db);
$return[$db] = $connection->result("SELECT COUNT(*) FROM information_schema.TABLES");
}
return $return;
}
function table_status($name = "") {
global $connection;
$return = array();
$result = $connection->query("SELECT TABLE_NAME AS Name, TABLE_TYPE AS Engine FROM information_schema.TABLES" . ($name != "" ? " WHERE TABLE_NAME = " . $connection->quote($name) : ""));
while ($row = $result->fetch_assoc()) {
if ($name != "") {
return $row;
}
$return[$row["Name"]] = $row;
}
return $return;
}
function fk_support($table_status) {
return true;
}
function fields($table) {
global $connection;
$return = array();
$result = $connection->query("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = " . $connection->quote($table));
while ($row = $result->fetch_assoc()) {
$return[$row["COLUMN_NAME"]] = array(
"field" => $row["COLUMN_NAME"],
"full_type" => $row["DATA_TYPE"],
"type" => $row["DATA_TYPE"],
"length" => $row["CHARACTER_MAXIMUM_LENGTH"], //! NUMERIC_, DATETIME_?
"default" => $row["COLUMN_DEFAULT"],
"null" => ($row["IS_NULLABLE"] == "YES"),
"collation" => $row["COLLATION_NAME"],
"privileges" => array("insert" => 1, "select" => 1, "update" => 1),
//! primary - is_identity in sys.columns
);
}
return $return;
}
function indexes($table, $connection2 = null) {
global $connection;
if (!is_object($connection2)) {
$connection2 = $connection;
}
$return = array();
// sp_statistics doesn't return information about primary key
$result = $connection2->query("SELECT indexes.name, key_ordinal, is_unique, is_primary_key, columns.name AS column_name
FROM sys.indexes
INNER JOIN sys.index_columns ON indexes.object_id = index_columns.object_id AND indexes.index_id = index_columns.index_id
INNER JOIN sys.columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id
WHERE OBJECT_NAME(indexes.object_id) = " . $connection2->quote($table));
if ($result) {
while ($row = $result->fetch_assoc()) {
$return[$row["name"]]["type"] = ($row["is_primary_key"] ? "PRIMARY" : ($row["is_unique"] ? "UNIQUE" : "INDEX"));
$return[$row["name"]]["columns"][$row["key_ordinal"]] = $row["column_name"];
}
}
return $return;
}
function collations() {
$return = array();
foreach (get_vals("SELECT name FROM fn_helpcollations()") as $collation) {
$return[ereg_replace("_.*", "", $collation)][] = $collation;
}
return $return;
}
function information_schema($db) {
return false;
}
function error() {
global $connection;
return nl_br(h(ereg_replace("^(\\[[^]]*])+", "", $connection->error)));
}
function exact_value($val) {
global $connection;
return $connection->quote($val);
}
function rename_database($name, $collation) {
if ($collation) {
queries("ALTER DATABASE " . idf_escape(DB) . " COLLATE " . idf_escape($collation));
}
return queries("ALTER DATABASE " . idf_escape(DB) . " MODIFY NAME = " . idf_escape($name)); //! false negative "The database name 'test2' has been set."
}
function auto_increment() {
return " IDENTITY";
}
function explain($connection, $query) {
$connection->query("SET SHOWPLAN_ALL ON");
$return = $connection->query($query);
$connection->query("SET SHOWPLAN_ALL OFF"); // connection is used also for indexes
return $return;
}
function support($feature) {
return ereg('^(view|routine|trigger)$', $feature);
}
$driver = "mssql";
$types = array();
$structured_types = array();
foreach (array(
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
$unsigned = array();
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
$functions = array("len", "lower", "round", "upper");
$grouping = array("avg", "count", "count distinct", "max", "min", "sum");
$edit_functions = array(
array(
"date|time" => "getdate",
), array(
"int|decimal|real|float|money|datetime" => "+/-",
"char|text" => "+",
)
);
}

View file

@ -0,0 +1,713 @@
<?php
$possible_drivers[] = "MySQLi";
$possible_drivers[] = "MySQL";
$possible_drivers[] = "PDO_MySQL";
if (extension_loaded("mysqli") || extension_loaded("mysql") || extension_loaded("pdo_mysql")) {
$drivers = array("server" => "MySQL") + $drivers;
}
if (!defined("DRIVER")) {
define("DRIVER", "server"); // server - backwards compatibility
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
if (extension_loaded("mysqli")) {
class Min_DB extends MySQLi {
var $extension = "MySQLi";
function Min_DB() {
parent::init();
}
function connect($server, $username, $password) {
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
return @$this->real_connect(
($server != "" ? $host : ini_get("mysqli.default_host")),
("$server$username" != "" ? $username : ini_get("mysqli.default_user")),
("$server$username$password" != "" ? $password : ini_get("mysqli.default_pw")),
null,
(is_numeric($port) ? $port : ini_get("mysqli.default_port")),
(!is_numeric($port) ? $port : null)
);
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result) {
return false;
}
$row = $result->fetch_array();
return $row[$field];
}
function quote($string) {
return "'" . $this->escape_string($string) . "'";
}
}
} elseif (extension_loaded("mysql")) {
class Min_DB {
var
$extension = "MySQL", ///< @var string extension name
$server_info, ///< @var string server version
$affected_rows, ///< @var int number of affected rows
$error, ///< @var string last error message
$_link, $_result ///< @access private
;
/** Connect to server
* @param string
* @param string
* @param string
* @return bool
*/
function connect($server, $username, $password) {
$this->_link = @mysql_connect(
($server != "" ? $server : ini_get("mysql.default_host")),
("$server$username" != "" ? $username : ini_get("mysql.default_user")),
("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
true,
131072 // CLIENT_MULTI_RESULTS for CALL
);
if ($this->_link) {
$this->server_info = mysql_get_server_info($this->_link);
} else {
$this->error = mysql_error();
}
return (bool) $this->_link;
}
/** Quote string to use in SQL
* @param string
* @return string escaped string enclosed in '
*/
function quote($string) {
return "'" . mysql_real_escape_string($string, $this->_link) . "'";
}
/** Select database
* @param string
* @return bool
*/
function select_db($database) {
return mysql_select_db($database, $this->_link);
}
/** Send query
* @param string
* @param bool
* @return mixed bool or Min_Result
*/
function query($query, $unbuffered = false) {
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
if (!$result) {
$this->error = mysql_error($this->_link);
return false;
}
if ($result === true) {
$this->affected_rows = mysql_affected_rows($this->_link);
$this->info = mysql_info($this->_link);
return true;
}
return new Min_Result($result);
}
/** Send query with more resultsets
* @param string
* @return bool
*/
function multi_query($query) {
return $this->_result = $this->query($query);
}
/** Get current resultset
* @return Min_Result
*/
function store_result() {
return $this->_result;
}
/** Fetch next resultset
* @return bool
*/
function next_result() {
// MySQL extension doesn't support multiple results
return false;
}
/** Get single field from result
* @param string
* @param int
* @return string
*/
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result) {
return false;
}
return mysql_result($result->_result, 0, $field);
}
}
class Min_Result {
var
$num_rows, ///< @var int number of rows in the result
$_result ///< @access private
;
/** Constructor
* @param resource
*/
function Min_Result($result) {
$this->_result = $result;
$this->num_rows = mysql_num_rows($result);
}
/** Fetch next row as associative array
* @return array
*/
function fetch_assoc() {
return mysql_fetch_assoc($this->_result);
}
/** Fetch next row as numbered array
* @return array
*/
function fetch_row() {
return mysql_fetch_row($this->_result);
}
/** Fetch next field
* @return object properties: name, type, orgtable, orgname, charsetnr
*/
function fetch_field() {
$return = mysql_fetch_field($this->_result);
$return->orgtable = $return->table;
$return->orgname = $return->name;
$return->charsetnr = ($return->blob ? 63 : 0);
return $return;
}
/** Free result set
*/
function __destruct() {
mysql_free_result($this->_result); //! not called in PHP 4 which is a problem with mysql.trace_mode
}
}
} elseif (extension_loaded("pdo_mysql")) {
class Min_DB extends Min_PDO {
var $extension = "PDO_MySQL";
function connect($server, $username, $password) {
$this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:([0-9])~', ';port=\\1', $server)), $username, $password);
return true;
}
function select_db($database) {
// database selection is separated from the connection so dbname in DSN can't be used
return $this->query("USE " . idf_escape($database));
}
function query($query, $unbuffered = false) {
$this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
return parent::query($query, $unbuffered);
}
}
}
/** Escape database identifier
* @param string
* @return string
*/
function idf_escape($idf) {
return "`" . str_replace("`", "``", $idf) . "`";
}
/** Connect to the database
* @return mixed Min_DB or string for error
*/
function connect() {
global $adminer;
$connection = new Min_DB;
$credentials = $adminer->credentials();
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
$connection->query("SET SQL_QUOTE_SHOW_CREATE=1");
$connection->query("SET NAMES utf8");
return $connection;
}
return $connection->error;
}
/** Get cached list of databases
* @param bool
* @return array
*/
function get_databases($flush = true) {
// SHOW DATABASES can take a very long time so it is cached
$return = &get_session("databases");
if (!isset($return)) {
if ($flush) {
restart_session();
ob_flush();
flush();
}
$return = get_vals("SHOW DATABASES");
}
return $return;
}
/** Formulate SQL query with limit
* @param string everything after SELECT
* @param int
* @param int
* @return string
*/
function limit($query, $limit, $offset = 0) {
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
}
/** Formulate SQL modification query with limit 1
* @param string everything after UPDATE or DELETE
* @return string
*/
function limit1($query) {
return limit($query, 1);
}
/** Get database collation
* @param string
* @param array result of collations()
* @return string
*/
function db_collation($db, $collations) {
global $connection;
$return = null;
$create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1);
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
$return = $match[1];
} elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
// default collation
$return = $collations[$match[1]][0];
}
return $return;
}
/** Get supported engines
* @return array
*/
function engines() {
global $connection;
$return = array();
$result = $connection->query("SHOW ENGINES");
while ($row = $result->fetch_assoc()) {
if (ereg("YES|DEFAULT", $row["Support"])) {
$return[] = $row["Engine"];
}
}
return $return;
}
/** Get logged user
* @return string
*/
function logged_user() {
global $connection;
return $connection->result("SELECT USER()");
}
/** Get tables list
* @return array
*/
function tables_list() {
global $connection;
return get_key_vals("SHOW" . ($connection->server_info >= 5 ? " FULL" : "") . " TABLES");
}
/** Count tables in all databases
* @param array
* @return array array($db => $tables)
*/
function count_tables($databases) {
$return = array();
foreach ($databases as $db) {
$return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db)));
}
return $return;
}
/** Get table status
* @param string
* @return array
*/
function table_status($name = "") {
global $connection;
$return = array();
$result = $connection->query("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . $connection->quote(addcslashes($name, "%_")) : ""));
while ($row = $result->fetch_assoc()) {
if ($row["Engine"] == "InnoDB") {
// ignore internal comment, unnecessary since MySQL 5.1.21
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
}
if (!isset($row["Rows"])) {
$row["Engine"] = "VIEW";
$row["Comment"] = "";
}
if ($name != "") {
return $row;
}
$return[$row["Name"]] = $row;
}
return $return;
}
/** Check if table supports foreign keys
* @param array result of table_status
* @return bool
*/
function fk_support($table_status) {
return ($table_status["Engine"] == "InnoDB");
}
/** Get information about fields
* @param string
* @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
*/
function fields($table) {
global $connection;
$return = array();
$result = $connection->query("SHOW FULL COLUMNS FROM " . idf_escape($table));
if ($result) {
while ($row = $result->fetch_assoc()) {
preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
$return[$row["Field"]] = array(
"field" => $row["Field"],
"full_type" => $row["Type"],
"type" => $match[1],
"length" => $match[2],
"unsigned" => ltrim($match[3] . $match[4]),
"default" => ($row["Default"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
"null" => ($row["Null"] == "YES"),
"auto_increment" => ($row["Extra"] == "auto_increment"),
"on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
"collation" => $row["Collation"],
"privileges" => array_flip(explode(",", $row["Privileges"])),
"comment" => $row["Comment"],
"primary" => ($row["Key"] == "PRI"),
);
}
}
return $return;
}
/** Get table indexes
* @param string
* @param string Min_DB to use
* @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array()))
*/
function indexes($table, $connection2 = null) {
global $connection;
if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
$connection2 = $connection;
}
$return = array();
$result = $connection2->query("SHOW INDEX FROM " . idf_escape($table));
if ($result) {
while ($row = $result->fetch_assoc()) {
$return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE")));
$return[$row["Key_name"]]["columns"][] = $row["Column_name"];
$return[$row["Key_name"]]["lengths"][] = $row["Sub_part"];
}
}
return $return;
}
/** Get foreign keys in table
* @param string
* @return array array($name => array("db" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
*/
function foreign_keys($table) {
global $connection, $on_actions;
static $pattern = '`(?:[^`]|``)+`';
$return = array();
$create_table = $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
if ($create_table) {
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $on_actions) . "))?~", $create_table, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
preg_match_all("~$pattern~", $match[2], $source);
preg_match_all("~$pattern~", $match[5], $target);
$return[idf_unescape($match[1])] = array(
"db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
"table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
"source" => array_map('idf_unescape', $source[0]),
"target" => array_map('idf_unescape', $target[0]),
"on_delete" => $match[6],
"on_update" => $match[7],
);
}
}
return $return;
}
/** Get view SELECT
* @param string
* @return array array("select" => )
*/
function view($name) {
global $connection;
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result("SHOW CREATE VIEW " . idf_escape($name), 1)));
}
/** Get sorted grouped list of collations
* @return array
*/
function collations() {
global $connection;
$return = array();
$result = $connection->query("SHOW COLLATION");
while ($row = $result->fetch_assoc()) {
$return[$row["Charset"]][] = $row["Collation"];
}
ksort($return);
foreach ($return as $key => $val) {
sort($return[$key]);
}
return $return;
}
/** Find out if database is information_schema
* @param string
* @return bool
*/
function information_schema($db) {
global $connection;
return ($connection->server_info >= 5 && $db == "information_schema");
}
/** Get escaped error message
* @return string
*/
function error() {
global $connection;
return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error));
}
/** Return expression for binary comparison
* @param string
* @return string
*/
function exact_value($val) {
global $connection;
return "BINARY " . $connection->quote($val);
}
/** Rename database from DB
* @param string new name
* @return string
* @return bool
*/
function rename_database($name, $collation) {
global $connection;
$return = false;
if (queries("CREATE DATABASE " . idf_escape($name) . ($collation ? " COLLATE " . $connection->quote($collation) : ""))) {
//! move triggers
$return = true; // table list may by empty
foreach (tables_list() as $table) {
if (!queries("RENAME TABLE " . idf_escape($table) . " TO " . idf_escape($name) . "." . idf_escape($table))) {
$return = false;
break;
}
}
if ($return) {
queries("DROP DATABASE " . idf_escape(DB));
//! saved to history of removed database
}
}
return $return;
}
/** Generate modifier for auto increment column
* @return string
*/
function auto_increment() {
$auto_increment_index = " PRIMARY KEY";
// don't overwrite primary key by auto_increment
if ($_GET["create"] != "" && $_POST["auto_increment_col"]) {
foreach (indexes($_GET["create"]) as $index) {
if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
$auto_increment_index = "";
break;
}
if ($index["type"] == "PRIMARY") {
$auto_increment_index = " UNIQUE";
}
}
}
return " AUTO_INCREMENT$auto_increment_index";
}
/** Run commands to create or alter table
* @param string "" to create
* @param string new name
* @param array of array($orig, $process_field, $after)
* @param array of strings
* @param string
* @param string
* @param string
* @param int
* @param string
* @return bool
*/
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
global $connection;
$alter = array();
foreach ($fields as $field) {
$alter[] = ($field[1]
? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode("", $field[1]) . ($table != "" ? " $field[2]" : "")
: "DROP " . idf_escape($field[0])
);
}
$alter = array_merge($alter, $foreign);
$status = "COMMENT=" . $connection->quote($comment)
. ($engine ? " ENGINE=" . $connection->quote($engine) : "")
. ($collation ? " COLLATE " . $connection->quote($collation) : "")
. ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "")
. $partitioning
;
if ($table == "") {
return queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n) $status");
}
if ($table != $name) {
$alter[] = "RENAME TO " . idf_escape($name);
}
$alter[] = $status;
return queries("ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
}
/** Run commands to alter indexes
* @param string escaped table name
* @param array of array("index type", "(columns definition)") or array("index type", "escaped name", "DROP")
* @return bool
*/
function alter_indexes($table, $alter) {
foreach ($alter as $key => $val) {
$alter[$key] = ($val[2] ? "\nDROP INDEX " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
}
return queries("ALTER TABLE " . idf_escape($table) . implode(",", $alter));
}
/** Run commands to truncate tables
* @param array
* @return bool
*/
function truncate_tables($tables) {
foreach ($tables as $table) {
if (!queries("TRUNCATE TABLE " . idf_escape($table))) {
return false;
}
}
return true;
}
/** Drop views
* @param array
* @return bool
*/
function drop_views($views) {
return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
}
/** Drop tables
* @param array
* @return bool
*/
function drop_tables($tables) {
return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
}
/** Get information about trigger
* @param string trigger name
* @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
*/
function trigger($name) {
global $connection;
$result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($name));
return $result->fetch_assoc();
}
/** Get defined triggers
* @param string
* @return array array($name => array($timing, $event))
*/
function triggers($table) {
global $connection;
$return = array();
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_")));
while ($row = $result->fetch_assoc()) {
$return[$row["Trigger"]] = array($row["Timing"], $row["Event"]);
}
return $return;
}
/** Explain select
* @param Min_DB
* @param string
* @return Min_Result
*/
function explain($connection, $query) {
return $connection->query("EXPLAIN $query");
}
/** Get SQL command to create table
* @param string
* @return string
*/
function create_sql($table) {
global $connection;
return $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
}
/** Check whether a feature is supported
* @param string
* @return bool
*/
function support($feature) {
global $connection;
$features = array(
"view" => ($connection->server_info >= 5),
"routine" => ($connection->server_info >= 5),
"trigger" => ($connection->server_info >= 5),
"event" => ($connection->server_info >= 5.1),
"partitioning" => ($connection->server_info >= 5.1),
);
return (isset($features[$feature]) ? $features[$feature] : true);
}
$driver = "sql"; ///< @var string JUSH identifier
$types = array(); ///< @var array ($type => $maximum_unsigned_length, ...)
$structured_types = array(); ///< @var array ($description => array($type, ...), ...)
foreach (array(
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
lang('Binary') => array("binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
lang('Lists') => array("enum" => 65535, "set" => 64),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
$unsigned = array("unsigned", "zerofill", "unsigned zerofill"); ///< @var array number variants
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL"); ///< @var array operators used in select
$functions = array("char_length", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "upper"); ///< @var array functions used in select
$grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select
$edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
array(
"char" => "md5/sha1/password/encrypt/uuid", //! JavaScript for disabling maxlength
"date|time" => "now",
), array(
"int|float|double|decimal" => "+/-",
"date" => "+ interval/- interval",
"time" => "addtime/subtime",
"char|text" => "concat",
)
);
}

View file

@ -0,0 +1,443 @@
<?php
$possible_drivers[] = "PgSQL";
$possible_drivers[] = "PDO_PgSQL";
if (extension_loaded("pgsql") || extension_loaded("pdo_pgsql")) {
$drivers["pgsql"] = "PostgreSQL";
}
if (isset($_GET["pgsql"])) {
define("DRIVER", "pgsql");
if (extension_loaded("pgsql")) {
class Min_DB {
var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error;
function _error($errno, $error) {
if (ini_bool("html_errors")) {
$error = html_entity_decode(strip_tags($error));
}
$error = ereg_replace('^[^:]*: ', '', $error);
$this->error = $error;
}
function connect($server, $username, $password) {
set_error_handler(array($this, '_error'));
$this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
$this->_link = @pg_connect($this->_string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), PGSQL_CONNECT_FORCE_NEW);
if (!$this->_link && DB != "") {
// try to connect directly with database for performance
$this->_database = false;
$this->_link = @pg_connect($this->_string, PGSQL_CONNECT_FORCE_NEW);
}
restore_error_handler();
if ($this->_link) {
$version = pg_version($this->_link);
$this->server_info = $version["server"];
pg_set_client_encoding($this->_link, "UTF8");
}
return (bool) $this->_link;
}
function quote($string) {
return "'" . pg_escape_string($this->_link, $string) . "'"; //! bytea
}
function select_db($database) {
if ($database == DB) {
return $this->_database;
}
$link = @pg_connect($this->_connection . " dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
if ($link) {
$this->_link = $link;
}
return $link;
}
function query($query, $unbuffered = false) {
$result = @pg_query($this->_link, $query);
if (!$result) {
$this->error = pg_last_error($this->_link);
return false;
} elseif (!pg_num_fields($result)) {
$this->affected_rows = pg_affected_rows($result);
return true;
}
return new Min_Result($result);
}
function multi_query($query) {
return $this->_result = $this->query($query);
}
function store_result() {
return $this->_result;
}
function next_result() {
// PgSQL extension doesn't support multiple results
return false;
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result) {
return false;
}
return pg_fetch_result($result->_result, 0, $field);
}
}
class Min_Result {
var $_result, $_offset = 0, $num_rows;
function Min_Result($result) {
$this->_result = $result;
$this->num_rows = pg_num_rows($result);
}
function fetch_assoc() {
return pg_fetch_assoc($this->_result);
}
function fetch_row() {
return pg_fetch_row($this->_result);
}
function fetch_field() {
$column = $this->_offset++;
$row = new stdClass;
$row->orgtable = pg_field_table($this->_result, $column);
$row->name = pg_field_name($this->_result, $column);
$row->orgname = $row->name;
$row->type = pg_field_type($this->_result, $column);
$row->charsetnr = ($row->type == "bytea" ? 63 : 0);
return $row;
}
function __destruct() {
pg_free_result($this->_result);
}
}
} elseif (extension_loaded("pdo_pgsql")) {
class Min_DB extends Min_PDO {
var $extension = "PDO_PgSQL";
function connect($server, $username, $password) {
$string = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' options='-c client_encoding=utf8'";
$this->dsn($string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), $username, $password);
//! connect without DB in case of an error
return true;
}
function select_db($database) {
return (DB == $database);
}
}
}
function idf_escape($idf) {
return '"' . str_replace('"', '""', $idf) . '"';
}
function connect() {
global $adminer;
$connection = new Min_DB;
$credentials = $adminer->credentials();
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection;
}
return $connection->error;
}
function get_databases() {
return get_vals("SELECT datname FROM pg_database");
}
function limit($query, $limit, $offset = 0) {
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
}
function limit1($query) {
return " $query";
}
function db_collation($db, $collations) {
global $connection;
return $connection->result("SHOW LC_COLLATE"); //! respect $db
}
function engines() {
return array();
}
function logged_user() {
global $connection;
return $connection->result("SELECT user");
}
function tables_list() {
global $connection;
return get_key_vals("SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name");
}
function count_tables($databases) {
return array(); // would require reconnect
}
function table_status($name = "") {
global $connection;
$return = array();
$result = $connection->query("SELECT relname AS \"Name\", CASE relkind WHEN 'r' THEN '' ELSE 'view' END AS \"Engine\", pg_relation_size(oid) AS \"Data_length\", pg_catalog.obj_description(oid, 'pg_class') AS \"Comment\" FROM pg_catalog.pg_class WHERE relkind IN ('r','v') AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')" . ($name != "" ? " AND relname = " . $connection->quote($name) : "")); //! Index_length, Auto_increment
while ($row = $result->fetch_assoc()) {
$return[$row["Name"]] = $row;
}
return ($name != "" ? $return[$name] : $return);
}
function fk_support($table_status) {
return true;
}
function fields($table) {
global $connection;
$return = array();
$table_oid = $connection->result("SELECT oid FROM pg_class WHERE relname = " . $connection->quote($table));
$result = $connection->query("SELECT *, col_description($table_oid, ordinal_position) AS comment FROM information_schema.columns WHERE table_name = " . $connection->quote($table) . " ORDER BY ordinal_position");
if ($result) {
while ($row = $result->fetch_assoc()) {
$length = $row["character_maximum_length"];
$return[$row["column_name"]] = array(
"field" => $row["column_name"],
"full_type" => $row["data_type"] . ($length ? "($length)" : ""),
"type" => $row["data_type"],
"length" => $length,
"default" => $row["column_default"],
"null" => ($row["is_nullable"] == "YES"),
"auto_increment" => eregi("^nextval\\(", $row["column_default"]),
"on_update" => "", //!
"collation" => $row["collation_name"],
"privileges" => array("insert" => 1, "select" => 1, "update" => 1), //! is_updatable
"primary" => false, //!
"comment" => $row["comment"],
);
}
}
return $return;
}
function indexes($table, $connection2 = null) {
global $connection;
if (!is_object($connection2)) {
$connection2 = $connection;
}
$return = array();
$table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relname = " . $connection2->quote($table));
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
$result = $connection2->query("SELECT relname, indisunique, indisprimary, indkey FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid");
while ($row = $result->fetch_assoc()) {
$return[$row["relname"]]["type"] = ($row["indisprimary"] == "t" ? "PRIMARY" : ($row["indisunique"] == "t" ? "UNIQUE" : "INDEX"));
$return[$row["relname"]]["columns"] = array();
foreach (explode(" ", $row["indkey"]) as $indkey) {
$return[$row["relname"]]["columns"][] = $columns[$indkey];
}
$return[$row["relname"]]["lengths"] = array();
}
return $return;
}
function foreign_keys($table) {
global $connection;
$return = array();
$result = $connection->query("SELECT tc.constraint_name, kcu.column_name, rc.update_rule AS on_update, rc.delete_rule AS on_delete, ccu.table_name AS table, ccu.column_name AS ref
FROM information_schema.table_constraints tc
LEFT JOIN information_schema.key_column_usage kcu USING (constraint_catalog, constraint_schema, constraint_name)
LEFT JOIN information_schema.referential_constraints rc USING (constraint_catalog, constraint_schema, constraint_name)
LEFT JOIN information_schema.constraint_column_usage ccu ON rc.unique_constraint_catalog = ccu.constraint_catalog AND rc.unique_constraint_schema = ccu.constraint_schema AND rc.unique_constraint_name = ccu.constraint_name
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = " . $connection->quote($table)); //! there can be more unique_constraint_name
while ($row = $result->fetch_assoc()) {
$foreign_key = &$return[$row["constraint_name"]];
if (!$foreign_key) {
$foreign_key = $row;
}
$foreign_key["source"][] = $row["column_name"];
$foreign_key["target"][] = $row["ref"];
}
return $return;
}
function view($name) {
global $connection;
return array("select" => $connection->result("SELECT pg_get_viewdef(" . $connection->quote($name) . ")"));
}
function collations() {
//! supported in CREATE DATABASE
return array();
}
function information_schema($db) {
return ($db == "information_schema");
}
function error() {
global $connection;
$return = h($connection->error);
if (preg_match('~^(.*\\n)?([^\\n]*)\\n( *)\\^(\\n.*)?$~s', $return, $match)) {
$return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\\1<b>\\2</b>', $match[2]) . $match[4];
}
return nl_br($return);
}
function exact_value($val) {
global $connection;
return $connection->quote($val);
}
function rename_database($name, $collation) {
//! current database cannot be renamed
return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name));
}
function auto_increment() {
return true;
}
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
global $connection;
$alter = array();
$queries = array();
foreach ($fields as $field) {
$column = idf_escape($field[0]);
$val = $field[1];
if (!$val) {
$alter[] = "DROP $column";
} else {
$val5 = $val[5];
unset($val[5]);
if ($val[6]) { // auto_increment
$val = array($val[0], ($val[1] == "bigint" ? "big" : "") . "serial");
}
if ($field[0] == "") {
$alter[] = ($table != "" ? "ADD " : " ") . implode("", $val);
} else {
if ($column != $val[0]) {
$queries[] = "ALTER TABLE " . idf_escape($table) . " RENAME $column TO $val[0]";
}
$alter[] = "ALTER $column TYPE $val[1]";
if (!$val[6]) {
$alter[] = "ALTER $column" . ($val[3] ? " SET$val[3]" : " DROP DEFAULT"); //! quoting
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
}
}
if ($table != "" || $val5 != "") {
$queries[] = "COMMENT ON COLUMN " . idf_escape($table) . ".$val[0] IS " . substr($val5, 9);
}
}
}
$alter = array_merge($alter, $foreign);
if ($table == "") {
array_unshift($queries, "CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n)");
} elseif ($alter) {
array_unshift($queries, "ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
}
if ($table != "" && $table != $name) {
$queries[] = "ALTER TABLE " . idf_escape($table) . " RENAME TO " . idf_escape($name);
}
if ($table != "" || $comment != "") {
$queries[] = "COMMENT ON TABLE " . idf_escape($name) . " IS " . $connection->quote($comment);
}
if ($auto_increment != "") {
//! $queries[] = "SELECT setval(pg_get_serial_sequence(" . $connection->quote($name) . ", ), $auto_increment)";
}
foreach ($queries as $query) {
if (!queries($query)) {
return false;
}
}
return true;
}
function alter_indexes($table, $alter) {
$create = array();
$drop = array();
foreach ($alter as $val) {
if ($val[0] != "INDEX") {
$create[] = ($val[2] ? "\nDROP CONSTRAINT " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
} elseif ($val[2]) {
$drop[] = $val[1];
} elseif (!queries("CREATE INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table) . " $val[1]")) {
return false;
}
}
return ((!$create || queries("ALTER TABLE " . idf_escape($table) . implode(",", $create)))
&& (!$drop || queries("DROP INDEX " . implode(", ", $drop)))
);
}
function truncate_tables($tables) {
return queries("TRUNCATE " . implode(", ", array_map('idf_escape', $tables)));
return true;
}
function drop_views($views) {
return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
}
function drop_tables($tables) {
return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
}
function trigger($name) {
global $connection;
$result = $connection->query('SELECT trigger_name AS "Trigger", condition_timing AS "Timing", event_manipulation AS "Event", action_statement AS "Statement" FROM information_schema.triggers WHERE event_object_table = ' . $connection->quote($_GET["trigger"]) . ' AND trigger_name = ' . $connection->quote($name));
return $result->fetch_assoc();
}
function triggers($table) {
global $connection;
$return = array();
$result = $connection->query("SELECT * FROM information_schema.triggers WHERE event_object_table = " . $connection->quote($table));
while ($row = $result->fetch_assoc()) {
$return[$row["trigger_name"]] = array($row["condition_timing"], $row["event_manipulation"]);
}
return $return;
}
function explain($connection, $query) {
return $connection->query("EXPLAIN $query");
}
function support($feature) {
return ereg('^(comment|view|routine|trigger)$', $feature);
}
$driver = "pgsql";
$types = array();
$structured_types = array();
foreach (array( //! arrays
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "interval" => 0),
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "txid_snapshot" => 0),
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
$unsigned = array();
$operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
$functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
$grouping = array("avg", "count", "count distinct", "max", "min", "sum");
$edit_functions = array(
array(
"char" => "md5",
"date|time" => "now",
), array(
"int|numeric|real|money" => "+/-",
"date|time" => "+ interval/- interval", //! escape
"char|text" => "||",
)
);
}

View file

@ -0,0 +1,479 @@
<?php
$possible_drivers[] = "SQLite";
$possible_drivers[] = "SQLite3";
$possible_drivers[] = "PDO_SQLite";
if (extension_loaded("sqlite3") || extension_loaded("pdo_sqlite")) {
$drivers["sqlite"] = "SQLite 3";
}
if (extension_loaded("sqlite") || extension_loaded("pdo_sqlite")) {
$drivers["sqlite2"] = "SQLite 2";
}
if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
define("DRIVER", (isset($_GET["sqlite"]) ? "sqlite" : "sqlite2"));
if (extension_loaded(isset($_GET["sqlite2"]) ? "sqlite" : "sqlite3")) {
if (isset($_GET["sqlite2"])) {
class Min_SQLite {
var $extension = "SQLite", $server_info, $affected_rows, $error, $_connection;
function __construct() {
$this->server_info = sqlite_libversion();
}
function open($filename) {
$this->_connection = new SQLiteDatabase($filename);
}
function query($query, $unbuffered = false) {
$method = ($unbuffered ? "unbufferedQuery" : "query");
$result = @$this->_connection->$method($query, SQLITE_BOTH, $error);
if (!$result) {
$this->error = $error;
return false;
} elseif ($result === true) {
$this->affected_rows = $this->changes();
return true;
}
return new Min_Result($result);
}
function quote($string) {
return "'" . sqlite_escape_string($string) . "'";
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result) {
return false;
}
$row = $result->_result->fetch();
return $row[$field];
}
}
class Min_Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
$this->_result = $result;
if (method_exists($result, 'numRows')) { // not available in unbuffered query
$this->num_rows = $result->numRows();
}
}
function fetch_assoc() {
$row = $this->_result->fetch(SQLITE_ASSOC);
if (!$row) {
return false;
}
$return = array();
foreach ($row as $key => $val) {
$return[($key[0] == '"' ? idf_unescape($key) : $key)] = $val;
}
return $return;
}
function fetch_row() {
return $this->_result->fetch(SQLITE_NUM);
}
function fetch_field() {
return (object) array(
"name" => $this->_result->fieldName($this->_offset++),
//! type, orgtable, charsetnr
);
}
}
} else {
class Min_SQLite extends SQLite3 {
var $extension = "SQLite3", $server_info, $affected_rows, $error;
function __construct() {
$version = $this->version();
$this->server_info = $version["versionString"];
}
function open($filename) {
parent::__construct($filename);
}
function query($query) {
$result = @parent::query($query);
if (!$result) {
$this->error = $this->lastErrorMsg();
return false;
} elseif ($result->numColumns()) {
return new Min_Result($result);
}
$this->affected_rows = $this->changes();
return true;
}
function quote($string) {
return "'" . $this->escapeString($string) . "'";
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!$result) {
return false;
}
$row = $result->_result->fetchArray();
return $row[$field];
}
}
class Min_Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
$this->_result = $result;
$this->num_rows = 1; //!
}
function fetch_assoc() {
return $this->_result->fetchArray(SQLITE3_ASSOC);
}
function fetch_row() {
return $this->_result->fetchArray(SQLITE3_NUM);
}
function fetch_field() {
$column = $this->_offset++;
return (object) array(
"name" => $this->_result->columnName($column),
"type" => $this->_result->columnType($column),
//! orgtable, charsetnr
);
}
function __desctruct() {
return $this->_result->finalize();
}
}
}
class Min_DB extends Min_SQLite {
function select_db($filename) {
static $connected = false;
if ($connected) {
return true;
}
set_exception_handler('connect_error'); // try/catch is not compatible with PHP 4
$this->open($filename);
$connected = true;
restore_exception_handler();
return true;
}
function multi_query($query) {
return $this->_result = $this->query($query);
}
function store_result() {
return $this->_result;
}
function next_result() {
return false;
}
}
} elseif (extension_loaded("pdo_sqlite")) {
class Min_DB extends Min_PDO {
var $extension = "PDO_SQLite";
function select_db($filename) {
static $connected = false;
if ($connected) {
return true;
}
$connected = true;
$this->dsn(DRIVER . ":$filename", "", "", "connect_error");
//! $this->server_info needs to be filled in __construct()
return true;
}
}
}
function idf_escape($idf) {
return '"' . str_replace('"', '""', $idf) . '"';
}
function connect() {
global $connection;
if ($connection) {
return $connection; // can connect only once, function to get number of rows doesn't exist anyway
}
return new Min_DB;
}
function get_databases() {
return array();
}
function limit($query, $limit, $offset = 0) {
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
}
function limit1($query) {
global $connection;
return ($connection->result("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')") ? limit($query, 1) : " $query");
}
function db_collation($db, $collations) {
return null;
}
function engines() {
return array();
}
function logged_user() {
return ""; //! OS user
}
function tables_list() {
return get_key_vals("SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view')", 1);
}
function count_tables($databases) {
return array();
}
function table_status($name = "") {
global $connection;
$return = array();
$result = $connection->query("SELECT name AS Name, type AS Engine FROM sqlite_master WHERE type IN ('table', 'view')" . ($name != "" ? " AND name = " . $connection->quote($name) : ""));
while ($row = $result->fetch_assoc()) {
$return[$row["Name"]] = $row;
}
$result = $connection->query("SELECT * FROM sqlite_sequence");
if ($result) {
while ($row = $result->fetch_assoc()) {
$return[$row["name"]]["Auto_increment"] = $row["seq"];
}
}
return ($name != "" ? $return[$name] : $return);
}
function fk_support($table_status) {
global $connection;
return !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
}
function fields($table) {
global $connection;
$return = array();
$result = $connection->query("PRAGMA table_info(" . idf_escape($table) . ")");
if (is_object($result)) {
while ($row = $result->fetch_assoc()) {
$type = strtolower($row["type"]);
$return[$row["name"]] = array(
"field" => $row["name"],
"type" => (eregi("int", $type) ? "integer" : (eregi("char|clob|text", $type) ? "text" : (eregi("blob", $type) ? "blob" : (eregi("real|floa|doub", $type) ? "real" : "numeric")))),
"full_type" => $type,
"default" => $row["dflt_value"],
"null" => !$row["notnull"],
"auto_increment" => eregi('^integer$', $type) && $row["pk"], //! possible false positive
"collation" => null, //!
"privileges" => array("select" => 1, "insert" => 1, "update" => 1),
"primary" => $row["pk"],
);
}
}
return $return;
}
function indexes($table, $connection2 = null) {
global $connection;
$return = array();
$primary = array();
foreach (fields($table) as $field) {
if ($field["primary"]) {
$primary[] = $field["field"];
}
}
if ($primary) {
$return[""] = array("type" => "PRIMARY", "columns" => $primary, "lengths" => array());
}
$result = $connection->query("PRAGMA index_list(" . idf_escape($table) . ")");
if (is_object($result)) {
while ($row = $result->fetch_assoc()) {
$return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX");
$return[$row["name"]]["lengths"] = array();
$result1 = $connection->query("PRAGMA index_info(" . idf_escape($row["name"]) . ")");
while ($row1 = $result1->fetch_assoc()) {
$return[$row["name"]]["columns"][] = $row1["name"];
}
}
}
return $return;
}
function foreign_keys($table) {
global $connection;
$return = array();
$result = $connection->query("PRAGMA foreign_key_list(" . idf_escape($table) . ")");
if (is_object($result)) {
while ($row = $result->fetch_assoc()) {
$foreign_key = &$return[$row["id"]];
if (!$foreign_key) {
$foreign_key = $row;
}
$foreign_key["source"][] = $row["from"];
$foreign_key["target"][] = $row["to"];
}
}
return $return;
}
function view($name) {
global $connection;
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($name)))); //! identifiers may be inside []
}
function collations() {
return get_vals("PRAGMA collation_list", 1);
}
function information_schema($db) {
return false;
}
function error() {
global $connection;
return h($connection->error);
}
function exact_value($val) {
global $connection;
return $connection->quote($val);
}
function rename_database($name, $collation) {
global $connection;
$connection->close(); //! not available with all extensions
return rename(DB, $name);
}
function auto_increment() {
return " PRIMARY KEY" . (DRIVER == "sqlite" ? " AUTOINCREMENT" : "");
}
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
global $connection;
$alter = array();
foreach ($fields as $field) {
$alter[] = ($table != "" && $field[0] == "" ? "ADD " : " ") . implode("", $field[1]);
}
$alter = array_merge($alter, $foreign);
if ($table != "") {
foreach ($alter as $val) {
if (!queries("ALTER TABLE " . idf_escape($table) . " $val")) {
return false;
}
}
if ($table != $name && !queries("ALTER TABLE " . idf_escape($table) . " RENAME TO " . idf_escape($name))) {
return false;
}
} elseif (!queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n)")) {
return false;
}
if ($auto_increment) {
return queries("UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . $connection->quote($name) . "");
}
return true;
}
function alter_indexes($table, $alter) {
foreach ($alter as $val) {
if (!queries(($val[2] ? "DROP INDEX" : "CREATE" . ($val[0] != "INDEX" ? " UNIQUE" : "") . " INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table)) . " $val[1]")) { //! primary key must be created in CREATE TABLE
return false;
}
}
return true;
}
function truncate_tables($tables) {
foreach ($tables as $table) {
if (!queries("DELETE FROM " . idf_escape($table))) {
return false;
}
}
return true;
}
function drop_views($views) {
foreach ($views as $view) {
if (!queries("DROP VIEW " . idf_escape($view))) {
return false;
}
}
return true;
}
function drop_tables($tables) {
foreach ($tables as $table) {
if (!queries("DROP TABLE " . idf_escape($table))) {
return false;
}
}
return true;
}
function trigger($name) {
global $connection;
preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s+([a-z]+)\\s+ON\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*(?:FOR\\s*EACH\\s*ROW\\s)?(.*)~is', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($name)), $match);
return array("Timing" => strtoupper($match[1]), "Event" => strtoupper($match[2]), "Trigger" => $name, "Statement" => $match[3]);
}
function triggers($table) {
global $connection;
$return = array();
$result = $connection->query("SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . $connection->quote($table));
while ($row = $result->fetch_assoc()) {
preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s*([a-z]+)~i', $row["sql"], $match);
$return[$row["name"]] = array($match[1], $match[2]);
}
return $return;
}
function explain($connection, $query) {
return $connection->query("EXPLAIN $query");
}
function create_sql($table) {
global $connection;
return $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($table));
}
function support($feature) {
return ereg('^(view|trigger)$', $feature);
}
$driver = "sqlite";
$types = array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0);
$structured_types = array_keys($types);
$unsigned = array();
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // REGEXP can be user defined function
$functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
$grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
$edit_functions = array(
array(
// "text" => "date('now')/time('now')/datetime('now')",
), array(
"integer|real|numeric" => "+/-",
// "text" => "date/time/datetime",
"text" => "||",
)
);
}

View file

@ -2,25 +2,37 @@
$TABLE = $_GET["dump"]; $TABLE = $_GET["dump"];
if ($_POST) { if ($_POST) {
$cookie = "";
foreach (array("output", "format", "db_style", "table_style", "data_style") as $key) {
$cookie .= "&$key=" . urlencode($_POST[$key]);
}
cookie("adminer_export", substr($cookie, 1));
$ext = dump_headers(($TABLE != "" ? $TABLE : DB), (DB == "" || count((array) $_POST["tables"] + (array) $_POST["data"]) > 1)); $ext = dump_headers(($TABLE != "" ? $TABLE : DB), (DB == "" || count((array) $_POST["tables"] + (array) $_POST["data"]) > 1));
if ($_POST["format"] == "sql") { if ($_POST["format"] == "sql") {
echo "-- Adminer $VERSION dump echo "-- Adminer $VERSION " . $drivers[DRIVER] . " dump
SET NAMES utf8;
" . ($driver != "sql" ? "" : "SET NAMES utf8;
SET foreign_key_checks = 0; SET foreign_key_checks = 0;
SET time_zone = " . $connection->quote($connection->result($connection->query("SELECT @@time_zone"))) . "; SET time_zone = " . $connection->quote($connection->result("SELECT @@time_zone")) . ";
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
"; ");
} }
$style = $_POST["db_style"]; $style = $_POST["db_style"];
foreach ((DB != "" ? array(DB) : (array) $_POST["databases"]) as $db) { $databases = array(DB);
if (DB == "") {
$databases = $_POST["databases"];
if (is_string($databases)) {
$databases = explode("\n", rtrim(str_replace("\r", "", $databases), "\n"));
}
}
foreach ((array) $databases as $db) {
if ($connection->select_db($db)) { if ($connection->select_db($db)) {
if ($_POST["format"] == "sql" && ereg('CREATE', $style) && ($result = $connection->query("SHOW CREATE DATABASE " . idf_escape($db)))) { if ($_POST["format"] == "sql" && ereg('CREATE', $style) && ($create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1))) {
if ($style == "DROP+CREATE") { if ($style == "DROP+CREATE") {
echo "DROP DATABASE IF EXISTS " . idf_escape($db) . ";\n"; echo "DROP DATABASE IF EXISTS " . idf_escape($db) . ";\n";
} }
$create = $connection->result($result, 1);
echo ($style == "CREATE+ALTER" ? preg_replace('~^CREATE DATABASE ~', '\\0IF NOT EXISTS ', $create) : $create) . ";\n"; echo ($style == "CREATE+ALTER" ? preg_replace('~^CREATE DATABASE ~', '\\0IF NOT EXISTS ', $create) : $create) . ";\n";
} }
if ($_POST["format"] == "sql") { if ($_POST["format"] == "sql") {
@ -36,7 +48,7 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
$result = $connection->query("SHOW $routine STATUS WHERE Db = " . $connection->quote($db)); $result = $connection->query("SHOW $routine STATUS WHERE Db = " . $connection->quote($db));
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") $out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "")
. $connection->result($connection->query("SHOW CREATE $routine " . idf_escape($row["Name"])), 2) . ";;\n\n"; . $connection->result("SHOW CREATE $routine " . idf_escape($row["Name"]), 2) . ";;\n\n";
} }
} }
} }
@ -45,7 +57,7 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
if ($result) { if ($result) {
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
$out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") $out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "")
. $connection->result($connection->query("SHOW CREATE EVENT " . idf_escape($row["Name"])), 3) . ";;\n\n"; . $connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3) . ";;\n\n";
} }
} }
} }
@ -56,6 +68,7 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
if ($_POST["table_style"] || $_POST["data_style"]) { if ($_POST["table_style"] || $_POST["data_style"]) {
$views = array(); $views = array();
//! defer number of rows to JavaScript
foreach (table_status() as $row) { foreach (table_status() as $row) {
$table = (DB == "" || in_array($row["Name"], (array) $_POST["tables"])); $table = (DB == "" || in_array($row["Name"], (array) $_POST["tables"]));
$data = (DB == "" || in_array($row["Name"], (array) $_POST["data"])); $data = (DB == "" || in_array($row["Name"], (array) $_POST["data"]));
@ -143,22 +156,26 @@ page_header(lang('Export'), "", ($_GET["export"] != "" ? array("table" => $_GET[
$db_style = array('', 'USE', 'DROP+CREATE', 'CREATE'); $db_style = array('', 'USE', 'DROP+CREATE', 'CREATE');
$table_style = array('', 'DROP+CREATE', 'CREATE'); $table_style = array('', 'DROP+CREATE', 'CREATE');
$data_style = array('', 'TRUNCATE+INSERT', 'INSERT', 'INSERT+UPDATE'); $data_style = array('', 'TRUNCATE+INSERT', 'INSERT', 'INSERT+UPDATE');
if ($connection->server_info >= 5) { if (support("routine")) {
$db_style[] = 'CREATE+ALTER'; $db_style[] = 'CREATE+ALTER';
$table_style[] = 'CREATE+ALTER'; $table_style[] = 'CREATE+ALTER';
} }
echo "<tr><th>" . lang('Output') . "<td><input type='hidden' name='token' value='$token'>" . $adminer->dumpOutput(0) . "\n"; // token is not needed but checked in bootstrap for all POST data //! read from cookie parse_str($_COOKIE["adminer_export"], $row);
echo "<tr><th>" . lang('Format') . "<td>" . $adminer->dumpFormat(0) . "\n"; if (!$row) {
echo "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, (DB != "" ? '' : 'CREATE')); $row = array("output" => "text", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT");
if ($connection->server_info >= 5) {
$checked = $_GET["dump"] == "";
echo checkbox("routines", 1, $checked, lang('Routines'));
if ($connection->server_info >= 5.1) {
echo checkbox("events", 1, $checked, lang('Events'));
}
} }
echo "<tr><th>" . lang('Tables') . "<td>" . html_select('table_style', $table_style, 'DROP+CREATE'); echo "<tr><th>" . lang('Output') . "<td>" . $adminer->dumpOutput(0, $row["output"]) . "\n";
echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style, 'INSERT'); echo "<tr><th>" . lang('Format') . "<td>" . $adminer->dumpFormat(0, $row["format"]) . "\n";
echo "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"]);
$checked = ($_GET["dump"] == "");
if (support("routine")) {
echo checkbox("routines", 1, $checked, lang('Routines'));
}
if (support("event")) {
echo checkbox("events", 1, $checked, lang('Events'));
}
echo "<tr><th>" . lang('Tables') . "<td>" . html_select('table_style', $table_style, $row["table_style"]);
echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style, $row["data_style"]);
?> ?>
</table> </table>
<p><input type="submit" value="<?php echo lang('Export'); ?>"> <p><input type="submit" value="<?php echo lang('Export'); ?>">
@ -178,22 +195,27 @@ if (DB != "") {
$prefix = ereg_replace("_.*", "", $name); $prefix = ereg_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, "formUncheck('check-tables');"); $print = "<tr><td>" . checkbox("tables[]", $name, $checked, $name, "formUncheck('check-tables');");
if (!$row["Engine"]) { if (eregi("view", $row["Engine"])) {
$views .= "$print\n"; $views .= "$print\n";
} else { } else {
echo "$print<td align='right'><label>" . ($row["Engine"] == "InnoDB" && $row["Rows"] ? lang('~ %s', $row["Rows"]) : $row["Rows"]) . checkbox("data[]", $name, $checked, "", "formUncheck('check-data');") . "</label>\n"; echo "$print<td align='right'><label>" . ($row["Engine"] == "InnoDB" && $row["Rows"] ? "~ " : "") . $row["Rows"] . checkbox("data[]", $name, $checked, "", "formUncheck('check-data');") . "</label>\n";
} }
$prefixes[$prefix]++; $prefixes[$prefix]++;
} }
echo $views; echo $views;
} else { } else {
echo "<thead><tr><th style='text-align: left;'><label><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;'><label><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . " onclick='formCheck(this, /^databases\\[/);'>" . lang('Database') . "</label></thead>\n";
foreach (get_databases() as $db) { $databases = get_databases();
if (!information_schema($db)) { if ($databases) {
$prefix = ereg_replace("_.*", "", $db); foreach ($databases as $db) {
echo "<tr><td>" . checkbox("databases[]", $db, $TABLE == "" || $TABLE == "$prefix%", $db, "formUncheck('check-databases');") . "</label>\n"; if (!information_schema($db)) {
$prefixes[$prefix]++; $prefix = ereg_replace("_.*", "", $db);
echo "<tr><td>" . checkbox("databases[]", $db, $TABLE == "" || $TABLE == "$prefix%", $db, "formUncheck('check-databases');") . "</label>\n";
$prefixes[$prefix]++;
}
} }
} else {
echo "<tr><td><textarea name='databases' rows='10' cols='20'></textarea>";
} }
} }
?> ?>

View file

@ -14,30 +14,22 @@ if ($_POST && !$error && !isset($_GET["select"])) {
$location = ($update ? null : $_SERVER["REQUEST_URI"]); $location = ($update ? null : $_SERVER["REQUEST_URI"]);
} elseif (!ereg('^.+&select=.+$', $location)) { } elseif (!ereg('^.+&select=.+$', $location)) {
$location = ME . "select=" . urlencode($TABLE); $location = ME . "select=" . urlencode($TABLE);
$i = 0; // append &set converted to &where
foreach ((array) $_GET["set"] as $key => $val) {
if ($val == $_POST["fields"][$key]) {
$location .= where_link($i++, bracket_escape($key, "back"), $val);
}
}
} }
if (isset($_POST["delete"])) { if (isset($_POST["delete"])) {
query_redirect("DELETE FROM " . idf_escape($_GET["edit"]) . " WHERE $where LIMIT 1", $location, lang('Item has been deleted.')); query_redirect("DELETE" . limit1("FROM " . idf_escape($_GET["edit"]) . "\nWHERE $where"), $location, lang('Item has been deleted.'));
} else { } else {
$set = array(); $set = array();
foreach ($fields as $name => $field) { foreach ($fields as $name => $field) {
$val = process_input($field); $val = process_input($field);
if (!$update) { if ($val !== false && $val !== null) {
$set[idf_escape($name)] = ($val !== false ? $val : "''"); $set[idf_escape($name)] = ($update ? "\n" . idf_escape($name) . " = $val" : $val);
} elseif ($val !== false) {
$set[] = "\n" . idf_escape($name) . " = $val";
} }
} }
if (!$set) {
redirect($location);
}
if ($update) { if ($update) {
query_redirect("UPDATE " . idf_escape($TABLE) . " SET" . implode(",", $set) . "\nWHERE $where\nLIMIT 1", $location, lang('Item has been updated.')); if (!$set) {
redirect($location);
}
query_redirect("UPDATE" . limit1(idf_escape($TABLE) . " SET" . implode(",", $set) . "\nWHERE $where"), $location, lang('Item has been updated.'));
} else { } else {
query_redirect("INSERT INTO " . idf_escape($TABLE) . " (" . implode(", ", array_keys($set)) . ")\nVALUES (" . implode(", ", $set) . ")", $location, lang('Item has been inserted.')); query_redirect("INSERT INTO " . idf_escape($TABLE) . " (" . implode(", ", array_keys($set)) . ")\nVALUES (" . implode(", ", $set) . ")", $location, lang('Item has been inserted.'));
} }
@ -64,8 +56,11 @@ if ($_POST["save"]) {
} }
$row = array(); $row = array();
if ($select) { if ($select) {
$result = $connection->query("SELECT " . implode(", ", $select) . " FROM " . idf_escape($TABLE) . " WHERE $where " . (isset($_GET["select"]) ? "HAVING COUNT(*) = 1" : "LIMIT 1")); $result = $connection->query("SELECT" . limit(implode(", ", $select) . " FROM " . idf_escape($TABLE) . " WHERE $where", (isset($_GET["select"]) ? 2 : 1)));
$row = $result->fetch_assoc(); $row = $result->fetch_assoc();
if (isset($_GET["select"]) && $result->fetch_assoc()) {
$row = false;
}
} }
} }
?> ?>
@ -80,7 +75,7 @@ if ($fields) {
$default = $_GET["set"][bracket_escape($name)]; $default = $_GET["set"][bracket_escape($name)];
$value = (isset($row) $value = (isset($row)
? ($row[$name] != "" && ereg("enum|set", $field["type"]) ? intval($row[$name]) : $row[$name]) ? ($row[$name] != "" && ereg("enum|set", $field["type"]) ? intval($row[$name]) : $row[$name])
: ($_POST["clone"] && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : (isset($default) ? $default : $field["default"]))) : (!$update && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : (isset($default) ? $default : $field["default"])))
); );
if (!$_POST["save"] && is_string($value)) { if (!$_POST["save"] && is_string($value)) {
$value = $adminer->editVal($value, $field); $value = $adminer->editVal($value, $field);

View file

@ -2,7 +2,7 @@
$TABLE = $_GET["foreign"]; $TABLE = $_GET["foreign"];
if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) { if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
if ($_POST["drop"]) { if ($_POST["drop"]) {
query_redirect("ALTER TABLE " . idf_escape($TABLE) . "\nDROP FOREIGN KEY " . idf_escape($_GET["name"]), ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.')); query_redirect("ALTER TABLE " . idf_escape($TABLE) . "\nDROP " . ($driver == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($_GET["name"]), ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.'));
} else { } else {
$source = array_filter($_POST["source"], 'strlen'); $source = array_filter($_POST["source"], 'strlen');
ksort($source); // enforce input order ksort($source); // enforce input order
@ -39,13 +39,19 @@ if ($_POST) {
$source = array_keys(fields($TABLE)); //! no text and blob $source = array_keys(fields($TABLE)); //! no text and blob
$target = ($TABLE === $row["table"] ? $source : array_keys(fields($row["table"]))); $target = ($TABLE === $row["table"] ? $source : array_keys(fields($row["table"])));
$referencable = array();
foreach (table_status() as $name => $table_status) {
if (fk_support($table_status)) {
$referencable[] = $name;
}
}
?> ?>
<form action="" method="post"> <form action="" method="post">
<p> <p>
<?php if ($row["db"] == "") { ?> <?php if ($row["db"] == "") { ?>
<?php echo lang('Target table'); ?>: <?php echo lang('Target table'); ?>:
<?php echo html_select("table", array_keys(table_status_referencable()), $row["table"], "this.form['change-js'].value = '1'; this.form.submit();"); ?> <?php echo html_select("table", $referencable, $row["table"], "this.form['change-js'].value = '1'; this.form.submit();"); ?>
<input type="hidden" name="change-js" value=""> <input type="hidden" name="change-js" value="">
<noscript><p><input type="submit" name="change" value="<?php echo lang('Change'); ?>"></noscript> <noscript><p><input type="submit" name="change" value="<?php echo lang('Change'); ?>"></noscript>
<table cellspacing="0"> <table cellspacing="0">

View file

@ -1,13 +1,7 @@
<?php <?php
class Adminer { class Adminer {
/** @var array functions used in select */ /** @var array operators used in select, null for all operators */
var $functions = array("char_length", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "unix_timestamp", "upper"); var $operators;
/** @var array grouping functions used in select */
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
/** @var array operators used in select */
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL");
/** Name in title and navigation /** Name in title and navigation
* @return string * @return string
@ -20,7 +14,7 @@ class Adminer {
* @return array ($server, $username, $password) * @return array ($server, $username, $password)
*/ */
function credentials() { function credentials() {
return array($_GET["server"], $_SESSION["usernames"][$_GET["server"]], $_SESSION["passwords"][$_GET["server"]]); return array(SERVER, $_GET["username"], get_session("passwords"));
} }
/** Get key used for permanent login /** Get key used for permanent login
@ -39,14 +33,15 @@ class Adminer {
} }
/** Print login form /** Print login form
* @param string
* @return null * @return null
*/ */
function loginForm($username) { function loginForm() {
global $drivers, $possible_drivers;
?> ?>
<table cellspacing="0"> <table cellspacing="0">
<tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h($_GET["server"]); ?>"> <tr><th><?php echo lang('System'); ?><td><?php echo (count($possible_drivers) > 3 ? html_select("driver", $drivers, DRIVER) : "<input type='hidden' name='driver' value='" . key($drivers) . "'>" . reset($drivers)); ?></tr>
<tr><th><?php echo lang('Username'); ?><td><input name="username" value="<?php echo h($username); ?>"> <tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h(SERVER); ?>">
<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"> <tr><th><?php echo lang('Password'); ?><td><input type="password" name="password">
</table> </table>
<?php <?php
@ -90,10 +85,10 @@ class Adminer {
function selectLinks($tableStatus, $set = "") { function selectLinks($tableStatus, $set = "") {
echo '<p class="tabs">'; echo '<p class="tabs">';
$links = array("select" => lang('Select data'), "table" => lang('Show structure')); $links = array("select" => lang('Select data'), "table" => lang('Show structure'));
if (isset($tableStatus["Rows"])) { if (eregi("view", $tableStatus["Engine"])) {
$links["create"] = lang('Alter table');
} else {
$links["view"] = lang('Alter view'); $links["view"] = lang('Alter view');
} else {
$links["create"] = lang('Alter table');
} }
if (isset($set)) { if (isset($set)) {
$links["edit"] = lang('New item'); $links["edit"] = lang('New item');
@ -126,7 +121,8 @@ class Adminer {
* @return string * @return string
*/ */
function selectQuery($query) { function selectQuery($query) {
return "<p><code class='jush-sql'>" . h(str_replace("\n", " ", $query)) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n"; global $driver;
return "<p><code class='jush-$driver'>" . h(str_replace("\n", " ", $query)) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
} }
/** Description of a row in a table /** Description of a row in a table
@ -154,7 +150,7 @@ class Adminer {
*/ */
function selectVal($val, $link, $field) { function selectVal($val, $link, $field) {
$return = ($val != "<i>NULL</i>" && $field["type"] == "char" ? "<code>$val</code>" : $val); $return = ($val != "<i>NULL</i>" && $field["type"] == "char" ? "<code>$val</code>" : $val);
if (ereg('blob|binary', $field["type"]) && !is_utf8($val)) { if (ereg('binary|blob|bytea', $field["type"]) && !is_utf8($val)) {
$return = lang('%d byte(s)', strlen($val)); $return = lang('%d byte(s)', strlen($val));
} }
return ($link ? "<a href='$link'>$return</a>" : $return); return ($link ? "<a href='$link'>$return</a>" : $return);
@ -175,17 +171,18 @@ class Adminer {
* @return null * @return null
*/ */
function selectColumnsPrint($select, $columns) { function selectColumnsPrint($select, $columns) {
global $functions, $grouping;
print_fieldset("select", lang('Select'), $select); print_fieldset("select", lang('Select'), $select);
$i = 0; $i = 0;
$fun_group = array(lang('Functions') => $this->functions, lang('Aggregation') => $this->grouping); $fun_group = array(lang('Functions') => $functions, lang('Aggregation') => $grouping);
foreach ($select as $key => $val) { foreach ($select as $key => $val) {
$val = $_GET["columns"][$key]; $val = $_GET["columns"][$key];
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, $val["fun"]); echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, $val["fun"]);
echo "<select name='columns[$i][col]'><option>" . optionlist($columns, $val["col"], true) . "</select></div>\n"; echo "(<select name='columns[$i][col]'><option>" . optionlist($columns, $val["col"], true) . "</select>)</div>\n";
$i++; $i++;
} }
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.onchange();"); echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.nextSibling.onchange();");
echo "<select name='columns[$i][col]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select></div>\n"; echo "(<select name='columns[$i][col]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select>)</div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@ -208,13 +205,13 @@ class Adminer {
$i = 0; $i = 0;
foreach ((array) $_GET["where"] as $val) { foreach ((array) $_GET["where"] as $val) {
if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) { if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
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]", $this->operators, $val["op"]); echo html_select("where[$i][op]", $this->operators, $val["op"]);
echo "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n"; echo "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n";
$i++; $i++;
} }
} }
echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>" . lang('(anywhere)') . optionlist($columns, null, true) . "</select>"; echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
echo html_select("where[$i][op]", $this->operators); echo html_select("where[$i][op]", $this->operators);
echo "<input name='where[$i][val]'></div>\n"; echo "<input name='where[$i][val]'></div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
@ -286,12 +283,13 @@ class Adminer {
* @return array (array(select_expressions), array(group_expressions)) * @return array (array(select_expressions), array(group_expressions))
*/ */
function selectColumnsProcess($columns, $indexes) { function selectColumnsProcess($columns, $indexes) {
global $functions, $grouping;
$select = array(); // select expressions, empty for * $select = array(); // select expressions, empty for *
$group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used $group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
foreach ((array) $_GET["columns"] as $key => $val) { foreach ((array) $_GET["columns"] as $key => $val) {
if ($val["fun"] == "count" || (isset($columns[$val["col"]]) && (!$val["fun"] || in_array($val["fun"], $this->functions) || in_array($val["fun"], $this->grouping)))) { if ($val["fun"] == "count" || (isset($columns[$val["col"]]) && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
$select[$key] = apply_sql_function($val["fun"], (isset($columns[$val["col"]]) ? idf_escape($val["col"]) : "*")); $select[$key] = apply_sql_function($val["fun"], (isset($columns[$val["col"]]) ? idf_escape($val["col"]) : "*"));
if (!in_array($val["fun"], $this->grouping)) { if (!in_array($val["fun"], $grouping)) {
$group[] = $select[$key]; $group[] = $select[$key];
} }
} }
@ -314,8 +312,15 @@ class Adminer {
} }
foreach ((array) $_GET["where"] as $val) { foreach ((array) $_GET["where"] as $val) {
if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) { if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
$in = process_length($val["val"]); $cond = " $val[op]";
$cond = " $val[op]" . (ereg('NULL$', $val["op"]) ? "" : (ereg('IN$', $val["op"]) ? " (" . ($in != "" ? $in : "NULL") . ")" : " " . $this->processInput($fields[$val["col"]], $val["val"]))); if (ereg('IN$', $val["op"])) {
$in = process_length($val["val"]);
$cond .= " (" . ($in != "" ? $in : "NULL") . ")";
} elseif ($val["op"] == "LIKE %%") {
$cond = " LIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%");
} elseif (!ereg('NULL$', $val["op"])) {
$cond .= " " . $this->processInput($fields[$val["col"]], $val["val"]);
}
if ($val["col"] != "") { if ($val["col"] != "") {
$return[] = idf_escape($val["col"]) . $cond; $return[] = idf_escape($val["col"]) . $cond;
} else { } else {
@ -342,8 +347,8 @@ class Adminer {
function selectOrderProcess($fields, $indexes) { function selectOrderProcess($fields, $indexes) {
$return = array(); $return = array();
foreach ((array) $_GET["order"] as $key => $val) { foreach ((array) $_GET["order"] as $key => $val) {
if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()`(?:[^`]|``)+`\\)|COUNT\\(\\*\\))$~', $val)) { if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\\)|COUNT\\(\\*\\))$~', $val)) { //! MS SQL uses []
$return[] = idf_escape($val) . (isset($_GET["desc"][$key]) ? " DESC" : ""); $return[] = (isset($fields[$val]) ? idf_escape($val) : $val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
} }
} }
return $return; return $return;
@ -377,10 +382,12 @@ class Adminer {
* @return string * @return string
*/ */
function messageQuery($query) { function messageQuery($query) {
global $driver;
restart_session(); restart_session();
$id = "sql-" . count($_SESSION["messages"]); $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 $history = &get_session("history");
return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-sql'>" . shorten_utf8($query, 1000) . '</pre><a href="' . h(ME . 'sql=&history=' . (count($_SESSION["history"][$_GET["server"]][DB]) - 1)) . '">' . lang('Edit') . '</a></div>'; $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><p><a href="' . h(ME . 'sql=&history=' . (count($history[DB]) - 1)) . '">' . lang('Edit') . '</a></div>';
} }
/** Functions displayed in edit form /** Functions displayed in edit form
@ -388,31 +395,18 @@ class Adminer {
* @return array * @return array
*/ */
function editFunctions($field) { function editFunctions($field) {
$return = array(""); global $edit_functions;
if (ereg('char|date|time', $field["type"])) { $return = ($field["null"] ? "/NULL" : "");
$return = (ereg('char', $field["type"]) ? array("", "md5", "sha1", "password", "encrypt", "uuid") : array("", "now")); //! JavaScript for disabling maxlength foreach ($edit_functions as $key => $functions) {
} if (!$key || (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET)))) { // relative functions
if (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET))) { foreach ($functions as $pattern => $val) {
// relative functions if (!$pattern || ereg($pattern, $field["type"])) {
if (ereg('int|float|double|decimal', $field["type"])) { $return .= "/$val";
$return = array("", "+", "-"); }
} }
if (ereg('date', $field["type"])) {
$return[] = "+ interval";
$return[] = "- interval";
}
if (ereg('time', $field["type"])) {
$return[] = "addtime";
$return[] = "subtime";
}
if (ereg('char|text', $field["type"])) {
$return[] = "concat";
} }
} }
if ($field["null"]) { return explode("/", $return);
array_unshift($return, "NULL");
}
return $return;
} }
/** Get options to display edit field /** Get options to display edit field
@ -441,9 +435,9 @@ class Adminer {
global $connection; global $connection;
$name = $field["field"]; $name = $field["field"];
$return = $connection->quote($value); $return = $connection->quote($value);
if (ereg('^(now|uuid)$', $function)) { if (ereg('^(now|getdate|uuid)$', $function)) {
$return = "$function()"; $return = "$function()";
} elseif (ereg('^[+-]$', $function)) { } elseif (ereg('^([+-]|\\|\\|)$', $function)) {
$return = idf_escape($name) . " $function $return"; $return = idf_escape($name) . " $function $return";
} elseif (ereg('^[+-] interval$', $function)) { } elseif (ereg('^[+-] interval$', $function)) {
$return = idf_escape($name) . " $function " . (preg_match("~^([0-9]+|'[0-9.: -]') [A-Z_]+$~i", $value) ? $value : $return); $return = idf_escape($name) . " $function " . (preg_match("~^([0-9]+|'[0-9.: -]') [A-Z_]+$~i", $value) ? $value : $return);
@ -457,9 +451,10 @@ class Adminer {
/** Returns export output options /** Returns export output options
* @param bool generate select (otherwise radio) * @param bool generate select (otherwise radio)
* @param string
* @return string * @return string
*/ */
function dumpOutput($select) { function dumpOutput($select, $value = "") {
$return = array('text' => lang('open'), 'file' => lang('save')); $return = array('text' => lang('open'), 'file' => lang('save'));
if (function_exists('gzencode')) { if (function_exists('gzencode')) {
$return['gz'] = 'gzip'; $return['gz'] = 'gzip';
@ -468,15 +463,16 @@ class Adminer {
$return['bz2'] = 'bzip2'; $return['bz2'] = 'bzip2';
} }
// ZipArchive requires temporary file, ZIP can be created by gzcompress - see PEAR File_Archive // ZipArchive requires temporary file, ZIP can be created by gzcompress - see PEAR File_Archive
return html_select("output", $return, "text", $select); return html_select("output", $return, $value, $select);
} }
/** Returns export format options /** Returns export format options
* @param bool generate select (otherwise radio) * @param bool generate select (otherwise radio)
* @param string
* @return string * @return string
*/ */
function dumpFormat($select) { function dumpFormat($select, $value = "") {
return html_select("format", array('sql' => 'SQL', 'csv' => 'CSV'), "sql", $select); return html_select("format", array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;'), $value, $select);
} }
/** Prints navigation after Adminer title /** Prints navigation after Adminer title
@ -484,7 +480,7 @@ class Adminer {
* @return null * @return null
*/ */
function navigation($missing) { function navigation($missing) {
global $VERSION, $connection; global $VERSION, $connection, $token;
?> ?>
<h1> <h1>
<a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a> <a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a>
@ -499,19 +495,18 @@ class Adminer {
<p class="logout"> <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); ?>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> <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 $token; ?>">
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>"> <input type="submit" name="logout" value="<?php echo lang('Logout'); ?>">
</p> </p>
</form> </form>
<form action=""> <form action="">
<p> <p>
<?php echo SID_FORM; ?> <?php hidden_fields_get(); ?>
<?php if ($_GET["server"] != "") { ?><input type="hidden" name="server" value="<?php echo h($_GET["server"]); ?>"><?php } ?>
<?php echo ($databases ? html_select("db", array("" => "(" . lang('database') . ")") + $databases, DB, "this.form.submit();") : '<input name="db" value="' . h(DB) . '">'); ?> <?php echo ($databases ? html_select("db", array("" => "(" . lang('database') . ")") + $databases, DB, "this.form.submit();") : '<input name="db" value="' . h(DB) . '">'); ?>
<?php if (isset($_GET["sql"])) { ?><input type="hidden" name="sql" value=""><?php } ?> <?php if (isset($_GET["sql"])) { ?><input type="hidden" name="sql" value=""><?php } ?>
<?php if (isset($_GET["schema"])) { ?><input type="hidden" name="schema" value=""><?php } ?> <?php if (isset($_GET["schema"])) { ?><input type="hidden" name="schema" value=""><?php } ?>
<?php if (isset($_GET["dump"])) { ?><input type="hidden" name="dump" value=""><?php } ?> <?php if (isset($_GET["dump"])) { ?><input type="hidden" name="dump" value=""><?php } ?>
<input type="submit" value="<?php echo lang('Use'); ?>"<?php echo ($databases ? " class='hidden'" : ""); ?>> <input type="submit" value="<?php echo lang('Use'); ?>"<?php echo ($databases ? " class='hidden'" : ""); ?>>
</p> </p>
</form> </form>
<?php <?php
@ -533,7 +528,7 @@ class Adminer {
*/ */
function tablesPrint($tables) { function tablesPrint($tables) {
echo "<p id='tables'>\n"; echo "<p id='tables'>\n";
foreach ($tables as $table) { foreach ($tables as $table => $type) {
echo '<a href="' . h(ME) . 'select=' . urlencode($table) . '">' . bold(lang('select'), $_GET["select"] == $table) . '</a> '; echo '<a href="' . h(ME) . 'select=' . urlencode($table) . '">' . bold(lang('select'), $_GET["select"] == $table) . '</a> ';
echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '">' . bold($this->tableName(array("Name" => $table)), $_GET["table"] == $table) . "</a><br>\n"; //! Adminer::tableName may work with full table status echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '">' . bold($this->tableName(array("Name" => $table)), $_GET["table"] == $table) . "</a><br>\n"; //! Adminer::tableName may work with full table status
} }
@ -542,3 +537,6 @@ class Adminer {
} }
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer); $adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
if (!isset($adminer->operators)) {
$adminer->operators = $operators;
}

View file

@ -1,88 +1,100 @@
<?php <?php
$connection = '';
if (!$drivers) {
page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), null);
page_footer("auth");
exit;
}
$token = $_SESSION["token"];
if (!$_SESSION["token"]) {
$_SESSION["token"] = rand(1, 1e6); // defense against cross-site request forgery
}
if (isset($_POST["server"])) { if (isset($_POST["server"])) {
session_regenerate_id(); // defense against session fixation session_regenerate_id(); // defense against session fixation
$_SESSION["usernames"][$_POST["server"]] = $_POST["username"]; $_SESSION["passwords"][$_POST["driver"]][$_POST["server"]][$_POST["username"]] = $_POST["password"];
$_SESSION["passwords"][$_POST["server"]] = $_POST["password"];
if ($_POST["permanent"]) { 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["server"])
. ":" . base64_encode($_POST["username"]) . ":" . base64_encode($_POST["username"])
. ":" . base64_encode(encrypt_string($_POST["password"], $adminer->permanentLogin())) . ":" . base64_encode(encrypt_string($_POST["password"], $adminer->permanentLogin()))
. ":" . base64_encode($_POST["driver"])
); );
} }
if (count($_POST) == ($_POST["permanent"] ? 4 : 3)) { // 3 - server, username, password if (count($_POST) == ($_POST["permanent"] ? 5 : 4) // 4 - driver, server, username, password
$location = ((string) $_GET["server"] === $_POST["server"] ? remove_from_uri(session_name()) : preg_replace('~^([^?]*).*~', '\\1', ME) . ($_POST["server"] != "" ? '?server=' . urlencode($_POST["server"]) : '')); || DRIVER != $_POST["driver"]
if (SID_FORM) { || SERVER != $_POST["server"]
$pos = strpos($location, '?'); || $_GET["username"] !== $_POST["username"] // "0" == "00"
$location = ($pos ? substr_replace($location, SID . "&", $pos + 1, 0) : "$location?" . SID); ) {
} preg_match('~([^?]*)\\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . session_name()), $match);
redirect($location); redirect("$match[1]?"
. (SID ? SID . "&" : "")
. ($_POST["driver"] != "server" || $_POST["server"] != "" ? urlencode($_POST["driver"]) . "=" . urlencode($_POST["server"]) . "&" : "")
. "username=" . urlencode($_POST["username"])
. ($match[2] ? "&$match[2]" : "")
);
} }
$_GET["server"] = $_POST["server"]; //! used also in ME
} elseif ($_POST["logout"]) { } elseif ($_POST["logout"]) {
$token = $_SESSION["tokens"][$_GET["server"]];
if ($token && $_POST["token"] != $token) { if ($token && $_POST["token"] != $token) {
page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.')); page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.'));
page_footer("db"); page_footer("db");
exit; exit;
} else { } else {
foreach (array("usernames", "passwords", "databases", "tokens", "history") as $val) { foreach (array("passwords", "databases", "history") as $key) {
unset($_SESSION[$val][$_GET["server"]]); set_session($key, null);
}
if (!isset($_SESSION["passwords"])) { // don't require login to logout
$_SESSION["passwords"] = array();
} }
cookie("adminer_permanent", ""); cookie("adminer_permanent", "");
redirect(substr(preg_replace('~db=[^&]*&~', '', ME), 0, -1), lang('Logout successful.')); redirect(substr(preg_replace('~(username|db)=[^&]*&~', '', 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"])); list($server, $username, $cipher, $system) = array_map('base64_decode', explode(":", $_COOKIE["adminer_permanent"])); // $driver is a global variable
if (($_GET["server"] == "" && !$_POST) || $server == $_GET["server"]) { if ($server == SERVER && $username === $_GET["username"] && $system == DRIVER) {
session_regenerate_id(); // defense against session fixation session_regenerate_id(); // defense against session fixation
$_SESSION["usernames"][$server] = $username; set_session("passwords", decrypt_string($cipher, $adminer->permanentLogin()));
$_SESSION["passwords"][$server] = decrypt_string($cipher, $adminer->permanentLogin());
if ($server != $_GET["server"]) {
redirect(preg_replace('~^([^?]*).*~', '\\1', ME) . '?server=' . urlencode($server));
}
} }
//! redirect ?select=tab
} }
function auth_error($exception = null) { function auth_error($exception = null) {
global $connection, $adminer; global $connection, $adminer, $token;
$session_name = session_name(); $session_name = session_name();
$username = $_SESSION["usernames"][$_GET["server"]]; $error = "";
unset($_SESSION["usernames"][$_GET["server"]]); if (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_bool("session.use_only_cookies")) {
page_header(lang('Login'), (isset($username) ? h($exception ? $exception->getMessage() : (is_string($connection) ? $connection : lang('Invalid credentials.'))) $error = lang('Session support must be enabled.');
: (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_get("session.use_only_cookies") ? lang('Session support must be enabled.') } elseif (isset($_GET["username"])) {
: (($_COOKIE[$session_name] || $_GET[$session_name]) && !isset($_SESSION["passwords"]) ? lang('Session expired, please login again.') if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$token) {
: ""))), null); $error = lang('Session expired, please login again.');
} else {
$password = get_session("passwords");
if (isset($password)) {
$error = h($exception ? $exception->getMessage() : (is_string($connection) ? $connection : lang('Invalid credentials.')));
}
}
}
page_header(lang('Login'), $error, null);
echo "<form action='' method='post'>\n"; echo "<form action='' method='post'>\n";
$adminer->loginForm($username); $adminer->loginForm();
echo "<div>"; echo "<div>";
hidden_fields($_POST, array("server", "username", "password")); // expired session hidden_fields($_POST, array("driver", "server", "username", "password", "permanent")); // expired session
echo "</div>\n"; echo "</div>\n";
echo "</form>\n"; echo "</form>\n";
page_footer("auth"); page_footer("auth");
} }
$username = &$_SESSION["usernames"][$_GET["server"]]; if (isset($_GET["username"]) && class_exists("Min_DB")) { // doesn't exists with passing wrong driver
if (!isset($username)) { $connection = connect();
$username = $_GET["username"]; // default username can be passed in URL
} }
$connection = (isset($username) ? connect() : ''); if (is_string($connection) || !$adminer->login($_GET["username"], get_session("passwords"))) {
if (is_string($connection) || !$adminer->login($username, $_SESSION["passwords"][$_GET["server"]])) {
auth_error(); auth_error();
exit; exit;
} }
unset($username);
if (!$_SESSION["tokens"][$_GET["server"]]) { $token = $_SESSION["token"]; ///< @var string CSRF protection
$_SESSION["tokens"][$_GET["server"]] = rand(1, 1e6); // defense against cross-site request forgery
}
if (isset($_POST["server"]) && $_POST["token"]) { if (isset($_POST["server"]) && $_POST["token"]) {
$_POST["token"] = $_SESSION["tokens"][$_GET["server"]]; $_POST["token"] = $token; // reset token after explicit login
} }
$token = $_SESSION["tokens"][$_GET["server"]]; ///< @var string CSRF protection
$error = ($_POST ///< @var string $error = ($_POST ///< @var string
? ($_POST["token"] == $token ? "" : lang('Invalid CSRF token. Send the form again.')) ? ($_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 : ($_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

View file

@ -39,12 +39,14 @@ if (isset($_GET["file"])) {
exit; exit;
} }
include "../adminer/include/functions.inc.php";
if (!isset($_SERVER["REQUEST_URI"])) { if (!isset($_SERVER["REQUEST_URI"])) {
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"] . ($_SERVER["QUERY_STRING"] != "" ? "?$_SERVER[QUERY_STRING]" : ""); $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"] . ($_SERVER["QUERY_STRING"] != "" ? "?$_SERVER[QUERY_STRING]" : ""); // IIS 5 compatibility
} }
@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
if (!ini_get("session.auto_start")) { if (!ini_bool("session.auto_start")) {
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"]), "", $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")); $params = array(0, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off"));
if (version_compare(PHP_VERSION, '5.2.0') >= 0) { if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
@ -75,19 +77,26 @@ if (function_exists("set_magic_quotes_runtime")) {
} }
@set_time_limit(0); // @ - can be disabled @set_time_limit(0); // @ - can be disabled
include "../adminer/include/version.inc.php";
include "../adminer/include/functions.inc.php";
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["server"] != "" ? 'server=' . urlencode($_GET["server"]) . '&' : '') . (DB != "" ? 'db=' . urlencode(DB) . '&' : ''));
include "../adminer/include/lang.inc.php"; include "../adminer/include/lang.inc.php";
include "../adminer/lang/$LANG.inc.php"; include "../adminer/lang/$LANG.inc.php";
include "../adminer/include/pdo.inc.php";
include "../adminer/drivers/sqlite.inc.php";
include "../adminer/drivers/pgsql.inc.php";
include "../adminer/drivers/mssql.inc.php";
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost
define("DB", $_GET["db"]); // for the sake of speed and size
define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\\1', $_SERVER["REQUEST_URI"]) . '?'
. (SID && !$_COOKIE ? SID . '&' : '') // !$_COOKIE - don't pass SID with permanent login
. (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
. (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
. (DB != "" ? 'db=' . urlencode(DB) . '&' : '')
);
include "../adminer/include/version.inc.php";
include "./include/adminer.inc.php"; include "./include/adminer.inc.php";
include "../adminer/include/design.inc.php"; include "../adminer/include/design.inc.php";
include "../adminer/include/pdo.inc.php";
include "../adminer/include/mysql.inc.php";
include "../adminer/include/xxtea.inc.php"; include "../adminer/include/xxtea.inc.php";
include "../adminer/include/auth.inc.php"; include "../adminer/include/auth.inc.php";
include "./include/connect.inc.php"; include "./include/connect.inc.php";
@ -95,7 +104,7 @@ include "./include/editing.inc.php";
include "./include/export.inc.php"; include "./include/export.inc.php";
session_cache_limiter(""); // to allow restarting session session_cache_limiter(""); // to allow restarting session
if (!ini_get("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled if (!ini_bool("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled
session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
} }

View file

@ -1,11 +1,12 @@
<?php <?php
function connect_error() { function connect_error() {
global $connection, $VERSION, $token, $error; global $connection, $VERSION, $token, $error, $drivers;
$databases = array();
if (DB != "") { if (DB != "") {
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), false); page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), true);
} else { } else {
if ($_POST["db"] && !$error) { if ($_POST["db"] && !$error) {
unset($_SESSION["databases"][$_GET["server"]]); set_session("databases", null);
foreach ($_POST["db"] as $db) { foreach ($_POST["db"] as $db) {
if (!queries("DROP DATABASE " . idf_escape($db))) { if (!queries("DROP DATABASE " . idf_escape($db))) {
break; break;
@ -14,30 +15,32 @@ function connect_error() {
queries_redirect(substr(ME, 0, -1), lang('Database has been dropped.'), !$connection->error); queries_redirect(substr(ME, 0, -1), lang('Database has been dropped.'), !$connection->error);
} }
page_header(lang('Select database'), $error, null); page_header(lang('Select database'), $error, false);
echo "<p>"; echo "<p><a href='" . h(ME) . "database='>" . lang('Create new database') . "</a>\n";
foreach (array( foreach (array(
'database' => lang('Create new database'),
'privileges' => lang('Privileges'), 'privileges' => lang('Privileges'),
'processlist' => lang('Process list'), 'processlist' => lang('Process list'),
'variables' => lang('Variables'), 'variables' => lang('Variables'),
'status' => lang('Status'), 'status' => lang('Status'),
) as $key => $val) { ) as $key => $val) {
echo "<a href='" . h(ME) . "$key='>$val</a>\n"; if (support($key)) {
echo "<a href='" . h(ME) . "$key='>$val</a>\n";
}
} }
echo "<p>" . lang('MySQL version: %s through PHP extension %s', "<b" . ($connection->server_info < 4.1 ? " class='binary'" : "") . ">$connection->server_info</b>", "<b>$connection->extension</b>") . "\n"; echo "<p>" . lang('%s version: %s through PHP extension %s', $drivers[DRIVER], "<b>$connection->server_info</b>", "<b>$connection->extension</b>") . "\n";
echo "<p>" . lang('Logged as: %s', "<b>" . h($connection->result($connection->query("SELECT USER()"))) . "</b>") . "\n"; echo "<p>" . lang('Logged as: %s', "<b>" . h(logged_user()) . "</b>") . "\n";
$databases = get_databases(); $databases = get_databases();
if ($databases) { if ($databases) {
$collations = collations(); $collations = collations();
echo "<form action='' method='post'>\n"; echo "<form action='' method='post'>\n";
echo "<table cellspacing='0' onclick='tableClick(event);'>\n"; echo "<table cellspacing='0' onclick='tableClick(event);'>\n";
echo "<thead><tr><td><input type='hidden' name='token' value='$token'>&nbsp;<th>" . lang('Database') . "<td>" . lang('Collation') . "</thead>\n"; echo "<thead><tr><td><input type='hidden' name='token' value='$token'>&nbsp;<th>" . lang('Database') . "<td>" . lang('Collation') . "<td>" . lang('Tables') . "</thead>\n";
foreach ($databases as $db) { foreach ($databases as $db) {
$root = h(ME) . "db=" . urlencode($db); $root = h(ME) . "db=" . urlencode($db);
echo "<tr" . odd() . "><td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"])); echo "<tr" . odd() . "><td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]));
echo "<th><a href='$root'>" . h($db) . "</a>"; echo "<th><a href='$root'>" . h($db) . "</a>";
echo "<td><a href='$root&amp;database='>" . nbsp(db_collation($db, $collations)) . "</a>"; echo "<td><a href='$root&amp;database='>" . nbsp(db_collation($db, $collations)) . "</a>";
echo "<td align='right'><a href='$root&amp;schema=' id='tables-" . h($db) . "'>?</a>";
echo "\n"; echo "\n";
} }
echo "</table>\n"; echo "</table>\n";
@ -46,6 +49,11 @@ function connect_error() {
} }
} }
page_footer("db"); page_footer("db");
echo "<script type='text/javascript'>\n";
foreach (count_tables($databases) as $db => $val) {
echo "setHtml('tables-" . addcslashes($db, "\\'/") . "', '$val');\n";
}
echo "</script>\n";
} }
if (isset($_GET["status"])) { if (isset($_GET["status"])) {
@ -53,7 +61,7 @@ if (isset($_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"]))) { 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 != "") { if (DB != "") {
unset($_SESSION["databases"][$_GET["server"]]); set_session("databases", null);
} }
connect_error(); // separate function to catch SQLite error connect_error(); // separate function to catch SQLite error
exit; exit;

View file

@ -1,8 +1,15 @@
<?php <?php
/** Print HTML header
* @param string used in title, breadcrumb and heading
* @param string
* @param mixed array("key" => "link=desc", "key2" => array("link", "desc")), null for nothing, false for driver only, true for driver and server
* @param string used after colon in title and heading
* @return null
*/
function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") { function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
global $LANG, $VERSION, $adminer, $connection; global $LANG, $VERSION, $adminer, $connection, $drivers;
header("Content-Type: text/html; charset=utf-8"); header("Content-Type: text/html; charset=utf-8");
header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, NoScript plugin header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, Firefox NoScript plugin
$title_all = $title . ($title2 != "" ? ": " . h($title2) : ""); $title_all = $title . ($title2 != "" ? ": " . h($title2) : "");
?> ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
@ -10,34 +17,41 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
<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 http-equiv="Content-Script-Type" content="text/javascript">
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
<title><?php echo $title_all . ($_GET["server"] != "" && $_GET["server"] != "localhost" ? h(" - $_GET[server]") : "") . " - " . $adminer->name(); ?></title> <title><?php echo $title_all . (SERVER != "" && SERVER != "localhost" ? h(" - " . SERVER) : "") . " - " . $adminer->name(); ?></title>
<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="stylesheet" type="text/css" href="../adminer/static/default.css<?php // Ondrej Valka, http://valka.info ?>"> <link rel="stylesheet" type="text/css" href="../adminer/static/default.css<?php // Ondrej Valka, http://valka.info ?>">
<?php if (file_exists("adminer.css")) { ?> <?php if (file_exists("adminer.css")) { ?>
<link rel="stylesheet" type="text/css" href="adminer.css"> <link rel="stylesheet" type="text/css" href="adminer.css">
<?php } ?> <?php } ?>
<body onload="bodyLoad('<?php echo substr($connection->server_info, 0, 3); ?>');<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " verifyVersion();"); ?>"> <body onload="bodyLoad('<?php echo (is_object($connection) ? substr($connection->server_info, 0, 3) : ""); ?>');<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " verifyVersion();"); ?>">
<script type="text/javascript" src="../adminer/static/functions.js"></script> <script type="text/javascript" src="../adminer/static/functions.js"></script>
<script type="text/javascript" src="static/editing.js"></script> <script type="text/javascript" src="static/editing.js"></script>
<div id="content"> <div id="content">
<?php <?php
if (isset($breadcrumb)) { if (isset($breadcrumb)) {
$link = substr(preg_replace('~(username|db)=[^&]*&~', '', ME), 0, -1);
echo '<p id="breadcrumb"><a href="' . ($link ? h($link) : ".") . '">' . $drivers[DRIVER] . '</a> &raquo; ';
$link = substr(preg_replace('~db=[^&]*&~', '', ME), 0, -1); $link = substr(preg_replace('~db=[^&]*&~', '', ME), 0, -1);
echo '<p id="breadcrumb"><a href="' . ($link != "" ? h($link) : ".") . '">' . (isset($_GET["server"]) ? h($_GET["server"]) : lang('Server')) . '</a> &raquo; '; $server = (SERVER != "" ? h(SERVER) : lang('Server'));
if (is_array($breadcrumb)) { if ($breadcrumb === false) {
if (DB != "") { echo "$server\n";
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</a> &raquo; '; } else {
} echo "<a href='" . ($link ? h($link) : ".") . "'>$server</a> &raquo; ";
foreach ($breadcrumb as $key => $val) { if (is_array($breadcrumb)) {
$desc = (is_array($val) ? $val[1] : $val); if (DB != "") {
if ($desc != "") { echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</a> &raquo; ';
echo '<a href="' . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . '">' . h($desc) . '</a> &raquo; '; }
foreach ($breadcrumb as $key => $val) {
$desc = (is_array($val) ? $val[1] : $val);
if ($desc != "") {
echo '<a href="' . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . '">' . h($desc) . '</a> &raquo; ';
}
} }
} }
echo "$title\n";
} }
echo "$title\n";
} }
echo "<h2>$title_all</h2>\n"; echo "<h2>$title_all</h2>\n";
restart_session(); restart_session();
@ -45,10 +59,7 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
echo "<div class='message'>" . implode("</div>\n<div class='message'>", $_SESSION["messages"]) . "</div>\n"; echo "<div class='message'>" . implode("</div>\n<div class='message'>", $_SESSION["messages"]) . "</div>\n";
$_SESSION["messages"] = array(); $_SESSION["messages"] = array();
} }
if (!$_POST && !isset($_SESSION["passwords"])) { // used in auth $databases = &get_session("databases");
$_SESSION["passwords"] = array();
}
$databases = &$_SESSION["databases"][$_GET["server"]];
if (DB != "" && $databases && !in_array(DB, $databases, true)) { if (DB != "" && $databases && !in_array(DB, $databases, true)) {
$databases = null; $databases = null;
} }
@ -57,7 +68,11 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
} }
} }
function page_footer($missing = false) { /** Print HTML footer
* @param string auth|db
* @return null
*/
function page_footer($missing = "") {
global $adminer; global $adminer;
?> ?>
</div> </div>
@ -67,4 +82,8 @@ function page_footer($missing = false) {
<?php $adminer->navigation($missing); ?> <?php $adminer->navigation($missing); ?>
</div> </div>
<?php <?php
// don't wait for code after footer
session_write_close();
ob_flush();
flush();
} }

View file

@ -84,8 +84,8 @@ function select($result, $connection2 = null) {
*/ */
function referencable_primary($self) { function referencable_primary($self) {
$return = array(); // table_name => field $return = array(); // table_name => field
foreach (table_status_referencable() as $table_name => $table) { foreach (table_status() as $table_name => $table) {
if ($table_name != $self) { if ($table_name != $self && fk_support($table)) {
foreach (fields($table_name) as $field) { foreach (fields($table_name) as $field) {
if ($field["primary"]) { if ($field["primary"]) {
if ($return[$table_name]) { // multi column primary key if ($return[$table_name]) { // multi column primary key
@ -142,16 +142,19 @@ function process_type($field, $collate = "COLLATE") {
/** Create SQL string from field /** Create SQL string from field
* @param array basic field information * @param array basic field information
* @param array information about field type * @param array information about field type
* @return string * @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT")
*/ */
function process_field($field, $type_field) { function process_field($field, $type_field) {
global $connection; global $connection;
return idf_escape($field["field"]) . process_type($type_field) return array(
. ($field["null"] ? " NULL" : " NOT NULL") // NULL for timestamp idf_escape($field["field"]),
. (!isset($field["default"]) ? "" : " DEFAULT " . ($field["type"] == "timestamp" && eregi("^CURRENT_TIMESTAMP$", $field["default"]) ? $field["default"] : $connection->quote($field["default"]))) process_type($type_field),
. ($field["on_update"] ? " ON UPDATE $field[on_update]" : "") ($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp
. " COMMENT " . $connection->quote($field["comment"]) (isset($field["default"]) ? " DEFAULT " . ($field["type"] == "timestamp" && eregi("^CURRENT_TIMESTAMP$", $field["default"]) ? $field["default"] : $connection->quote($field["default"])) : ""),
; ($field["on_update"] ? " ON UPDATE $field[on_update]" : ""),
(support("comment") && $field["comment"] != "" ? " COMMENT " . $connection->quote($field["comment"]) : ""),
($field["auto_increment"] ? auto_increment() : ""),
);
} }
/** Get type class to use in CSS /** Get type class to use in CSS
@ -179,12 +182,11 @@ function type_class($type) {
* @param array returned by referencable_primary() * @param array returned by referencable_primary()
* @return bool column comments used * @return bool column comments used
*/ */
function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $foreign_keys = array()) { function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $foreign_keys = array(), $comments = false) {
global $inout; global $inout;
$column_comments = false;
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field["comment"] != "") { if ($field["comment"] != "") {
$column_comments = true; $comments = true;
break; break;
} }
} }
@ -197,9 +199,9 @@ function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $forei
<td><?php echo lang('Options'); ?> <td><?php echo lang('Options'); ?>
<?php if ($type == "TABLE") { ?> <?php if ($type == "TABLE") { ?>
<td>NULL <td>NULL
<td><input type="radio" name="auto_increment_col" value=""><acronym title="<?php echo lang('Auto Increment'); ?>">A_I</acronym> <td><input type="radio" name="auto_increment_col" value=""><acronym title="<?php echo lang('Auto Increment'); ?>">AI</acronym>
<td class="hidden"><?php echo lang('Default values'); ?> <td class="hidden"><?php echo lang('Default values'); ?>
<td<?php echo ($column_comments ? "" : " class='hidden'"); ?>><?php echo lang('Comment'); ?> <?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . ">" . lang('Comment') : ""); ?>
<?php } ?> <?php } ?>
<td><?php echo "<input type='image' name='add[0]' 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' name='add[0]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>"; ?><script type="text/javascript">row_count = <?php echo count($fields); ?>;</script>
</thead> </thead>
@ -209,27 +211,24 @@ function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $forei
$display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i])); $display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i]));
?> ?>
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>> <tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
<?php <?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", $inout, $field["inout"]) : ""); ?>
if ($type == "PROCEDURE") {
echo "<td>" . html_select("fields[$i][inout]", $inout, $field["inout"]);
}
?>
<th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" onchange="<?php echo ($field["field"] != "" || count($fields) > 1 ? "" : "editingAddRow(this, $allowed); "); ?>editingNameChange(this);" maxlength="64"><?php } ?><input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($field[($_POST ? "orig" : "field")]); ?>"> <th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" onchange="<?php echo ($field["field"] != "" || count($fields) > 1 ? "" : "editingAddRow(this, $allowed); "); ?>editingNameChange(this);" maxlength="64"><?php } ?><input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($field[($_POST ? "orig" : "field")]); ?>">
<?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"]); ?> <td><?php echo checkbox("fields[$i][null]", 1, $field["null"]); ?>
<td><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?>> <td><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?>>
<td class="hidden"><?php echo checkbox("fields[$i][has_default]", 1, $field["has_default"]); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" onchange="this.previousSibling.checked = true;"> <td class="hidden"><?php echo checkbox("fields[$i][has_default]", 1, $field["has_default"]); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" onchange="this.previousSibling.checked = true;">
<td<?php echo ($column_comments ? "" : " class='hidden'"); ?>><input name="fields[<?php echo $i; ?>][comment]" value="<?php echo h($field["comment"]); ?>" maxlength="255"> <?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . "><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' maxlength='255'>" : ""); ?>
<?php } ?> <?php } ?>
<?php <?php
//! hide operations not supported by the driver - column change, adding column not at the end, drop column, ...
echo "<td><input type='image' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "' onclick='return !editingAddRow(this, $allowed, 1);'>"; echo "<td><input type='image' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "' onclick='return !editingAddRow(this, $allowed, 1);'>";
echo "&nbsp;<input type='image' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "' onclick='return !editingRemoveRow(this);'>"; echo "&nbsp;<input type='image' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "' onclick='return !editingRemoveRow(this);'>";
echo "&nbsp;<input type='image' name='up[$i]' src='../adminer/static/up.gif' alt='^' title='" . lang('Move up') . "'>"; echo "&nbsp;<input type='image' name='up[$i]' src='../adminer/static/up.gif' alt='^' title='" . lang('Move up') . "'>";
echo "&nbsp;<input type='image' name='down[$i]' src='../adminer/static/down.gif' alt='v' title='" . lang('Move down') . "'>"; echo "&nbsp;<input type='image' name='down[$i]' src='../adminer/static/down.gif' alt='v' title='" . lang('Move down') . "'>";
echo "\n"; echo "\n";
} }
return $column_comments; return $comments;
} }
/** Move fields up and down or add field /** Move fields up and down or add field
@ -278,7 +277,7 @@ function process_fields(&$fields) {
* @return string * @return string
*/ */
function normalize_enum($match) { function normalize_enum($match) {
return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0]{0} . $match[0]{0}, $match[0]{0}, substr($match[0], 1, -1))), '\\')) . "'"; return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0][0] . $match[0][0], $match[0][0], substr($match[0], 1, -1))), '\\')) . "'";
} }
/** Get information about stored routine /** Get information about stored routine
@ -291,7 +290,7 @@ function routine($name, $type) {
$aliases = array("bit" => "tinyint", "bool" => "tinyint", "boolean" => "tinyint", "integer" => "int", "double precision" => "float", "real" => "float", "dec" => "decimal", "numeric" => "decimal", "fixed" => "decimal", "national char" => "char", "national varchar" => "varchar"); $aliases = array("bit" => "tinyint", "bool" => "tinyint", "boolean" => "tinyint", "integer" => "int", "double precision" => "float", "real" => "float", "dec" => "decimal", "numeric" => "decimal", "fixed" => "decimal", "national char" => "char", "national varchar" => "varchar");
$type_pattern = "(" . implode("|", array_keys($types + $aliases)) . ")(?:\\s*\\(((?:[^'\")]*|$enum_length)+)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s]+)['\"]?)?"; $type_pattern = "(" . implode("|", array_keys($types + $aliases)) . ")(?:\\s*\\(((?:[^'\")]*|$enum_length)+)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s]+)['\"]?)?";
$pattern = "\\s*(" . ($type == "FUNCTION" ? "" : implode("|", $inout)) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern"; $pattern = "\\s*(" . ($type == "FUNCTION" ? "" : implode("|", $inout)) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
$create = $connection->result($connection->query("SHOW CREATE $type " . idf_escape($name)), 2); $create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
preg_match("~\\(((?:$pattern\\s*,?)*)\\)" . ($type == "FUNCTION" ? "\\s*RETURNS\\s+$type_pattern" : "") . "\\s*(.*)~is", $create, $match); preg_match("~\\(((?:$pattern\\s*,?)*)\\)" . ($type == "FUNCTION" ? "\\s*RETURNS\\s+$type_pattern" : "") . "\\s*(.*)~is", $create, $match);
$fields = array(); $fields = array();
preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER); preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER);

View file

@ -11,7 +11,7 @@ function tar_file($filename, $contents) {
function dump_triggers($table, $style) { function dump_triggers($table, $style) {
global $connection; global $connection;
if ($_POST["format"] == "sql" && $style && $connection->server_info >= 5) { if ($_POST["format"] == "sql" && $style && support("trigger")) {
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_"))); $result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_")));
if ($result->num_rows) { if ($result->num_rows) {
$s = "\nDELIMITER ;;\n"; $s = "\nDELIMITER ;;\n";
@ -26,18 +26,17 @@ function dump_triggers($table, $style) {
function dump_table($table, $style, $is_view = false) { function dump_table($table, $style, $is_view = false) {
global $connection; global $connection;
if ($_POST["format"] == "csv") { if ($_POST["format"] != "sql") {
echo "\xef\xbb\xbf"; // UTF-8 byte order mark echo "\xef\xbb\xbf"; // UTF-8 byte order mark
if ($style) { if ($style) {
dump_csv(array_keys(fields($table))); dump_csv(array_keys(fields($table)));
} }
} elseif ($style) { } elseif ($style) {
$result = $connection->query("SHOW CREATE TABLE " . idf_escape($table)); $create = create_sql($table);
if ($result) { if ($create) {
if ($style == "DROP+CREATE") { if ($style == "DROP+CREATE") {
echo "DROP " . ($is_view ? "VIEW" : "TABLE") . " IF EXISTS " . idf_escape($table) . ";\n"; echo "DROP " . ($is_view ? "VIEW" : "TABLE") . " IF EXISTS " . idf_escape($table) . ";\n";
} }
$create = $connection->result($result, 1);
echo ($style != "CREATE+ALTER" ? $create : ($is_view ? substr_replace($create, " OR REPLACE", 6, 0) : substr_replace($create, " IF NOT EXISTS", 12, 0))) . ";\n\n"; echo ($style != "CREATE+ALTER" ? $create : ($is_view ? substr_replace($create, " OR REPLACE", 6, 0) : substr_replace($create, " IF NOT EXISTS", 12, 0))) . ";\n\n";
} }
if ($style == "CREATE+ALTER" && !$is_view) { if ($style == "CREATE+ALTER" && !$is_view) {
@ -116,10 +115,10 @@ DROP PROCEDURE adminer_alter;
} }
function dump_data($table, $style, $select = "") { function dump_data($table, $style, $select = "") {
global $connection; global $connection, $driver;
$max_packet = 1048576; // default, minimum is 1024 $max_packet = ($driver == "sqlite" ? 0 : 1048576); // default, minimum is 1024
if ($style) { if ($style) {
if ($_POST["format"] != "csv" && $style == "TRUNCATE+INSERT") { if ($_POST["format"] == "sql" && $style == "TRUNCATE+INSERT") {
echo "TRUNCATE " . idf_escape($table) . ";\n"; echo "TRUNCATE " . idf_escape($table) . ";\n";
} }
$fields = fields($table); $fields = fields($table);
@ -128,7 +127,7 @@ function dump_data($table, $style, $select = "") {
$insert = ""; $insert = "";
$buffer = ""; $buffer = "";
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
if ($_POST["format"] == "csv") { if ($_POST["format"] != "sql") {
dump_csv($row); dump_csv($row);
} else { } else {
if (!$insert) { if (!$insert) {
@ -145,7 +144,7 @@ function dump_data($table, $style, $select = "") {
} }
echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n"; echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n";
} else { } else {
$s = "\n($s)"; $s = ($max_packet ? "\n" : " ") . "($s)";
if (!$buffer) { if (!$buffer) {
$buffer = $insert . $s; $buffer = $insert . $s;
} elseif (strlen($buffer) + 2 + strlen($s) < $max_packet) { // 2 - separator and terminator length } elseif (strlen($buffer) + 2 + strlen($s) < $max_packet) { // 2 - separator and terminator length
@ -158,7 +157,7 @@ function dump_data($table, $style, $select = "") {
} }
} }
} }
if ($_POST["format"] != "csv" && $style != "INSERT+UPDATE" && $buffer) { if ($_POST["format"] == "sql" && $style != "INSERT+UPDATE" && $buffer) {
$buffer .= ";\n"; $buffer .= ";\n";
echo $buffer; echo $buffer;
} }

View file

@ -8,20 +8,12 @@ function connection() {
return $connection; return $connection;
} }
/** Escape database identifier
* @param string
* @return string
*/
function idf_escape($idf) {
return "`" . str_replace("`", "``", $idf) . "`";
}
/** Unescape database identifier /** Unescape database identifier
* @param string text inside `` * @param string text inside ``
* @return string * @return string
*/ */
function idf_unescape($idf) { function idf_unescape($idf) {
return str_replace("``", "`", $idf); return str_replace($idf[0] . $idf[0], $idf[0], substr($idf, 1, -1));
} }
/** Escape string to use inside '' /** Escape string to use inside ''
@ -60,6 +52,14 @@ function nbsp($string) {
return (trim($string) != "" ? h($string) : "&nbsp;"); return (trim($string) != "" ? h($string) : "&nbsp;");
} }
/** Convert \n to <br>
* @param string
* @return string
*/
function nl_br($string) {
return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
}
/** Generate HTML checkbox /** Generate HTML checkbox
* @param string * @param string
* @param string * @param string
@ -71,7 +71,7 @@ function nbsp($string) {
function checkbox($name, $value, $checked, $label = "", $onclick = "") { function checkbox($name, $value, $checked, $label = "", $onclick = "") {
static $id = 0; static $id = 0;
$id++; $id++;
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'" . ($checked ? " checked" : "") . ($onclick ? " onclick=\"$onclick\"" : "") . " id='checkbox-$id'>"; $return = "<input type='checkbox'" . ($name ? " name='$name' value='" . h($value) . "'" : "") . ($checked ? " checked" : "") . ($onclick ? " onclick=\"$onclick\"" : "") . " id='checkbox-$id'>";
return ($label != "" ? "<label for='checkbox-$id'>$return" . h($label) . "</label>" : $return); return ($label != "" ? "<label for='checkbox-$id'>$return" . h($label) . "</label>" : $return);
} }
@ -115,6 +115,15 @@ function html_select($name, $options, $value = "", $onchange = true) {
return $return; return $return;
} }
/** Get INI boolean value
* @param string
* @return bool
*/
function ini_bool($ini) {
$val = ini_get($ini);
return (eregi('^(on|true|yes)$', $val) || (int) $val); // boolean values set by php_value are strings
}
/** Get list of values from database /** Get list of values from database
* @param string * @param string
* @param mixed * @param mixed
@ -132,6 +141,24 @@ function get_vals($query, $column = 0) {
return $return; return $return;
} }
/** Get keys from first column and values from second
* @param string
* @param Min_DB
* @return array
*/
function get_key_vals($query, $connection2 = null) {
global $connection;
if (!is_object($connection2)) {
$connection2 = $connection;
}
$return = array();
$result = $connection2->query($query);
while ($row = $result->fetch_row()) {
$return[$row[0]] = $row[1];
}
return $return;
}
/** Find unique identifier of a row /** Find unique identifier of a row
* @param array * @param array
* @param array result of indexes() * @param array result of indexes()
@ -200,7 +227,14 @@ function where_link($i, $column, $value, $operator = "=") {
* @return bool * @return bool
*/ */
function cookie($name, $value) { function cookie($name, $value) {
$params = array($name, $value, time() + 2592000, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")); // 2592000 = 30 * 24 * 60 * 60 $params = array(
$name,
(ereg("\n", $value) ? "" : $value), // HTTP Response Splitting protection in PHP < 5.1.2
time() + 2592000, // 2592000 - 30 days
preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]),
"",
$_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")
);
if (version_compare(PHP_VERSION, '5.2.0') >= 0) { if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
$params[] = true; // HttpOnly $params[] = true; // HttpOnly
} }
@ -211,11 +245,28 @@ function cookie($name, $value) {
* @return null * @return null
*/ */
function restart_session() { function restart_session() {
if (!ini_get("session.use_cookies")) { if (!ini_bool("session.use_cookies")) {
session_start(); session_start();
} }
} }
/** Get session variable for current server
* @param string
* @return mixed
*/
function &get_session($key) {
return $_SESSION[$key][DRIVER][SERVER][$_GET["username"]];
}
/** Set session variable for current server
* @param string
* @param mixed
* @return mixed
*/
function set_session($key, $val) {
$_SESSION[$key][DRIVER][SERVER][$_GET["username"]] = $val; // used also in auth.inc.php
}
/** Send Location header and exit /** Send Location header and exit
* @param string null to only set a message * @param string null to only set a message
* @param string * @param string
@ -385,6 +436,15 @@ function hidden_fields($process, $ignore = array()) {
} }
} }
/** Print hidden fields for GET forms
* @return null
*/
function hidden_fields_get() {
echo (SID && !$_COOKIE ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : '');
echo (SERVER !== null ? '<input type="hidden" name="' . DRIVER . '" value="' . h(SERVER) . '">' : "");
echo '<input type="hidden" name="username" value="' . h($_GET["username"]) . '">';
}
/** Find out foreign keys for each column /** Find out foreign keys for each column
* @param string * @param string
* @return array array($col => array()) * @return array array($col => array())
@ -399,6 +459,22 @@ function column_foreign_keys($table) {
return $return; return $return;
} }
/** Print enum input field
* @param string "radio"|"checkbox"
* @param string
* @param array
* @param mixed int|string|array
* @return null
*/
function enum_input($type, $name, $field, $value) {
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_int($value) ? $value == $i+1 : (is_array($value) ? in_array($i+1, $value) : $value === $val));
echo " <label><input type='$type' name='$name' value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($val) . '</label>';
}
}
/** Print edit input field /** Print edit input field
* @param array one field from fields() * @param array one field from fields()
* @param mixed * @param mixed
@ -406,19 +482,14 @@ function column_foreign_keys($table) {
* @return null * @return null
*/ */
function input($field, $value, $function) { function input($field, $value, $function) {
global $types, $adminer; global $types, $adminer, $driver;
$name = h(bracket_escape($field["field"])); $name = h(bracket_escape($field["field"]));
echo "<td class='function'>"; echo "<td class='function'>";
$functions = (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field); $functions = (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
echo nbsp($functions[""]) . "<td>" . ($functions["orig"] ? "<label><input type='radio' name='fields[$name]' value='-1' checked><em>$functions[orig]</em></label> " : ""); echo nbsp($functions[""]) . "<td>" . ($functions["orig"] ? "<label><input type='radio' name='fields[$name]' value='-1' checked><em>$functions[orig]</em></label> " : "");
echo $adminer->editInput($_GET["edit"], $field, " name='fields[$name]'", $value); echo $adminer->editInput($_GET["edit"], $field, " name='fields[$name]'", $value);
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches); enum_input("radio", "fields[$name]", $field, $value);
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_int($value) ? $value == $i+1 : $value === $val);
echo " <label><input type='radio' name='fields[$name]' value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($val) . '</label>';
}
} else { } else {
$first = 0; $first = 0;
foreach ($functions as $key => $val) { foreach ($functions as $key => $val) {
@ -440,10 +511,10 @@ function input($field, $value, $function) {
$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($val) . '</label>'; echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . (1 << $i) . "'" . ($checked ? ' checked' : '') . "$onchange>" . h($val) . '</label>';
} }
} elseif (ereg('binary|blob', $field["type"]) && ini_get("file_uploads")) { } elseif (ereg('binary|blob|bytea', $field["type"]) && ini_bool("file_uploads")) {
echo "<input type='file' name='fields-$name'$onchange>"; echo "<input type='file' name='fields-$name'$onchange>";
} elseif (ereg('text|blob', $field["type"])) { } elseif (ereg('text|blob', $field["type"])) {
echo "<textarea cols='50' rows='12'$attrs>" . h($value) . '</textarea>'; echo "<textarea cols='50' rows='" . ($driver != "sqlite" || ereg("\n", $value) ? 12 : 1) . "'$attrs>" . h($value) . '</textarea>';
} else { } else {
// int(3) is only a display hint // int(3) is only a display hint
$maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)); $maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
@ -461,23 +532,35 @@ function process_input($field) {
$idf = bracket_escape($field["field"]); $idf = bracket_escape($field["field"]);
$function = $_POST["function"][$idf]; $function = $_POST["function"][$idf];
$value = $_POST["fields"][$idf]; $value = $_POST["fields"][$idf];
if ($field["type"] == "enum" ? $value == -1 : $function == "orig") { if ($field["type"] == "enum") {
return false; if ($value == -1) {
} elseif ($field["type"] == "enum" || $field["auto_increment"] ? $value == "" : $function == "NULL") { return false;
return "NULL"; }
} elseif ($field["type"] == "enum") { if ($value == "") {
return "NULL";
}
return intval($value); return intval($value);
} elseif ($field["type"] == "set") { }
if ($field["auto_increment"] && $value == "") {
return null;
}
if ($function == "orig") {
return false;
}
if ($function == "NULL") {
return "NULL";
}
if ($field["type"] == "set") {
return array_sum((array) $value); return array_sum((array) $value);
} elseif (ereg('binary|blob', $field["type"]) && ini_get("file_uploads")) { }
if (ereg('binary|blob|bytea', $field["type"]) && ini_bool("file_uploads")) {
$file = get_file("fields-$idf"); $file = get_file("fields-$idf");
if (!is_string($file)) { if (!is_string($file)) {
return false; //! report errors return false; //! report errors
} }
return $connection->quote($file); return $connection->quote($file);
} else {
return $adminer->processInput($field, $value, $function);
} }
return $adminer->processInput($field, $value, $function);
} }
/** Print results of search in all tables /** Print results of search in all tables
@ -491,7 +574,7 @@ function search_tables() {
foreach (table_status() as $table => $table_status) { foreach (table_status() as $table => $table_status) {
$name = $adminer->tableName($table_status); $name = $adminer->tableName($table_status);
if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) { if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) {
$result = $connection->query("SELECT 1 FROM " . idf_escape($table) . " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())) . " LIMIT 1"); $result = $connection->query("SELECT" . limit("1 FROM " . idf_escape($table) . " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())), 1));
if ($result->num_rows) { if ($result->num_rows) {
if (!$found) { if (!$found) {
echo "<ul>\n"; echo "<ul>\n";
@ -510,11 +593,11 @@ function search_tables() {
*/ */
function dump_csv($row) { function dump_csv($row) {
foreach ($row as $key => $val) { foreach ($row as $key => $val) {
if (preg_match("~[\"\n,]~", $val) || $val === "") { if (preg_match("~[\"\n,;]~", $val) || $val === "") {
$row[$key] = '"' . str_replace('"', '""', $val) . '"'; $row[$key] = '"' . str_replace('"', '""', $val) . '"';
} }
} }
echo implode(",", $row) . "\n"; echo implode(($_POST["format"] == "csv;" ? ";" : ","), $row) . "\n";
} }
/** Apply SQL function /** Apply SQL function
@ -523,7 +606,7 @@ function dump_csv($row) {
* @return string * @return string
*/ */
function apply_sql_function($function, $column) { function apply_sql_function($function, $column) {
return ($function ? ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)" : $column); return ($function ? ($function == "unixepoch" ? "DATETIME($column, '$function')" : ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)") : $column);
} }
/** Check whether the string is e-mail address /** Check whether the string is e-mail address

View file

@ -1,406 +0,0 @@
<?php
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
if (extension_loaded("mysqli")) {
class Min_DB extends MySQLi {
var $extension = "MySQLi";
function Min_DB() {
parent::init();
}
function connect($server, $username, $password) {
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
return @$this->real_connect(
($server != "" ? $host : ini_get("mysqli.default_host")),
("$server$username" != "" ? $username : ini_get("mysqli.default_user")),
("$server$username$password" != "" ? $password : ini_get("mysqli.default_pw")),
null,
(is_numeric($port) ? $port : ini_get("mysqli.default_port")),
(!is_numeric($port) ? $port : null)
);
}
function result($result, $field = 0) {
if (!$result) {
return false;
}
$row = $result->fetch_array();
return $row[$field];
}
function quote($string) {
return "'" . $this->escape_string($string) . "'";
}
}
} elseif (extension_loaded("mysql")) {
class Min_DB {
var $extension = "MySQL", $_link, $_result, $server_info, $affected_rows, $error;
function connect($server, $username, $password) {
$this->_link = @mysql_connect(
($server != "" ? $server : ini_get("mysql.default_host")),
("$server$username" != "" ? $username : ini_get("mysql.default_user")),
("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
true,
131072 // CLIENT_MULTI_RESULTS for CALL
);
if ($this->_link) {
$this->server_info = mysql_get_server_info($this->_link);
} else {
$this->error = mysql_error();
}
return (bool) $this->_link;
}
function quote($string) {
return "'" . mysql_real_escape_string($string, $this->_link) . "'";
}
function select_db($database) {
return mysql_select_db($database, $this->_link);
}
function query($query, $unbuffered = false) {
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
if (!$result) {
$this->error = mysql_error($this->_link);
return false;
}
if ($result === true) {
$this->affected_rows = mysql_affected_rows($this->_link);
$this->info = mysql_info($this->_link);
return true;
}
return new Min_Result($result);
}
function multi_query($query) {
return $this->_result = $this->query($query);
}
function store_result() {
return $this->_result;
}
function next_result() {
// MySQL extension doesn't support multiple results
return false;
}
function result($result, $field = 0) {
if (!$result) {
return false;
}
return mysql_result($result->_result, 0, $field);
}
}
class Min_Result {
var $_result, $_offset = 0, $num_rows;
function Min_Result($result) {
$this->_result = $result;
$this->num_rows = mysql_num_rows($result);
}
function fetch_assoc() {
return mysql_fetch_assoc($this->_result);
}
function fetch_row() {
return mysql_fetch_row($this->_result);
}
function fetch_field() {
$row = mysql_fetch_field($this->_result, $this->_offset++);
$row->orgtable = $row->table;
$row->orgname = $row->name;
$row->charsetnr = ($row->blob ? 63 : 0);
return $row;
}
function __destruct() {
mysql_free_result($this->_result); //! is not called in PHP 4 which is a problem with mysql.trace_mode
}
}
} elseif (extension_loaded("pdo_mysql")) {
class Min_DB extends Min_PDO {
var $extension = "PDO_MySQL";
function connect($server, $username, $password) {
$this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:([0-9])~', ';port=\\1', $server)), $username, $password);
$this->server_info = $this->result($this->query("SELECT VERSION()"));
return true;
}
function query($query, $unbuffered = false) {
$this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
return parent::query($query, $unbuffered);
}
}
} else {
page_header(lang('No MySQL extension'), lang('None of the supported PHP extensions (%s) are available.', 'MySQLi, MySQL, PDO_MySQL'), null);
page_footer("auth");
exit;
}
/** Connect to the database
* @return mixed Min_DB or string for error
*/
function connect() {
global $adminer;
$connection = new Min_DB;
$credentials = $adminer->credentials();
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
$connection->query("SET SQL_QUOTE_SHOW_CREATE=1");
$connection->query("SET NAMES utf8");
return $connection;
}
return $connection->error;
}
/** Get cached list of databases
* @param bool
* @return array
*/
function get_databases($flush = true) {
// SHOW DATABASES can take a very long time so it is cached
$return = &$_SESSION["databases"][$_GET["server"]];
if (!isset($return)) {
restart_session();
$return = get_vals("SHOW DATABASES");
if ($flush) {
ob_flush();
flush();
}
}
return $return;
}
/** Get database collation
* @param string
* @param array result of collations()
* @return array
*/
function db_collation($db, $collations) {
global $connection;
$return = null;
$result = $connection->query("SHOW CREATE DATABASE " . idf_escape($db));
if ($result) {
$create = $connection->result($result, 1);
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
$return = $match[1];
} elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
// default collation
$return = $collations[$match[1]][0];
}
}
return $return;
}
/**Get supported engines
* @return array
*/
function engines() {
global $connection;
$return = array();
$result = $connection->query("SHOW ENGINES");
while ($row = $result->fetch_assoc()) {
if (ereg("YES|DEFAULT", $row["Support"])) {
$return[] = $row["Engine"];
}
}
return $return;
}
/** Get tables list
* @return array
*/
function tables_list() {
return get_vals("SHOW TABLES");
}
/** Get table status
* @param string
* @return array
*/
function table_status($name = "") {
global $connection;
$return = array();
$result = $connection->query("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . $connection->quote(addcslashes($name, "%_")) : ""));
while ($row = $result->fetch_assoc()) {
if ($row["Engine"] == "InnoDB") {
// ignore internal comment, unnecessary since MySQL 5.1.21
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
}
if ($name != "") {
return $row;
}
$return[$row["Name"]] = $row;
}
return $return;
}
/** Get status of referencable tables
* @return array
*/
function table_status_referencable() {
$return = array();
foreach (table_status() as $name => $row) {
if ($row["Engine"] == "InnoDB") {
$return[$name] = $row;
}
}
return $return;
}
/** Get information about fields
* @param string
* @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
*/
function fields($table) {
global $connection;
$return = array();
$result = $connection->query("SHOW FULL COLUMNS FROM " . idf_escape($table));
if ($result) {
while ($row = $result->fetch_assoc()) {
preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
$return[$row["Field"]] = array(
"field" => $row["Field"],
"full_type" => $row["Type"],
"type" => $match[1],
"length" => $match[2],
"unsigned" => ltrim($match[3] . $match[4]),
"default" => ($row["Default"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
"null" => ($row["Null"] == "YES"),
"auto_increment" => ($row["Extra"] == "auto_increment"),
"on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
"collation" => $row["Collation"],
"privileges" => array_flip(explode(",", $row["Privileges"])),
"comment" => $row["Comment"],
"primary" => ($row["Key"] == "PRI"),
);
}
}
return $return;
}
/** Get table indexes
* @param string
* @param string Min_DB to use
* @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array()))
*/
function indexes($table, $connection2 = null) {
global $connection;
if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
$connection2 = $connection;
}
$return = array();
$result = $connection2->query("SHOW INDEX FROM " . idf_escape($table));
if ($result) {
while ($row = $result->fetch_assoc()) {
$return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE")));
$return[$row["Key_name"]]["columns"][$row["Seq_in_index"]] = $row["Column_name"];
$return[$row["Key_name"]]["lengths"][$row["Seq_in_index"]] = $row["Sub_part"];
}
}
return $return;
}
/** Get foreign keys in table
* @param string
* @return array array($name => array("db" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
*/
function foreign_keys($table) {
global $connection, $on_actions;
static $pattern = '(?:[^`]|``)+';
$return = array();
$result = $connection->query("SHOW CREATE TABLE " . idf_escape($table));
if ($result) {
$create_table = $connection->result($result, 1);
preg_match_all("~CONSTRAINT `($pattern)` FOREIGN KEY \\(((?:`$pattern`,? ?)+)\\) REFERENCES `($pattern)`(?:\\.`($pattern)`)? \\(((?:`$pattern`,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $on_actions) . "))?~", $create_table, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
preg_match_all("~`($pattern)`~", $match[2], $source);
preg_match_all("~`($pattern)`~", $match[5], $target);
$return[$match[1]] = array(
"db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
"table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
"source" => array_map('idf_unescape', $source[1]),
"target" => array_map('idf_unescape', $target[1]),
"on_delete" => $match[6],
"on_update" => $match[7],
);
}
}
return $return;
}
/** Get view SELECT
* @param string
* @return array array("select" => )
*/
function view($name) {
global $connection;
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result($connection->query("SHOW CREATE VIEW " . idf_escape($name)), 1)));
}
/** Get sorted grouped list of collations
* @return array
*/
function collations() {
global $connection;
$return = array();
$result = $connection->query("SHOW COLLATION");
while ($row = $result->fetch_assoc()) {
$return[$row["Charset"]][] = $row["Collation"];
}
ksort($return);
foreach ($return as $key => $val) {
sort($return[$key]);
}
return $return;
}
/** Find out if database is information_schema
* @param string
* @return bool
*/
function information_schema($db) {
global $connection;
return ($connection->server_info >= 5 && $db == "information_schema");
}
/** Get escaped error message
* @return string
*/
function error() {
global $connection;
return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error));
}
/** Return expression for binary comparison
* @param string
* @return string
*/
function exact_value($val) {
global $connection;
return "BINARY " . $connection->quote($val);
}
// value means maximum unsigned length
$types = array();
$structured_types = array();
foreach (array(
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
lang('Binary') => array("binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
lang('Lists') => array("enum" => 65535, "set" => 64),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
$unsigned = array("unsigned", "zerofill", "unsigned zerofill");

View file

@ -1,23 +1,21 @@
<?php <?php
// PDO can be used in several database drivers // PDO can be used in several database drivers
if (extension_loaded('pdo')) { if (extension_loaded('pdo')) {
class Min_PDO extends PDO { /*abstract */class Min_PDO extends PDO {
var $_result, $server_info, $affected_rows, $error; var $_result, $server_info, $affected_rows, $error;
function __construct() { function __construct() {
} }
function dsn($dsn, $username, $password) { function dsn($dsn, $username, $password, $exception_handler = 'auth_error') {
set_exception_handler('auth_error'); // try/catch is not compatible with PHP 4 set_exception_handler($exception_handler); // try/catch is not compatible with PHP 4
parent::__construct($dsn, $username, $password); parent::__construct($dsn, $username, $password);
restore_exception_handler(); restore_exception_handler();
$this->setAttribute(13, array('Min_PDOStatement')); // PDO::ATTR_STATEMENT_CLASS $this->setAttribute(13, array('Min_PDOStatement')); // 13 - PDO::ATTR_STATEMENT_CLASS
$this->server_info = $this->getAttribute(4); // 4 - PDO::ATTR_SERVER_VERSION
} }
function select_db($database) { /*abstract function select_db($database);*/
// database selection is separated from the connection so dbname in DSN can't be used
return $this->query("USE " . idf_escape($database));
}
function query($query, $unbuffered = false) { function query($query, $unbuffered = false) {
$result = parent::query($query); $result = parent::query($query);
@ -50,7 +48,8 @@ if (extension_loaded('pdo')) {
return $this->_result->nextRowset(); return $this->_result->nextRowset();
} }
function result($result, $field = 0) { function result($query, $field = 0) {
$result = $this->query($query);
if (!$result) { if (!$result) {
return false; return false;
} }
@ -79,3 +78,6 @@ if (extension_loaded('pdo')) {
} }
} }
} }
$possible_drivers = array();
$drivers = array();

View file

@ -1,2 +1,2 @@
<?php <?php
$VERSION = "2.3.2"; $VERSION = "3.0.0-dev";

View file

@ -1,5 +1,5 @@
<?php <?php
/** Adminer - Compact MySQL management /** Adminer - Compact database management
* @link http://www.adminer.org/ * @link http://www.adminer.org/
* @author Jakub Vrana, http://php.vrana.cz/ * @author Jakub Vrana, http://php.vrana.cz/
* @copyright 2007 Jakub Vrana * @copyright 2007 Jakub Vrana

View file

@ -1,6 +1,10 @@
<?php <?php
$TABLE = $_GET["indexes"]; $TABLE = $_GET["indexes"];
$index_types = array("PRIMARY", "UNIQUE", "INDEX", "FULLTEXT"); $index_types = array("PRIMARY", "UNIQUE", "INDEX");
$table_status = table_status($TABLE);
if (ereg("MyISAM|Maria", $table_status["Engine"])) {
$index_types[] = "FULLTEXT";
}
$indexes = indexes($TABLE); $indexes = indexes($TABLE);
if ($_POST && !$error && !$_POST["add"]) { if ($_POST && !$error && !$_POST["add"]) {
$alter = array(); $alter = array();
@ -14,32 +18,32 @@ if ($_POST && !$error && !$_POST["add"]) {
if ($column != "") { if ($column != "") {
$length = $index["lengths"][$key]; $length = $index["lengths"][$key];
$set[] = idf_escape($column) . ($length ? "(" . intval($length) . ")" : ""); $set[] = idf_escape($column) . ($length ? "(" . intval($length) . ")" : "");
$columns[count($columns) + 1] = $column; $columns[] = $column;
$lengths[count($lengths) + 1] = ($length ? $length : null); $lengths[] = ($length ? $length : null);
} }
} }
if ($columns) { if ($columns) {
foreach ($indexes as $name => $existing) { foreach ($indexes as $name => $existing) {
ksort($existing["columns"]); ksort($existing["columns"]);
ksort($existing["lengths"]); ksort($existing["lengths"]);
if ($index["type"] == $existing["type"] && $existing["columns"] === $columns && $existing["lengths"] === $lengths) { if ($index["type"] == $existing["type"] && array_values($existing["columns"]) === $columns && (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)) {
// skip existing index // skip existing index
unset($indexes[$name]); unset($indexes[$name]);
continue 2; continue 2;
} }
} }
$alter[] = "\nADD $index[type]" . ($index["type"] == "PRIMARY" ? " KEY" : "") . " (" . implode(", ", $set) . ")"; $alter[] = array($index["type"], "(" . implode(", ", $set) . ")");
} }
} }
} }
// drop removed indexes // drop removed indexes
foreach ($indexes as $name => $existing) { foreach ($indexes as $name => $existing) {
$alter[] = "\nDROP INDEX " . idf_escape($name); $alter[] = array($existing["type"], idf_escape($name), "DROP");
} }
if (!$alter) { if (!$alter) {
redirect(ME . "table=" . urlencode($TABLE)); redirect(ME . "table=" . urlencode($TABLE));
} }
query_redirect("ALTER TABLE " . idf_escape($TABLE) . implode(",", $alter), ME . "table=" . urlencode($TABLE), lang('Indexes have been altered.')); queries_redirect(ME . "table=" . urlencode($TABLE), lang('Indexes have been altered.'), alter_indexes($TABLE, $alter));
} }
page_header(lang('Indexes'), $error, array("table" => $TABLE), $TABLE); page_header(lang('Indexes'), $error, array("table" => $TABLE), $TABLE);
@ -77,7 +81,7 @@ foreach ($row["indexes"] as $index) {
ksort($index["columns"]); ksort($index["columns"]);
foreach ($index["columns"] as $i => $column) { foreach ($index["columns"] as $i => $column) {
echo "<span>" . html_select("indexes[$j][columns][$i]", array(-1 => "") + $fields, $column, ($i == count($index["columns"]) ? "indexesAddColumn(this);" : 1)); echo "<span>" . html_select("indexes[$j][columns][$i]", array(-1 => "") + $fields, $column, ($i == count($index["columns"]) ? "indexesAddColumn(this);" : 1));
echo "<input name='indexes[$j][lengths][$i]' size='2' value='" . h($index["lengths"][$i]) . "'> </span>\n"; echo "<input name='indexes[$j][lengths][$i]' size='2' value='" . h($index["lengths"][$i]) . "'> </span>\n"; //! hide for non-MySQL drivers, add ASC|DESC
} }
echo "\n"; echo "\n";
$j++; $j++;

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Nahrávání souborů není povoleno.', 'File uploads are disabled.' => 'Nahrávání souborů není povoleno.',
'Routine has been called, %d row(s) affected.' => array('Procedura byla zavolána, byl změněn %d záznam.', 'Procedura byla zavolána, byly změněny %d záznamy.', 'Procedura byla zavolána, bylo změněno %d záznamů.'), 'Routine has been called, %d row(s) affected.' => array('Procedura byla zavolána, byl změněn %d záznam.', 'Procedura byla zavolána, byly změněny %d záznamy.', 'Procedura byla zavolána, bylo změněno %d záznamů.'),
'Call' => 'Zavolat', 'Call' => 'Zavolat',
'No MySQL extension' => 'Žádná MySQL extenze', 'No extension' => 'Žádná extenze',
'None of the supported PHP extensions (%s) are available.' => 'Není dostupná žádná z podporovaných PHP extenzí (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Není dostupná žádná z podporovaných PHP extenzí (%s).',
'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.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Vytvořit trigger', 'Create trigger' => 'Vytvořit trigger',
'Time' => 'Čas', 'Time' => 'Čas',
'Event' => 'Událost', 'Event' => 'Událost',
'MySQL version: %s through PHP extension %s' => 'Verze MySQL: %s přes PHP extenzi %s', '%s version: %s through PHP extension %s' => 'Verze %s: %s přes PHP extenzi %s',
'%d row(s)' => array('%d řádek', '%d řádky', '%d řádků'), '%d row(s)' => array('%d řádek', '%d řádky', '%d řádků'),
'~ %s' => '~ %s',
'Remove' => 'Odebrat', 'Remove' => 'Odebrat',
'Are you sure?' => 'Opravdu?', 'Are you sure?' => 'Opravdu?',
'Privileges' => 'Oprávnění', 'Privileges' => 'Oprávnění',
@ -203,7 +202,7 @@ $translations = array(
'Select data' => 'Vypsat data', 'Select data' => 'Vypsat data',
'Stop on error' => 'Zastavit při chybě', 'Stop on error' => 'Zastavit při chybě',
'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Byl překročen maximální povolený počet polí. Zvyšte prosím %s a %s.', 'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Byl překročen maximální povolený počet polí. Zvyšte prosím %s a %s.',
'(anywhere)' => '(kdekoliv)', 'anywhere' => 'kdekoliv',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1', '$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 'd.m.[rrrr]', '[yyyy]-mm-dd' => 'd.m.[rrrr]',
@ -229,4 +228,9 @@ $translations = array(
'File does not exist.' => 'Soubor neexistuje.', 'File does not exist.' => 'Soubor neexistuje.',
'Permanent login' => 'Trvalé přihlášení', 'Permanent login' => 'Trvalé přihlášení',
'%d in total' => '%d celkem', '%d in total' => '%d celkem',
'Attachments' => 'Přílohy',
'System' => 'Systém',
'last' => 'poslední',
'Network' => 'Síť',
'Geometry' => 'Geometrie',
); );

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Importieren von Dateien abgeschaltet.', 'File uploads are disabled.' => 'Importieren von Dateien abgeschaltet.',
'Routine has been called, %d row(s) affected.' => array('Kommando SQL ausgeführt, %d Datensatz betroffen.', 'Kommando SQL ausgeführt, %d Datensätze betroffen.'), 'Routine has been called, %d row(s) affected.' => array('Kommando SQL ausgeführt, %d Datensatz betroffen.', 'Kommando SQL ausgeführt, %d Datensätze betroffen.'),
'Call' => 'Aufrufen', 'Call' => 'Aufrufen',
'No MySQL extension' => 'Keine MySQL-Erweiterungen installiert', 'No extension' => 'Keine Erweiterungen installiert',
'None of the supported PHP extensions (%s) are available.' => 'Keine der unterstützten PHP-Erweiterungen (%s) ist vorhanden.', 'None of the supported PHP extensions (%s) are available.' => 'Keine der unterstützten PHP-Erweiterungen (%s) ist vorhanden.',
'Session support must be enabled.' => 'Sitzungen müssen aktiviert sein.', 'Session support must be enabled.' => 'Sitzungen müssen aktiviert sein.',
'Session expired, please login again.' => 'Sitzungsdauer abgelaufen, bitte erneut anmelden.', 'Session expired, please login again.' => 'Sitzungsdauer abgelaufen, bitte erneut anmelden.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Trigger hinzufügen', 'Create trigger' => 'Trigger hinzufügen',
'Time' => 'Zeitpunkt', 'Time' => 'Zeitpunkt',
'Event' => 'Ereignis', 'Event' => 'Ereignis',
'MySQL version: %s through PHP extension %s' => 'Version MySQL: %s, mit PHP-Erweiterung %s', '%s version: %s through PHP extension %s' => 'Version %s: %s, mit PHP-Erweiterung %s',
'%d row(s)' => array('%d Datensatz', '%d Datensätze'), '%d row(s)' => array('%d Datensatz', '%d Datensätze'),
'~ %s' => '~ %s',
'Remove' => 'Entfernen', 'Remove' => 'Entfernen',
'Are you sure?' => 'Sind Sie sicher ?', 'Are you sure?' => 'Sind Sie sicher ?',
'Privileges' => 'Rechte', 'Privileges' => 'Rechte',
@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Name der Partition', 'Partition name' => 'Name der Partition',
'Values' => 'Werte', 'Values' => 'Werte',
'%d row(s) have been imported.' => array('%d Datensatz importiert.', '%d Datensätze wurden importiert.'), '%d row(s) have been imported.' => array('%d Datensatz importiert.', '%d Datensätze wurden importiert.'),
'Show structure' => 'Tabellenstruktur', 'anywhere' => 'beliebig',
'(anywhere)' => '(beliebig)',
'CSV Import' => 'Importiere CSV', 'CSV Import' => 'Importiere CSV',
'Import' => 'Importieren', 'Import' => 'Importieren',
'Stop on error' => 'Bei Fehler anhaltan', 'Stop on error' => 'Bei Fehler anhaltan',
'Select data' => 'Tabelle auswählen',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1', '$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 't.m.[jjjj]', '[yyyy]-mm-dd' => 't.m.[jjjj]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Importación de archivos deshablilitado.', 'File uploads are disabled.' => 'Importación de archivos deshablilitado.',
'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 MySQL extension' => 'No hay extension MySQL', 'No extension' => 'No hay extension',
'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 expirada, favor loguéese de nuevo.', 'Session expired, please login again.' => 'Sesión expirada, favor loguéese de nuevo.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Agregar Trigger', 'Create trigger' => 'Agregar Trigger',
'Time' => 'Tiempo', 'Time' => 'Tiempo',
'Event' => 'Evento', 'Event' => 'Evento',
'MySQL version: %s through PHP extension %s' => 'Versión MySQL: %s a través de extensión PHP %s', '%s version: %s through PHP extension %s' => 'Versión %s: %s a través de extensión PHP %s',
'%d row(s)' => array('%d registro', '%d registros'), '%d row(s)' => array('%d registro', '%d registros'),
'~ %s' => '~ %s',
'Remove' => 'Eliminar', 'Remove' => 'Eliminar',
'Are you sure?' => 'Está seguro?', 'Are you sure?' => 'Está seguro?',
'Privileges' => 'Privilegios', 'Privileges' => 'Privilegios',
@ -198,12 +197,10 @@ $translations = array(
'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.'),
'Show structure' => 'Información de la Tabla', 'anywhere' => 'donde sea',
'(anywhere)' => '(donde sea)',
'CSV Import' => 'Importar CSV', 'CSV Import' => 'Importar CSV',
'Import' => 'Importar', 'Import' => 'Importar',
'Stop on error' => 'Parar en caso de error', 'Stop on error' => 'Parar en caso de error',
'Select data' => 'Mostrar datos',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$5/$3/$1', '$1-$3-$5' => '$5/$3/$1',
'[yyyy]-mm-dd' => 'dd/mm/[aaaa]', '[yyyy]-mm-dd' => 'dd/mm/[aaaa]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Failide üleslaadimine on keelatud.', 'File uploads are disabled.' => 'Failide üleslaadimine on keelatud.',
'Routine has been called, %d row(s) affected.' => array('Protseduur täideti edukalt, mõjutatud ridu: %d.', 'Protseduur täideti edukalt, mõjutatud ridu: %d.'), 'Routine has been called, %d row(s) affected.' => array('Protseduur täideti edukalt, mõjutatud ridu: %d.', 'Protseduur täideti edukalt, mõjutatud ridu: %d.'),
'Call' => 'Käivita', 'Call' => 'Käivita',
'No MySQL extension' => 'Ei leitud MySQL laiendust', 'No extension' => 'Ei leitud laiendust',
'None of the supported PHP extensions (%s) are available.' => 'Serveris pole ühtegi toetatud PHP laiendustest (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Serveris pole ühtegi toetatud PHP laiendustest (%s).',
'Session support must be enabled.' => 'Sessioonid peavad olema lubatud.', 'Session support must be enabled.' => 'Sessioonid peavad olema lubatud.',
'Session expired, please login again.' => 'Sessioon on aegunud, palun logige uuesti sisse.', 'Session expired, please login again.' => 'Sessioon on aegunud, palun logige uuesti sisse.',
@ -129,7 +129,6 @@ $translations = array(
'Time' => 'Aeg', 'Time' => 'Aeg',
'Event' => 'Sündmus', 'Event' => 'Sündmus',
'%d row(s)' => array('%d rida', '%d rida'), '%d row(s)' => array('%d rida', '%d rida'),
'~ %s' => '~ %s',
'Remove' => 'Eemalda', 'Remove' => 'Eemalda',
'Are you sure?' => 'Kas oled kindel?', 'Are you sure?' => 'Kas oled kindel?',
'Privileges' => 'Õigused', 'Privileges' => 'Õigused',
@ -142,7 +141,7 @@ $translations = array(
'Routine' => 'Protseduur', 'Routine' => 'Protseduur',
'Grant' => 'Anna', 'Grant' => 'Anna',
'Revoke' => 'Eemalda', 'Revoke' => 'Eemalda',
'MySQL version: %s through PHP extension %s' => 'MySQL versioon: %s, kasutatud PHP moodul: %s', '%s version: %s through PHP extension %s' => '%s versioon: %s, kasutatud PHP moodul: %s',
'Logged as: %s' => 'Sisse logitud: %s', 'Logged as: %s' => 'Sisse logitud: %s',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST-andmete maht on liialt suur. Palun vähendage andmeid või suurendage %s php-seadet.', 'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST-andmete maht on liialt suur. Palun vähendage andmeid või suurendage %s php-seadet.',
'Move up' => 'Liiguta ülespoole', 'Move up' => 'Liiguta ülespoole',
@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Partitsiooni nimi', 'Partition name' => 'Partitsiooni nimi',
'Values' => 'Väärtused', 'Values' => 'Väärtused',
'%d row(s) have been imported.' => array('Imporditi %d rida.', 'Imporditi %d rida.'), '%d row(s) have been imported.' => array('Imporditi %d rida.', 'Imporditi %d rida.'),
'Show structure' => 'Tabeli struktuur', 'anywhere' => 'vahet pole',
'(anywhere)' => '(vahet pole)',
'CSV Import' => 'Impordi CSV', 'CSV Import' => 'Impordi CSV',
'Import' => 'Impordi', 'Import' => 'Impordi',
'Stop on error' => 'Peatuda vea esinemisel', 'Stop on error' => 'Peatuda vea esinemisel',
'Select data' => 'Vali tabel',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1', '$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 'd.m.[yyyy]', '[yyyy]-mm-dd' => 'd.m.[yyyy]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Importation de fichier désactivé.', 'File uploads are disabled.' => 'Importation de fichier désactivé.',
'Routine has been called, %d row(s) affected.' => array('Routine exécutée, %d ligne modifiée.', 'Routine exécutée, %d lignes modifiées.'), 'Routine has been called, %d row(s) affected.' => array('Routine exécutée, %d ligne modifiée.', 'Routine exécutée, %d lignes modifiées.'),
'Call' => 'Appeler', 'Call' => 'Appeler',
'No MySQL extension' => 'Extension MySQL introuvable', 'No extension' => 'Extension introuvable',
'None of the supported PHP extensions (%s) are available.' => 'Aucune des extensions PHP supportées (%s) n\'est disponible.', 'None of the supported PHP extensions (%s) are available.' => 'Aucune des extensions PHP supportées (%s) n\'est disponible.',
'Session support must be enabled.' => 'Veuillez activer les sessions.', 'Session support must be enabled.' => 'Veuillez activer les sessions.',
'Session expired, please login again.' => 'Session expirée, veuillez vous authentifier à nouveau.', 'Session expired, please login again.' => 'Session expirée, veuillez vous authentifier à nouveau.',
@ -129,7 +129,6 @@ $translations = array(
'Time' => 'Temps', 'Time' => 'Temps',
'Event' => 'Évènement', 'Event' => 'Évènement',
'%d row(s)' => array('%d ligne', '%d lignes'), '%d row(s)' => array('%d ligne', '%d lignes'),
'~ %s' => '~ %s',
'Remove' => 'Effacer', 'Remove' => 'Effacer',
'Are you sure?' => 'Êtes-vous certain?', 'Are you sure?' => 'Êtes-vous certain?',
'Privileges' => 'Privilège', 'Privileges' => 'Privilège',
@ -142,7 +141,7 @@ $translations = array(
'Routine' => 'Routine', 'Routine' => 'Routine',
'Grant' => 'Grant', 'Grant' => 'Grant',
'Revoke' => 'Revoke', 'Revoke' => 'Revoke',
'MySQL version: %s through PHP extension %s' => 'Version de MySQL: %s utilisant l\'extension %s', '%s version: %s through PHP extension %s' => 'Version de %s: %s utilisant l\'extension %s',
'Logged as: %s' => 'Authentifié en tant que %s', 'Logged as: %s' => 'Authentifié en tant que %s',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'Donnée POST trop grande . Réduire la taille des données ou modifier le %s dans la configuration de PHP.', 'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'Donnée POST trop grande . Réduire la taille des données ou modifier le %s dans la configuration de PHP.',
'Move up' => 'Déplacer vers le haut', 'Move up' => 'Déplacer vers le haut',
@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Nom de la partition', 'Partition name' => 'Nom de la partition',
'Values' => 'Valeurs', 'Values' => 'Valeurs',
'%d row(s) have been imported.' => array('%d ligne a été importé.','%d lignes ont été importé.'), '%d row(s) have been imported.' => array('%d ligne a été importé.','%d lignes ont été importé.'),
'Show structure' => 'Structure de la table', 'anywhere' => 'n\'importe où',
'(anywhere)' => '(n\'importe où)',
'CSV Import' => 'Importation CVS', 'CSV Import' => 'Importation CVS',
'Import' => 'Importer', 'Import' => 'Importer',
'Stop on error' => 'Arrêt sur erreur', 'Stop on error' => 'Arrêt sur erreur',
'Select data' => 'Selectionner la table',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$5/$3/$1', '$1-$3-$5' => '$5/$3/$1',
'[yyyy]-mm-dd' => 'jj/mm/[aaaa]', '[yyyy]-mm-dd' => 'jj/mm/[aaaa]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Caricamento file disabilitato.', 'File uploads are disabled.' => 'Caricamento file disabilitato.',
'Routine has been called, %d row(s) affected.' => array('Routine chiamata, %d riga interessata.', 'Routine chiamata, %d righe interessate.'), 'Routine has been called, %d row(s) affected.' => array('Routine chiamata, %d riga interessata.', 'Routine chiamata, %d righe interessate.'),
'Call' => 'Chiama', 'Call' => 'Chiama',
'No MySQL extension' => 'Estensioni MySQL non presenti', 'No extension' => 'Estensioni non presenti',
'None of the supported PHP extensions (%s) are available.' => 'Nessuna delle estensioni PHP supportate (%s) disponibile.', 'None of the supported PHP extensions (%s) are available.' => 'Nessuna delle estensioni PHP supportate (%s) disponibile.',
'Session support must be enabled.' => 'Le sessioni devono essere abilitate.', 'Session support must be enabled.' => 'Le sessioni devono essere abilitate.',
'Session expired, please login again.' => 'Sessione scaduta, autenticarsi di nuovo.', 'Session expired, please login again.' => 'Sessione scaduta, autenticarsi di nuovo.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Crea trigger', 'Create trigger' => 'Crea trigger',
'Time' => 'Orario', 'Time' => 'Orario',
'Event' => 'Evento', 'Event' => 'Evento',
'MySQL version: %s through PHP extension %s' => 'Versione MySQL: %s via estensione PHP %s', '%s version: %s through PHP extension %s' => 'Versione %s: %s via estensione PHP %s',
'%d row(s)' => array('%d riga', '%d righe'), '%d row(s)' => array('%d riga', '%d righe'),
'~ %s' => '~ %s',
'Remove' => 'Rimuovi', 'Remove' => 'Rimuovi',
'Are you sure?' => 'Sicuro?', 'Are you sure?' => 'Sicuro?',
'Privileges' => 'Privilegi', 'Privileges' => 'Privilegi',
@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Nome partizione', 'Partition name' => 'Nome partizione',
'Values' => 'Valori', 'Values' => 'Valori',
'%d row(s) have been imported.' => array('%d riga importata.','%d righe importate.'), '%d row(s) have been imported.' => array('%d riga importata.','%d righe importate.'),
'Show structure' => 'Struttura tabella', 'anywhere' => 'ovunque',
'(anywhere)' => '(ovunque)',
'CSV Import' => 'Importa da CSV', 'CSV Import' => 'Importa da CSV',
'Import' => 'Importa', 'Import' => 'Importa',
'Stop on error' => 'Stop su errore', 'Stop on error' => 'Stop su errore',
'Select data' => 'Scegli tabella',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$5/$3/$1', '$1-$3-$5' => '$5/$3/$1',
'[yyyy]-mm-dd' => 'dd/mm/[yyyy]', '[yyyy]-mm-dd' => 'dd/mm/[yyyy]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Bestanden uploaden is uitgeschakeld.', 'File uploads are disabled.' => 'Bestanden uploaden is uitgeschakeld.',
'Routine has been called, %d row(s) affected.' => array('Procedure uitgevoerd, %d rij geraakt.', 'Procedure uitgevoerd, %d rijen geraakt.'), 'Routine has been called, %d row(s) affected.' => array('Procedure uitgevoerd, %d rij geraakt.', 'Procedure uitgevoerd, %d rijen geraakt.'),
'Call' => 'Uitvoeren', 'Call' => 'Uitvoeren',
'No MySQL extension' => 'Geen MySQL extensie', 'No extension' => 'Geen extensie',
'None of the supported PHP extensions (%s) are available.' => 'Geen geldige PHP extensies beschikbaar (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Geen geldige PHP extensies beschikbaar (%s).',
'Session support must be enabled.' => 'Sessies moeten geactiveerd zijn.', 'Session support must be enabled.' => 'Sessies moeten geactiveerd zijn.',
'Session expired, please login again.' => 'Uw sessie is verlopen. Gelieve opnieuw in te loggen.', 'Session expired, please login again.' => 'Uw sessie is verlopen. Gelieve opnieuw in te loggen.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Trigger aanmaken', 'Create trigger' => 'Trigger aanmaken',
'Time' => 'Time', 'Time' => 'Time',
'Event' => 'Event', 'Event' => 'Event',
'MySQL version: %s through PHP extension %s' => 'MySQL versie: %s met PHP extensie %s', '%s version: %s through PHP extension %s' => '%s versie: %s met PHP extensie %s',
'%d row(s)' => array('%d rij', '%d rijen'), '%d row(s)' => array('%d rij', '%d rijen'),
'~ %s' => '~ %s',
'Remove' => 'Verwijderen', 'Remove' => 'Verwijderen',
'Are you sure?' => 'Weet u het zeker?', 'Are you sure?' => 'Weet u het zeker?',
'Privileges' => 'Rechten', 'Privileges' => 'Rechten',
@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Partitie naam', 'Partition name' => 'Partitie naam',
'Values' => 'Waarden', 'Values' => 'Waarden',
'%d row(s) have been imported.' => array('%d rij werd geïmporteerd.', '%d rijen werden geïmporteerd.'), '%d row(s) have been imported.' => array('%d rij werd geïmporteerd.', '%d rijen werden geïmporteerd.'),
'Show structure' => 'Tabelstructuur', 'anywhere' => 'overal',
'(anywhere)' => '(overal)',
'CSV Import' => 'CSV Import', 'CSV Import' => 'CSV Import',
'Import' => 'Importeren', 'Import' => 'Importeren',
'Stop on error' => 'Stoppen bij fout', 'Stop on error' => 'Stoppen bij fout',
'Select data' => 'Selecteer tabel',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$5-$3-$1', '$1-$3-$5' => '$5-$3-$1',
'[yyyy]-mm-dd' => 'dd-mm-[jjjj]', '[yyyy]-mm-dd' => 'dd-mm-[jjjj]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Загрузка файлов на сервер запрещена.', 'File uploads are disabled.' => 'Загрузка файлов на сервер запрещена.',
'Routine has been called, %d row(s) affected.' => array('Была вызвана процедура, %d запись была изменена.', 'Была вызвана процедура, %d записи было изменено.', 'Была вызвана процедура, %d записей было изменено.'), 'Routine has been called, %d row(s) affected.' => array('Была вызвана процедура, %d запись была изменена.', 'Была вызвана процедура, %d записи было изменено.', 'Была вызвана процедура, %d записей было изменено.'),
'Call' => 'Вызвать', 'Call' => 'Вызвать',
'No MySQL extension' => 'Нет MySQL расширений', 'No extension' => 'Нет расширений',
'None of the supported PHP extensions (%s) are available.' => 'Не доступно ни одного расширения из поддерживаемых (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Не доступно ни одного расширения из поддерживаемых (%s).',
'Session support must be enabled.' => 'Сессии должны быть включены.', 'Session support must be enabled.' => 'Сессии должны быть включены.',
'Session expired, please login again.' => 'Срок действия сесси истек, нужно снова войти в систему.', 'Session expired, please login again.' => 'Срок действия сесси истек, нужно снова войти в систему.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Создать триггер', 'Create trigger' => 'Создать триггер',
'Time' => 'Время', 'Time' => 'Время',
'Event' => 'Событие', 'Event' => 'Событие',
'MySQL version: %s through PHP extension %s' => 'Версия MySQL: %s с PHP-расширением %s', '%s version: %s through PHP extension %s' => 'Версия %s: %s с PHP-расширением %s',
'%d row(s)' => array('%d строка', '%d строки', '%d строк'), '%d row(s)' => array('%d строка', '%d строки', '%d строк'),
'~ %s' => '~ %s',
'Remove' => 'Удалить', 'Remove' => 'Удалить',
'Are you sure?' => 'Вы уверены?', 'Are you sure?' => 'Вы уверены?',
'Privileges' => 'Полномочия', 'Privileges' => 'Полномочия',
@ -199,11 +198,9 @@ $translations = array(
'%d row(s) have been imported.' => array('Импортирована %d строка.', 'Импортировано %d строки.', 'Импортировано %d строк.'), '%d row(s) have been imported.' => array('Импортирована %d строка.', 'Импортировано %d строки.', 'Импортировано %d строк.'),
'CSV Import' => 'Импорт CSV', 'CSV Import' => 'Импорт CSV',
'Import' => 'Импорт', 'Import' => 'Импорт',
'Show structure' => 'Структура таблицы',
'Select data' => 'Выбрать данные из таблицы',
'Stop on error' => 'Остановить при ошибке', 'Stop on error' => 'Остановить при ошибке',
'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Достигнуто максимальное значение количества доступных полей. Увеличьте %s и %s.', 'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Достигнуто максимальное значение количества доступных полей. Увеличьте %s и %s.',
'(anywhere)' => '(в любом месте)', 'anywhere' => 'в любом месте',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$5.$3.$1', '$1-$3-$5' => '$5.$3.$1',
'[yyyy]-mm-dd' => 'дд.мм.[гггг]', '[yyyy]-mm-dd' => 'дд.мм.[гггг]',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => 'Nahrávánie súborov nie je povolené.', 'File uploads are disabled.' => 'Nahrávánie súborov nie je povolené.',
'Routine has been called, %d row(s) affected.' => array('Procedúra bola zavolaná, bol zmenený %d záznam.', 'Procedúra bola zavolaná, boli zmenené %d záznamy.', 'Procedúra bola zavolaná, bolo zmenených %d záznamov.'), 'Routine has been called, %d row(s) affected.' => array('Procedúra bola zavolaná, bol zmenený %d záznam.', 'Procedúra bola zavolaná, boli zmenené %d záznamy.', 'Procedúra bola zavolaná, bolo zmenených %d záznamov.'),
'Call' => 'Zavolať', 'Call' => 'Zavolať',
'No MySQL extension' => 'Žiadne MySQL rozšírenie', 'No extension' => 'Žiadne rozšírenie',
'None of the supported PHP extensions (%s) are available.' => 'Nie je dostupné žiadne z podporovaných rozšírení (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Nie je dostupné žiadne z podporovaných rozšírení (%s).',
'Session support must be enabled.' => 'Session premenné musia byť povolené.', 'Session support must be enabled.' => 'Session premenné musia byť povolené.',
'Session expired, please login again.' => 'Session vypršala, prihláste sa prosím znova.', 'Session expired, please login again.' => 'Session vypršala, prihláste sa prosím znova.',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Vytvoriť trigger', 'Create trigger' => 'Vytvoriť trigger',
'Time' => 'Čas', 'Time' => 'Čas',
'Event' => 'Udalosť', 'Event' => 'Udalosť',
'MySQL version: %s through PHP extension %s' => 'Verzia MySQL: %s cez PHP rozšírenie %s', '%s version: %s through PHP extension %s' => 'Verzia %s: %s cez PHP rozšírenie %s',
'%d row(s)' => array('%d riadok', '%d riadky', '%d riadkov'), '%d row(s)' => array('%d riadok', '%d riadky', '%d riadkov'),
'~ %s' => '~ %s',
'Remove' => 'Odobrať', 'Remove' => 'Odobrať',
'Are you sure?' => 'Naozaj?', 'Are you sure?' => 'Naozaj?',
'Privileges' => 'Oprávnenia', 'Privileges' => 'Oprávnenia',
@ -199,11 +198,9 @@ $translations = array(
'%d row(s) have been imported.' => array('Bol importovaný %d záznam.', 'Boli importované %d záznamy.', 'Bolo importovaných %d záznamov.'), '%d row(s) have been imported.' => array('Bol importovaný %d záznam.', 'Boli importované %d záznamy.', 'Bolo importovaných %d záznamov.'),
'CSV Import' => 'Import CSV', 'CSV Import' => 'Import CSV',
'Import' => 'Import', 'Import' => 'Import',
'Show structure' => 'Štruktúra tabuľky',
'Select data' => 'Vypísať tabuľku',
'Stop on error' => 'Zastaviť pri chybe', 'Stop on error' => 'Zastaviť pri chybe',
'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Bol prekročený maximálny počet povolených polí. Zvýšte prosím %s a %s.', 'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Bol prekročený maximálny počet povolených polí. Zvýšte prosím %s a %s.',
'(anywhere)' => '(kdekoľvek)', 'anywhere' => 'kdekoľvek',
'%.3f s' => '%.3f s', '%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1', '$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 'd.m.[rrrr]', '[yyyy]-mm-dd' => 'd.m.[rrrr]',

View file

@ -79,7 +79,7 @@ $translations = array(
'File uploads are disabled.' => '檔案上傳被禁用。', 'File uploads are disabled.' => '檔案上傳被禁用。',
'Routine has been called, %d row(s) affected.' => '程序已被執行,%d行被影響', 'Routine has been called, %d row(s) affected.' => '程序已被執行,%d行被影響',
'Call' => '呼叫', 'Call' => '呼叫',
'No MySQL extension' => '沒有 MySQL 擴充模組', 'No extension' => '沒有 擴充模組',
'None of the supported PHP extensions (%s) are available.' => '沒有任何支援的PHP擴充模組%s。', 'None of the supported PHP extensions (%s) are available.' => '沒有任何支援的PHP擴充模組%s。',
'Session support must be enabled.' => 'Session 必須被啟用。', 'Session support must be enabled.' => 'Session 必須被啟用。',
'Session expired, please login again.' => 'Session 已過期,請重新登入。', 'Session expired, please login again.' => 'Session 已過期,請重新登入。',
@ -126,9 +126,8 @@ $translations = array(
'Create trigger' => '建立觸發器', 'Create trigger' => '建立觸發器',
'Time' => '時間', 'Time' => '時間',
'Event' => '事件', 'Event' => '事件',
'MySQL version: %s through PHP extension %s' => 'MySQL版本:%s 透過PHP擴充模組 %s', '%s version: %s through PHP extension %s' => '%s版本:%s 透過PHP擴充模組 %s',
'%d row(s)' => '%d行', '%d row(s)' => '%d行',
'~ %s' => '~ %s',
'Remove' => '移除', 'Remove' => '移除',
'Are you sure?' => '你確定嗎?', 'Are you sure?' => '你確定嗎?',
'Privileges' => '權限', 'Privileges' => '權限',
@ -196,12 +195,10 @@ $translations = array(
'Partition name' => '分區名', 'Partition name' => '分區名',
'Values' => '值', 'Values' => '值',
'%d row(s) have been imported.' => '%d行已導入。', '%d row(s) have been imported.' => '%d行已導入。',
'Show structure' => '資料表結構', 'anywhere' => '任意位置',
'(anywhere)' => '(任意位置)',
'CSV Import' => '匯入 CSV', 'CSV Import' => '匯入 CSV',
'Import' => '匯入', 'Import' => '匯入',
'Stop on error' => '出錯時停止', 'Stop on error' => '出錯時停止',
'Select data' => '選擇資料表',
'%.3f s' => '%.3f秒', '%.3f s' => '%.3f秒',
'$1-$3-$5' => '$1.$3.$5', '$1-$3-$5' => '$1.$3.$5',
'[yyyy]-mm-dd' => '[yyyy].mm.dd', '[yyyy]-mm-dd' => '[yyyy].mm.dd',

View file

@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => '文件上传被禁用。', 'File uploads are disabled.' => '文件上传被禁用。',
'Routine has been called, %d row(s) affected.' => '子程序被调用,%d 行被影响', 'Routine has been called, %d row(s) affected.' => '子程序被调用,%d 行被影响',
'Call' => '调用', 'Call' => '调用',
'No MySQL extension' => '没有MySQL扩展', 'No extension' => '没有扩展',
'None of the supported PHP extensions (%s) are available.' => '没有支持的 PHP 扩展可用(%s。', 'None of the supported PHP extensions (%s) are available.' => '没有支持的 PHP 扩展可用(%s。',
'Session support must be enabled.' => '会话必须被启用。', 'Session support must be enabled.' => '会话必须被启用。',
'Session expired, please login again.' => '会话已过期,请重新登录。', 'Session expired, please login again.' => '会话已过期,请重新登录。',
@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => '创建触发器', 'Create trigger' => '创建触发器',
'Time' => '时间', 'Time' => '时间',
'Event' => '事件', 'Event' => '事件',
'MySQL version: %s through PHP extension %s' => 'MySQL 版本:%s 通过 PHP 扩展 %s', '%s version: %s through PHP extension %s' => '%s 版本:%s 通过 PHP 扩展 %s',
'%d row(s)' => '%d 行', '%d row(s)' => '%d 行',
'~ %s' => '~ %s',
'Remove' => '移除', 'Remove' => '移除',
'Are you sure?' => '你确定吗?', 'Are you sure?' => '你确定吗?',
'Privileges' => '权限', 'Privileges' => '权限',
@ -198,12 +197,10 @@ $translations = array(
'Partition name' => '分区名', 'Partition name' => '分区名',
'Values' => '值', 'Values' => '值',
'%d row(s) have been imported.' => '%d 行已导入。', '%d row(s) have been imported.' => '%d 行已导入。',
'Show structure' => '表结构', 'anywhere' => '任意位置',
'(anywhere)' => '(任意位置)',
'CSV Import' => 'CSV 导入', 'CSV Import' => 'CSV 导入',
'Import' => '导入', 'Import' => '导入',
'Stop on error' => '出错时停止', 'Stop on error' => '出错时停止',
'Select data' => '选择表',
'%.3f s' => '%.3f 秒', '%.3f s' => '%.3f 秒',
'$1-$3-$5' => '$1.$3.$5', '$1-$3-$5' => '$1.$3.$5',
'[yyyy]-mm-dd' => '[yyyy].mm.dd', '[yyyy]-mm-dd' => '[yyyy].mm.dd',

View file

@ -5,8 +5,7 @@ $result = $connection->query("SELECT User, Host FROM mysql.user ORDER BY Host, U
if (!$result) { if (!$result) {
?> ?>
<form action=""><p> <form action=""><p>
<?php echo SID_FORM; ?> <?php hidden_fields_get(); ?>
<?php if ($_GET["server"] != "") { ?><input type="hidden" name="server" value="<?php echo h($_GET["server"]); ?>"><?php } ?>
<?php echo lang('Username'); ?>: <input name="user"> <?php echo lang('Username'); ?>: <input name="user">
<?php echo lang('Server'); ?>: <input name="host" value="localhost"> <?php echo lang('Server'); ?>: <input name="host" value="localhost">
<input type="hidden" name="grant" value=""> <input type="hidden" name="grant" value="">

View file

@ -7,7 +7,7 @@ $table_pos_js = array();
preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~', $_COOKIE["adminer_schema"], $matches, PREG_SET_ORDER); //! ':' in table name preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~', $_COOKIE["adminer_schema"], $matches, PREG_SET_ORDER); //! ':' in table name
foreach ($matches as $i => $match) { foreach ($matches as $i => $match) {
$table_pos[$match[1]] = array($match[2], $match[3]); $table_pos[$match[1]] = array($match[2], $match[3]);
$table_pos_js[] = "\n\t'" . addcslashes($match[1], "\r\n'\\") . "': [ $match[2], $match[3] ]"; $table_pos_js[] = "\n\t'" . addcslashes($match[1], "\r\n'\\/") . "': [ $match[2], $match[3] ]";
} }
$top = 0; $top = 0;
@ -27,7 +27,7 @@ foreach (table_status() as $row) {
$schema[$row["Name"]]["fields"][$name] = $field; $schema[$row["Name"]]["fields"][$name] = $field;
} }
$schema[$row["Name"]]["pos"] = ($table_pos[$row["Name"]] ? $table_pos[$row["Name"]] : array($top, 0)); $schema[$row["Name"]]["pos"] = ($table_pos[$row["Name"]] ? $table_pos[$row["Name"]] : array($top, 0));
if ($row["Engine"] == "InnoDB") { if (fk_support($row)) {
foreach (foreign_keys($row["Name"]) as $val) { foreach (foreign_keys($row["Name"]) as $val) {
if (!$val["db"]) { if (!$val["db"]) {
$left = $base_left; $left = $base_left;

View file

@ -26,6 +26,12 @@ $limit = $adminer->selectLimitProcess();
$from = ($select ? implode(", ", $select) : "*") . "\nFROM " . idf_escape($TABLE) . ($where ? "\nWHERE " . implode(" AND ", $where) : ""); $from = ($select ? implode(", ", $select) : "*") . "\nFROM " . idf_escape($TABLE) . ($where ? "\nWHERE " . implode(" AND ", $where) : "");
$group_by = ($group && count($group) < count($select) ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : ""); $group_by = ($group && count($group) < count($select) ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : "");
if ($_GET["page"] == "last") {
session_write_close();
$found_rows = $connection->result("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : ""));
redirect(remove_from_uri("page") . ($found_rows > $limit ? "&page=" . floor(($found_rows - 1) / $limit) : ""));
}
if ($_POST && !$error) { if ($_POST && !$error) {
$where_check = "(" . implode(") OR (", array_map('where_check', (array) $_POST["check"])) . ")"; $where_check = "(" . implode(") OR (", array_map('where_check', (array) $_POST["check"])) . ")";
$primary = ($indexes["PRIMARY"] ? ($select ? array_flip($indexes["PRIMARY"]["columns"]) : array()) : null); // empty array means that all primary fields are selected $primary = ($indexes["PRIMARY"] ? ($select ? array_flip($indexes["PRIMARY"]["columns"]) : array()) : null); // empty array means that all primary fields are selected
@ -43,7 +49,7 @@ if ($_POST && !$error) {
if ($select) { if ($select) {
$row = array(); $row = array();
foreach ($select as $val) { foreach ($select as $val) {
$row[] = (ereg('^`(.*)`$', $val, $match) ? idf_unescape($match[1]) : $val); //! columns looking like functions $row[] = (ereg('^`.*`$', $val) ? idf_unescape($val) : $val); //! columns looking like functions
} }
} }
dump_csv($row); dump_csv($row);
@ -54,7 +60,7 @@ if ($_POST && !$error) {
$union = array(); $union = array();
foreach ($_POST["check"] as $val) { foreach ($_POST["check"] as $val) {
// where is not unique so OR can't be used // where is not unique so OR can't be used
$union[] = "(SELECT $from " . ($where ? "AND " : "WHERE ") . where_check($val) . $group_by . " LIMIT 1)"; $union[] = "(SELECT" . limit("$from " . ($where ? "AND " : "WHERE ") . where_check($val) . $group_by, 1) . ")";
} }
dump_data($TABLE, "INSERT", implode(" UNION ALL ", $union)); dump_data($TABLE, "INSERT", implode(" UNION ALL ", $union));
} }
@ -64,27 +70,38 @@ if ($_POST && !$error) {
if (!$_POST["import"]) { // edit if (!$_POST["import"]) { // edit
$result = true; $result = true;
$affected = 0; $affected = 0;
$command = ($_POST["delete"] ? "DELETE FROM " : ($_POST["clone"] ? "INSERT INTO " : "UPDATE ")) . idf_escape($TABLE); $query = idf_escape($TABLE);
$set = array(); $set = array();
if (!$_POST["delete"]) { if (!$_POST["delete"]) {
foreach ($columns as $name => $val) { //! should check also for edit or insert privileges foreach ($columns as $name => $val) { //! should check also for edit or insert privileges
$val = process_input($fields[$name]); $val = process_input($fields[$name]);
if ($_POST["clone"]) { if ($val !== null) {
$set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name)); if ($_POST["clone"]) {
} elseif ($val !== false) { $set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name));
$set[] = idf_escape($name) . " = $val"; } elseif ($val !== false) {
$set[] = idf_escape($name) . " = $val";
}
} }
} }
$command .= ($_POST["clone"] ? " (" . implode(", ", array_keys($set)) . ")\nSELECT " . implode(", ", $set) . "\nFROM " . idf_escape($TABLE) : " SET\n" . implode(",\n", $set)); $query .= ($_POST["clone"] ? " (" . implode(", ", array_keys($set)) . ")\nSELECT " . implode(", ", $set) . "\nFROM " . idf_escape($TABLE) : " SET\n" . implode(",\n", $set));
} }
if ($_POST["delete"] || $set) { if ($_POST["delete"] || $set) {
if ($_POST["all"] || ($primary === array() && $_POST["check"])) { $command = "UPDATE";
$result = queries($command . ($_POST["all"] ? ($where ? "\nWHERE " . implode(" AND ", $where) : "") : "\nWHERE $where_check")); if ($_POST["delete"]) {
$command = "DELETE";
$query = "FROM $query";
}
if ($_POST["clone"]) {
$command = "INSERT";
$query = "INTO $query";
}
if ($_POST["all"] || ($primary === array() && $_POST["check"]) || count($group) < count($select)) {
$result = queries($command . " $query" . ($_POST["all"] ? ($where ? "\nWHERE " . implode(" AND ", $where) : "") : "\nWHERE $where_check"));
$affected = $connection->affected_rows; $affected = $connection->affected_rows;
} else { } else {
foreach ((array) $_POST["check"] as $val) { foreach ((array) $_POST["check"] as $val) {
// where is not unique so OR can't be used // where is not unique so OR can't be used
$result = queries($command . "\nWHERE " . where_check($val) . (count($group) < count($select) ? "" : "\nLIMIT 1")); $result = queries($command . limit1($query . "\nWHERE " . where_check($val)));
if (!$result) { if (!$result) {
break; break;
} }
@ -101,8 +118,9 @@ if ($_POST && !$error) {
preg_match_all('~(?>"[^"]*"|[^"\\r\\n]+)+~', $file, $matches); preg_match_all('~(?>"[^"]*"|[^"\\r\\n]+)+~', $file, $matches);
$affected = count($matches[0]); $affected = count($matches[0]);
queries("START TRANSACTION"); queries("START TRANSACTION");
$separator = ($_POST["separator"] == ";" ? ";" : ",");
foreach ($matches[0] as $key => $val) { foreach ($matches[0] as $key => $val) {
preg_match_all('~(("[^"]*")+|[^,]*),~', "$val,", $matches2); preg_match_all("~((\"[^\"]*\")+|[^$separator]*)$separator~", $val . $separator, $matches2);
if (!$key && !array_diff($matches2[1], $cols)) { //! doesn't work with column names containing ",\n if (!$key && !array_diff($matches2[1], $cols)) { //! doesn't work with column names containing ",\n
// first row corresponds to column names - use it for table structure // first row corresponds to column names - use it for table structure
$cols = $matches2[1]; $cols = $matches2[1];
@ -120,7 +138,7 @@ if ($_POST && !$error) {
} }
} }
if ($result) { if ($result) {
queries("COMMIT"); queries("COMMIT");
} }
queries_redirect(remove_from_uri("page"), lang('%d row(s) have been imported.', $affected), $result); queries_redirect(remove_from_uri("page"), lang('%d row(s) have been imported.', $affected), $result);
queries("ROLLBACK"); queries("ROLLBACK");
@ -147,11 +165,11 @@ if (isset($rights["insert"])) {
$adminer->selectLinks($table_status, $set); $adminer->selectLinks($table_status, $set);
if (!$columns) { if (!$columns) {
echo "<p class='error'>" . lang('Unable to select the table') . ($fields ? "" : ": " . error()) . ".\n"; echo "<p class='error'>" . lang('Unable to select the table') . ($fields ? "." : ": " . error()) . "\n";
} else { } else {
echo "<form action='' id='form'>\n"; echo "<form action='' id='form'>\n";
echo "<div style='display: none;'>"; echo "<div style='display: none;'>";
echo ($_GET["server"] != "" ? '<input type="hidden" name="server" value="' . h($_GET["server"]) . '">' : ""); hidden_fields_get();
echo (DB != "" ? '<input type="hidden" name="db" value="' . h(DB) . '">' : ""); // not used in Editor echo (DB != "" ? '<input type="hidden" name="db" value="' . h(DB) . '">' : ""); // not used in Editor
echo '<input type="hidden" name="select" value="' . h($TABLE) . '">'; echo '<input type="hidden" name="select" value="' . h($TABLE) . '">';
echo "</div>\n"; echo "</div>\n";
@ -163,7 +181,7 @@ if (!$columns) {
$adminer->selectActionPrint($text_length); $adminer->selectActionPrint($text_length);
echo "</form>\n"; echo "</form>\n";
$query = "SELECT " . (intval($limit) && $group && count($group) < count($select) ? "SQL_CALC_FOUND_ROWS " : "") . $from . $group_by . ($limit != "" ? "\nLIMIT " . intval($limit) . ($_GET["page"] ? " OFFSET " . ($limit * $_GET["page"]) : "") : ""); $query = "SELECT" . limit((intval($limit) && $group && count($group) < count($select) && $driver == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . $from . $group_by, ($limit != "" ? intval($limit) : null), ($_GET["page"] ? $limit * $_GET["page"] : 0));
echo $adminer->selectQuery($query); echo $adminer->selectQuery($query);
$result = $connection->query($query); $result = $connection->query($query);
@ -172,19 +190,19 @@ if (!$columns) {
} else { } else {
$email_fields = array(); $email_fields = array();
echo "<form action='' method='post' enctype='multipart/form-data'>\n"; echo "<form action='' method='post' enctype='multipart/form-data'>\n";
if (!$result->num_rows) { $rows = array();
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
$found_rows = (intval($limit) && $group && count($group) < count($select)
? ($driver == "sql" ? $connection->result(" SELECT FOUND_ROWS()") : $connection->result("SELECT COUNT(*) FROM ($query) x")) // space to allow mysql.trace_mode
: count($rows)
);
if (!$rows) {
echo "<p class='message'>" . lang('No rows.') . "\n"; echo "<p class='message'>" . lang('No rows.') . "\n";
} else { } else {
$rows = array();
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
$found_rows = (intval($limit) && $group && count($group) < count($select)
? $connection->result($connection->query(" SELECT FOUND_ROWS()")) // space to allow mysql.trace_mode
: count($rows)
);
$backward_keys = $adminer->backwardKeys($TABLE, $table_name); $backward_keys = $adminer->backwardKeys($TABLE, $table_name);
echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n"; echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n";
@ -205,7 +223,7 @@ if (!$columns) {
} }
echo ($backward_keys ? "<th>" . lang('Relations') : "") . "</thead>\n"; echo ($backward_keys ? "<th>" . lang('Relations') : "") . "</thead>\n";
foreach ($adminer->rowDescriptions($rows, $foreign_keys) as $n => $row) { foreach ($adminer->rowDescriptions($rows, $foreign_keys) as $n => $row) {
$unique_array = unique_array($row, $indexes); $unique_array = unique_array($rows[$n], $indexes);
$unique_idf = ""; $unique_idf = "";
foreach ($unique_array as $key => $val) { foreach ($unique_array as $key => $val) {
$unique_idf .= "&" . (isset($val) ? urlencode("where[" . bracket_escape($key) . "]") . "=" . urlencode($val) : "null%5B%5D=" . urlencode($key)); $unique_idf .= "&" . (isset($val) ? urlencode("where[" . bracket_escape($key) . "]") . "=" . urlencode($val) : "null%5B%5D=" . urlencode($key));
@ -222,7 +240,7 @@ if (!$columns) {
if (!isset($val)) { if (!isset($val)) {
$val = "<i>NULL</i>"; $val = "<i>NULL</i>";
} else { } else {
if (ereg('blob|binary', $field["type"]) && $val != "") { if (ereg('binary|blob|bytea', $field["type"]) && $val != "") {
$link = h(ME . 'download=' . urlencode($TABLE) . '&field=' . urlencode($key) . $unique_idf); $link = h(ME . 'download=' . urlencode($TABLE) . '&field=' . urlencode($key) . $unique_idf);
} }
if ($val == "") { if ($val == "") {
@ -271,33 +289,45 @@ if (!$columns) {
echo "</tr>\n"; // close to allow white-space: pre echo "</tr>\n"; // close to allow white-space: pre
} }
echo "</table>\n"; echo "</table>\n";
}
if (intval($limit) && count($group) >= count($select)) {
// slow with big tables parse_str($_COOKIE["adminer_export"], $adminer_export);
ob_flush();
flush(); if ($rows || $_GET["page"]) {
$found_rows = $connection->result($connection->query("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : ""))); $exact_count = true;
if (intval($limit) && count($group) >= count($select) && ($found_rows >= $limit || $_GET["page"])) {
$found_rows = $table_status["Rows"];
if (!isset($found_rows) || $where || $_GET["page"] * $limit * 2 > $found_rows || ($table_status["Engine"] == "InnoDB" && $found_rows < 1e5)) {
// slow with big tables
ob_flush();
flush();
$found_rows = $connection->result("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : ""));
} else {
$exact_count = false;
}
} }
echo "<p class='pages'>"; echo "<p class='pages'>";
if (intval($limit) && $found_rows > $limit) { if (intval($limit) && $found_rows > $limit) {
// display first, previous 3, next 3 and last page // display first, previous 5, next 5 and last page
$max_page = floor(($found_rows - 1) / $limit); $max_page = floor(($found_rows - 1) / $limit);
echo lang('Page') . ":" . pagination(0) . ($_GET["page"] > 3 ? " ..." : ""); echo lang('Page') . ":" . pagination(0) . ($_GET["page"] > 5 ? " ..." : "");
for ($i = max(1, $_GET["page"] - 2); $i < min($max_page, $_GET["page"] + 3); $i++) { for ($i = max(1, $_GET["page"] - 2); $i < min($max_page, $_GET["page"] + 5); $i++) {
echo pagination($i); echo pagination($i);
} }
echo ($_GET["page"] + 3 < $max_page ? " ..." : "") . pagination($max_page); echo ($_GET["page"] + 5 < $max_page ? " ..." : "") . ($exact_count ? pagination($max_page) : ' <a href="' . h(remove_from_uri() . "&page=last") . '">' . lang('last') . "</a>");
} }
echo " (" . lang('%d row(s)', $found_rows) . ") " . checkbox("all", 1, 0, lang('whole result')) . "\n"; echo " (" . ($exact_count ? "" : "~ ") . lang('%d row(s)', $found_rows) . ") " . checkbox("all", 1, 0, lang('whole result')) . "\n";
echo (information_schema(DB) ? "" : "<fieldset><legend>" . lang('Edit') . "</legend><div><input type='submit' name='edit' value='" . lang('Edit') . "'> <input type='submit' name='clone' value='" . lang('Clone') . "'> <input type='submit' name='delete' value='" . lang('Delete') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + (this.form['all'].checked ? $found_rows : formChecked(this, /check/)) + ')');\"></div></fieldset>\n"); echo (information_schema(DB) ? "" : "<fieldset><legend>" . lang('Edit') . "</legend><div><input type='submit' name='edit' value='" . lang('Edit') . "'> <input type='submit' name='clone' value='" . lang('Clone') . "'> <input type='submit' name='delete' value='" . lang('Delete') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + (this.form['all'].checked ? $found_rows : formChecked(this, /check/)) + ')');\"></div></fieldset>\n");
print_fieldset("export", lang('Export')); print_fieldset("export", lang('Export'));
echo $adminer->dumpOutput(1) . " " . $adminer->dumpFormat(1); // 1 - select echo $adminer->dumpOutput(1, $adminer_export["output"]) . " " . $adminer->dumpFormat(1, $adminer_export["format"]); // 1 - select
echo " <input type='submit' name='export' value='" . lang('Export') . "'>\n"; echo " <input type='submit' name='export' value='" . lang('Export') . "'>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
print_fieldset("import", lang('CSV Import'), !$result->num_rows); print_fieldset("import", lang('CSV Import'), !$result->num_rows);
echo "<input type='hidden' name='token' value='$token'><input type='file' name='csv_file'> <input type='submit' name='import' value='" . lang('Import') . "'>\n"; echo "<input type='hidden' name='token' value='$token'><input type='file' name='csv_file'> ";
echo html_select("separator", array(",", ";"), ($adminer_export["format"] == "csv;" ? ";" : ","), 1); // 1 - select
echo " <input type='submit' name='import' value='" . lang('Import') . "'>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
$adminer->selectEmailPrint(array_filter($email_fields, 'strlen'), $columns); $adminer->selectEmailPrint(array_filter($email_fields, 'strlen'), $columns);

View file

@ -1,6 +1,7 @@
<?php <?php
restart_session(); restart_session();
$history = &$_SESSION["history"][$_GET["server"]][DB]; $history_all = &get_session("history");
$history = &$history_all[DB];
if (!$error && $_POST["clear"]) { if (!$error && $_POST["clear"]) {
$history = array(); $history = array();
redirect(remove_from_uri("history")); redirect(remove_from_uri("history"));
@ -28,15 +29,14 @@ if (!$error && $_POST) {
$history[] = $query; $history[] = $query;
} }
$space = "(\\s|/\\*.*\\*/|(#|-- )[^\n]*\n|--\n)"; $space = "(\\s|/\\*.*\\*/|(#|-- )[^\n]*\n|--\n)";
$alter_database = "(CREATE|DROP)$space+(DATABASE|SCHEMA)\\b~isU"; if (!ini_bool("session.use_cookies")) {
if (!ini_get("session.use_cookies")) {
session_write_close(); session_write_close();
} }
$delimiter = ";"; $delimiter = ";";
$offset = 0; $offset = 0;
$empty = true; $empty = true;
$connection2 = (DB != "" ? connect() : null); // connection for exploring indexes and EXPLAIN (to not replace FOUND_ROWS()) //! PDO - silent error $connection2 = connect(); // connection for exploring indexes and EXPLAIN (to not replace FOUND_ROWS()) //! PDO - silent error
if (is_object($connection2)) { if (is_object($connection2) && DB != "") {
$connection2->select_db(DB); $connection2->select_db(DB);
} }
$queries = 0; $queries = 0;
@ -59,7 +59,7 @@ if (!$error && $_POST) {
$empty = false; $empty = false;
$q = substr($query, 0, $match[0][1]); $q = substr($query, 0, $match[0][1]);
$queries++; $queries++;
echo "<pre class='jush-sql' id='sql-$queries'>" . shorten_utf8(trim($q), 1000) . "</pre>\n"; echo "<pre class='jush-$driver' id='sql-$queries'>" . shorten_utf8(trim($q), 1000) . "</pre>\n";
ob_flush(); ob_flush();
flush(); // can take a long time - show the running query flush(); // can take a long time - show the running query
$start = explode(" ", microtime()); // microtime(true) is available since PHP 5 $start = explode(" ", microtime()); // microtime(true) is available since PHP 5
@ -71,6 +71,9 @@ if (!$error && $_POST) {
break; break;
} }
} else { } else {
if (is_object($connection2) && preg_match("~^$space*(USE)\\b~isU", $q)) {
$connection2->query($q);
}
do { do {
$result = $connection->store_result(); $result = $connection->store_result();
$end = explode(" ", microtime()); $end = explode(" ", microtime());
@ -82,18 +85,17 @@ if (!$error && $_POST) {
$id = "explain-$queries"; $id = "explain-$queries";
echo ", <a href='#$id' onclick=\"return !toggle('$id');\">EXPLAIN</a>\n"; echo ", <a href='#$id' onclick=\"return !toggle('$id');\">EXPLAIN</a>\n";
echo "<div id='$id' class='hidden'>\n"; echo "<div id='$id' class='hidden'>\n";
select($connection2->query("EXPLAIN $q")); select(explain($connection2, $q));
echo "</div>\n"; echo "</div>\n";
} }
} else { } else {
if (preg_match("~^$space*$alter_database", $query)) { if (preg_match("~^$space*(CREATE|DROP|ALTER)$space+(DATABASE|SCHEMA)\\b~isU", $q)) {
restart_session(); restart_session();
$_SESSION["databases"][$_GET["server"]] = null; // clear cache set_session("databases", null); // clear cache
session_write_close(); session_write_close();
} }
echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $connection->affected_rows) . "$time\n"; echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $connection->affected_rows) . "$time\n";
} }
unset($result); // free resultset
$start = $end; $start = $end;
} while ($connection->next_result()); } while ($connection->next_result());
} }
@ -119,6 +121,7 @@ if (!$error && $_POST) {
if ($empty) { if ($empty) {
echo "<p class='message'>" . lang('No commands to execute.') . "\n"; echo "<p class='message'>" . lang('No commands to execute.') . "\n";
} }
//! MS SQL - SET SHOWPLAN_ALL OFF
} else { } else {
echo "<p class='error'>" . upload_error($query) . "\n"; echo "<p class='error'>" . upload_error($query) . "\n";
} }
@ -142,7 +145,7 @@ echo h($q);
<p> <p>
<?php <?php
if (!ini_get("file_uploads")) { if (!ini_bool("file_uploads")) {
echo lang('File uploads are disabled.'); echo lang('File uploads are disabled.');
} else { ?> } else { ?>
<?php echo lang('File upload'); ?>: <input type="file" name="sql_file"> <?php echo lang('File upload'); ?>: <input type="file" name="sql_file">
@ -164,7 +167,7 @@ if ($history) {
print_fieldset("history", lang('History'), $_GET["history"] != ""); print_fieldset("history", lang('History'), $_GET["history"] != "");
foreach ($history as $key => $val) { foreach ($history as $key => $val) {
//! save and display timestamp //! save and display timestamp
echo '<a href="' . h(ME . "sql=&history=$key") . '">' . lang('Edit') . '</a> <code class="jush-sql">' . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $val)))), 80, "</code>") . "<br>\n"; echo '<a href="' . h(ME . "sql=&history=$key") . '">' . lang('Edit') . "</a> <code class='jush-$driver'>" . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $val)))), 80, "</code>") . "<br>\n";
} }
echo "<input type='submit' name='clear' value='" . lang('Clear') . "'>\n"; echo "<input type='submit' name='clear' value='" . lang('Clear') . "'>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";

View file

@ -4,26 +4,28 @@ a:visited { color: navy; }
a:hover { color: red; } a:hover { color: red; }
h1 { font-size: 150%; margin: 0; padding: .8em 1em; border-bottom: 1px solid #999; font-weight: normal; color: #777; background: #eee; } h1 { font-size: 150%; margin: 0; padding: .8em 1em; border-bottom: 1px solid #999; font-weight: normal; color: #777; background: #eee; }
h2 { font-size: 150%; margin: 0 0 20px -18px; padding: .8em 1em; border-bottom: 1px solid #000; color: #000; font-weight: normal; background: #ddf; } h2 { font-size: 150%; margin: 0 0 20px -18px; padding: .8em 1em; border-bottom: 1px solid #000; color: #000; font-weight: normal; background: #ddf; }
h3 { font-weight: normal; font-size: 130%; margin: .8em 0; } h3 { font-weight: normal; font-size: 130%; margin: 1em 0 0; }
form { margin: 0; } form { margin: 0; }
table { margin: 1em 20px .8em 0; border: 0; border-top: 1px solid #999; border-left: 1px solid #999; font-size: 90%; } table { margin: 1em 20px 0 0; border: 0; border-top: 1px solid #999; border-left: 1px solid #999; font-size: 90%; }
td, th { margin-bottom: 1em; border: 0; border-right: 1px solid #999; border-bottom: 1px solid #999; padding: .2em .3em; } td, th { border: 0; border-right: 1px solid #999; border-bottom: 1px solid #999; padding: .2em .3em; }
th { background: #eee; text-align: left; } th { background: #eee; text-align: left; }
thead th { text-align: center; } thead th { text-align: center; }
thead td, thead th { background: #ddf; } thead td, thead th { background: #ddf; }
fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: 0 .5em .5em 0; border: 1px solid #999; } fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: .8em .5em 0 0; border: 1px solid #999; }
p { margin: 0 20px 1em 0; } p { margin: .8em 20px 0 0; }
img { vertical-align: middle; border: 0; } img { vertical-align: middle; border: 0; }
td img { max-width: 200px; max-height: 200px; } td img { max-width: 200px; max-height: 200px; }
code { background: #eee; } code { background: #eee; }
tr:hover td, tr:hover th { background: #ddf; } tr:hover td, tr:hover th { background: #ddf; }
pre { margin: 1em 0 0; }
.version { color: #777; font-size: 67%; } .version { color: #777; font-size: 67%; }
.js .hidden { display: none; } .js .hidden { display: none; }
.nowrap td, .nowrap th, td.nowrap { white-space: pre; } .nowrap td, .nowrap th, td.nowrap { white-space: pre; }
.wrap td { white-space: normal; } .wrap td { white-space: normal; }
.error { color: red; background: #fee; } .error { color: red; background: #fee; }
.error b { background: #fff; font-weight: normal; }
.message { color: green; background: #efe; } .message { color: green; background: #efe; }
.error, .message { padding: .5em .8em; margin: 0 20px 1em 0; } .error, .message { padding: .5em .8em; margin: 1em 20px 0 0; }
.char { color: #007F00; } .char { color: #007F00; }
.date { color: #7F007F; } .date { color: #7F007F; }
.enum { color: #007F7F; } .enum { color: #007F7F; }

View file

@ -1,7 +1,7 @@
// Adminer specific functions // Adminer specific functions
/** Load syntax highlighting /** Load syntax highlighting
* @param string first three characters of MySQL version * @param string first three characters of database system version
*/ */
function bodyLoad(version) { function bodyLoad(version) {
var jushRoot = '../externals/jush/'; var jushRoot = '../externals/jush/';
@ -10,6 +10,7 @@ function bodyLoad(version) {
script.onload = function () { script.onload = function () {
if (window.jush) { // IE runs in case of an error too if (window.jush) { // IE runs in case of an error too
jush.create_links = ' target="_blank"'; jush.create_links = ' target="_blank"';
jush.urls.pgsql[0] = 'http://www.postgresql.org/docs/' + version + '/static/$key';
jush.urls.sql[0] = 'http://dev.mysql.com/doc/refman/' + version + '/en/$key'; jush.urls.sql[0] = 'http://dev.mysql.com/doc/refman/' + version + '/en/$key';
jush.urls.sqlset[0] = jush.urls.sql[0]; jush.urls.sqlset[0] = jush.urls.sql[0];
jush.urls.sqlstatus[0] = jush.urls.sql[0]; jush.urls.sqlstatus[0] = jush.urls.sql[0];
@ -26,8 +27,6 @@ function bodyLoad(version) {
document.body.appendChild(script); document.body.appendChild(script);
} }
/** Get value of select /** Get value of select
* @param HTMLSelectElement * @param HTMLSelectElement
* @return string * @return string

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 318 B

View file

@ -27,7 +27,7 @@ function cookie(assign, days, params) {
function verifyVersion() { function verifyVersion() {
cookie('adminer_version=0', 1); cookie('adminer_version=0', 1);
var script = document.createElement('script'); var script = document.createElement('script');
script.src = 'https://adminer.svn.sourceforge.net/svnroot/adminer/trunk/version.js'; script.src = 'https://www.adminer.org/version.php';
document.body.appendChild(script); document.body.appendChild(script);
} }
@ -83,6 +83,21 @@ function tableClick(event) {
el.onclick && el.onclick(); el.onclick && el.onclick();
} }
/** Set HTML code of an element
* @param string
* @param string undefined to set parentNode to &nbsp;
*/
function setHtml(id, html) {
var el = document.getElementById(id);
if (el) {
if (html == undefined) {
el.parentNode.innerHTML = '&nbsp;';
} else {
el.innerHTML = html;
}
}
}
/** Add row in select fieldset /** Add row in select fieldset

View file

@ -6,21 +6,21 @@ if (!$fields) {
} }
$table_status = ($fields ? table_status($TABLE) : array()); $table_status = ($fields ? table_status($TABLE) : array());
page_header(($fields && !isset($table_status["Rows"]) ? lang('View') : lang('Table')) . ": " . h($TABLE), $error); page_header(($fields && $table_status["Engine"] == "VIEW" ? lang('View') : lang('Table')) . ": " . h($TABLE), $error);
$adminer->selectLinks($table_status); $adminer->selectLinks($table_status);
if ($fields) { if ($fields) {
echo "<table cellspacing='0'>\n"; echo "<table cellspacing='0'>\n";
echo "<thead><tr><th>" . lang('Column') . "<td>" . lang('Type') . "<td>" . lang('Comment') . "</thead>\n"; echo "<thead><tr><th>" . lang('Column') . "<td>" . lang('Type') . (support("comment") ? "<td>" . lang('Comment') : "") . "</thead>\n";
foreach ($fields as $field) { foreach ($fields as $field) {
echo "<tr" . odd() . "><th>" . h($field["field"]); echo "<tr" . odd() . "><th>" . h($field["field"]);
echo "<td>" . h($field["full_type"]) . ($field["null"] ? " <i>NULL</i>" : "") . ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : ""); echo "<td>" . h($field["full_type"]) . ($field["null"] ? " <i>NULL</i>" : "") . ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : "");
echo "<td>" . nbsp($field["comment"]); echo (support("comment") ? "<td>" . nbsp($field["comment"]) : "");
echo "\n"; echo "\n";
} }
echo "</table>\n"; echo "</table>\n";
if (isset($table_status["Rows"])) { if ($table_status["Engine"] != "VIEW") {
echo "<h3>" . lang('Indexes') . "</h3>\n"; echo "<h3>" . lang('Indexes') . "</h3>\n";
$indexes = indexes($TABLE); $indexes = indexes($TABLE);
if ($indexes) { if ($indexes) {
@ -37,7 +37,7 @@ if ($fields) {
} }
echo '<p><a href="' . h(ME) . 'indexes=' . urlencode($TABLE) . '">' . lang('Alter indexes') . "</a>\n"; echo '<p><a href="' . h(ME) . 'indexes=' . urlencode($TABLE) . '">' . lang('Alter indexes') . "</a>\n";
if ($table_status["Engine"] == "InnoDB") { if (fk_support($table_status)) {
echo "<h3>" . lang('Foreign keys') . "</h3>\n"; echo "<h3>" . lang('Foreign keys') . "</h3>\n";
$foreign_keys = foreign_keys($TABLE); $foreign_keys = foreign_keys($TABLE);
if ($foreign_keys) { if ($foreign_keys) {
@ -52,16 +52,18 @@ if ($fields) {
} }
echo "</table>\n"; echo "</table>\n";
} }
echo '<p><a href="' . h(ME) . 'foreign=' . urlencode($TABLE) . '">' . lang('Add foreign key') . "</a>\n"; if ($driver != "sqlite") {
echo '<p><a href="' . h(ME) . 'foreign=' . urlencode($TABLE) . '">' . lang('Add foreign key') . "</a>\n";
}
} }
if ($connection->server_info >= 5) { if (support("trigger")) {
echo "<h3>" . lang('Triggers') . "</h3>\n"; echo "<h3>" . lang('Triggers') . "</h3>\n";
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($TABLE, "%_"))); $triggers = triggers($TABLE);
if ($result->num_rows) { if ($triggers) {
echo "<table cellspacing='0'>\n"; echo "<table cellspacing='0'>\n";
while ($row = $result->fetch_assoc()) { foreach ($triggers as $key => $val) {
echo "<tr valign='top'><td>$row[Timing]<td>$row[Event]<th>" . h($row["Trigger"]) . "<td><a href='" . h(ME . 'trigger=' . urlencode($TABLE) . '&name=' . urlencode($row["Trigger"])) . "'>" . lang('Alter') . "</a>\n"; echo "<tr valign='top'><td>$val[0]<td>$val[1]<th>" . h($key) . "<td><a href='" . h(ME . 'trigger=' . urlencode($TABLE) . '&name=' . urlencode($key)) . "'>" . lang('Alter') . "</a>\n";
} }
echo "</table>\n"; echo "</table>\n";
} }

View file

@ -6,8 +6,8 @@ $trigger_event = array("INSERT", "UPDATE", "DELETE");
$dropped = false; $dropped = false;
if ($_POST && !$error && in_array($_POST["Timing"], $trigger_time) && in_array($_POST["Event"], $trigger_event)) { if ($_POST && !$error && in_array($_POST["Timing"], $trigger_time) && in_array($_POST["Event"], $trigger_event)) {
$dropped = drop_create( $dropped = drop_create(
"DROP TRIGGER " . idf_escape($_GET["name"]), "DROP TRIGGER " . idf_escape($_GET["name"]) . ($driver == "pgsql" ? " ON " . idf_escape($TABLE) : ""),
"CREATE TRIGGER " . idf_escape($_POST["Trigger"]) . " $_POST[Timing] $_POST[Event] ON " . idf_escape($TABLE) . " FOR EACH ROW\n$_POST[Statement]", "CREATE TRIGGER " . idf_escape($_POST["Trigger"]) . " $_POST[Timing] $_POST[Event] ON " . idf_escape($TABLE) . " FOR EACH ROW\n$_POST[Statement]", //! FOR EACH STATEMENT
ME . "table=" . urlencode($TABLE), ME . "table=" . urlencode($TABLE),
lang('Trigger has been dropped.'), lang('Trigger has been dropped.'),
lang('Trigger has been altered.'), lang('Trigger has been altered.'),
@ -22,8 +22,7 @@ $row = array("Trigger" => $TABLE . "_bi");
if ($_POST) { if ($_POST) {
$row = $_POST; $row = $_POST;
} elseif ($_GET["name"] != "") { } elseif ($_GET["name"] != "") {
$result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($_GET["name"])); $row = trigger($_GET["name"]);
$row = $result->fetch_assoc();
} }
?> ?>

View file

@ -107,7 +107,7 @@ if ($_POST) {
$row = $_POST; $row = $_POST;
$grants = $new_grants; $grants = $new_grants;
} else { } else {
$row = $_GET + array("host" => $connection->result($connection->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)"))); // create user on the same domain by default $row = $_GET + array("host" => $connection->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)")); // create user on the same domain by default
$row["pass"] = $old_pass; $row["pass"] = $old_pass;
$row["hashed"] = true; $row["hashed"] = true;
$grants[""] = true; $grants[""] = true;

View file

@ -5,7 +5,7 @@ if ($_POST && !$error) {
$dropped = drop_create( $dropped = drop_create(
"DROP VIEW " . idf_escape($TABLE), "DROP VIEW " . idf_escape($TABLE),
"CREATE VIEW " . idf_escape($_POST["name"]) . " AS\n$_POST[select]", "CREATE VIEW " . idf_escape($_POST["name"]) . " AS\n$_POST[select]",
substr(ME, 0, -1), ($_POST["drop"] ? substr(ME, 0, -1) : ME . "table=" . urlencode($_POST["name"])),
lang('View has been dropped.'), lang('View has been dropped.'),
lang('View has been altered.'), lang('View has been altered.'),
lang('View has been created.'), lang('View has been created.'),

View file

@ -1,3 +1,13 @@
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
Operator LIKE %%
Remember export parameters in cookie
Allow semicolon as CSV separator
Defer table information in database overview to JavaScript (performance)
Big tables optimizations (performance)
Adminer 2.3.2 (released 2010-04-21): Adminer 2.3.2 (released 2010-04-21):
Fix COUNT(*) link Fix COUNT(*) link
Fix Save and continue edit Fix Save and continue edit

View file

@ -138,7 +138,7 @@ function php_shrink($input) {
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) { } elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$token[1] = '$' . $short_variables[$token[1]]; $token[1] = '$' . $short_variables[$token[1]];
} }
if (isset($set[substr($output, -1)]) || isset($set[$token[1]{0}])) { if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
$space = ''; $space = '';
} }
$output .= $space . $token[1]; $output .= $space . $token[1];
@ -157,10 +157,16 @@ function compile_file($match) {
return call_user_func($match[2], file_get_contents(dirname(__FILE__) . "/$project/$match[1]")); return call_user_func($match[2], file_get_contents(dirname(__FILE__) . "/$project/$match[1]"));
} }
$DRIVER = "";
if (file_exists(dirname(__FILE__) . "/adminer/drivers/" . $_SERVER["argv"][1] . ".inc.php")) {
$DRIVER = $_SERVER["argv"][1];
array_shift($_SERVER["argv"]);
}
unset($_COOKIE["adminer_lang"]); unset($_COOKIE["adminer_lang"]);
$_SESSION["lang"] = $_SERVER["argv"][1]; // Adminer functions read language from session $_SESSION["lang"] = $_SERVER["argv"][1]; // Adminer functions read language from session
include dirname(__FILE__) . "/adminer/include/lang.inc.php";
if (isset($_SESSION["lang"])) { if (isset($_SESSION["lang"])) {
include dirname(__FILE__) . "/adminer/include/lang.inc.php";
if (isset($_SERVER["argv"][2]) || !isset($langs[$_SESSION["lang"]])) { if (isset($_SERVER["argv"][2]) || !isset($langs[$_SESSION["lang"]])) {
echo "Usage: php compile.php [lang]\nPurpose: Compile adminer[-lang].php and editor[-lang].php.\n"; echo "Usage: php compile.php [lang]\nPurpose: Compile adminer[-lang].php and editor[-lang].php.\n";
exit(1); exit(1);
@ -168,11 +174,44 @@ if (isset($_SESSION["lang"])) {
include dirname(__FILE__) . "/adminer/lang/$_SESSION[lang].inc.php"; include dirname(__FILE__) . "/adminer/lang/$_SESSION[lang].inc.php";
} }
// check function definition in drivers
$filename = dirname(__FILE__) . "/adminer/drivers/mysql.inc.php";
preg_match_all('~\\bfunction ([^(]+)~', file_get_contents($filename), $matches); //! respect context (extension, class)
$functions = array_combine($matches[1], $matches[0]);
unset($functions["__destruct"], $functions["Min_DB"], $functions["Min_Result"]);
foreach (glob(dirname(__FILE__) . "/adminer/drivers/" . ($DRIVER ? $DRIVER : "*") . ".inc.php") as $filename) {
if ($filename != "mysql.inc.php") {
$file = file_get_contents($filename);
foreach ($functions as $val) {
if (!strpos($file, "$val(")) {
echo "Missing $val in $filename\n";
}
}
}
}
foreach (array("adminer", "editor") as $project) { foreach (array("adminer", "editor") as $project) {
$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 && $DRIVER != "mysql") {
$_GET[$DRIVER] = true; // to load the driver
include_once dirname(__FILE__) . "/adminer/drivers/$DRIVER.inc.php";
foreach (array("view", "event", "privileges", "user", "processlist", "variables", "trigger") as $feature) {
if (!support($feature)) {
$file = str_replace("} elseif (isset(\$_GET[\"$feature\"])) {\n\tinclude \"./$feature.inc.php\";\n", "", $file);
}
}
if (!support("routine")) {
$file = str_replace("} elseif (isset(\$_GET[\"procedure\"])) {\n\tinclude \"./procedure.inc.php\";\n", "", $file);
$file = str_replace("} elseif (isset(\$_GET[\"call\"])) {\n\tinclude \"./call.inc.php\";\n", "", $file);
$file = str_replace("if (isset(\$_GET[\"callf\"])) {\n\t\$_GET[\"call\"] = \$_GET[\"callf\"];\n}\nif (isset(\$_GET[\"function\"])) {\n\t\$_GET[\"procedure\"] = \$_GET[\"function\"];\n}\n", "", $file);
}
}
$file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file); $file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file);
$file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file); $file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file);
if ($DRIVER) {
$file = preg_replace('(include "../adminer/drivers/(?!' . preg_quote($DRIVER) . ').*\\s*)', '', $file);
}
$file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php $file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php
$file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file); $file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file);
$file = preg_replace_callback('~\\b(include|require) "([^"]*\\$LANG.inc.php)";~', 'put_file_lang', $file); $file = preg_replace_callback('~\\b(include|require) "([^"]*\\$LANG.inc.php)";~', 'put_file_lang', $file);
@ -187,11 +226,11 @@ foreach (array("adminer", "editor") as $project) {
$replace = 'h(preg_replace("~\\\\\\\\?.*~", "", $_SERVER["REQUEST_URI"])) . "?file=\\1&amp;version=' . $VERSION; $replace = 'h(preg_replace("~\\\\\\\\?.*~", "", $_SERVER["REQUEST_URI"])) . "?file=\\1&amp;version=' . $VERSION;
$file = preg_replace('~\\.\\./adminer/static/(default\\.css|functions\\.js|favicon\\.ico)~', '<?php echo ' . $replace . '"; ?>', $file); $file = preg_replace('~\\.\\./adminer/static/(default\\.css|functions\\.js|favicon\\.ico)~', '<?php echo ' . $replace . '"; ?>', $file);
$file = preg_replace('~\\.\\./adminer/static/([^\'"]*)~', '" . ' . $replace, $file); $file = preg_replace('~\\.\\./adminer/static/([^\'"]*)~', '" . ' . $replace, $file);
$file = str_replace("../externals/jush/", "https://jush.svn.sourceforge.net/svnroot/jush/trunk/", $file); // mixed-content warning if Adminer runs on HTTPS and external files on HTTP $file = str_replace("../externals/jush/", "https://www.adminer.org/static/", $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);
$filename = $project . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php"; // "$project-$VERSION" $filename = $project . ($DRIVER ? "-$DRIVER" : "") . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php"; // . "-$VERSION"
fwrite(fopen($filename, "w"), $file); // file_put_contents() since PHP 5 fwrite(fopen($filename, "w"), $file); // file_put_contents() since PHP 5
echo "$filename created.\n"; echo "$filename created (" . strlen($file) . " B).\n";
} }

View file

@ -13,7 +13,7 @@ function xhtml_open_tags($s) {
$return = array(); $return = array();
preg_match_all('~<([^>]+)~', $s, $matches); preg_match_all('~<([^>]+)~', $s, $matches);
foreach ($matches[1] as $val) { foreach ($matches[1] as $val) {
if ($val{0} == "/") { if ($val[0] == "/") {
array_pop($return); array_pop($return);
} elseif (substr($val, -1) != "/") { } elseif (substr($val, -1) != "/") {
$return[] = $val; $return[] = $val;

View file

@ -1,9 +1,9 @@
<?php <?php
page_header(lang('Server'), "", null); page_header(lang('Server'), "", false);
?> ?>
<form action=""><p> <form action=""><p>
<?php echo SID_FORM; ?> <?php hidden_fields_get(); ?>
<input name="where[0][val]" value="<?php echo h($_GET["where"][0]["val"]); ?>"> <input name="where[0][val]" value="<?php echo h($_GET["where"][0]["val"]); ?>">
<input type="submit" value="<?php echo lang('Search'); ?>" /> <input type="submit" value="<?php echo lang('Search'); ?>" />
</form> </form>

View file

@ -1,12 +1,14 @@
<?php <?php
class Adminer { class Adminer {
var $operators = array("<=", ">="); var $operators = array("<=", ">=");
var $values = array(); // protected var $_values = array();
function name() { function name() {
return lang('Editor'); return lang('Editor');
} }
//! driver
function credentials() { function credentials() {
return array(); // default INI settings return array(); // default INI settings
} }
@ -19,15 +21,15 @@ class Adminer {
global $connection; global $connection;
$dbs = get_databases(false); $dbs = get_databases(false);
return (!$dbs return (!$dbs
? $connection->result($connection->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)")) // username without the database list ? $connection->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)") // username without the database list
: $dbs[(information_schema($dbs[0]) ? 1 : 0)] // first available database : $dbs[(information_schema($dbs[0]) ? 1 : 0)] // first available database
); );
} }
function loginForm($username) { function loginForm() {
?> ?>
<table cellspacing="0"> <table cellspacing="0">
<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="server" value=""><input name="username" value="<?php echo h($username); ?>"> <tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="driver" value="server"><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"> <tr><th><?php echo lang('Password'); ?><td><input type="password" name="password">
</table> </table>
<?php <?php
@ -59,13 +61,13 @@ class Adminer {
function backwardKeys($table, $tableName) { function backwardKeys($table, $tableName) {
global $connection; global $connection;
$return = array(); $return = array();
if ($connection->server_info >= 5) { //! requires MySQL 5 $result = $connection->query("SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
$result = $connection->query("SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = " . $connection->quote($this->database()) . " WHERE TABLE_SCHEMA = " . $connection->quote($this->database()) . "
AND REFERENCED_TABLE_SCHEMA = " . $connection->quote($this->database()) . " AND REFERENCED_TABLE_SCHEMA = " . $connection->quote($this->database()) . "
AND REFERENCED_TABLE_NAME = " . $connection->quote($table) . " AND REFERENCED_TABLE_NAME = " . $connection->quote($table) . "
ORDER BY ORDINAL_POSITION"); ORDER BY ORDINAL_POSITION");
if ($result) { //! requires MySQL 5
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
$return[$row["TABLE_NAME"]]["keys"][$row["CONSTRAINT_NAME"]][$row["COLUMN_NAME"]] = $row["REFERENCED_COLUMN_NAME"]; $return[$row["TABLE_NAME"]]["keys"][$row["CONSTRAINT_NAME"]][$row["COLUMN_NAME"]] = $row["REFERENCED_COLUMN_NAME"];
} }
@ -93,7 +95,7 @@ ORDER BY ORDINAL_POSITION");
foreach ($cols as $column => $val) { foreach ($cols as $column => $val) {
$link .= where_link($i++, $column, $row[$val]); $link .= where_link($i++, $column, $row[$val]);
} }
echo "<a href='" . h($link) . "'>$backwardKey[name]</a>"; echo "<a href='" . h($link) . "'>" . h($backwardKey["name"]) . "</a>";
$link = ME . 'edit=' . urlencode($table); $link = ME . 'edit=' . urlencode($table);
foreach ($cols as $column => $val) { foreach ($cols as $column => $val) {
$link .= "&set" . urlencode("[" . bracket_escape($column) . "]") . "=" . urlencode($row[$val]); $link .= "&set" . urlencode("[" . bracket_escape($column) . "]") . "=" . urlencode($row[$val]);
@ -119,7 +121,6 @@ ORDER BY ORDINAL_POSITION");
} }
function rowDescriptions($rows, $foreignKeys) { function rowDescriptions($rows, $foreignKeys) {
global $connection;
$return = $rows; $return = $rows;
foreach ($rows[0] as $key => $val) { foreach ($rows[0] as $key => $val) {
foreach ((array) $foreignKeys[$key] as $foreignKey) { foreach ((array) $foreignKeys[$key] as $foreignKey) {
@ -133,7 +134,7 @@ ORDER BY ORDINAL_POSITION");
$ids[$row[$key]] = exact_value($row[$key]); $ids[$row[$key]] = exact_value($row[$key]);
} }
// uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow // uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow
$descriptions = $this->values[$foreignKey["table"]]; $descriptions = $this->_values[$foreignKey["table"]];
if (!$descriptions) { if (!$descriptions) {
$descriptions = get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")"); $descriptions = get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")");
} }
@ -153,7 +154,7 @@ ORDER BY ORDINAL_POSITION");
function selectVal($val, $link, $field) { function selectVal($val, $link, $field) {
$return = ($val == "<i>NULL</i>" ? "&nbsp;" : $val); $return = ($val == "<i>NULL</i>" ? "&nbsp;" : $val);
if (ereg('blob|binary', $field["type"]) && !is_utf8($val)) { if (ereg('binary|blob|bytea', $field["type"]) && !is_utf8($val)) {
$return = lang('%d byte(s)', strlen($val)); $return = lang('%d byte(s)', strlen($val));
if (ereg("^(GIF|\xFF\xD8\xFF|\x89\x50\x4E\x47\x0D\x0A\x1A\x0A)", $val)) { // GIF|JPG|PNG, getimagetype() works with filename if (ereg("^(GIF|\xFF\xD8\xFF|\x89\x50\x4E\x47\x0D\x0A\x1A\x0A)", $val)) { // GIF|JPG|PNG, getimagetype() works with filename
$return = "<img src='$link' alt='$return'>"; $return = "<img src='$link' alt='$return'>";
@ -181,39 +182,47 @@ ORDER BY ORDINAL_POSITION");
} }
function selectColumnsPrint($select, $columns) { function selectColumnsPrint($select, $columns) {
//! allow grouping functions by indexes // can allow grouping functions by indexes
} }
function selectSearchPrint($where, $columns, $indexes) { function selectSearchPrint($where, $columns, $indexes) {
//! foreign keys $where = (array) $_GET["where"];
echo '<fieldset><legend>' . lang('Search') . "</legend><div>\n"; echo '<fieldset><legend>' . lang('Search') . "</legend><div>\n";
$keys = array(); $keys = array();
foreach ((array) $_GET["where"] as $key => $val) { foreach ($where as $key => $val) {
$keys[$val["col"]] = $key; $keys[$val["col"]] = $key;
} }
$i = -1; $i = 0;
foreach ($columns as $name => $desc) { foreach (fields($_GET["select"]) as $name => $field) {
$key = $keys[$name]; if (ereg("enum", $field["type"])) { //! set - uses 1 << $i and FIND_IN_SET()
$options = $this->foreignKeyOptions($_GET["select"], $name); $desc = $columns[$name];
if ($options) { $key = $keys[$name];
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'><input type='hidden' name='where[$i][op]' value='='>: <select name='where[$i][val]'>" . optionlist($options, $_GET["where"][$key]["val"], true) . "</select></div>\n";
$i--; $i--;
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'>:";
enum_input("checkbox", "where[$i][val][]", $field, (array) $where[$key]["val"]); //! impossible to search for NULL
echo "</div>\n";
unset($columns[$name]);
}
}
foreach ($columns as $name => $desc) {
$options = $this->_foreignKeyOptions($_GET["select"], $name);
if ($options) {
$key = $keys[$name];
$i--;
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'><input type='hidden' name='where[$i][op]' value='='>: <select name='where[$i][val]'>" . optionlist($options, $where[$key]["val"], true) . "</select></div>\n";
unset($columns[$name]); unset($columns[$name]);
if (isset($key)) {
unset($_GET["where"][$key]);
}
} }
} }
$i = 0; $i = 0;
foreach ((array) $_GET["where"] as $val) { foreach ($where as $val) {
if ("$val[col]$val[val]" != "") { if ($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 name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n"; echo "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n";
$i++; $i++;
} }
} }
echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>" . lang('(anywhere)') . optionlist($columns, null, true) . "</select>"; echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
echo html_select("where[$i][op]", array(-1 => "") + $this->operators); echo html_select("where[$i][op]", array(-1 => "") + $this->operators);
echo "<input name='where[$i][val]'></div>\n"; echo "<input name='where[$i][val]'></div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
@ -260,7 +269,7 @@ ORDER BY ORDINAL_POSITION");
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><br>\n"; echo "<p><textarea name='email_message' rows='15' cols='75'>" . h($_POST["email_message"] . ($_POST["email_append"] ? '{$' . "$_POST[email_addition]}" : "")) . "</textarea><br>\n";
echo html_select("email_addition", $columns, $_POST["email_addition"]) . "<input type='submit' name='email_append' value='" . lang('Insert') . "'>\n"; //! JavaScript echo html_select("email_addition", $columns, $_POST["email_addition"]) . "<input type='submit' name='email_append' value='" . lang('Insert') . "'>\n"; //! JavaScript
echo "<p><input type='file' name='email_files[]' onchange=\"var el = this.cloneNode(true); el.value = ''; this.parentNode.appendChild(el); this.onchange = function () { };\">"; echo "<p>" . lang('Attachments') . ": <input type='file' name='email_files[]' onchange=\"var el = this.cloneNode(true); el.value = ''; this.parentNode.appendChild(el); this.onchange = function () { };\">";
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') . "' onclick=\"return this.form['delete'].onclick();\">\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
@ -273,15 +282,21 @@ ORDER BY ORDINAL_POSITION");
function selectSearchProcess($fields, $indexes) { function selectSearchProcess($fields, $indexes) {
$return = array(); $return = array();
foreach ((array) $_GET["where"] as $key => $val) { foreach ((array) $_GET["where"] as $key => $where) {
$col = $val["col"]; $col = $where["col"];
if (($key < 0 ? "" : $col) . $val["val"] != "") { $op = $where["op"];
$val = $where["val"];
if (($key < 0 ? "" : $col) . $val != "") {
$conds = array(); $conds = array();
foreach (($col != "" ? array($col => $fields[$col]) : $fields) as $name => $field) { foreach (($col != "" ? array($col => $fields[$col]) : $fields) as $name => $field) {
if ($col != "" || is_numeric($val["val"]) || !ereg('int|float|double|decimal', $field["type"])) { if ($col != "" || is_numeric($val) || !ereg('int|float|double|decimal', $field["type"])) {
$text_type = ereg('char|text|enum|set', $field["type"]); if ($col != "" && $field["type"] == "enum") {
$value = $this->processInput($field, ($text_type && ereg('^[^%]+$', $val["val"]) ? "%$val[val]%" : $val["val"])); $conds[] = idf_escape($name) . " IN (" . implode(", ", array_map('intval', $val)) . ")";
$conds[] = idf_escape($name) . ($value == "NULL" ? " IS" . ($val["op"] == ">=" ? " NOT" : "") : (in_array($val["op"], $this->operators) ? " $val[op]" : ($val["op"] != "=" && $text_type ? " LIKE" : " ="))) . " $value"; //! can issue "Illegal mix of collations" for columns in other character sets - solve by CONVERT($name using utf8) } else {
$text_type = ereg('char|text|enum|set', $field["type"]);
$value = $this->processInput($field, ($text_type && ereg('^[^%]+$', $val) ? "%$val%" : $val));
$conds[] = idf_escape($name) . ($value == "NULL" ? " IS" . ($op == ">=" ? " NOT" : "") : (in_array($op, $this->operators) ? " $op" : ($op != "=" && $text_type ? " LIKE" : " ="))) . " $value"; //! can issue "Illegal mix of collations" for columns in other character sets - solve by CONVERT($name using utf8)
}
} }
} }
$return[] = ($conds ? "(" . implode(" OR ", $conds) . ")" : "0"); $return[] = ($conds ? "(" . implode(" OR ", $conds) . ")" : "0");
@ -332,8 +347,7 @@ ORDER BY ORDINAL_POSITION");
if ($_POST["all"] || $_POST["check"]) { if ($_POST["all"] || $_POST["check"]) {
$field = idf_escape($_POST["email_field"]); $field = idf_escape($_POST["email_field"]);
$subject = $_POST["email_subject"]; $subject = $_POST["email_subject"];
$eol = (strncasecmp(PHP_OS, "win", 3) ? "\n" : "\r\n"); $message = $_POST["email_message"];
$message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$_POST[email_message]\n")));
preg_match_all('~\\{\\$([a-z0-9_]+)\\}~i', "$subject.$message", $matches); // allows {$name} in subject or message preg_match_all('~\\{\\$([a-z0-9_]+)\\}~i', "$subject.$message", $matches); // allows {$name} in subject or message
$result = $connection->query("SELECT DISTINCT $field" . ($matches[1] ? ", " . implode(", ", array_map('idf_escape', array_unique($matches[1]))) : "") . " FROM " . idf_escape($_GET["select"]) $result = $connection->query("SELECT DISTINCT $field" . ($matches[1] ? ", " . implode(", ", array_map('idf_escape', array_unique($matches[1]))) : "") . " FROM " . idf_escape($_GET["select"])
. " WHERE $field IS NOT NULL AND $field != ''" . " WHERE $field IS NOT NULL AND $field != ''"
@ -344,37 +358,14 @@ ORDER BY ORDINAL_POSITION");
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
$rows[] = $row; $rows[] = $row;
} }
$boundary = uniqid("boundary");
$attachments = "";
$email_files = $_FILES["email_files"];
foreach ($email_files["error"] as $key => $val) {
if (!$val) {
$attachments .= "--$boundary$eol"
. "Content-Type: " . str_replace("\n", "", $email_files["type"][$key]) . $eol
. "Content-Disposition: attachment; filename=\"" . preg_replace('~["\\n]~', '', $email_files["name"][$key]) . "\"$eol"
. "Content-Transfer-Encoding: base64$eol"
. $eol . chunk_split(base64_encode(file_get_contents($email_files["tmp_name"][$key])), 76, $eol) . $eol
;
}
}
$beginning = "";
$headers = "Content-Type: text/plain; charset=utf-8$eol" . "Content-Transfer-Encoding: 8bit";
if ($attachments) {
$attachments .= "--$boundary--$eol";
$beginning = "--$boundary$eol$headers$eol$eol";
$headers = "Content-Type: multipart/mixed; boundary=\"$boundary\"";
}
$headers .= $eol . "MIME-Version: 1.0$eol" . "X-Mailer: Adminer Editor"
. ($_POST["email_from"] ? $eol . "From: " . str_replace("\n", "", $_POST["email_from"]) : "") //! should escape display name
;
$fields = fields($_GET["select"]); $fields = fields($_GET["select"]);
foreach ($this->rowDescriptions($rows, $foreignKeys) as $row) { foreach ($this->rowDescriptions($rows, $foreignKeys) as $row) {
$replace = array(); $replace = array('{\\' => '{'); // allow literal {$name}
foreach ($matches[1] as $val) { foreach ($matches[1] as $val) {
$replace['{$' . "$val}"] = $this->editVal($row[$val], $fields[$val]); //! allow literal {$name} $replace['{$' . "$val}"] = $this->editVal($row[$val], $fields[$val]);
} }
$email = $row[$_POST["email_field"]]; $email = $row[$_POST["email_field"]];
if (is_email($email) && mail($email, email_header(strtr($subject, $replace)), $beginning . strtr($message, $replace) . $attachments, $headers)) { if (is_email($email) && send_email($email, strtr($subject, $replace), strtr($message, $replace), $_POST["email_from"], $_FILES["email_files"])) {
$sent++; $sent++;
} }
} }
@ -391,6 +382,7 @@ ORDER BY ORDINAL_POSITION");
function editFunctions($field) { function editFunctions($field) {
$return = array("" => ($field["null"] || $field["auto_increment"] || $field["full_type"] == "tinyint(1)" ? "" : "*")); $return = array("" => ($field["null"] || $field["auto_increment"] || $field["full_type"] == "tinyint(1)" ? "" : "*"));
//! respect driver
if (ereg('date|time', $field["type"])) { if (ereg('date|time', $field["type"])) {
$return[] = "now"; $return[] = "now";
} }
@ -404,7 +396,7 @@ ORDER BY ORDINAL_POSITION");
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
return ($field["null"] ? "<input type='radio'$attrs value=''" . ($value || isset($_GET["select"]) ? "" : " checked") . ">" : ""); return ($field["null"] ? "<input type='radio'$attrs value=''" . ($value || isset($_GET["select"]) ? "" : " checked") . ">" : "");
} }
$options = $this->foreignKeyOptions($table, $field["field"]); $options = $this->_foreignKeyOptions($table, $field["field"]);
if ($options) { if ($options) {
return "<select$attrs>" . optionlist($options, $value, true) . "</select>"; return "<select$attrs>" . optionlist($options, $value, true) . "</select>";
} }
@ -429,20 +421,22 @@ ORDER BY ORDINAL_POSITION");
$return = $connection->quote($return); $return = $connection->quote($return);
if (!ereg('varchar|text', $field["type"]) && $field["full_type"] != "tinyint(1)" && $value == "") { if (!ereg('varchar|text', $field["type"]) && $field["full_type"] != "tinyint(1)" && $value == "") {
$return = "NULL"; $return = "NULL";
} elseif (ereg('^(md5|sha1)$', $function)) {
$return = "$function($return)";
} }
return $return; return $return;
} }
function dumpOutput($select) { function dumpOutput($select, $value = "") {
return ""; return "";
} }
function dumpFormat($select) { function dumpFormat($select, $value = "") {
return "CSV"; return html_select("format", array('csv' => 'CSV,', 'csv;' => 'CSV;'), $value, $select);
} }
function navigation($missing) { function navigation($missing) {
global $VERSION; global $VERSION, $token;
?> ?>
<h1> <h1>
<a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a> <a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a>
@ -454,7 +448,7 @@ ORDER BY ORDINAL_POSITION");
?> ?>
<form action="" method="post"> <form action="" method="post">
<p class="logout"> <p class="logout">
<input type="hidden" name="token" value="<?php echo $_SESSION["tokens"][$_GET["server"]]; ?>"> <input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>"> <input type="submit" name="logout" value="<?php echo lang('Logout'); ?>">
</p> </p>
</form> </form>
@ -480,27 +474,25 @@ ORDER BY ORDINAL_POSITION");
} }
} }
function foreignKeyOptions($table, $column) { // protected function _foreignKeyOptions($table, $column) {
global $connection; global $connection;
$table_status = table_status($table);
$foreignKeys = column_foreign_keys($table); $foreignKeys = column_foreign_keys($table);
foreach ((array) $foreignKeys[$column] as $foreignKey) { foreach ((array) $foreignKeys[$column] as $foreignKey) {
if (count($foreignKey["source"]) == 1) { if (count($foreignKey["source"]) == 1) {
$id = idf_escape($foreignKey["target"][0]); $id = idf_escape($foreignKey["target"][0]);
$name = $this->rowDescription($foreignKey["table"]); $name = $this->rowDescription($foreignKey["table"]);
if ($name != "") { if ($name != "") {
$return = &$this->values[$foreignKey["table"]]; $return = &$this->_values[$foreignKey["table"]];
if (!isset($return)) { if (!isset($return)) {
$return = array("" => "") + get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " ORDER BY 2 LIMIT 1001"); $return = ($table_status["Rows"] > 1000 ? array() : array("" => "") + get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " ORDER BY 2"));
if (count($return) > 1001) {
$return = array();
}
} }
return $return; return $return;
} }
} }
} }
} }
} }
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer); $adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);

View file

@ -8,16 +8,38 @@ function email_header($header) {
return "=?UTF-8?B?" . base64_encode($header) . "?="; //! split long lines return "=?UTF-8?B?" . base64_encode($header) . "?="; //! split long lines
} }
/** Get keys from first column and values from second /** Send e-mail in UTF-8
* @param string * @param string
* @return array * @param string
* @param string
* @param string
* @param array
* @return
*/ */
function get_key_vals($query) { function send_email($email, $subject, $message, $from = "", $files = array()) {
global $connection; $eol = (strncasecmp(PHP_OS, "win", 3) ? "\n" : "\r\n"); // PHP_EOL available since PHP 4.3.10 and 5.0.2
$return = array(); $message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$message\n")));
$result = $connection->query($query); $boundary = uniqid("boundary");
while ($row = $result->fetch_row()) { $attachments = "";
$return[$row[0]] = $row[1]; foreach ($files["error"] as $key => $val) {
if (!$val) {
$attachments .= "--$boundary$eol"
. "Content-Type: " . str_replace("\n", "", $files["type"][$key]) . $eol
. "Content-Disposition: attachment; filename=\"" . preg_replace('~["\\n]~', '', $files["name"][$key]) . "\"$eol"
. "Content-Transfer-Encoding: base64$eol$eol"
. chunk_split(base64_encode(file_get_contents($files["tmp_name"][$key])), 76, $eol) . $eol
;
}
} }
return $return; $beginning = "";
$headers = "Content-Type: text/plain; charset=utf-8$eol" . "Content-Transfer-Encoding: 8bit";
if ($attachments) {
$attachments .= "--$boundary--$eol";
$beginning = "--$boundary$eol$headers$eol$eol";
$headers = "Content-Type: multipart/mixed; boundary=\"$boundary\"";
}
$headers .= $eol . "MIME-Version: 1.0$eol" . "X-Mailer: Adminer Editor"
. ($from ? $eol . "From: " . str_replace("\n", "", $from) : "") //! should escape display name
;
return mail($email, email_header($subject), $beginning . $message . $attachments, $headers);
} }

View file

@ -1,5 +1,5 @@
<?php <?php
/** Adminer Editor - Compact MySQL editor /** Adminer Editor - Compact database editor
* @link http://www.adminer.org/ * @link http://www.adminer.org/
* @author Jakub Vrana, http://php.vrana.cz/ * @author Jakub Vrana, http://php.vrana.cz/
* @copyright 2009 Jakub Vrana * @copyright 2009 Jakub Vrana
@ -7,6 +7,7 @@
*/ */
include "../adminer/include/bootstrap.inc.php"; include "../adminer/include/bootstrap.inc.php";
$drivers[DRIVER] = lang('Login');
if (isset($_GET["select"]) && ($_POST["edit"] || $_POST["clone"]) && !$_POST["save"]) { if (isset($_GET["select"]) && ($_POST["edit"] || $_POST["clone"]) && !$_POST["save"]) {
$_GET["edit"] = $_GET["select"]; $_GET["edit"] = $_GET["select"];

View file

@ -14,6 +14,7 @@ $messages_all = array();
foreach (array_merge( foreach (array_merge(
glob(dirname(__FILE__) . "/adminer/*.php"), glob(dirname(__FILE__) . "/adminer/*.php"),
glob(dirname(__FILE__) . "/adminer/include/*.php"), glob(dirname(__FILE__) . "/adminer/include/*.php"),
glob(dirname(__FILE__) . "/adminer/drivers/*.php"),
glob(dirname(__FILE__) . "/editor/*.php"), glob(dirname(__FILE__) . "/editor/*.php"),
glob(dirname(__FILE__) . "/editor/include/*.php") glob(dirname(__FILE__) . "/editor/include/*.php")
) as $filename) { ) as $filename) {

View file

@ -13,12 +13,12 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/coverage.php?coverage=0</td> <td>coverage.php?coverage=0</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?lang=en&amp;username=ODBC</td> <td>adminer/?username=ODBC&amp;lang=en</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/</td> <td>adminer/?username=ODBC</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;select=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;select=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;select=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;select=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;edit=albums&amp;where%5Bid%5D=2</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;edit=albums&amp;where%5Bid%5D=2</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;select=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;select=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;select=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;select=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?user=</td> <td>adminer/?username=ODBC&amp;user=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?processlist=</td> <td>adminer/?username=ODBC&amp;processlist=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;dump=</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;dump=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;event=</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;event=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;procedure=</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;procedure=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test</td> <td>adminer/?username=ODBC&amp;db=adminer_test</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;table=interprets</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;table=interprets</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?variables=</td> <td>adminer/?username=ODBC&amp;variables=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?sql=</td> <td>adminer/?username=ODBC&amp;sql=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/editor/example.php?lang=en&amp;username=admin</td> <td>editor/example.php?lang=en&amp;username=admin</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;select=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;select=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;table=interprets</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;table=interprets</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;table=interprets&amp;lang=en</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;table=interprets&amp;lang=en</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;table=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;table=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;table=interprets</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;table=interprets</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;trigger=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;trigger=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;view=</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;view=</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;edit=interprets</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;edit=interprets</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
@ -33,7 +33,7 @@
</tr> </tr>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/?db=adminer_test&amp;edit=albums</td> <td>adminer/?username=ODBC&amp;db=adminer_test&amp;edit=albums</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -13,7 +13,7 @@
</thead><tbody> </thead><tbody>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/adminer/</td> <td>adminer/?username=ODBC</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
@ -38,7 +38,7 @@
</tr> </tr>
<tr> <tr>
<td>open</td> <td>open</td>
<td>/adminer/coverage.php</td> <td>coverage.php</td>
<td></td> <td></td>
</tr> </tr>

View file

@ -2,9 +2,7 @@ MySQL 5 BIT data type
Transactions in export Transactions in export
Create view and routine options Create view and routine options
Mass editation of individual rows Mass editation of individual rows
Offer enum and set items in search - whisperer
Variables editation, especially timezone Variables editation, especially timezone
Use event $intervals + microseconds in relative date functions
Optionally check IP address Optionally check IP address
Disable spell checking in SQL textareas - spellcheck="false" Disable spell checking in SQL textareas - spellcheck="false"
Accept Tab in SQL textareas, Ctrl+Enter to send form Accept Tab in SQL textareas, Ctrl+Enter to send form
@ -12,14 +10,40 @@ Highlight SQL textarea, then display query inside textarea in select - may use e
Blob download and image display in edit form (important for Editor with hidden fields in select) Blob download and image display in edit form (important for Editor with hidden fields in select)
Add title to Logout, edit (in select) and select (in menu) in style "hever" Add title to Logout, edit (in select) and select (in menu) in style "hever"
Shift-click in checkboxes to select range Shift-click in checkboxes to select range
? LIKE %% operator Export by GET parameters
Only first part of big BZ2 export is readable
? Column and table names auto-completition in SQL textarea ? Column and table names auto-completition in SQL textarea
? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB ? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, aliasing of $connection->query, $connection->result and $connection->quote can save ~ 3 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB
? Branch binary_compile: LZW compression of translations can save 30 KB, LZW compression of all texts can save 11 KB, remove of base64_decode() + using chars 127-255 in minification can save 1 KB ? Branch binary_compile: LZW compression of translations can save 30 KB, LZW compression of all texts can save 11 KB, remove of base64_decode() + using chars 127-255 in minification can save 1 KB
? AJAX editing - select page has all data to display edit form ? AJAX editing - select page has all data to display edit form
? MySQL geometry support
Translations - database(s) have been dropped
Editor: Editor:
JavaScript data validation - columns containing word email, url, ... JavaScript data validation - columns containing word email, url, ...
Joining tables - PRIMARY KEY (table, joining) Joining tables - PRIMARY KEY (table, joining)
Rank, Tree structure Rank, Tree structure
Add whisperer to fields with foreign key to big table Add whisperer to fields with foreign key to big table
SQLite:
CREATE DATABASE - PRAGMA encoding = "UTF-8"
Detecion of non-existing database
DROP DATABASE by file operations
CSV import - ON DUPLICATE KEY UPDATE
Export - views, triggers
Delimiter in export and SQL command
PostgreSQL:
Users - SELECT * FROM pg_user
ORDER BY COUNT(*)
Table schema
Export - http://www.postgresql.org/docs/8.4/static/functions-info.html
Table status - http://www.postgresql.org/docs/8.4/static/functions-admin.html
Column rights - http://www.postgresql.org/docs/8.4/static/functions-info.html
Move table - ALTER TABLE SET SCHEMA
bool in Editor
MS SQL:
Rename by sp_rename
Detection of table collation
PDO driver

View file

@ -1,4 +1,4 @@
// downloaded from repository by verifyVersion() // downloaded from repository by verifyVersion() before Adminer 3.0.0
(function () { // cookie function is not defined in older versions (function () { // cookie function is not defined in older versions
var date = new Date(); var date = new Date();
date.setDate(date.getDate() + 7); // valid for 7 days date.setDate(date.getDate() + 7); // valid for 7 days