Compare commits

..

44 Commits

Author SHA1 Message Date
Jakub Vrana
9ef9b8646e Release 2011-08-08 16:26:10 +02:00
Jakub Vrana
709ef12a88 Improve test 2011-08-08 16:19:23 +02:00
Jakub Vrana
593e071dbf Credits only in commit log 2011-08-08 10:38:41 +02:00
Jakub Vrana
0e2438c98e Comment 2011-08-05 17:53:40 +02:00
Jakub Vrana
52c15bf251 Fix Stop on error
Broken since commit 5576d84980
2011-08-05 17:47:33 +02:00
Jakub Vrana
388c21a0f9 Database name is LIKE pattern 2011-08-05 10:42:11 +02:00
Jakub Vrana
55223eb10c Avoid infinite loop 2011-08-05 09:01:36 +02:00
Jakub Vrana
f0d0bdbf39 Parse 'a\';' on webserver file separation 2011-08-04 23:49:38 +02:00
Jakub Vrana
323f4ab34c MySQL specific characters 2011-08-04 23:18:50 +02:00
Jakub Vrana
ad45a666cc Adminer 3.3.0 compatibility (bug #3383184) 2011-08-03 16:03:42 +02:00
Jakub Vrana
c99c11648d Display schema in title 2011-08-03 10:54:31 +02:00
Jakub Vrana
3efcd4d5b7 Comment 2011-08-03 10:54:29 +02:00
Jakub Vrana
fd65b4c9b9 Comment 2011-08-02 23:30:52 +02:00
Jakub Vrana
8e75d54e44 Save bytes 2011-08-02 17:46:13 +02:00
Jakub Vrana
c91185c435 Fix foreign key schema 2011-08-02 17:36:12 +02:00
Jakub Vrana
bbe46b7c0d Utilize variable 2011-08-02 17:34:21 +02:00
Jan Dolecek
a80c1d1632 Faster foreign keys 2011-08-02 17:33:00 +02:00
Jakub Vrana
2d721016d9 Display error with non-existent row 2011-08-01 21:50:57 +02:00
Jakub Vrana
0ecf84f987 Comment (bug #3380103) 2011-07-29 20:21:13 +02:00
Jakub Vrana
9dda217d55 Sort schemas in PostgreSQL 2011-07-29 17:59:14 +02:00
Jan Dolecek
21e88515c1 Sort databases in PostgreSQL 2011-07-29 17:57:30 +02:00
Jakub Vrana
b01d0cec22 Function found_rows should return null 2011-07-29 17:27:26 +02:00
Jakub Vrana
c82829942c Fast number of rows with big tables in PostgreSQL (thanks to juzna) 2011-07-29 17:08:06 +02:00
Jakub Vrana
2e1d38a920 Rename variable 2011-07-29 16:42:44 +02:00
Jakub Vrana
b1f1b03424 Comment 2011-07-29 16:41:52 +02:00
Jakub Vrana
aeae30ffb7 Don't scroll with AJAX select order and alter move column 2011-07-28 14:25:16 +02:00
Jakub Vrana
5046f71f9a Update design 2011-07-28 13:47:36 +02:00
Jakub Vrana
503034d010 Develop 2011-07-27 10:25:51 +02:00
Jakub Vrana
f4204386c7 Release 2011-07-27 10:16:57 +02:00
Jakub Vrana
f80e15f987 Typo 2011-07-27 09:08:53 +02:00
Jakub Vrana
4b4055432d Reorganize functions 2011-07-27 09:04:43 +02:00
Jakub Vrana
be4f2ef76c More thorough escaping 2011-07-27 08:58:07 +02:00
Jakub Vrana
037c547365 Fix XSS (thanks to Jigal van Hemert) 2011-07-27 08:01:51 +02:00
Jakub Vrana
71efbc545a Remove CodeMirror 2011-07-26 22:20:26 +02:00
Jakub Vrana
1c415dbcf8 WYMeditor 2011-07-26 22:10:45 +02:00
Jakub Vrana
903a0377af Lithuanian translation 2011-07-26 19:42:51 +02:00
Jakub Vrana
628a43156d Hide search for hidden enums (thanks to hever) 2011-07-25 17:20:32 +02:00
Jakub Vrana
6c1598ebaf Save bytes 2011-07-22 16:27:06 +02:00
Jan Dolecek
cde1d43e89 Fix altering of default values in PostgreSQL 2011-07-22 15:34:35 +02:00
Jan Dolecek
06aa0f842b Process list for PostgreSQL 2011-07-22 14:32:16 +02:00
Jakub Vrana
7f05e73689 Missing variable (thanks to juzna) 2011-07-22 13:41:05 +02:00
Jakub Vrana
83d82d6eee Pass $filter to remove_slashes (thanks to juzna) 2011-07-22 13:37:01 +02:00
Jakub Vrana
a3663066b0 Use $adminer->database() instead of DB (thanks to Lubor Bilek) 2011-07-19 17:58:44 +02:00
Jakub Vrana
dc4851dacd Develop 2011-07-19 15:06:16 +02:00
31 changed files with 306 additions and 152 deletions

3
.gitmodules vendored
View File

@@ -13,3 +13,6 @@
[submodule "jquery-timepicker"]
path = externals/jquery-timepicker
url = git://github.com/trentrichardson/jQuery-Timepicker-Addon.git
[submodule "wymeditor"]
path = externals/wymeditor
url = git://github.com/wymeditor/wymeditor.git

View File

@@ -47,7 +47,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
$fields[] = array($field["orig"], $process_field, $after);
}
if (isset($foreign_key)) {
$foreign[idf_escape($field["field"])] = ($TABLE != "" ? "ADD" : " ") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . table($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")" . (in_array($field["on_delete"], $on_actions) ? " ON DELETE $field[on_delete]" : "");
$foreign[idf_escape($field["field"])] = ($TABLE != "" ? "ADD" : " ") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . table($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")" . (ereg("^($on_actions)\$", $field["on_delete"]) ? " ON DELETE $field[on_delete]" : "");
}
$after = "AFTER " . idf_escape($field["field"]);
} elseif ($field["orig"] != "") {

View File

@@ -490,6 +490,9 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
return $return;
}
function found_rows($table_status, $where) {
}
function foreign_keys($table) {
$return = array();
foreach (get_rows("EXEC sp_fkeys @fktable_name = " . q($table)) as $row) {

View File

@@ -335,7 +335,7 @@ if (!defined("DRIVER")) {
}
/** Get tables list
* @return array
* @return array array($name => $type)
*/
function tables_list() {
global $connection;
@@ -356,7 +356,7 @@ if (!defined("DRIVER")) {
/** Get table status
* @param string
* @return array
* @return array array($name => array("Name" => , "Engine" => , "Comment" => , "Oid" => , "Rows" => , "Collation" => , "Auto_increment" => , "Data_length" => , "Index_length" => , "Data_free" => )) or only inner array with $name
*/
function table_status($name = "") {
$return = array();
@@ -444,7 +444,7 @@ if (!defined("DRIVER")) {
$return = array();
$create_table = $connection->result("SHOW CREATE TABLE " . table($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);
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($on_actions))?(?: ON UPDATE ($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);
@@ -822,6 +822,15 @@ if (!defined("DRIVER")) {
return $connection->query("EXPLAIN $query");
}
/** Get approximate number of rows
* @param array
* @param array
* @return int or null if approximate number can't be retrieved
*/
function found_rows($table_status, $where) {
return ($where || $table_status["Engine"] != "InnoDB" ? null : $table_status["Rows"]);
}
/** Get user defined types
* @return array
*/
@@ -902,6 +911,13 @@ if (!defined("DRIVER")) {
return get_key_vals("SHOW VARIABLES");
}
/** Get process list
* @return array ($row)
*/
function process_list() {
return get_rows("SHOW FULL PROCESSLIST");
}
/** Get status variables
* @return array ($name => $value)
*/
@@ -910,7 +926,7 @@ if (!defined("DRIVER")) {
}
/** Check whether a feature is supported
* @param string "comment", "copy", "drop_col", "dump", "event", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "variables", "view"
* @param string "comment", "copy", "drop_col", "dump", "event", "kill", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "variables", "view"
* @return bool
*/
function support($feature) {

View File

@@ -275,6 +275,9 @@ ORDER BY uc.constraint_type, uic.column_position", $connection2) as $row) {
return $connection->query("SELECT * FROM plan_table");
}
function found_rows($table_status, $where) {
}
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
$alter = $drop = array();
foreach ($fields as $field) {

View File

@@ -17,10 +17,12 @@ if (isset($_GET["pgsql"])) {
}
function connect($server, $username, $password) {
global $adminer;
$db = $adminer->database();
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, "'\\") . "'" : " dbname='template1'"), PGSQL_CONNECT_FORCE_NEW);
if (!$this->_link && DB != "") {
$this->_link = @pg_connect($this->_string . ($db != "" ? " dbname='" . addcslashes($db, "'\\") . "'" : " dbname='template1'"), 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 dbname='template1'", PGSQL_CONNECT_FORCE_NEW);
@@ -39,7 +41,8 @@ if (isset($_GET["pgsql"])) {
}
function select_db($database) {
if ($database == DB) {
global $adminer;
if ($database == $adminer->database()) {
return $this->_database;
}
$return = @pg_connect("$this->_string dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
@@ -126,14 +129,17 @@ if (isset($_GET["pgsql"])) {
var $extension = "PDO_PgSQL";
function connect($server, $username, $password) {
global $adminer;
$db = $adminer->database();
$string = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' options='-c client_encoding=utf8'";
$this->dsn($string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), $username, $password);
$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);
global $adminer;
return ($adminer->database() == $database);
}
function close() {
@@ -161,7 +167,7 @@ if (isset($_GET["pgsql"])) {
}
function get_databases() {
return get_vals("SELECT datname FROM pg_database");
return get_vals("SELECT datname FROM pg_database ORDER BY datname");
}
function limit($query, $where, $limit, $offset = 0, $separator = " ") {
@@ -235,6 +241,9 @@ ORDER BY a.attnum"
$row["null"] = ($row["attnotnull"] == "f");
$row["auto_increment"] = eregi("^nextval\\(", $row["default"]);
$row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1);
if (preg_match('~^(.*)::.+$~', $row["default"], $match)) {
$row["default"] = ($match[1][0] == "'" ? idf_unescape($match[1]) : $match[1]);
}
$return[$row["field"]] = $row;
}
return $return;
@@ -260,20 +269,25 @@ ORDER BY a.attnum"
}
function foreign_keys($table) {
global $on_actions;
$return = array();
foreach (get_rows("SELECT tc.constraint_name, kcu.column_name, rc.update_rule AS on_update, rc.delete_rule AS on_delete, unique_constraint_schema AS ns, 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.constraint_schema = current_schema() AND tc.table_name = " . q($table) //! there can be more unique_constraint_name
) as $row) {
$foreign_key = &$return[$row["constraint_name"]];
if (!$foreign_key) {
$foreign_key = $row;
foreach (get_rows("SELECT conname, pg_get_constraintdef(oid) AS definition
FROM pg_constraint
WHERE conrelid = (SELECT oid FROM pg_class WHERE relname = " . q($table) . ")
AND contype = 'f'::char
ORDER BY conkey, conname") as $row) {
if (preg_match('~FOREIGN KEY\s*\((.+)\)\s*REFERENCES (.+)\((.+)\)(.*)$~iA', $row['definition'], $match)) {
$row['source'] = array_map('trim', explode(',', $match[1]));
$row['table'] = $match[2];
if (preg_match('~(.+)\.(.+)~', $match[2], $match2)) {
$row['ns'] = $match2[1];
$row['table'] = $match2[2];
}
$row['target'] = array_map('trim', explode(',', $match[3]));
$row['on_delete'] = (preg_match("~ON DELETE ($on_actions)~", $match[4], $match2) ? $match2[1] : '');
$row['on_update'] = (preg_match("~ON UPDATE ($on_actions)~", $match[4], $match2) ? $match2[1] : '');
$return[$row['conname']] = $row;
}
$foreign_key["source"][] = $row["column_name"];
$foreign_key["target"][] = $row["ref"];
}
return $return;
}
@@ -502,6 +516,18 @@ ORDER BY p.proname');
return $connection->query("EXPLAIN $query");
}
function found_rows($table_status, $where) {
global $connection;
if (ereg(
" rows=([0-9]+)",
$connection->result("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")),
$regs
)) {
return $regs[1];
}
return false;
}
function types() {
return get_vals("SELECT typname
FROM pg_type
@@ -512,7 +538,7 @@ AND typelem = 0"
}
function schemas() {
return get_vals("SELECT nspname FROM pg_namespace");
return get_vals("SELECT nspname FROM pg_namespace ORDER BY nspname");
}
function get_schema() {
@@ -539,12 +565,16 @@ AND typelem = 0"
function show_variables() {
return get_key_vals("SHOW ALL");
}
function process_list() {
return get_rows("SELECT * FROM pg_stat_activity ORDER BY procpid");
}
function show_status() {
}
function support($feature) {
return ereg('^(comment|view|scheme|sequence|trigger|type|variables|drop_col)$', $feature); //! routine|
return ereg('^(comment|view|scheme|processlist|sequence|trigger|type|variables|drop_col)$', $feature); //! routine|
}
$jush = "pgsql";

View File

@@ -503,6 +503,9 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return $connection->query("EXPLAIN $query");
}
function found_rows($table_status, $where) {
}
function types() {
return array();
}

View File

@@ -62,6 +62,10 @@ if ($_POST["save"]) {
$row = (isset($_GET["select"]) && count($rows) != 1 ? null : reset($rows));
}
}
if ($row === false) {
echo "<p class='error'>" . lang('No rows.') . "\n";
}
?>
<form action="" method="post" enctype="multipart/form-data" id="form">

View File

@@ -13,8 +13,8 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-
query_redirect("ALTER TABLE " . table($TABLE)
. ($_GET["name"] != "" ? "\nDROP FOREIGN KEY " . idf_escape($_GET["name"]) . "," : "")
. "\nADD FOREIGN KEY (" . implode(", ", array_map('idf_escape', $source)) . ") REFERENCES " . table($_POST["table"]) . " (" . implode(", ", array_map('idf_escape', $target)) . ")" //! reuse $_GET["name"] - check in older MySQL versions
. (in_array($_POST["on_delete"], $on_actions) ? " ON DELETE $_POST[on_delete]" : "")
. (in_array($_POST["on_update"], $on_actions) ? " ON UPDATE $_POST[on_update]" : "")
. (ereg("^($on_actions)\$", $_POST["on_delete"]) ? " ON DELETE $_POST[on_delete]" : "")
. (ereg("^($on_actions)\$", $_POST["on_update"]) ? " ON UPDATE $_POST[on_update]" : "")
, ME . "table=" . urlencode($TABLE), ($_GET["name"] != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.')));
$error = lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.') . "<br>$error"; //! no partitioning
}
@@ -67,8 +67,8 @@ foreach ($row["source"] as $key => $val) {
?>
</table>
<p>
<?php echo lang('ON DELETE'); ?>: <?php echo html_select("on_delete", array(-1 => "") + $on_actions, $row["on_delete"]); ?>
<?php echo lang('ON UPDATE'); ?>: <?php echo html_select("on_update", array(-1 => "") + $on_actions, $row["on_update"]); ?>
<?php echo lang('ON DELETE'); ?>: <?php echo html_select("on_delete", array(-1 => "") + explode("|", $on_actions), $row["on_delete"]); ?>
<?php echo lang('ON UPDATE'); ?>: <?php echo html_select("on_update", array(-1 => "") + explode("|", $on_actions), $row["on_update"]); ?>
<p>
<input type="submit" value="<?php echo lang('Save'); ?>">
<noscript><p><input type="submit" name="add" value="<?php echo lang('Add column'); ?>"></noscript>

View File

@@ -798,7 +798,6 @@ DROP PROCEDURE adminer_alter;
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
echo "jushLinks.$val = jushLinks.$jush;\n";
}
echo "var cmComplete = [ '" . implode("', '", array_map('js_escape', array_keys($tables))) . "' ];\n";
echo "</script>\n";
}
}

View File

@@ -4,8 +4,8 @@ error_reporting(6135); // errors and warnings
include "../adminer/include/coverage.inc.php";
// disable filter.default
$filter = (!ereg('^(unsafe_raw)?$', ini_get("filter.default")) || ini_get("filter.default_flags"));
if ($filter) {
$filter = (!ereg('^(unsafe_raw)?$', ini_get("filter.default")));
if ($filter || ini_get("filter.default_flags")) {
foreach (array('_GET', '_POST', '_COOKIE', '_SERVER') as $val) {
$unsafe = filter_input_array(constant("INPUT$val"), FILTER_UNSAFE_RAW);
if ($unsafe) {
@@ -39,7 +39,7 @@ if (!defined("SID")) {
}
// disable magic quotes to be able to use database escaping function
remove_slashes(array(&$_GET, &$_POST, &$_COOKIE));
remove_slashes(array(&$_GET, &$_POST, &$_COOKIE), $filter);
if (function_exists("set_magic_quotes_runtime")) { // removed in PHP 6
set_magic_quotes_runtime(false);
}
@@ -78,4 +78,4 @@ if (!ini_bool("session.use_cookies") || @ini_set("session.use_cookies", false) !
session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
}
$on_actions = array("RESTRICT", "CASCADE", "SET NULL", "NO ACTION"); ///< @var array used in foreign_keys()
$on_actions = "RESTRICT|CASCADE|SET NULL|NO ACTION"; ///< @var string used in foreign_keys()

View File

@@ -38,7 +38,7 @@ var areYouSure = '<?php echo lang('Resend POST data?'); ?>';
<?php } ?>
<?php } ?>
<body class="<?php echo lang('ltr'); ?> nojs"<?php echo ($_POST ? "" : " onclick=\"return bodyClick(event, '" . js_escape(DB) . "', '" . js_escape($_GET["ns"]) . "');\""); // avoid re-post confirmation after refreshing the next page in Google Chrome ?> onkeydown="bodyKeydown(event);" onload="bodyLoad('<?php echo (is_object($connection) ? substr($connection->server_info, 0, 3) : ""); ?>');<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " verifyVersion();"); ?>">
<body class="<?php echo lang('ltr'); ?> nojs"<?php echo ($_POST ? "" : " onclick=\"return bodyClick(event, '" . h(js_escape(DB) . "', '" . js_escape($_GET["ns"])) . "');\""); // avoid re-post confirmation after refreshing the next page in Google Chrome ?> onkeydown="bodyKeydown(event);" onload="bodyLoad('<?php echo (is_object($connection) ? substr($connection->server_info, 0, 3) : ""); ?>');<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " verifyVersion();"); ?>">
<script type="text/javascript">
document.body.className = document.body.className.replace(/(^|\s)nojs(\s|$)/, '$1js$2');
</script>

View File

@@ -145,7 +145,7 @@ function edit_type($key, $field, $collations, $foreign_keys = array()) {
<td><input name="<?php echo $key; ?>[length]" value="<?php echo h($field["length"]); ?>" size="3" onfocus="editingLengthFocus(this);"><td class="options"><?php
echo "<select name='$key" . "[collation]'" . (ereg('(char|text|enum|set)$', $field["type"]) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>';
echo ($unsigned ? "<select name='$key" . "[unsigned]'" . (!$field["type"] || ereg('(int|float|double|decimal)$', $field["type"]) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
echo ($foreign_keys ? "<select name='$key" . "[on_delete]'" . (ereg("`", $field["type"]) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist($on_actions, $field["on_delete"]) . "</select> " : " "); // space for IE
echo ($foreign_keys ? "<select name='$key" . "[on_delete]'" . (ereg("`", $field["type"]) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $on_actions), $field["on_delete"]) . "</select> " : " "); // space for IE
}
/** Filter length value including enums

View File

@@ -27,9 +27,10 @@ function escape_string($val) {
/** Disable magic_quotes_gpc
* @param array e.g. (&$_GET, &$_POST, &$_COOKIE)
* @param bool whether to leave values as is
* @return null modified in place
*/
function remove_slashes($process) {
function remove_slashes($process, $filter = false) {
if (get_magic_quotes_gpc()) {
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
@@ -92,7 +93,7 @@ function nl_br($string) {
function checkbox($name, $value, $checked, $label = "", $onclick = "", $jsonly = false) {
static $id = 0;
$id++;
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'" . ($checked ? " checked" : "") . ($onclick ? " onclick=\"$onclick\"" : "") . ($jsonly ? " class='jsonly'" : "") . " id='checkbox-$id'>";
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'" . ($checked ? " checked" : "") . ($onclick ? ' onclick="' . h($onclick) . '"' : '') . ($jsonly ? " class='jsonly'" : "") . " id='checkbox-$id'>";
return ($label != "" ? "<label for='checkbox-$id'>$return" . h($label) . "</label>" : $return);
}
@@ -129,7 +130,7 @@ function optionlist($options, $selected = null, $use_keys = false) {
*/
function html_select($name, $options, $value = "", $onchange = true) {
if ($onchange) {
return "<select name='" . h($name) . "'" . (is_string($onchange) ? " onchange=\"$onchange\"" : "") . ">" . optionlist($options, $value) . "</select>";
return "<select name='" . h($name) . "'" . (is_string($onchange) ? ' onchange="' . h($onchange) . '"' : "") . ">" . optionlist($options, $value) . "</select>";
}
$return = "";
foreach ($options as $key => $val) {
@@ -147,6 +148,37 @@ function confirm($count = "", $stop = false) {
return " onclick=\"" . ($stop ? "eventStop(event); " : "") . "return confirm('" . lang('Are you sure?') . ($count ? " (' + $count + ')" : "") . "');\"";
}
/** Print header for hidden fieldset (close by </div></fieldset>)
* @param string
* @param string
* @param bool
* @param string
* @return null
*/
function print_fieldset($id, $legend, $visible = false, $onclick = "") {
echo "<fieldset><legend><a href='#fieldset-$id' onclick=\"" . h($onclick) . "return !toggle('fieldset-$id');\">$legend</a></legend><div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
}
/** Return class='active' if $bold is true
* @param bool
* @return string
*/
function bold($bold) {
return ($bold ? " class='active'" : "");
}
/** Generate class for odd rows
* @param string return this for odd rows, empty to reset counter
* @return string
*/
function odd($return = ' class="odd"') {
static $i = 0;
if (!$return) { // reset counter
$i = -1;
}
return ($i++ % 2 ? $return : '');
}
/** Escape string for JavaScript apostrophes
* @param string
* @return string
@@ -155,6 +187,25 @@ function js_escape($string) {
return addcslashes($string, "\r\n'\\/"); // slash for <script>
}
/** Print one row in JSON object
* @param string or "" to close the object
* @param string
* @return null
*/
function json_row($key, $val = null) {
static $first = true;
if ($first) {
echo "{";
}
if ($key != "") {
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\"\\") . '": ' . (isset($val) ? '"' . addcslashes($val, "\r\n\"\\") . '"' : 'undefined');
$first = false;
} else {
echo "\n}\n";
$first = true;
}
}
/** Get INI boolean value
* @param string
* @return bool
@@ -516,35 +567,14 @@ function upload_error($error) {
return ($error ? lang('Unable to upload a file.') . ($max_size ? " " . lang('Maximum allowed file size is %sB.', $max_size) : "") : lang('File does not exist.'));
}
/** Generate class for odd rows
* @param string return this for odd rows, empty to reset counter
/** Create repeat pattern for preg
* @param string
* @param int
* @return string
*/
function odd($return = ' class="odd"') {
static $i = 0;
if (!$return) { // reset counter
$i = -1;
}
return ($i++ % 2 ? $return : '');
}
/** Print one row in JSON object
* @param string or "" to close the object
* @param string
* @return null
*/
function json_row($key, $val = null) {
static $first = true;
if ($first) {
echo "{";
}
if ($key != "") {
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\"\\") . '": ' . (isset($val) ? '"' . addcslashes($val, "\r\n\"\\") . '"' : 'undefined');
$first = false;
} else {
echo "\n}\n";
$first = true;
}
function repeat_pattern($pattern, $length) {
// fix for Compilation failed: number too big in {} quantifier
return str_repeat("$pattern{0,65535}", $length / 65535) . "$pattern{0," . ($length % 65535) . "}"; // can create {0,0} which is OK
}
/** Check whether the string is in UTF-8
@@ -556,16 +586,6 @@ function is_utf8($val) {
return (preg_match('~~u', $val) && !preg_match('~[\\0-\\x8\\xB\\xC\\xE-\\x1F]~', $val));
}
/** Create repeat pattern for preg
* @param string
* @param int
* @return string
*/
function repeat_pattern($pattern, $length) {
// fix for Compilation failed: number too big in {} quantifier
return str_repeat("$pattern{0,65535}", $length / 65535) . "$pattern{0," . ($length % 65535) . "}"; // can create {0,0} which is OK
}
/** Shorten UTF-8 string
* @param string
* @param int
@@ -675,7 +695,7 @@ function input($field, $value, $function) {
}
$first++;
}
$onchange = ($first ? " onchange=\"var f = this.form['function[" . js_escape($name) . "]']; if ($first > f.selectedIndex) f.selectedIndex = $first;\"" : "");
$onchange = ($first ? " onchange=\"var f = this.form['function[" . h(js_escape(bracket_escape($field["field"]))) . "]']; if ($first > f.selectedIndex) f.selectedIndex = $first;\"" : "");
$attrs .= $onchange;
echo (count($functions) > 1 ? html_select("function[$name]", $functions, !isset($function) || in_array($function, $functions) || isset($functions[$function]) ? $function : "", "functionChange(this);") : nbsp(reset($functions))) . '<td>';
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
@@ -854,22 +874,3 @@ function is_url($string) {
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN
return (preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string, $match) ? strtolower($match[1]) : ""); //! restrict path, query and fragment characters
}
/** Print header for hidden fieldset (close by </div></fieldset>)
* @param string
* @param string
* @param bool
* @param string
* @return null
*/
function print_fieldset($id, $legend, $visible = false, $onclick = "") {
echo "<fieldset><legend><a href='#fieldset-$id' onclick=\"$onclick" . "return !toggle('fieldset-$id');\">$legend</a></legend><div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
}
/** Return class='active' if $bold is true
* @param bool
* @return string
*/
function bold($bold) {
return ($bold ? " class='active'" : "");
}

View File

@@ -1,2 +1,2 @@
<?php
$VERSION = "3.3.0";
$VERSION = "3.3.2";

View File

@@ -14,6 +14,7 @@ function adminer_object() {
new AdminerDumpXml,
//~ new AdminerEditCalendar("<script type='text/javascript' src='../externals/jquery-ui/jquery-1.4.4.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.core.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.widget.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.datepicker.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.mouse.js'></script>\n<script type='text/javascript' src='../externals/jquery-ui/ui/jquery.ui.slider.js'></script>\n<script type='text/javascript' src='../externals/jquery-timepicker/jquery-ui-timepicker-addon.js'></script>\n<link rel='stylesheet' href='../externals/jquery-ui/themes/base/jquery.ui.all.css'>\n<style type='text/css'>\n.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }\n.ui-timepicker-div dl { text-align: left; }\n.ui-timepicker-div dl dt { height: 25px; }\n.ui-timepicker-div dl dd { margin: -25px 0 10px 65px; }\n.ui-timepicker-div td { font-size: 90%; }\n</style>\n", "../externals/jquery-ui/ui/i18n/jquery.ui.datepicker-%s.js"),
//~ new AdminerTinymce("../externals/tinymce/jscripts/tiny_mce/tiny_mce_dev.js"),
//~ new AdminerWymeditor(array("../externals/wymeditor/src/jquery/jquery.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.explorer.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.mozilla.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.opera.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.safari.js")),
new AdminerFileUpload(""),
new AdminerSlugify,
new AdminerTranslation,

View File

@@ -1,5 +1,5 @@
<?php
if ($_POST && !$error) {
if (support("kill") && $_POST && !$error) {
$killed = 0;
foreach ((array) $_POST["kill"] as $val) {
if (queries("KILL " . (+$val))) {
@@ -16,20 +16,24 @@ page_header(lang('Process list'), $error);
<table cellspacing="0" onclick="tableClick(event);" class="nowrap">
<?php
$i = -1;
foreach (get_rows("SHOW FULL PROCESSLIST") as $i => $row) {
foreach (process_list() as $i => $row) {
if (!$i) {
echo "<thead><tr lang='en'><th>&nbsp;<th>" . implode("<th>", array_keys($row)) . "</thead>\n";
echo "<thead><tr lang='en'>" . (support("kill") ? "<th>&nbsp;" : "") . "<th>" . implode("<th>", array_keys($row)) . "</thead>\n";
}
echo "<tr" . odd() . "><td>" . checkbox("kill[]", $row["Id"], 0);
echo "<tr" . odd() . ">" . (support("kill") ? "<td>" . checkbox("kill[]", $row["Id"], 0) : "");
foreach ($row as $key => $val) {
echo "<td>" . ($key == "Info" && $val != "" ? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Edit') . '</a>' : nbsp($val));
echo "<td>" . (($jush == "sql" ? $key == "Info" && $val != "" : $key == "current_query" && $val != "<IDLE>") ? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Edit') . '</a>' : nbsp($val));
}
echo "\n";
}
?>
</table>
<p><?php echo ($i + 1) . "/" . lang('%d in total', $connection->result("SELECT @@max_connections")); ?>
<p>
<input type="submit" value="<?php echo lang('Kill'); ?>">
<?php
if (support("kill")) {
echo ($i + 1) . "/" . lang('%d in total', $connection->result("SELECT @@max_connections"));
echo "<p><input type='submit' value='" . lang('Kill') . "'>\n";
}
?>
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>

View File

@@ -1,9 +1,8 @@
<?php
page_header(lang('Database schema'), "", array(), DB);
page_header(lang('Database schema'), "", array(), DB . ($_GET["ns"] ? ".$_GET[ns]" : ""));
$table_pos = array();
$table_pos_js = array();
// saved in one cookie because there is a limit of 20 cookies per domain
$name = "adminer_schema";
$SCHEMA = ($_GET["schema"] ? $_GET["schema"] : $_COOKIE[($_COOKIE["$name-" . DB] ? "$name-" . DB : $name)]); // $_COOKIE["adminer_schema"] was used before 3.2.0 //! ':' in table name
preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~', $SCHEMA, $matches, PREG_SET_ORDER);

View File

@@ -3,21 +3,21 @@ header("Content-Type: text/javascript; charset=utf-8");
if ($_GET["script"] == "db") {
$sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
foreach (table_status() as $row) {
$id = js_escape($row["Name"]);
json_row("Comment-$id", nbsp($row["Comment"]));
if (!is_view($row)) {
foreach (table_status() as $table_status) {
$id = js_escape($table_status["Name"]);
json_row("Comment-$id", nbsp($table_status["Comment"]));
if (!is_view($table_status)) {
foreach (array("Engine", "Collation") as $key) {
json_row("$key-$id", nbsp($row[$key]));
json_row("$key-$id", nbsp($table_status[$key]));
}
foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
if ($row[$key] != "") {
$val = number_format($row[$key], 0, '.', lang(','));
json_row("$key-$id", ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? "~ $val" : $val));
if ($table_status[$key] != "") {
$val = number_format($table_status[$key], 0, '.', lang(','));
json_row("$key-$id", ($key == "Rows" && $table_status["Engine"] == "InnoDB" && $val ? "~ $val" : $val));
if (isset($sums[$key])) {
$sums[$key] += ($row["Engine"] != "InnoDB" || $key != "Data_free" ? $row[$key] : 0);
$sums[$key] += ($table_status["Engine"] != "InnoDB" || $key != "Data_free" ? $table_status[$key] : 0);
}
} elseif (array_key_exists($key, $row)) {
} elseif (array_key_exists($key, $table_status)) {
json_row("$key-$id");
}
}

View File

@@ -373,8 +373,8 @@ if (!$columns) {
if ($rows || $page) {
$exact_count = true;
if ($_GET["page"] != "last" && +$limit && count($group) >= count($select) && ($found_rows >= $limit || $page)) {
$found_rows = $table_status["Rows"];
if (!isset($found_rows) || $where || ($table_status["Engine"] == "InnoDB" && $found_rows < max(1e4, 2 * ($page + 1) * $limit))) {
$found_rows = found_rows($table_status, $where);
if ($found_rows < max(1e4, 2 * ($page + 1) * $limit)) {
// slow with big tables
ob_flush(); //! doesn't work with AJAX
flush();

View File

@@ -51,7 +51,7 @@ if (!$error && $_POST) {
}
$commands = 0;
$errors = array();
$parse = '[\'`"]' . ($jush == "pgsql" ? '|\\$[^$]*\\$' : ($jush == "mssql" || $jush == "sqlite" ? '|\\[' : '')) . '|/\\*|-- |#'; //! ` and # not everywhere
$parse = '[\'"' . ($jush == "sql" ? '`#' : ($jush == "sqlite" ? '`[' : ($jush == "mssql" ? '[' : ''))) . ']|/\\*|-- |$' . ($jush == "pgsql" ? '|\\$[^$]*\\$' : '');
$total_start = microtime();
parse_str($_COOKIE["adminer_export"], $adminer_export);
$dump_format = $adminer->dumpFormat();
@@ -61,12 +61,12 @@ if (!$error && $_POST) {
$delimiter = $match[1];
$query = substr($query, strlen($match[0]));
} else {
preg_match('(' . preg_quote($delimiter) . "|$parse|\$)", $query, $match, PREG_OFFSET_CAPTURE, $offset); // should always match
preg_match('(' . preg_quote($delimiter) . "|$parse)", $query, $match, PREG_OFFSET_CAPTURE, $offset); // should always match
$found = $match[0][0];
$offset = $match[0][1] + strlen($found);
if (!$found && $fp && !feof($fp)) {
$query .= fread($fp, 1e5);
} else {
$offset = $match[0][1] + strlen($found);
if (!$found && rtrim($query) == "") {
break;
}
@@ -75,7 +75,8 @@ if (!$error && $_POST) {
$s = $match[0][0];
$offset = $match[0][1] + strlen($s);
if (!$s && $fp && !feof($fp)) {
$query .= fread($fp, 1e6);
$offset -= strlen($found); // strlen($found) >= strlen("\\.") - 1
$query .= fread($fp, 1e5);
} elseif ($s[0] != "\\") {
break;
}
@@ -104,7 +105,7 @@ if (!$error && $_POST) {
echo "<p class='error'>" . lang('Error in query') . ": " . error() . "\n";
$errors[] = " <a href='#sql-$commands'>$commands</a>";
if ($_POST["error_stops"]) {
break;
break 2;
}
} elseif (is_object($result)) {
select($result, $connection2);
@@ -116,16 +117,16 @@ if (!$error && $_POST) {
. html_select("output", $adminer->dumpOutput(), $adminer_export["output"]) . " "
. html_select("format", $dump_format, $adminer_export["format"])
. "<input type='hidden' name='query' value='" . h($q) . "'>"
. " <input type='submit' name='export' value='" . lang('Export') . "' onclick='eventStop(event);'><input type='hidden' name='token' value='$token'></span>"
. " <input type='submit' name='export' value='" . lang('Export') . "' onclick='eventStop(event);'><input type='hidden' name='token' value='$token'></span>\n"
;
if ($connection2 && preg_match("~^($space|\\()*SELECT\\b~isU", $q) && ($explain = explain($connection2, $q))) {
$id = "explain-$commands";
echo ", <a href='#$id' onclick=\"return !toggle('$id');\">EXPLAIN</a>$export\n";
echo ", <a href='#$id' onclick=\"return !toggle('$id');\">EXPLAIN</a>$export";
echo "<div id='$id' class='hidden'>\n";
select($explain, $connection2, ($jush == "sql" ? "http://dev.mysql.com/doc/refman/" . substr($connection->server_info, 0, 3) . "/en/explain-output.html#explain_" : ""));
echo "</div>\n";
} else {
echo "$export\n";
echo $export;
}
echo "</form>\n";
}

View File

@@ -309,7 +309,7 @@ function ajaxSend(url, data, popState, noscroll) {
history.pushState(data, '', url); //! remember window position
}
}
if (!noscroll) {
if (!noscroll && !/&order/.test(url)) {
scrollTo(0, 0);
}
setHtml('content', xmlhttp.responseText);
@@ -376,9 +376,9 @@ function ajaxForm(form, data, noscroll) {
params.push(data);
}
if (form.method == 'post') {
return ajaxSend((/\?/.test(form.action) ? form.action : location.href), params.join('&'), noscroll); // ? - always part of Adminer URL
return ajaxSend((/\?/.test(form.action) ? form.action : location.href), params.join('&'), false, noscroll); // ? - always part of Adminer URL
}
return ajaxSend((form.action || location.href).replace(/\?.*/, '') + '?' + params.join('&'), noscroll);
return ajaxSend((form.action || location.href).replace(/\?.*/, '') + '?' + params.join('&'), '', false, noscroll);
}

View File

@@ -30,7 +30,7 @@ if ($_POST) {
<form action="" method="post" id="form">
<table cellspacing="0">
<tr><th><?php echo lang('Time'); ?><td><?php echo html_select("Timing", $trigger_options["Timing"], $row["Timing"], "if (/^" . h(preg_quote($TABLE, "/")) . "_[ba][iud]$/.test(this.form['Trigger'].value)) this.form['Trigger'].value = '" . h(js_escape($TABLE)) . "_' + selectValue(this).charAt(0).toLowerCase() + selectValue(this.form['Event']).charAt(0).toLowerCase();"); ?>
<tr><th><?php echo lang('Time'); ?><td><?php echo html_select("Timing", $trigger_options["Timing"], $row["Timing"], "if (/^" . preg_quote($TABLE, "/") . "_[ba][iud]$/.test(this.form['Trigger'].value)) this.form['Trigger'].value = '" . js_escape($TABLE) . "_' + selectValue(this).charAt(0).toLowerCase() + selectValue(this.form['Event']).charAt(0).toLowerCase();"); ?>
<tr><th><?php echo lang('Event'); ?><td><?php echo html_select("Event", $trigger_event, $row["Event"], "this.form['Timing'].onchange();"); ?>
<tr><th><?php echo lang('Type'); ?><td><?php echo html_select("Type", $trigger_options["Type"], $row["Type"]); ?>
</table>

View File

@@ -111,7 +111,7 @@ if ($_POST) {
if ($old_pass != "") {
$row["hashed"] = true;
}
$grants[DB != "" && !isset($_GET["host"]) ? idf_escape($_GET["db"]) . ".*" : ""] = array();
$grants[DB != "" && !isset($_GET["host"]) ? idf_escape(addcslashes(DB, "%_")) . ".*" : ""] = array();
}
?>

View File

@@ -1,3 +1,16 @@
Adminer 3.3.2 (released 2011-08-08):
Display error with non-existent row in edit
Fix minor parser bug in SQL command with webserver file
Fix SQL command Stop on error
Don't scroll with AJAX select order and alter move column
Fast number of rows with big tables (PostgreSQL)
Sort databases and schemas (PostgreSQL)
Adminer 3.3.1 (released 2011-07-27):
Fix XSS introduced in Adminer 3.2.0
Fix altering default values (PostgreSQL)
Process list (PostgreSQL)
Adminer 3.3.0 (released 2011-07-19):
Use Esc to disable in-place edit
Shortcut for database privileges
@@ -22,7 +35,7 @@ Display searched columns (Editor)
Customizable favicon (customization)
Method name can return a link (customization)
Easier sending of default headers (customization)
Romanian translation
Lithuanian and Romanian translation
Adminer 3.2.2 (released 2011-03-28):
Fix AJAX history after reload
@@ -31,14 +44,14 @@ Adminer 3.2.1 (released 2011-03-23):
Ability to save expression in edit
Respect default database collation (bug #3191489)
Don't export triggers without table (bug #3193489)
Esc to focus next field in Tab textarea (thanks to David Grudl)
Esc to focus next field in Tab textarea
Send forms by Ctrl+Enter on <select>
Enum editor and textarea Ctrl+Enter working in IE
AJAX forms in Google Chrome
Parse UTF-16 and UTF-8 BOM in all text uploads
Display ; in history (thanks to Jan Cerny)
Display ; in history
Use DELIMITER in history
Show databases even with skip_show_database in MySQL 5 (thanks to Radoslaw Kowalewski)
Show databases even with skip_show_database in MySQL 5
Disable maxlength with functions in edit
Better placement of AJAX icon
Table header in CSV export (Editor)
@@ -194,9 +207,9 @@ Localize date (Editor)
Treat tinyint(1) as bool (Editor)
Divide types to groups in table creation
Link e-mails in select
Show type in field name title (thanks to Jakub Sochor)
Preselect now() for timestamp columns (thanks to paranoiq)
Clear history (thanks to paranoiq)
Show type in field name title
Preselect now() for timestamp columns
Clear history
Prefill insert by foreign key searches
Print number of rows in SQL command
Remove Delete button from Edit page - use mass operation for it
@@ -207,7 +220,7 @@ Use HTML Strict instead of XHTML
Remove function minification in favor of performance and customization
Fix grant ALL PRIVILEGES with GRANT OPTION
Fix CSV import
Fix work with default values (thanks to Jiri Pospisil)
Fix work with default values
Adminer 1.11.1 (released 2009-07-03):
Fix problem with enabled Filter extension
@@ -236,15 +249,15 @@ Use \n in SQL commands
phpMinAdmin 1.10.1 (released 2009-05-07):
Highlight odd and hover rows
Partition editing comfort (bug #2783446)
Allow full length in limited int (thanks to Vlasta Neubauer)
Allow full length in limited int
phpMinAdmin 1.10.0 (released 2009-04-28):
Partitioning (MySQL 5.1)
CSV import
Plus and minus functions
Option to stop on error in SQL command (thanks to Vaclav Marik)
Option to stop on error in SQL command
Cross links to select and table (bug #2236232), link new item
Suhosin compatibility (thanks to Klemens Hackel)
Suhosin compatibility
Remove max_allowed_packet from export
Read style from phpMinAdmin.css if exists
Size reduction by minification of variables and functions
@@ -263,11 +276,11 @@ Search without column restriction
Use type=password for unhashed password
Only one button for each action in select
Choose language through option-list
XHTML syntax errors (thanks to kozotoc)
XHTML syntax errors
Don't set global variable in export
SHOW DATABASES can be revoked
Order by function result working also in older MySQL versions
Tested on IIS (thanks to krasl.cz)
Tested on IIS
phpMinAdmin 1.8.0 (released 2008-09-12):
Events (MySQL 5.1)

View File

@@ -17,7 +17,7 @@ html/*\*/>/*/*/body #menu p a[href*="&select="] {background:url("data:image/png;
html/*\*/>/*/*/body #menu p a[href*="&table="], html/*\*/>/*/*/body #menu p a[href*="&view="] {clear:right; margin-left:24px; display:block; height:17px; padding-bottom:1px; text-decoration:none;}
html/*\*/>/*/*/body #menu p#tables br {display:none;}
html/*\*/>/*/*/body #menu p br {display:none;}
html/*\*/>/*/*/body a[href*="&create="] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ6SURBVDjLpZNZSNRRGMV//2XGsjFrMg2z0so2K21xIFpepYUiAsGIICLffI8eWiBBeg3qQV+KwBYKLB8qpHUmrahcKLc0QsxldNSxdPz/79LD1ChBUXTh8sG93POdc75zDa01/7NsgGvPR09rzQmpVZZSCqlAKIWUCqk0QqoZWyKFRir1uvxIbsAGUFqXHQqkpP1L57M3Pm5MMJBKpQHUdF9BKIGQAlcJXOlOVykSdye3leO6MmkGQNyHw+uO/1X3bzGBK+S0B1IqAKqDg3986HeCZPffwvJtoNT7lOZLvUdtAPEDAKBkRzo3QwMUb89InN1uGGD3spdE214xe8MRUnM2MfppNW0Pqy7YAK5UKK2xLbhdP4hlmdxpGMQwwQT8ziNiI534c7cT6WrFazikzF2Eb8HS1IQEDdiWwcHAQmpehTkQSAcgNvSMiYFW5uUUMdV3HW+ywefGNqITJsbUUL75k4FWYJtQ+yaMZcXrk1ANk/33mbdiD7EvlRieETy+FJLkMFcjRRSW3emIAwiF1hqPBfu2LGSWbbA1uZ41SfWkrtxPrPcypsfFiWYzFGzGKTjFV28WEJeIUHETLdOgrmkI1VdHpCdEet5enP4qLK9mKrqMgedv6cyrAP+qxOTiUxAi7oEJi8frELoFoTLpa7nI/HQvscgSRt+0kV1SSW7qYtp7xrBMphm4Mi5h/VIfTcEq1u0oJaknSEdNiMYHET7UvcMpPEN31Ed7zxgASmk1I0g6dK66s8CRak5mVxjnfS05+TsZCw/T9baTx1nnGb47DrQksjE6HrsHYPz6nYt3+Sc3L8+wA2tz0J6pF5OD4WP7Kpq7f5fO79DfSxjdtCtDAAAAAElFTkSuQmCC") no-repeat scroll 2px bottom; padding-left:22px;}
@@ -41,8 +41,10 @@ html/*\*/>/*/*/body table tbody input[name*="check"] {display:block; float:left;
html/*\*/>/*/*/body table a[href*="&edit="][href*="&where"] {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFUSURBVDjLrZM/SAJxGIZdWwuDlnCplkAEm1zkaIiGFFpyMIwGK5KGoK2lphDKkMDg3LLUSIJsSKhIi+684CokOtTiMizCGuzEU5K3vOEgKvtBDe/2Pc8H3x8NAM1fQlx4H9M3pcOWp6TXWmM8A7j0629v1nraiAVC0IrrwATKIgs5xyG5QiE+Z4iQdoeU2oAsnqCSO1NSTu+D9VhqRLD8nIB8F0Q2MgmJDyipCzjvYJkIfpN2UBLG8MpP4dxvQ3ZzGuyyBQ2H+AnOOCBd9aL6soh81A5hyYSGWyCFvxUcerqI4S+CvYVOFPMHxLAq8I3qdHVY5LbBhJzEsCrwutpRFBlUHy6wO2tEYtWAzLELPN2P03kjfj3luqDycV2F8AgefWbEnVqEHa2IznSD6BdsVDNStB0lfh0FPoQjdx8RrAqGzC0YprSgxzsUMOY2bf37N/6Ud1Vc9yYcH50CAAAAAElFTkSuQmCC") no-repeat scroll right bottom; padding-right:18px;}
html/*\*/>/*/*/body table input + a[href*="&edit="][href*="&where"] {width:0; float:left; display:block; height:16px; overflow:hidden; text-decoration:none; padding:0 0 0 18px; background-position:2px bottom;}
html/*\*/>/*/*/body table tbody td:first-child {white-space:normal;}
html/*\*/>/*/*/body table thead input {margin-right:30px;}
html/*\*/>/*/*/body table thead #all-page + a {background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFUSURBVDjLrZM/SAJxGIZdWwuDlnCplkAEm1zkaIiGFFpyMIwGK5KGoK2lphDKkMDg3LLUSIJsSKhIi+684CokOtTiMizCGuzEU5K3vOEgKvtBDe/2Pc8H3x8NAM1fQlx4H9M3pcOWp6TXWmM8A7j0629v1nraiAVC0IrrwATKIgs5xyG5QiE+Z4iQdoeU2oAsnqCSO1NSTu+D9VhqRLD8nIB8F0Q2MgmJDyipCzjvYJkIfpN2UBLG8MpP4dxvQ3ZzGuyyBQ2H+AnOOCBd9aL6soh81A5hyYSGWyCFvxUcerqI4S+CvYVOFPMHxLAq8I3qdHVY5LbBhJzEsCrwutpRFBlUHy6wO2tEYtWAzLELPN2P03kjfj3luqDycV2F8AgefWbEnVqEHa2IznSD6BdsVDNStB0lfh0FPoQjdx8RrAqGzC0YprSgxzsUMOY2bf37N/6Ud1Vc9yYcH50CAAAAAElFTkSuQmCC") no-repeat scroll right bottom; padding-right:18px;}
html/*\*/>/*/*/body table thead #all-page + a {width:0; display:inline-block; height:16px; overflow:hidden; text-decoration:none; padding:0 0 0 16px;}
html/*\*/>/*/*/body table td:first-child {white-space:nowrap;}
html/*\*/>/*/*/body input[name="delete"], html/*\*/>/*/*/body input[name="drop"] {background:transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHSSURBVHjapFM5bsJQEB2zSIDFJrHYpEtyAyoKJAp6CrqIkBPkNDlBAKXjBEgUpKOBCyQNijFiEZvZl8z7wsjESYpkpNFfPO/Nmz9j6Xg80n/M9fWi3W7fMOnd4XAo8qogAbvO5xKvL6lU6s0aL1kVMDjP5ye/36+Gw2FyOp3EQFqtVtTr9WixWHT5/JhOp6s2ghP4ORaLyaFQiGazGa3Xa0HgdrvJ6/WSpmk0Go0MjnvIZDLVM0Gr1brm/WskEkkA3O/3abvdQjq5XC6xgoiVka7rNB6PNT6ns9nsu+OkpODxeBLBYJAGgwHt9/uzQ8Vms6Hdbie+KYqC+ASTFrARBMx2HwgEaDKZiHqn0yktl0uxtzrMMAyKx+MCc+4Cs13hwQCC1GQy+W3Lms2mUIUygbEqEBLNun8z8zswVgUfLO0WD4Z6kekn8/l8okNM8GFVUMYDoVWQ6HA4bEAzoyzL1O12kbRsJajwhYZhiUajJEnShWSAQaqqKnU6HahEGysXg9RoNPJ8+cwZZLSKp47m8/k5Kxzg4XBocNxDLper2ka5Xq+LUeatilahJLN1mEJ+ZDHKJthGAKvVauJnYi9ysHIqQee1xOsLg3/+mf5inwIMAJMhb74NwG5wAAAAAElFTkSuQmCC") no-repeat scroll left center; padding:1px 5px 1px 18px; border:0; cursor:pointer; font-size:.9em;}
html/*\*/>/*/*/body input[name="delete"]:hover, html/*\*/>/*/*/body input[name="drop"]:hover {color:red; background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJdSURBVDjLpZP7S1NhGMf9W7YfogSJboSEUVCY8zJ31trcps6zTI9bLGJpjp1hmkGNxVz4Q6ildtXKXzJNbJRaRmrXoeWx8tJOTWptnrNryre5YCYuI3rh+8vL+/m8PA/PkwIg5X+y5mJWrxfOUBXm91QZM6UluUmthntHqplxUml2lciF6wrmdHriI0Wx3xw2hAediLwZRWRkCPzdDswaSvGqkGCfq8VEUsEyPF1O8Qu3O7A09RbRvjuIttsRbT6HHzebsDjcB4/JgFFlNv9MnkmsEszodIIY7Oaut2OJcSF68Qx8dgv8tmqEL1gQaaARtp5A+N4NzB0lMXxon/uxbI8gIYjB9HytGYuusfiPIQcN71kjgnW6VeFOkgh3XcHLvAwMSDPohOADdYQJdF1FtLMZPmslvhZJk2ahkgRvq4HHUoWHRDqTEDDl2mDkfheiDgt8pw340/EocuClCuFvboQzb0cwIZgki4KhzlaE6w0InipbVzBfqoK/qRH94i0rgokSFeO11iBkp8EdV8cfJo0yD75aE2ZNRvSJ0lZKcBXLaUYmQrCzDT6tDN5SyRqYlWeDLZAg0H4JQ+Jt6M3atNLE10VSwQsN4Z6r0CBwqzXesHmV+BeoyAUri8EyMfi2FowXS5dhd7doo2DVII0V5BAjigP89GEVAtda8b2ehodU4rNaAW+dGfzlFkyo89GTlcrHYCLpKD+V7yeeHNzLjkp24Uu1Ed6G8/F8qjqGRzlbl2H2dzjpMg1KdwsHxOlmJ7GTeZC/nesXbeZ6c9OYnuxUc3fmBuFft/Ff8xMd0s65SXIb/gAAAABJRU5ErkJggg==")}

View File

@@ -197,8 +197,8 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
$i = 0;
$fields = fields($_GET["select"]);
foreach ($fields as $name => $field) {
if (ereg("enum", $field["type"])) { //! set - uses 1 << $i and FIND_IN_SET()
$desc = $columns[$name];
$desc = $columns[$name];
if (ereg("enum", $field["type"]) && $desc != "") { //! set - uses 1 << $i and FIND_IN_SET()
$key = $keys[$name];
$i--;
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'>:";

View File

@@ -36,7 +36,7 @@ class AdminerEditCalendar {
if (ereg("date|time", $field["type"])) {
$dateFormat = "changeYear: true, dateFormat: 'yy-mm-dd'"; //! yy-mm-dd regional
$timeFormat = "showSecond: true, timeFormat: 'hh:mm:ss'";
return "<input id='fields-" . h($field["field"]) . "' value='" . h($value) . "'" . ($maxlength ? " maxlength='$maxlength'" : "") . "$attrs><script type='text/javascript'>jQuery(function () { jQuery('#fields-" . js_escape($field["field"]) . "')."
return "<input id='fields-" . h($field["field"]) . "' value='" . h($value) . "'" . (+$field["length"] ? " maxlength='" . (+$field["length"]) . "'" : "") . "$attrs><script type='text/javascript'>jQuery(function () { jQuery('#fields-" . js_escape($field["field"]) . "')."
. ($field["type"] == "time" ? "timepicker({ $timeFormat })"
: (ereg("time", $field["type"]) ? "datetimepicker({ $dateFormat, $timeFormat })"
: "datepicker({ $dateFormat })"

View File

@@ -21,7 +21,7 @@ class AdminerFrames {
header("X-Frame-Options: SameOrigin");
}
header("X-XSS-Protection: 0");
return true;
return false;
}
}

68
plugins/wymeditor.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
/** Edit all fields containing "_html" by HTML editor WYMeditor and display the HTML in select
* @uses WYMeditor, http://www.wymeditor.org/
* @author Jakub Vrana, http://www.vrana.cz/
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerWymeditor {
/** @var array @access protected */
var $scripts;
/** @var string @access protected */
var $options;
/**
* @param array
* @param string in format "skin: 'custom', preInit: function () { }"
*/
function AdminerWymeditor($scripts = array("jquery/jquery.js", "wymeditor/jquery.wymeditor.min.js"), $options = "") {
$this->scripts = $scripts;
$this->options = $options;
}
function head() {
foreach ($this->scripts as $script) {
echo "<script type='text/javascript' src='" . h($script) . "'></script>\n";
}
}
function selectVal(&$val, $link, $field) {
// copied from tinymce.php
if (ereg("_html", $field["field"]) && $val != '&nbsp;') {
$shortened = (substr($val, -10) == "<i>...</i>");
if ($shortened) {
$val = substr($val, 0, -10);
}
//! shorten with regard to HTML tags - http://php.vrana.cz/zkraceni-textu-s-xhtml-znackami.php
$val = preg_replace('~<[^>]*$~', '', html_entity_decode($val, ENT_QUOTES)); // remove ending incomplete tag (text can be shortened)
if ($shortened) {
$val .= "<i>...</i>";
}
if (class_exists('DOMDocument')) { // close all opened tags
$dom = new DOMDocument;
if (@$dom->loadHTML("<meta http-equiv='Content-Type' content='text/html; charset=utf-8'></head>$val")) { // @ - $val can contain errors
$val = preg_replace('~.*<body[^>]*>(.*)</body>.*~is', '\\1', $dom->saveHTML());
}
}
}
}
function editInput($table, $field, $attrs, $value) {
static $lang = "";
if (!$lang && ereg("text", $field["type"]) && ereg("_html", $field["field"])) {
$lang = "en";
if (function_exists('get_lang')) { // since Adminer 3.2.0
$lang = get_lang();
$lang = ($lang == "zh" || $lang == "zh-tw" ? "zh_cn" : $lang);
}
return "<textarea$attrs id='fields-" . h($field["field"]) . "' rows='12' cols='50'>" . h($value) . "</textarea><script type='text/javascript'>
jQuery(function () {
jQuery('textarea[name*=\"_html\"]').wymeditor({ updateSelector: '#form [type=\"submit\"]', lang: '$lang'" . ($this->options ? ", $this->options" : "") . " });
});
</script>";
}
}
}

View File

@@ -31,6 +31,11 @@
<td>indexes[2][columns][1]</td>
<td>label=name</td>
</tr>
<tr>
<td>verifyValue</td>
<td>name=indexes[2][name]</td>
<td>name</td>
</tr>
<tr>
<td>clickAndWait</td>
<td>//input[@value='Save']</td>
@@ -56,7 +61,6 @@
<td>Indexes have been altered.</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>