1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-28 08:39:53 +02:00

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);
}
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";
} else {
do {
@@ -52,8 +54,9 @@ if ($in) {
echo "<table cellspacing='0'>\n";
foreach ($in as $key) {
$field = $routine["fields"][$key];
echo "<tr><th>" . h($field["field"]);
$value = $_POST["fields"][$key];
$name = $field["field"];
echo "<tr><th>" . h($name);
$value = $_POST["fields"][$name];
if ($value != "" && ereg("enum|set", $field["type"])) {
$value = intval($value);
}

View File

@@ -19,20 +19,8 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
if ($_POST["drop"]) {
query_redirect("DROP TABLE " . idf_escape($_GET["create"]), substr(ME, 0, -1), lang('Table has been dropped.'));
} else {
$auto_increment_index = " PRIMARY KEY";
// don't overwrite primary key by auto_increment
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 = "";
$fields = array();
$foreign = array();
ksort($_POST["fields"]);
$orig_field = reset($orig_fields);
$after = "FIRST";
@@ -48,33 +36,26 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
$field["on_update"] = "CURRENT_TIMESTAMP";
$field["default"] = $default;
}
if ($key == $_POST["auto_increment_col"]) {
$field["auto_increment"] = true;
}
$process_field = process_field($field, $type_field);
$auto_increment = ($key == $_POST["auto_increment_col"]);
if ($process_field != process_field($orig_field, $orig_field) || $orig_field["auto_increment"] != $auto_increment) {
$fields .= "\n" . ($TABLE != "" ? ($field["orig"] != "" ? "CHANGE " . idf_escape($field["orig"]) : "ADD") : " ")
. " $process_field"
. ($auto_increment ? " AUTO_INCREMENT$auto_increment_index" : "")
. ($TABLE != "" ? " $after" : "") . ","
;
if ($process_field != process_field($orig_field, $orig_field)) {
$fields[] = array($field["orig"], $process_field, $after);
}
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"]);
//! drop and create foreign keys with renamed columns
} elseif ($field["orig"] != "") {
$fields .= "\nDROP " . idf_escape($field["orig"]) . ",";
$fields[] = array($field["orig"]);
}
if ($field["orig"] != "") {
$orig_field = next($orig_fields);
}
}
$status = "COMMENT=" . $connection->quote($_POST["Comment"])
. ($_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"]) : "")
;
$partitioning = "";
if (in_array($_POST["partition_by"], $partition_by)) {
$partitions = array();
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
}
}
$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)"
: ($_POST["partitions"] ? " PARTITIONS " . intval($_POST["partitions"]) : "")
);
} elseif ($connection->server_info >= 5.1 && $TABLE != "") {
$status .= "\nREMOVE PARTITIONING";
} elseif ($TABLE != "") {
$partitioning .= "\nREMOVE PARTITIONING";
}
$location = ME . "table=" . urlencode($_POST["name"]);
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 {
$message = lang('Table has been altered.');
if ($TABLE == "") {
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;
}
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);
$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();
$row["partition_names"] = array();
$row["partition_values"] = array();
@@ -162,24 +152,23 @@ foreach ($engines as $engine) {
<p>
<?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 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'); ?>">
<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>
<p>
<?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">
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>
<?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>
<input type="hidden" name="token" value="<?php echo $token; ?>">
<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 ($connection->server_info >= 5.1) {
if (support("partitioning")) {
$partition_table = ereg('RANGE|LIST', $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
restart_session();
if ($_POST["drop"]) {
unset($_SESSION["databases"][$_GET["server"]]);
set_session("databases", null);
query_redirect("DROP DATABASE " . idf_escape(DB), remove_from_uri("db|database"), lang('Database has been dropped.'));
} elseif (DB !== $_POST["name"]) {
// create or rename database
unset($_SESSION["databases"][$_GET["server"]]); // clear cache
$dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
$failed = false;
$last = "";
foreach ($dbs as $db) {
if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
$failed = true;
}
$last = $db;
}
}
if (query_redirect(queries(), ME . "db=" . urlencode($last), lang('Database has been created.'), DB == "", false, $failed)) {
//! 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;
set_session("databases", null); // clear cache
if (DB != "") {
queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), rename_database($_POST["name"], $_POST["collation"]));
} else {
$dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
$success = true;
$last = "";
foreach ($dbs as $db) {
if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
$success = false;
}
$last = $db;
}
}
if (!$row) {
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);
queries_redirect(ME . "db=" . urlencode($last), lang('Database has been created.'), $success);
}
} else {
// alter database
@@ -49,17 +40,16 @@ $collate = null;
if ($_POST) {
$name = $_POST["name"];
$collate = $_POST["collation"];
} elseif (DB == "") {
} elseif (DB != "") {
$collate = db_collation(DB, $collations);
} elseif ($driver == "sql") {
// propose database name with limited privileges
$result = $connection->query("SHOW GRANTS");
while ($row = $result->fetch_row()) {
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $row[0], $match) && $match[1]) {
$name = stripcslashes(idf_unescape($match[2]));
foreach (get_vals("SHOW GRANTS") as $grant) {
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $grant, $match) && $match[1]) {
$name = stripcslashes(idf_unescape("`$match[2]`"));
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"]) {
$result = true;
$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
}
if (isset($_POST["truncate"])) {
foreach ((array) $_POST["tables"] as $table) {
if (!queries("TRUNCATE " . idf_escape($table))) {
$result = false;
break;
}
if ($_POST["truncate"]) {
if ($_POST["tables"]) {
$result = truncate_tables($_POST["tables"]);
}
$message = lang('Tables have been truncated.');
} elseif (isset($_POST["move"])) {
} elseif ($_POST["move"]) {
$rename = array();
foreach ($tables_views as $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));
//! move triggers
$message = lang('Tables have been moved.');
} elseif ((!isset($_POST["drop"]) || !$_POST["views"] || queries("DROP VIEW " . implode(", ", array_map('idf_escape', $_POST["views"]))))
&& (!$_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 (isset($_POST["drop"])) {
$message = lang('Tables have been dropped.');
} else {
while ($row = $result->fetch_assoc()) {
$message .= h("$row[Table]: $row[Msg_text]") . "<br>";
}
} elseif ($_POST["drop"]) {
if ($_POST["views"]) {
$result = drop_views($_POST["views"]);
}
if ($result && $_POST["tables"]) {
$result = drop_tables($_POST["tables"]);
}
$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);
}
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 '<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";
$table_status = table_status();
if (!$table_status) {
$tables_list = tables_list();
if (!$tables_list) {
echo "<p class='message'>" . lang('No tables.') . "\n";
} else {
echo "<form action='' method='post'>\n";
echo "<p><input name='query' value='" . h($_POST["query"]) . "'> <input type='submit' name='search' value='" . lang('Search') . "'>\n";
if ($_POST["search"] && $_POST["query"] != "") {
$_GET["where"][0]["op"] = "LIKE";
$_GET["where"][0]["val"] = "%$_POST[query]%";
$_GET["where"][0]["op"] = "LIKE %%";
$_GET["where"][0]["val"] = $_POST["query"];
search_tables();
}
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";
$sums = array();
foreach ($table_status as $row) {
$name = $row["Name"];
echo '<tr' . odd() . '><td>' . checkbox((isset($row["Rows"]) ? "tables[]" : "views[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
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";
foreach ($tables_list as $name => $type) {
$view = (isset($type) && !eregi("table", $type));
echo '<tr' . odd() . '><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
echo '<th><a href="' . h(ME) . 'table=' . urlencode($name) . '">' . h($name) . '</a>';
if (isset($row["Rows"])) {
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 {
if ($view) {
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>&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 "<td>" . $connection->result($connection->query("SELECT @@storage_engine"));
echo "<tr><td>&nbsp;<th>" . lang('%d in total', count($tables_list));
echo "<td>" . $connection->result("SELECT @@storage_engine");
echo "<td>" . db_collation(DB, collations());
foreach (array("create", "indexes", "edit") as $val) {
echo "<td align='right'>" . number_format($sums[$val], 0, '.', lang(','));
foreach ($sums as $key => $val) {
echo "<td align='right' id='sum-$key'>&nbsp;";
}
echo "</table>\n";
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();
if (count($dbs) != 1) {
$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";
if ($connection->server_info >= 5) {
if (support("view")) {
echo '<a href="' . h(ME) . 'view=">' . lang('Create view') . "</a>\n";
}
if (support("routine")) {
echo "<h3>" . lang('Routines') . "</h3>\n";
$result = $connection->query("SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . $connection->quote(DB));
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";
}
if ($connection->server_info >= 5.1 && ($result = $connection->query("SHOW EVENTS"))) {
if (support("event")) {
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 "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "</thead>\n";
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";
}
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"];
header("Content-Type: application/octet-stream");
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

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"];
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));
if ($_POST["format"] == "sql") {
echo "-- Adminer $VERSION dump
SET NAMES utf8;
echo "-- Adminer $VERSION " . $drivers[DRIVER] . " dump
" . ($driver != "sql" ? "" : "SET NAMES utf8;
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';
";
");
}
$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 ($_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") {
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";
}
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));
while ($row = $result->fetch_assoc()) {
$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) {
while ($row = $result->fetch_assoc()) {
$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"]) {
$views = array();
//! defer number of rows to JavaScript
foreach (table_status() as $row) {
$table = (DB == "" || in_array($row["Name"], (array) $_POST["tables"]));
$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');
$table_style = array('', 'DROP+CREATE', 'CREATE');
$data_style = array('', 'TRUNCATE+INSERT', 'INSERT', 'INSERT+UPDATE');
if ($connection->server_info >= 5) {
if (support("routine")) {
$db_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
echo "<tr><th>" . lang('Format') . "<td>" . $adminer->dumpFormat(0) . "\n";
echo "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, (DB != "" ? '' : 'CREATE'));
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'));
}
parse_str($_COOKIE["adminer_export"], $row);
if (!$row) {
$row = array("output" => "text", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT");
}
echo "<tr><th>" . lang('Tables') . "<td>" . html_select('table_style', $table_style, 'DROP+CREATE');
echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style, 'INSERT');
echo "<tr><th>" . lang('Output') . "<td>" . $adminer->dumpOutput(0, $row["output"]) . "\n";
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>
<p><input type="submit" value="<?php echo lang('Export'); ?>">
@@ -178,22 +195,27 @@ if (DB != "") {
$prefix = ereg_replace("_.*", "", $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');");
if (!$row["Engine"]) {
if (eregi("view", $row["Engine"])) {
$views .= "$print\n";
} 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]++;
}
echo $views;
} 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";
foreach (get_databases() as $db) {
if (!information_schema($db)) {
$prefix = ereg_replace("_.*", "", $db);
echo "<tr><td>" . checkbox("databases[]", $db, $TABLE == "" || $TABLE == "$prefix%", $db, "formUncheck('check-databases');") . "</label>\n";
$prefixes[$prefix]++;
$databases = get_databases();
if ($databases) {
foreach ($databases as $db) {
if (!information_schema($db)) {
$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"]);
} elseif (!ereg('^.+&select=.+$', $location)) {
$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"])) {
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 {
$set = array();
foreach ($fields as $name => $field) {
$val = process_input($field);
if (!$update) {
$set[idf_escape($name)] = ($val !== false ? $val : "''");
} elseif ($val !== false) {
$set[] = "\n" . idf_escape($name) . " = $val";
if ($val !== false && $val !== null) {
$set[idf_escape($name)] = ($update ? "\n" . idf_escape($name) . " = $val" : $val);
}
}
if (!$set) {
redirect($location);
}
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 {
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();
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();
if (isset($_GET["select"]) && $result->fetch_assoc()) {
$row = false;
}
}
}
?>
@@ -80,7 +75,7 @@ if ($fields) {
$default = $_GET["set"][bracket_escape($name)];
$value = (isset($row)
? ($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)) {
$value = $adminer->editVal($value, $field);

View File

@@ -2,7 +2,7 @@
$TABLE = $_GET["foreign"];
if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
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 {
$source = array_filter($_POST["source"], 'strlen');
ksort($source); // enforce input order
@@ -39,13 +39,19 @@ if ($_POST) {
$source = array_keys(fields($TABLE)); //! no text and blob
$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">
<p>
<?php if ($row["db"] == "") { ?>
<?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="">
<noscript><p><input type="submit" name="change" value="<?php echo lang('Change'); ?>"></noscript>
<table cellspacing="0">

View File

@@ -1,13 +1,7 @@
<?php
class Adminer {
/** @var array functions used in select */
var $functions = array("char_length", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "unix_timestamp", "upper");
/** @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");
/** @var array operators used in select, null for all operators */
var $operators;
/** Name in title and navigation
* @return string
@@ -20,7 +14,7 @@ class Adminer {
* @return array ($server, $username, $password)
*/
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
@@ -39,14 +33,15 @@ class Adminer {
}
/** Print login form
* @param string
* @return null
*/
function loginForm($username) {
function loginForm() {
global $drivers, $possible_drivers;
?>
<table cellspacing="0">
<tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h($_GET["server"]); ?>">
<tr><th><?php echo lang('Username'); ?><td><input name="username" value="<?php echo h($username); ?>">
<tr><th><?php echo lang('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('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">
</table>
<?php
@@ -90,10 +85,10 @@ class Adminer {
function selectLinks($tableStatus, $set = "") {
echo '<p class="tabs">';
$links = array("select" => lang('Select data'), "table" => lang('Show structure'));
if (isset($tableStatus["Rows"])) {
$links["create"] = lang('Alter table');
} else {
if (eregi("view", $tableStatus["Engine"])) {
$links["view"] = lang('Alter view');
} else {
$links["create"] = lang('Alter table');
}
if (isset($set)) {
$links["edit"] = lang('New item');
@@ -126,7 +121,8 @@ class Adminer {
* @return string
*/
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
@@ -154,7 +150,7 @@ class Adminer {
*/
function selectVal($val, $link, $field) {
$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 ($link ? "<a href='$link'>$return</a>" : $return);
@@ -175,17 +171,18 @@ class Adminer {
* @return null
*/
function selectColumnsPrint($select, $columns) {
global $functions, $grouping;
print_fieldset("select", lang('Select'), $select);
$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) {
$val = $_GET["columns"][$key];
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++;
}
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.onchange();");
echo "<select name='columns[$i][col]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select></div>\n";
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 "</div></fieldset>\n";
}
@@ -208,13 +205,13 @@ class Adminer {
$i = 0;
foreach ((array) $_GET["where"] as $val) {
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 "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n";
$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 "<input name='where[$i][val]'></div>\n";
echo "</div></fieldset>\n";
@@ -286,12 +283,13 @@ class Adminer {
* @return array (array(select_expressions), array(group_expressions))
*/
function selectColumnsProcess($columns, $indexes) {
global $functions, $grouping;
$select = array(); // select expressions, empty for *
$group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
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"]) : "*"));
if (!in_array($val["fun"], $this->grouping)) {
if (!in_array($val["fun"], $grouping)) {
$group[] = $select[$key];
}
}
@@ -314,8 +312,15 @@ class Adminer {
}
foreach ((array) $_GET["where"] as $val) {
if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
$in = process_length($val["val"]);
$cond = " $val[op]" . (ereg('NULL$', $val["op"]) ? "" : (ereg('IN$', $val["op"]) ? " (" . ($in != "" ? $in : "NULL") . ")" : " " . $this->processInput($fields[$val["col"]], $val["val"])));
$cond = " $val[op]";
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"] != "") {
$return[] = idf_escape($val["col"]) . $cond;
} else {
@@ -342,8 +347,8 @@ class Adminer {
function selectOrderProcess($fields, $indexes) {
$return = array();
foreach ((array) $_GET["order"] as $key => $val) {
if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()`(?:[^`]|``)+`\\)|COUNT\\(\\*\\))$~', $val)) {
$return[] = idf_escape($val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\\)|COUNT\\(\\*\\))$~', $val)) { //! MS SQL uses []
$return[] = (isset($fields[$val]) ? idf_escape($val) : $val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
}
}
return $return;
@@ -377,10 +382,12 @@ class Adminer {
* @return string
*/
function messageQuery($query) {
global $driver;
restart_session();
$id = "sql-" . count($_SESSION["messages"]);
$_SESSION["history"][$_GET["server"]][DB][] = (strlen($query) > 1e6 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." : $query); // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-sql'>" . shorten_utf8($query, 1000) . '</pre><a href="' . h(ME . 'sql=&history=' . (count($_SESSION["history"][$_GET["server"]][DB]) - 1)) . '">' . lang('Edit') . '</a></div>';
$history = &get_session("history");
$history[DB][] = (strlen($query) > 1e6 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." : $query); // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-$driver'>" . shorten_utf8($query, 1000) . '</pre><p><a href="' . h(ME . 'sql=&history=' . (count($history[DB]) - 1)) . '">' . lang('Edit') . '</a></div>';
}
/** Functions displayed in edit form
@@ -388,31 +395,18 @@ class Adminer {
* @return array
*/
function editFunctions($field) {
$return = array("");
if (ereg('char|date|time', $field["type"])) {
$return = (ereg('char', $field["type"]) ? array("", "md5", "sha1", "password", "encrypt", "uuid") : array("", "now")); //! JavaScript for disabling maxlength
}
if (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET))) {
// relative functions
if (ereg('int|float|double|decimal', $field["type"])) {
$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";
global $edit_functions;
$return = ($field["null"] ? "/NULL" : "");
foreach ($edit_functions as $key => $functions) {
if (!$key || (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET)))) { // relative functions
foreach ($functions as $pattern => $val) {
if (!$pattern || ereg($pattern, $field["type"])) {
$return .= "/$val";
}
}
}
}
if ($field["null"]) {
array_unshift($return, "NULL");
}
return $return;
return explode("/", $return);
}
/** Get options to display edit field
@@ -441,9 +435,9 @@ class Adminer {
global $connection;
$name = $field["field"];
$return = $connection->quote($value);
if (ereg('^(now|uuid)$', $function)) {
if (ereg('^(now|getdate|uuid)$', $function)) {
$return = "$function()";
} elseif (ereg('^[+-]$', $function)) {
} elseif (ereg('^([+-]|\\|\\|)$', $function)) {
$return = idf_escape($name) . " $function $return";
} elseif (ereg('^[+-] interval$', $function)) {
$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
* @param bool generate select (otherwise radio)
* @param string
* @return string
*/
function dumpOutput($select) {
function dumpOutput($select, $value = "") {
$return = array('text' => lang('open'), 'file' => lang('save'));
if (function_exists('gzencode')) {
$return['gz'] = 'gzip';
@@ -468,15 +463,16 @@ class Adminer {
$return['bz2'] = 'bzip2';
}
// 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
* @param bool generate select (otherwise radio)
* @param string
* @return string
*/
function dumpFormat($select) {
return html_select("format", array('sql' => 'SQL', 'csv' => 'CSV'), "sql", $select);
function dumpFormat($select, $value = "") {
return html_select("format", array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;'), $value, $select);
}
/** Prints navigation after Adminer title
@@ -484,7 +480,7 @@ class Adminer {
* @return null
*/
function navigation($missing) {
global $VERSION, $connection;
global $VERSION, $connection, $token;
?>
<h1>
<a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a>
@@ -499,19 +495,18 @@ class Adminer {
<p class="logout">
<a href="<?php echo h(ME); ?>sql="><?php echo bold(lang('SQL command'), isset($_GET["sql"])); ?></a>
<a href="<?php echo h(ME); ?>dump=<?php echo urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]); ?>"><?php echo bold(lang('Dump'), isset($_GET["dump"])); ?></a>
<input type="hidden" name="token" value="<?php echo $_SESSION["tokens"][$_GET["server"]]; ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>">
</p>
</form>
<form action="">
<p>
<?php echo SID_FORM; ?>
<?php if ($_GET["server"] != "") { ?><input type="hidden" name="server" value="<?php echo h($_GET["server"]); ?>"><?php } ?>
<?php hidden_fields_get(); ?>
<?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["schema"])) { ?><input type="hidden" name="schema" 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>
</form>
<?php
@@ -533,7 +528,7 @@ class Adminer {
*/
function tablesPrint($tables) {
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) . '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);
if (!isset($adminer->operators)) {
$adminer->operators = $operators;
}

View File

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

View File

@@ -39,12 +39,14 @@ if (isset($_GET["file"])) {
exit;
}
include "../adminer/include/functions.inc.php";
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
if (!ini_get("session.auto_start")) {
if (!ini_bool("session.auto_start")) {
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"));
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
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/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 "../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/auth.inc.php";
include "./include/connect.inc.php";
@@ -95,7 +104,7 @@ include "./include/editing.inc.php";
include "./include/export.inc.php";
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
}

View File

@@ -1,11 +1,12 @@
<?php
function connect_error() {
global $connection, $VERSION, $token, $error;
global $connection, $VERSION, $token, $error, $drivers;
$databases = array();
if (DB != "") {
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), false);
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), true);
} else {
if ($_POST["db"] && !$error) {
unset($_SESSION["databases"][$_GET["server"]]);
set_session("databases", null);
foreach ($_POST["db"] as $db) {
if (!queries("DROP DATABASE " . idf_escape($db))) {
break;
@@ -14,30 +15,32 @@ function connect_error() {
queries_redirect(substr(ME, 0, -1), lang('Database has been dropped.'), !$connection->error);
}
page_header(lang('Select database'), $error, null);
echo "<p>";
page_header(lang('Select database'), $error, false);
echo "<p><a href='" . h(ME) . "database='>" . lang('Create new database') . "</a>\n";
foreach (array(
'database' => lang('Create new database'),
'privileges' => lang('Privileges'),
'processlist' => lang('Process list'),
'variables' => lang('Variables'),
'status' => lang('Status'),
) 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('Logged as: %s', "<b>" . h($connection->result($connection->query("SELECT USER()"))) . "</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(logged_user()) . "</b>") . "\n";
$databases = get_databases();
if ($databases) {
$collations = collations();
echo "<form action='' method='post'>\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) {
$root = h(ME) . "db=" . urlencode($db);
echo "<tr" . odd() . "><td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]));
echo "<th><a href='$root'>" . h($db) . "</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 "</table>\n";
@@ -46,6 +49,11 @@ function connect_error() {
}
}
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"])) {
@@ -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 != "") {
unset($_SESSION["databases"][$_GET["server"]]);
set_session("databases", null);
}
connect_error(); // separate function to catch SQLite error
exit;

View File

@@ -1,8 +1,15 @@
<?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 = "") {
global $LANG, $VERSION, $adminer, $connection;
global $LANG, $VERSION, $adminer, $connection, $drivers;
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) : "");
?>
<!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-Script-Type" content="text/javascript">
<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="stylesheet" type="text/css" href="../adminer/static/default.css<?php // Ondrej Valka, http://valka.info ?>">
<?php if (file_exists("adminer.css")) { ?>
<link rel="stylesheet" type="text/css" href="adminer.css">
<?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="static/editing.js"></script>
<div id="content">
<?php
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);
echo '<p id="breadcrumb"><a href="' . ($link != "" ? h($link) : ".") . '">' . (isset($_GET["server"]) ? h($_GET["server"]) : lang('Server')) . '</a> &raquo; ';
if (is_array($breadcrumb)) {
if (DB != "") {
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</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; ';
$server = (SERVER != "" ? h(SERVER) : lang('Server'));
if ($breadcrumb === false) {
echo "$server\n";
} else {
echo "<a href='" . ($link ? h($link) : ".") . "'>$server</a> &raquo; ";
if (is_array($breadcrumb)) {
if (DB != "") {
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</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";
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";
$_SESSION["messages"] = array();
}
if (!$_POST && !isset($_SESSION["passwords"])) { // used in auth
$_SESSION["passwords"] = array();
}
$databases = &$_SESSION["databases"][$_GET["server"]];
$databases = &get_session("databases");
if (DB != "" && $databases && !in_array(DB, $databases, true)) {
$databases = null;
}
@@ -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;
?>
</div>
@@ -67,4 +82,8 @@ function page_footer($missing = false) {
<?php $adminer->navigation($missing); ?>
</div>
<?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) {
$return = array(); // table_name => field
foreach (table_status_referencable() as $table_name => $table) {
if ($table_name != $self) {
foreach (table_status() as $table_name => $table) {
if ($table_name != $self && fk_support($table)) {
foreach (fields($table_name) as $field) {
if ($field["primary"]) {
if ($return[$table_name]) { // multi column primary key
@@ -142,16 +142,19 @@ function process_type($field, $collate = "COLLATE") {
/** Create SQL string from field
* @param array basic field information
* @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) {
global $connection;
return idf_escape($field["field"]) . process_type($type_field)
. ($field["null"] ? " NULL" : " NOT NULL") // NULL for timestamp
. (!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]" : "")
. " COMMENT " . $connection->quote($field["comment"])
;
return array(
idf_escape($field["field"]),
process_type($type_field),
($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp
(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
@@ -179,12 +182,11 @@ function type_class($type) {
* @param array returned by referencable_primary()
* @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;
$column_comments = false;
foreach ($fields as $field) {
if ($field["comment"] != "") {
$column_comments = true;
$comments = true;
break;
}
}
@@ -197,9 +199,9 @@ function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $forei
<td><?php echo lang('Options'); ?>
<?php if ($type == "TABLE") { ?>
<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<?php echo ($column_comments ? "" : " class='hidden'"); ?>><?php echo lang('Comment'); ?>
<?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . ">" . lang('Comment') : ""); ?>
<?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>
</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]));
?>
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
<?php
if ($type == "PROCEDURE") {
echo "<td>" . html_select("fields[$i][inout]", $inout, $field["inout"]);
}
?>
<?php echo ($type == "PROCEDURE" ? "<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")]); ?>">
<?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?>
<?php if ($type == "TABLE") { ?>
<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 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
//! 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 "&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='down[$i]' src='../adminer/static/down.gif' alt='v' title='" . lang('Move down') . "'>";
echo "\n";
}
return $column_comments;
return $comments;
}
/** Move fields up and down or add field
@@ -278,7 +277,7 @@ function process_fields(&$fields) {
* @return string
*/
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
@@ -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");
$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";
$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);
$fields = array();
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) {
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, "%_")));
if ($result->num_rows) {
$s = "\nDELIMITER ;;\n";
@@ -26,18 +26,17 @@ function dump_triggers($table, $style) {
function dump_table($table, $style, $is_view = false) {
global $connection;
if ($_POST["format"] == "csv") {
if ($_POST["format"] != "sql") {
echo "\xef\xbb\xbf"; // UTF-8 byte order mark
if ($style) {
dump_csv(array_keys(fields($table)));
}
} elseif ($style) {
$result = $connection->query("SHOW CREATE TABLE " . idf_escape($table));
if ($result) {
$create = create_sql($table);
if ($create) {
if ($style == "DROP+CREATE") {
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";
}
if ($style == "CREATE+ALTER" && !$is_view) {
@@ -116,10 +115,10 @@ DROP PROCEDURE adminer_alter;
}
function dump_data($table, $style, $select = "") {
global $connection;
$max_packet = 1048576; // default, minimum is 1024
global $connection, $driver;
$max_packet = ($driver == "sqlite" ? 0 : 1048576); // default, minimum is 1024
if ($style) {
if ($_POST["format"] != "csv" && $style == "TRUNCATE+INSERT") {
if ($_POST["format"] == "sql" && $style == "TRUNCATE+INSERT") {
echo "TRUNCATE " . idf_escape($table) . ";\n";
}
$fields = fields($table);
@@ -128,7 +127,7 @@ function dump_data($table, $style, $select = "") {
$insert = "";
$buffer = "";
while ($row = $result->fetch_assoc()) {
if ($_POST["format"] == "csv") {
if ($_POST["format"] != "sql") {
dump_csv($row);
} else {
if (!$insert) {
@@ -145,7 +144,7 @@ function dump_data($table, $style, $select = "") {
}
echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n";
} else {
$s = "\n($s)";
$s = ($max_packet ? "\n" : " ") . "($s)";
if (!$buffer) {
$buffer = $insert . $s;
} 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";
echo $buffer;
}

View File

@@ -8,20 +8,12 @@ function connection() {
return $connection;
}
/** Escape database identifier
* @param string
* @return string
*/
function idf_escape($idf) {
return "`" . str_replace("`", "``", $idf) . "`";
}
/** Unescape database identifier
* @param string text inside ``
* @return string
*/
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 ''
@@ -60,6 +52,14 @@ function nbsp($string) {
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
* @param string
* @param string
@@ -71,7 +71,7 @@ function nbsp($string) {
function checkbox($name, $value, $checked, $label = "", $onclick = "") {
static $id = 0;
$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);
}
@@ -115,6 +115,15 @@ function html_select($name, $options, $value = "", $onchange = true) {
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
* @param string
* @param mixed
@@ -132,6 +141,24 @@ function get_vals($query, $column = 0) {
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
* @param array
* @param array result of indexes()
@@ -200,7 +227,14 @@ function where_link($i, $column, $value, $operator = "=") {
* @return bool
*/
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) {
$params[] = true; // HttpOnly
}
@@ -211,11 +245,28 @@ function cookie($name, $value) {
* @return null
*/
function restart_session() {
if (!ini_get("session.use_cookies")) {
if (!ini_bool("session.use_cookies")) {
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
* @param string null to only set a message
* @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
* @param string
* @return array array($col => array())
@@ -399,6 +459,22 @@ function column_foreign_keys($table) {
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
* @param array one field from fields()
* @param mixed
@@ -406,19 +482,14 @@ function column_foreign_keys($table) {
* @return null
*/
function input($field, $value, $function) {
global $types, $adminer;
global $types, $adminer, $driver;
$name = h(bracket_escape($field["field"]));
echo "<td class='function'>";
$functions = (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
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 $adminer->editInput($_GET["edit"], $field, " name='fields[$name]'", $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 : $value === $val);
echo " <label><input type='radio' name='fields[$name]' value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($val) . '</label>';
}
enum_input("radio", "fields[$name]", $field, $value);
} else {
$first = 0;
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));
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>";
} 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 {
// 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));
@@ -461,23 +532,35 @@ function process_input($field) {
$idf = bracket_escape($field["field"]);
$function = $_POST["function"][$idf];
$value = $_POST["fields"][$idf];
if ($field["type"] == "enum" ? $value == -1 : $function == "orig") {
return false;
} elseif ($field["type"] == "enum" || $field["auto_increment"] ? $value == "" : $function == "NULL") {
return "NULL";
} elseif ($field["type"] == "enum") {
if ($field["type"] == "enum") {
if ($value == -1) {
return false;
}
if ($value == "") {
return "NULL";
}
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);
} 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");
if (!is_string($file)) {
return false; //! report errors
}
return $connection->quote($file);
} else {
return $adminer->processInput($field, $value, $function);
}
return $adminer->processInput($field, $value, $function);
}
/** Print results of search in all tables
@@ -491,7 +574,7 @@ function search_tables() {
foreach (table_status() as $table => $table_status) {
$name = $adminer->tableName($table_status);
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 (!$found) {
echo "<ul>\n";
@@ -510,11 +593,11 @@ function search_tables() {
*/
function dump_csv($row) {
foreach ($row as $key => $val) {
if (preg_match("~[\"\n,]~", $val) || $val === "") {
if (preg_match("~[\"\n,;]~", $val) || $val === "") {
$row[$key] = '"' . str_replace('"', '""', $val) . '"';
}
}
echo implode(",", $row) . "\n";
echo implode(($_POST["format"] == "csv;" ? ";" : ","), $row) . "\n";
}
/** Apply SQL function
@@ -523,7 +606,7 @@ function dump_csv($row) {
* @return string
*/
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

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

View File

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

View File

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

View File

@@ -1,6 +1,10 @@
<?php
$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);
if ($_POST && !$error && !$_POST["add"]) {
$alter = array();
@@ -14,32 +18,32 @@ if ($_POST && !$error && !$_POST["add"]) {
if ($column != "") {
$length = $index["lengths"][$key];
$set[] = idf_escape($column) . ($length ? "(" . intval($length) . ")" : "");
$columns[count($columns) + 1] = $column;
$lengths[count($lengths) + 1] = ($length ? $length : null);
$columns[] = $column;
$lengths[] = ($length ? $length : null);
}
}
if ($columns) {
foreach ($indexes as $name => $existing) {
ksort($existing["columns"]);
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
unset($indexes[$name]);
continue 2;
}
}
$alter[] = "\nADD $index[type]" . ($index["type"] == "PRIMARY" ? " KEY" : "") . " (" . implode(", ", $set) . ")";
$alter[] = array($index["type"], "(" . implode(", ", $set) . ")");
}
}
}
// drop removed indexes
foreach ($indexes as $name => $existing) {
$alter[] = "\nDROP INDEX " . idf_escape($name);
$alter[] = array($existing["type"], idf_escape($name), "DROP");
}
if (!$alter) {
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);
@@ -77,7 +81,7 @@ foreach ($row["indexes"] as $index) {
ksort($index["columns"]);
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 "<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";
$j++;

View File

@@ -81,7 +81,7 @@ $translations = array(
'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ů.'),
'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).',
'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.',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Vytvořit trigger',
'Time' => 'Čas',
'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ů'),
'~ %s' => '~ %s',
'Remove' => 'Odebrat',
'Are you sure?' => 'Opravdu?',
'Privileges' => 'Oprávnění',
@@ -203,7 +202,7 @@ $translations = array(
'Select data' => 'Vypsat data',
'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.',
'(anywhere)' => '(kdekoliv)',
'anywhere' => 'kdekoliv',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 'd.m.[rrrr]',
@@ -229,4 +228,9 @@ $translations = array(
'File does not exist.' => 'Soubor neexistuje.',
'Permanent login' => 'Trvalé přihlášení',
'%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.',
'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',
'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.',
'Session support must be enabled.' => 'Sitzungen müssen aktiviert sein.',
'Session expired, please login again.' => 'Sitzungsdauer abgelaufen, bitte erneut anmelden.',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Trigger hinzufügen',
'Time' => 'Zeitpunkt',
'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'),
'~ %s' => '~ %s',
'Remove' => 'Entfernen',
'Are you sure?' => 'Sind Sie sicher ?',
'Privileges' => 'Rechte',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Name der Partition',
'Values' => 'Werte',
'%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',
'Import' => 'Importieren',
'Stop on error' => 'Bei Fehler anhaltan',
'Select data' => 'Tabelle auswählen',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 't.m.[jjjj]',

View File

@@ -81,7 +81,7 @@ $translations = array(
'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.'),
'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.',
'Session support must be enabled.' => 'Deben estar habilitadas las sesiones.',
'Session expired, please login again.' => 'Sesión expirada, favor loguéese de nuevo.',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Agregar Trigger',
'Time' => 'Tiempo',
'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'),
'~ %s' => '~ %s',
'Remove' => 'Eliminar',
'Are you sure?' => 'Está seguro?',
'Privileges' => 'Privilegios',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Nombre de Partición',
'Values' => 'Valores',
'%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',
'Import' => 'Importar',
'Stop on error' => 'Parar en caso de error',
'Select data' => 'Mostrar datos',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$5/$3/$1',
'[yyyy]-mm-dd' => 'dd/mm/[aaaa]',

View File

@@ -81,7 +81,7 @@ $translations = array(
'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.'),
'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).',
'Session support must be enabled.' => 'Sessioonid peavad olema lubatud.',
'Session expired, please login again.' => 'Sessioon on aegunud, palun logige uuesti sisse.',
@@ -129,7 +129,6 @@ $translations = array(
'Time' => 'Aeg',
'Event' => 'Sündmus',
'%d row(s)' => array('%d rida', '%d rida'),
'~ %s' => '~ %s',
'Remove' => 'Eemalda',
'Are you sure?' => 'Kas oled kindel?',
'Privileges' => 'Õigused',
@@ -142,7 +141,7 @@ $translations = array(
'Routine' => 'Protseduur',
'Grant' => 'Anna',
'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',
'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',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Partitsiooni nimi',
'Values' => 'Väärtused',
'%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',
'Import' => 'Impordi',
'Stop on error' => 'Peatuda vea esinemisel',
'Select data' => 'Vali tabel',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 'd.m.[yyyy]',

View File

@@ -81,7 +81,7 @@ $translations = array(
'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.'),
'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.',
'Session support must be enabled.' => 'Veuillez activer les sessions.',
'Session expired, please login again.' => 'Session expirée, veuillez vous authentifier à nouveau.',
@@ -129,7 +129,6 @@ $translations = array(
'Time' => 'Temps',
'Event' => 'Évènement',
'%d row(s)' => array('%d ligne', '%d lignes'),
'~ %s' => '~ %s',
'Remove' => 'Effacer',
'Are you sure?' => 'Êtes-vous certain?',
'Privileges' => 'Privilège',
@@ -142,7 +141,7 @@ $translations = array(
'Routine' => 'Routine',
'Grant' => 'Grant',
'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',
'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',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Nom de la partition',
'Values' => 'Valeurs',
'%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',
'Import' => 'Importer',
'Stop on error' => 'Arrêt sur erreur',
'Select data' => 'Selectionner la table',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$5/$3/$1',
'[yyyy]-mm-dd' => 'jj/mm/[aaaa]',

View File

@@ -81,7 +81,7 @@ $translations = array(
'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.'),
'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.',
'Session support must be enabled.' => 'Le sessioni devono essere abilitate.',
'Session expired, please login again.' => 'Sessione scaduta, autenticarsi di nuovo.',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Crea trigger',
'Time' => 'Orario',
'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'),
'~ %s' => '~ %s',
'Remove' => 'Rimuovi',
'Are you sure?' => 'Sicuro?',
'Privileges' => 'Privilegi',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Nome partizione',
'Values' => 'Valori',
'%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',
'Import' => 'Importa',
'Stop on error' => 'Stop su errore',
'Select data' => 'Scegli tabella',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$5/$3/$1',
'[yyyy]-mm-dd' => 'dd/mm/[yyyy]',

View File

@@ -81,7 +81,7 @@ $translations = array(
'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.'),
'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).',
'Session support must be enabled.' => 'Sessies moeten geactiveerd zijn.',
'Session expired, please login again.' => 'Uw sessie is verlopen. Gelieve opnieuw in te loggen.',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Trigger aanmaken',
'Time' => 'Time',
'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'),
'~ %s' => '~ %s',
'Remove' => 'Verwijderen',
'Are you sure?' => 'Weet u het zeker?',
'Privileges' => 'Rechten',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => 'Partitie naam',
'Values' => 'Waarden',
'%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',
'Import' => 'Importeren',
'Stop on error' => 'Stoppen bij fout',
'Select data' => 'Selecteer tabel',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$5-$3-$1',
'[yyyy]-mm-dd' => 'dd-mm-[jjjj]',

View File

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

View File

@@ -81,7 +81,7 @@ $translations = array(
'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.'),
'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).',
'Session support must be enabled.' => 'Session premenné musia byť povolené.',
'Session expired, please login again.' => 'Session vypršala, prihláste sa prosím znova.',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => 'Vytvoriť trigger',
'Time' => 'Čas',
'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'),
'~ %s' => '~ %s',
'Remove' => 'Odobrať',
'Are you sure?' => 'Naozaj?',
'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.'),
'CSV Import' => 'Import CSV',
'Import' => 'Import',
'Show structure' => 'Štruktúra tabuľky',
'Select data' => 'Vypísať tabuľku',
'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.',
'(anywhere)' => '(kdekoľvek)',
'anywhere' => 'kdekoľvek',
'%.3f s' => '%.3f s',
'$1-$3-$5' => '$6.$4.$1',
'[yyyy]-mm-dd' => 'd.m.[rrrr]',

View File

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

View File

@@ -81,7 +81,7 @@ $translations = array(
'File uploads are disabled.' => '文件上传被禁用。',
'Routine has been called, %d row(s) affected.' => '子程序被调用,%d 行被影响',
'Call' => '调用',
'No MySQL extension' => '没有MySQL扩展',
'No extension' => '没有扩展',
'None of the supported PHP extensions (%s) are available.' => '没有支持的 PHP 扩展可用(%s。',
'Session support must be enabled.' => '会话必须被启用。',
'Session expired, please login again.' => '会话已过期,请重新登录。',
@@ -128,9 +128,8 @@ $translations = array(
'Create trigger' => '创建触发器',
'Time' => '时间',
'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 行',
'~ %s' => '~ %s',
'Remove' => '移除',
'Are you sure?' => '你确定吗?',
'Privileges' => '权限',
@@ -198,12 +197,10 @@ $translations = array(
'Partition name' => '分区名',
'Values' => '值',
'%d row(s) have been imported.' => '%d 行已导入。',
'Show structure' => '表结构',
'(anywhere)' => '(任意位置)',
'anywhere' => '任意位置',
'CSV Import' => 'CSV 导入',
'Import' => '导入',
'Stop on error' => '出错时停止',
'Select data' => '选择表',
'%.3f s' => '%.3f 秒',
'$1-$3-$5' => '$1.$3.$5',
'[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) {
?>
<form action=""><p>
<?php echo SID_FORM; ?>
<?php if ($_GET["server"] != "") { ?><input type="hidden" name="server" value="<?php echo h($_GET["server"]); ?>"><?php } ?>
<?php hidden_fields_get(); ?>
<?php echo lang('Username'); ?>: <input name="user">
<?php echo lang('Server'); ?>: <input name="host" value="localhost">
<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
foreach ($matches as $i => $match) {
$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;
@@ -27,7 +27,7 @@ foreach (table_status() as $row) {
$schema[$row["Name"]]["fields"][$name] = $field;
}
$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) {
if (!$val["db"]) {
$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) : "");
$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) {
$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
@@ -43,7 +49,7 @@ if ($_POST && !$error) {
if ($select) {
$row = array();
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);
@@ -54,7 +60,7 @@ if ($_POST && !$error) {
$union = array();
foreach ($_POST["check"] as $val) {
// 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));
}
@@ -64,27 +70,38 @@ if ($_POST && !$error) {
if (!$_POST["import"]) { // edit
$result = true;
$affected = 0;
$command = ($_POST["delete"] ? "DELETE FROM " : ($_POST["clone"] ? "INSERT INTO " : "UPDATE ")) . idf_escape($TABLE);
$query = idf_escape($TABLE);
$set = array();
if (!$_POST["delete"]) {
foreach ($columns as $name => $val) { //! should check also for edit or insert privileges
$val = process_input($fields[$name]);
if ($_POST["clone"]) {
$set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name));
} elseif ($val !== false) {
$set[] = idf_escape($name) . " = $val";
if ($val !== null) {
if ($_POST["clone"]) {
$set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name));
} 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["all"] || ($primary === array() && $_POST["check"])) {
$result = queries($command . ($_POST["all"] ? ($where ? "\nWHERE " . implode(" AND ", $where) : "") : "\nWHERE $where_check"));
$command = "UPDATE";
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;
} else {
foreach ((array) $_POST["check"] as $val) {
// 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) {
break;
}
@@ -101,8 +118,9 @@ if ($_POST && !$error) {
preg_match_all('~(?>"[^"]*"|[^"\\r\\n]+)+~', $file, $matches);
$affected = count($matches[0]);
queries("START TRANSACTION");
$separator = ($_POST["separator"] == ";" ? ";" : ",");
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
// first row corresponds to column names - use it for table structure
$cols = $matches2[1];
@@ -120,7 +138,7 @@ if ($_POST && !$error) {
}
}
if ($result) {
queries("COMMIT");
queries("COMMIT");
}
queries_redirect(remove_from_uri("page"), lang('%d row(s) have been imported.', $affected), $result);
queries("ROLLBACK");
@@ -147,11 +165,11 @@ if (isset($rights["insert"])) {
$adminer->selectLinks($table_status, $set);
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 {
echo "<form action='' id='form'>\n";
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 '<input type="hidden" name="select" value="' . h($TABLE) . '">';
echo "</div>\n";
@@ -163,7 +181,7 @@ if (!$columns) {
$adminer->selectActionPrint($text_length);
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);
$result = $connection->query($query);
@@ -172,19 +190,19 @@ if (!$columns) {
} else {
$email_fields = array();
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";
} 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);
echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n";
@@ -205,7 +223,7 @@ if (!$columns) {
}
echo ($backward_keys ? "<th>" . lang('Relations') : "") . "</thead>\n";
foreach ($adminer->rowDescriptions($rows, $foreign_keys) as $n => $row) {
$unique_array = unique_array($row, $indexes);
$unique_array = unique_array($rows[$n], $indexes);
$unique_idf = "";
foreach ($unique_array as $key => $val) {
$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)) {
$val = "<i>NULL</i>";
} 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);
}
if ($val == "") {
@@ -271,33 +289,45 @@ if (!$columns) {
echo "</tr>\n"; // close to allow white-space: pre
}
echo "</table>\n";
if (intval($limit) && count($group) >= count($select)) {
// slow with big tables
ob_flush();
flush();
$found_rows = $connection->result($connection->query("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : "")));
}
parse_str($_COOKIE["adminer_export"], $adminer_export);
if ($rows || $_GET["page"]) {
$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'>";
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);
echo lang('Page') . ":" . pagination(0) . ($_GET["page"] > 3 ? " ..." : "");
for ($i = max(1, $_GET["page"] - 2); $i < min($max_page, $_GET["page"] + 3); $i++) {
echo lang('Page') . ":" . pagination(0) . ($_GET["page"] > 5 ? " ..." : "");
for ($i = max(1, $_GET["page"] - 2); $i < min($max_page, $_GET["page"] + 5); $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");
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 "</div></fieldset>\n";
}
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";
$adminer->selectEmailPrint(array_filter($email_fields, 'strlen'), $columns);

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// Adminer specific functions
/** Load syntax highlighting
* @param string first three characters of MySQL version
* @param string first three characters of database system version
*/
function bodyLoad(version) {
var jushRoot = '../externals/jush/';
@@ -10,6 +10,7 @@ function bodyLoad(version) {
script.onload = function () {
if (window.jush) { // IE runs in case of an error too
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.sqlset[0] = jush.urls.sql[0];
jush.urls.sqlstatus[0] = jush.urls.sql[0];
@@ -26,8 +27,6 @@ function bodyLoad(version) {
document.body.appendChild(script);
}
/** Get value of select
* @param HTMLSelectElement
* @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() {
cookie('adminer_version=0', 1);
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);
}
@@ -83,6 +83,21 @@ function tableClick(event) {
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

View File

@@ -6,21 +6,21 @@ if (!$fields) {
}
$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);
if ($fields) {
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) {
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>" . nbsp($field["comment"]);
echo (support("comment") ? "<td>" . nbsp($field["comment"]) : "");
echo "\n";
}
echo "</table>\n";
if (isset($table_status["Rows"])) {
if ($table_status["Engine"] != "VIEW") {
echo "<h3>" . lang('Indexes') . "</h3>\n";
$indexes = indexes($TABLE);
if ($indexes) {
@@ -37,7 +37,7 @@ if ($fields) {
}
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";
$foreign_keys = foreign_keys($TABLE);
if ($foreign_keys) {
@@ -52,16 +52,18 @@ if ($fields) {
}
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";
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($TABLE, "%_")));
if ($result->num_rows) {
$triggers = triggers($TABLE);
if ($triggers) {
echo "<table cellspacing='0'>\n";
while ($row = $result->fetch_assoc()) {
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";
foreach ($triggers as $key => $val) {
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";
}

View File

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

View File

@@ -107,7 +107,7 @@ if ($_POST) {
$row = $_POST;
$grants = $new_grants;
} 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["hashed"] = true;
$grants[""] = true;

View File

@@ -5,7 +5,7 @@ if ($_POST && !$error) {
$dropped = drop_create(
"DROP VIEW " . idf_escape($TABLE),
"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 altered.'),
lang('View has been created.'),