diff --git a/adminer/download.inc.php b/adminer/download.inc.php
index 8795b01d..355c74cd 100644
--- a/adminer/download.inc.php
+++ b/adminer/download.inc.php
@@ -1,5 +1,5 @@
result($dbh->query("SELECT " . idf_escape($_GET["field"]) . " FROM " . idf_escape($_GET["download"]) . " WHERE " . implode(" AND ", where($_GET)) . " LIMIT 1"));
+echo $dbh->result($dbh->query("SELECT " . idf_escape($_GET["field"]) . " FROM " . idf_escape($_GET["download"]) . " WHERE " . where($_GET) . " LIMIT 1"));
exit; // don't output footer
diff --git a/adminer/edit.inc.php b/adminer/edit.inc.php
index ba634fd3..b5791f68 100644
--- a/adminer/edit.inc.php
+++ b/adminer/edit.inc.php
@@ -1,5 +1,5 @@
$field) {
@@ -10,7 +10,7 @@ foreach ($fields as $name => $field) {
if ($_POST && !$error && !isset($_GET["select"])) {
$location = ($_POST["insert"] ? $_SERVER["REQUEST_URI"] : $SELF . (isset($_GET["default"]) ? "table=" : "select=") . urlencode($_GET["edit"])); // "insert" to continue edit or insert
if (isset($_POST["delete"])) {
- query_redirect("DELETE FROM " . idf_escape($_GET["edit"]) . " WHERE " . implode(" AND ", $where) . " LIMIT 1", $location, lang('Item has been deleted.'));
+ query_redirect("DELETE FROM " . idf_escape($_GET["edit"]) . " WHERE $where LIMIT 1", $location, lang('Item has been deleted.'));
} else {
$set = array();
foreach ($fields as $name => $field) {
@@ -33,13 +33,20 @@ if ($_POST && !$error && !isset($_GET["select"])) {
if (isset($_GET["default"])) {
query_redirect("ALTER TABLE " . idf_escape($_GET["edit"]) . implode(",", $set), $location, lang('Default values has been set.'));
} elseif ($update) {
- query_redirect("UPDATE " . idf_escape($_GET["edit"]) . " SET" . implode(",", $set) . "\nWHERE " . implode(" AND ", $where) . " LIMIT 1", $location, lang('Item has been updated.'));
+ query_redirect("UPDATE " . idf_escape($_GET["edit"]) . " SET" . implode(",", $set) . "\nWHERE $where LIMIT 1", $location, lang('Item has been updated.'));
} else {
query_redirect("INSERT INTO " . idf_escape($_GET["edit"]) . " SET" . implode(",", $set), $location, lang('Item has been inserted.'));
}
}
}
-page_header((isset($_GET["default"]) ? lang('Default values') : ($_GET["where"] || (isset($_GET["select"]) && !$_POST["clone"]) ? lang('Edit') : lang('Insert'))), $error, array((isset($_GET["default"]) ? "table" : "select") => $_GET["edit"]), $_GET["edit"]);
+
+$table_name = adminer_table_name(table_status($_GET["edit"]));
+page_header(
+ (isset($_GET["default"]) ? lang('Default values') : ($_GET["where"] || (isset($_GET["select"]) && !$_POST["clone"]) ? lang('Edit') : lang('Insert'))),
+ $error,
+ array((isset($_GET["default"]) ? "table" : "select") => array($_GET["edit"], $table_name)),
+ $table_name
+);
unset($row);
if ($_POST["save"]) {
@@ -53,7 +60,7 @@ if ($_POST["save"]) {
}
$row = array();
if ($select) {
- $result = $dbh->query("SELECT " . implode(", ", $select) . " FROM " . idf_escape($_GET["edit"]) . " WHERE " . implode(" AND ", $where) . " LIMIT 1");
+ $result = $dbh->query("SELECT " . implode(", ", $select) . " FROM " . idf_escape($_GET["edit"]) . " WHERE $where LIMIT 1");
$row = $result->fetch_assoc();
$result->free();
}
@@ -66,7 +73,7 @@ if ($fields) {
unset($create);
echo "
\n";
foreach ($fields as $name => $field) {
- echo "" . $adminer->field_name($fields, $name) . " ";
+ echo "" . adminer_field_name($fields, $name) . " ";
$value = (isset($row)
? (strlen($row[$name]) && ($field["type"] == "enum" || $field["type"] == "set") ? intval($row[$name]) : $row[$name])
: ($_POST["clone"] && $field["auto_increment"] ? "" : ($where ? $field["default"] : false))
diff --git a/adminer/editing.js b/adminer/editing.js
index 98df0498..a4dc4065 100644
--- a/adminer/editing.js
+++ b/adminer/editing.js
@@ -1,5 +1,23 @@
// Adminer specific functions
+function body_load() {
+ var script = document.createElement('script');
+ script.src = '../externals/jush/jush.js';
+ script.onload = function () {
+ jush.style('../externals/jush/jush.css');
+ jush.highlight_tag('pre');
+ jush.highlight_tag('code');
+ }
+ script.onreadystatechange = function () {
+ if (script.readyState == 'loaded' || script.readyState == 'complete') {
+ script.onload();
+ }
+ }
+ document.body.appendChild(script);
+}
+
+
+
var added = '.', row_count;
function re_escape(s) {
diff --git a/adminer/functions.js b/adminer/functions.js
index 3c2fd363..9c2e62f0 100644
--- a/adminer/functions.js
+++ b/adminer/functions.js
@@ -13,22 +13,6 @@ function verify_version(version) {
document.body.appendChild(script);
}
-function load_jush() {
- var script = document.createElement('script');
- script.src = '../externals/jush/jush.js';
- script.onload = function () {
- jush.style('../externals/jush/jush.css');
- jush.highlight_tag('pre');
- jush.highlight_tag('code');
- }
- script.onreadystatechange = function () {
- if (script.readyState == 'loaded' || script.readyState == 'complete') {
- script.onload();
- }
- }
- document.body.appendChild(script);
-}
-
function form_check(el, name) {
var elems = el.form.elements;
for (var i=0; i < elems.length; i++) {
diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php
index 08100477..fe94acf4 100644
--- a/adminer/include/adminer.inc.php
+++ b/adminer/include/adminer.inc.php
@@ -1,35 +1,86 @@
' . lang('Table structure') . '', $table_status);
+}
+
+/** Process and print select query before execution
+* @param string query to be executed
+* @return string
+*/
+function adminer_select_query($query) {
+ global $SELF;
+ // it would be nice if $query can be passed by reference and printed value would be returned but call_user() doesn't allow reference parameters
+ $return = call_adminer('select_query', "", $query);
+ if (!$return) {
+ echo "" . htmlspecialchars($query) . "
" . lang('Edit') . "
\n";
+ return $query;
}
-
- function server() {
- return $_GET["server"];
- }
-
- function username() {
- return $_SESSION["usernames"][$_GET["server"]];
- }
-
- function password() {
- return $_SESSION["passwords"][$_GET["server"]];
- }
-
- function table_name($row) {
- return htmlspecialchars($row["Name"]);
- }
-
- function field_name($fields, $key) {
- return htmlspecialchars($key);
- }
-
- function navigation($missing) {
- global $SELF;
- if ($missing != "auth") {
- $databases = get_databases();
- ?>
+ return $return;
+}
+
+/** Query printed after execution in the message
+* @param string executed query
+* @return string
+*/
+function adminer_message_query($query) {
+ global $SELF;
+ $id = "sql-" . count($_SESSION["messages"]);
+ return call_adminer('message_query', " " . lang('SQL command') . " ', $query);
+}
+
+/** Prints navigation after Adminer title
+* @param string can be "auth" if there is no database connection or "db" if there is no database selected
+* @return bool true if default navigation should be printed
+*/
+function adminer_navigation($missing) {
+ global $SELF;
+ if (call_adminer('navigation', true, $missing) && $missing != "auth") {
+ $databases = get_databases();
+ ?>
" . lang('No tables.') . "\n";
- } else {
- echo "\n";
- foreach ($table_status as $row) {
- echo '' . lang('select') . ' ';
- echo '' . $this->table_name($row) . " \n";
- }
- echo "
\n";
+ if ($missing != "db" && strlen($_GET["db"])) {
+ $table_status = table_status();
+ if (!$table_status) {
+ echo "" . lang('No tables.') . "
\n";
+ } else {
+ echo "\n";
+ foreach ($table_status as $row) {
+ echo '' . lang('select') . ' ';
+ echo '' . adminer_table_name($row) . " \n";
}
- echo '
' . lang('Create new table') . "
\n";
+ echo "\n";
}
+ echo '' . lang('Create new table') . "
\n";
}
}
}
-
-$adminer = (class_exists("Adminer") ? new Adminer : new AdminerBase);
diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php
index 7b539425..79f3699b 100644
--- a/adminer/include/bootstrap.inc.php
+++ b/adminer/include/bootstrap.inc.php
@@ -24,6 +24,9 @@ if (isset($_GET["file"])) {
} elseif ($_GET["file"] == "functions.js") {
header("Content-Type: text/javascript");
?>compile_file('functions.js', 'JSMin::minify')compile_file('editing.js', 'JSMin::minify')
@@ -9,17 +9,17 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
-name(); ?>
-
+
+
-">
+">
-
+
' . htmlspecialchars($_GET["db"]) . ' » ';
}
foreach ($breadcrumb as $key => $val) {
- if (strlen($val)) {
- echo '
' . htmlspecialchars($val) . ' » ';
+ $desc = (is_array($val) ? $val[1] : $val);
+ if (strlen($desc)) {
+ echo '
' . htmlspecialchars($desc) . ' » ';
}
}
}
@@ -57,16 +58,16 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
}
function page_footer($missing = false) {
- global $SELF, $VERSION, $dbh, $adminer;
+ global $SELF, $VERSION, $dbh;
?>
diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php
index 2c71c0c0..96d64fd6 100644
--- a/adminer/include/editing.inc.php
+++ b/adminer/include/editing.inc.php
@@ -58,7 +58,7 @@ function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $forei
>
-"; ?>
+"; ?>
$field) {
diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php
index d95ee7ed..64e050c3 100644
--- a/adminer/include/functions.inc.php
+++ b/adminer/include/functions.inc.php
@@ -73,7 +73,7 @@ function where($where) {
$key = bracket_escape($key, "back");
$return[] = (preg_match('~^[A-Z0-9_]+\\(`(?:[^`]+|``)+`\\)$~', $key) ? $key : idf_escape($key)) . " IS NULL";
}
- return $return;
+ return implode(" AND ", $return);
}
function where_check($val) {
@@ -100,10 +100,9 @@ function redirect($location, $message = null) {
function query_redirect($query, $location, $message, $redirect = true, $execute = true, $failed = false) {
global $dbh, $error, $SELF;
- $id = "sql-" . count($_SESSION["messages"]);
$sql = "";
if ($query) {
- $sql = " " . lang('SQL command') . " " . htmlspecialchars($query) . ' ' . lang('Edit') . ' ';
+ $sql = adminer_message_query($query);
$_SESSION["history"][$_GET["server"]][$_GET["db"]][] = $query;
}
if ($execute) {
@@ -367,3 +366,26 @@ function dump_csv($row) {
}
echo implode(",", $row) . "\n";
}
+
+function is_email($email) {
+ $atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name
+ $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component
+ return eregi("^$atom+(\\.$atom+)*@($domain?\\.)+$domain\$", $email);
+}
+
+function email_header($header) {
+ return chunk_split("=?UTF-8?B?" . base64_encode($header), 67, "\n "); // iconv_mime_encode requires PHP 5, imap_8bit requires IMAP extension
+}
+
+function call_adminer($method, $default, $arg1 = null, $arg2 = null) {
+ static $adminer;
+ if (!isset($adminer)) {
+ $adminer = (class_exists('Adminer') ? new Adminer : false); // user defined class
+ }
+ // maintains original method name in minification
+ if (method_exists($adminer, $method)) {
+ // can use func_get_args() and call_user_func_array()
+ return $adminer->$method($arg1, $arg2);
+ }
+ return $default; //! $default is evaluated even if not neccessary
+}
diff --git a/adminer/include/lang.inc.php b/adminer/include/lang.inc.php
index c0ee3a34..3f26478c 100644
--- a/adminer/include/lang.inc.php
+++ b/adminer/include/lang.inc.php
@@ -1,5 +1,5 @@
'English', // Jakub Vrána - http://php.vrana.cz
diff --git a/adminer/include/mysql.inc.php b/adminer/include/mysql.inc.php
index b44feaa3..e55614a3 100644
--- a/adminer/include/mysql.inc.php
+++ b/adminer/include/mysql.inc.php
@@ -204,9 +204,9 @@ $types = array(
$unsigned = array("unsigned", "zerofill", "unsigned zerofill");
function connect() {
- global $adminer;
$dbh = new Min_DB;
- if ($dbh->connect($adminer->server(), $adminer->username(), $adminer->password())) {
+ $credentials = adminer_credentials();
+ if ($dbh->connect($credentials[0], $credentials[1], $credentials[2])) {
$dbh->query("SET SQL_QUOTE_SHOW_CREATE=1");
$dbh->query("SET NAMES utf8");
return $dbh;
diff --git a/adminer/index.php b/adminer/index.php
index 5c07c190..80efcc17 100644
--- a/adminer/index.php
+++ b/adminer/index.php
@@ -7,21 +7,6 @@
*/
include "./include/bootstrap.inc.php";
-include "./include/version.inc.php";
-include "./include/functions.inc.php";
-include "./include/lang.inc.php";
-include "./lang/$LANG.inc.php";
-include "./include/adminer.inc.php";
-include "./include/design.inc.php";
-if (isset($_GET["coverage"])) {
- include "./coverage.inc.php";
-}
-include "./include/pdo.inc.php";
-include "./include/mysql.inc.php";
-include "./include/auth.inc.php";
-include "./include/connect.inc.php";
-include "./include/editing.inc.php";
-include "./include/export.inc.php";
$enum_length = '\'(?:\'\'|[^\'\\\\]+|\\\\.)*\'|"(?:""|[^"\\\\]+|\\\\.)*"';
$inout = array("IN", "OUT", "INOUT");
@@ -54,7 +39,7 @@ if (isset($_GET["download"])) {
// edit form is used for default values and distinguished by checking isset($_GET["default"]) in edit.inc.php
$_GET["edit"] = $_GET["default"];
}
- if (isset($_GET["select"]) && $_POST && (!$_POST["delete"] && !$_POST["export"] && !$_POST["import"] && !$_POST["save"])) {
+ if (isset($_GET["select"]) && $_POST && (!$_POST["delete"] && !$_POST["export"] && !$_POST["import"] && !$_POST["save"] && !$_POST["email"])) {
// POST form on select page is used to edit or clone data
$_GET["edit"] = $_GET["select"];
}
diff --git a/adminer/lang/cs.inc.php b/adminer/lang/cs.inc.php
index 6fb82aed..5925ba8e 100644
--- a/adminer/lang/cs.inc.php
+++ b/adminer/lang/cs.inc.php
@@ -216,4 +216,9 @@ $translations = array(
'History' => 'Historie',
'Variables' => 'Proměnné',
'Source and target columns must have the same data type and there must be an index on the target columns.' => 'Zdrojové a cílové sloupce musí mít stejný datový typ a nad cílovými sloupci musí být definován index.',
+ 'E-mail' => 'E-mail',
+ 'From' => 'Odesílatel',
+ 'Subject' => 'Předmět',
+ 'Send' => 'Odeslat',
+ '%d e-mail(s) have been sent.' => array('Byl odeslán %d e-mail.', 'Byly odeslány %d e-maily.', 'Bylo odesláno %d e-mailů.'),
);
diff --git a/adminer/lang/en.inc.php b/adminer/lang/en.inc.php
index 414c91a9..d2df76db 100644
--- a/adminer/lang/en.inc.php
+++ b/adminer/lang/en.inc.php
@@ -7,4 +7,5 @@ $translations = array(
'%d row(s)' => array('%d row', '%d rows'),
'%d item(s) have been affected.' => array('%d item have been affected.', '%d items have been affected.'),
'%d row(s) has been imported.' => array('%d row has been imported.', '%d rows has been imported.'),
+ '%d e-mail(s) have been sent.' => array('%d e-mail has been sent.', '%d e-mails have been sent.'),
);
diff --git a/adminer/select.inc.php b/adminer/select.inc.php
index 2d6b3f47..afb2ffd1 100644
--- a/adminer/select.inc.php
+++ b/adminer/select.inc.php
@@ -13,7 +13,7 @@ $columns = array(); // selectable columns
unset($text_length);
foreach ($fields as $key => $field) {
if (isset($field["privileges"]["select"])) {
- $columns[] = $key;
+ $columns[$key] = adminer_field_name($fields, $key); //! numeric $key is problematic in optionlist()
if (preg_match('~text|blob~', $field["type"])) {
$text_length = (isset($_GET["text_length"]) ? $_GET["text_length"] : "100");
}
@@ -24,8 +24,8 @@ foreach ($fields as $key => $field) {
$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" || (in_array($val["col"], $columns, true) && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
- $select[$key] = (in_array($val["col"], $columns, true) ? (!$val["fun"] ? idf_escape($val["col"]) : ($val["fun"] == "distinct" ? "COUNT(DISTINCT " : strtoupper("$val[fun](")) . idf_escape($val["col"]) . ")") : "COUNT(*)");
+ if ($val["fun"] == "count" || (isset($columns[$val["col"]]) && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
+ $select[$key] = (isset($columns[$val["col"]]) ? ($val["fun"] ? ($val["fun"] == "distinct" ? "COUNT(DISTINCT " : strtoupper("$val[fun](")) . idf_escape($val["col"]) . ")" : idf_escape($val["col"])) : "COUNT(*)");
if (!in_array($val["fun"], $grouping)) {
$group[] = $select[$key];
}
@@ -61,7 +61,7 @@ foreach ((array) $_GET["where"] as $val) {
}
$order = array(); // order expressions - will be joined by comma
foreach ((array) $_GET["order"] as $key => $val) {
- if (in_array($val, $columns, true) || in_array($val, $select, true)) {
+ if (isset($columns[$val]) || in_array($val, $select, true)) {
$order[] = idf_escape($val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
}
}
@@ -77,7 +77,7 @@ if ($_POST && !$error) {
$union = array();
foreach ($_POST["check"] as $val) {
// where may not be unique so OR can't be used
- $union[] = "(SELECT $from " . ($where ? "AND " : "WHERE ") . implode(" AND ", where_check($val)) . $group_by . " LIMIT 1)";
+ $union[] = "(SELECT $from " . ($where ? "AND " : "WHERE ") . where_check($val) . $group_by . " LIMIT 1)";
}
dump_data($_GET["select"], "INSERT", implode(" UNION ALL ", $union));
} else {
@@ -85,7 +85,18 @@ if ($_POST && !$error) {
}
exit;
}
- if (!$_POST["import"]) { // edit
+ if ($_POST["email"]) {
+ $sent = 0;
+ if ($_POST["all"] || $_POST["check"]) {
+ $field = idf_escape($_POST["email_field"]);
+ $result = $dbh->query("SELECT DISTINCT $field FROM " . idf_escape($_GET["select"]) . " WHERE $field IS NOT NULL AND $field != ''" . ($where ? " AND " . implode(" AND ", $where) : "") . ($_POST["all"] ? "" : " AND ((" . implode(") OR (", array_map('where_check', $_POST["check"])) . "))"));
+ while ($row = $result->fetch_row()) {
+ $sent += mail($row[0], email_header($_POST["email_subject"]), $_POST["email_message"], "MIME-Version: 1.0\nContent-Type: text/plain; charset=utf-8\nContent-Transfer-Encoding: 8bit" . ($_POST["email_from"] ? "\nFrom: " . email_header($_POST["email_from"]) : ""));
+ }
+ $result->free();
+ }
+ redirect(remove_from_uri(), lang('%d e-mail(s) have been sent.', $sent));
+ } elseif (!$_POST["import"]) { // edit
$result = true;
$affected = 0;
$command = ($_POST["delete"] ? ($_POST["all"] && !$where ? "TRUNCATE " : "DELETE FROM ") : ($_POST["clone"] ? "INSERT INTO " : "UPDATE ")) . idf_escape($_GET["select"]);
@@ -107,9 +118,8 @@ if ($_POST && !$error) {
$affected = $dbh->affected_rows;
} else {
foreach ((array) $_POST["check"] as $val) {
- parse_str($val, $check);
// where may not be unique so OR can't be used
- $result = queries($command . "\nWHERE " . implode(" AND ", where($check)) . " LIMIT 1");
+ $result = queries($command . "\nWHERE " . where_check($val) . " LIMIT 1");
if (!$result) {
break;
}
@@ -143,14 +153,15 @@ if ($_POST && !$error) {
$error = lang('Unable to upload a file.');
}
}
-page_header(lang('Select') . ": " . $adminer->table_name($table_status), $error);
+
+page_header(lang('Select') . ": " . adminer_table_name($table_status), $error);
echo "";
if (isset($rights["insert"])) {
//! pass search values forth and back
echo '' . lang('New item') . ' ';
}
-echo '' . lang('Table structure') . ' ';
+echo adminer_select_links($table_status);
echo "
\n";
if (!$columns) {
@@ -202,7 +213,7 @@ if (!$columns) {
echo '' . lang('Sort') . " 1 ? "" : " class='hidden'") . ">\n";
$i = 0;
foreach ((array) $_GET["order"] as $key => $val) {
- if (in_array($val, $columns, true)) {
+ if (isset($columns[$val])) {
echo "
" . optionlist($columns, $val) . " ";
echo " " . lang('descending') . "
\n";
$i++;
@@ -228,7 +239,7 @@ if (!$columns) {
echo "\n";
$query = "SELECT " . (count($group) < count($select) ? "SQL_CALC_FOUND_ROWS " : "") . $from . $group_by . (strlen($limit) ? " LIMIT " . intval($limit) . (intval($_GET["page"]) ? " OFFSET " . ($limit * $_GET["page"]) : "") : "");
- echo "
" . htmlspecialchars($query) . "
" . lang('Edit') . "
\n";
+ $query = adminer_select_query($query);
$result = $dbh->query($query);
if (!$result) {
@@ -245,18 +256,23 @@ if (!$columns) {
}
}
+ $email_fields = array();
+
echo "
\n";
for ($j=0; $row = $result->fetch_assoc(); $j++) {
if (!$j) {
echo ' ';
foreach ($row as $key => $val) {
- echo '' . $adminer->field_name($fields, $key) . ' ';
+ echo '' . adminer_field_name($fields, $key) . ' ';
}
echo " \n";
}
$unique_idf = implode('&', unique_idf($row, $indexes)); //! don't use aggregation functions
echo ' ' . (count($select) != count($group) || information_schema($_GET["db"]) ? '' : ' ' . lang('edit') . ' ') . ' ';
foreach ($row as $key => $val) {
+ if (strlen($val) && (!isset($email_fields[$key]) || $email_fields[$key])) {
+ $email_fields[$key] = is_email($val); //! filled e-mails may be contained on other pages
+ }
if (!isset($val)) {
$val = "NULL ";
} elseif (preg_match('~blob|binary~', $fields[$key]["type"]) && !is_utf8($val)) {
@@ -319,6 +335,19 @@ if (!$columns) {
}
$result->free();
echo "" . lang('CSV Import') . "
\n";
+
+ //! Editor only
+ $email_fields = array_filter($email_fields);
+ if ($email_fields) {
+ echo '' . lang('E-mail') . " \n";
+ }
+
echo "\n";
}
}
diff --git a/adminer/user.inc.php b/adminer/user.inc.php
index 5c59af8c..cafaba16 100644
--- a/adminer/user.inc.php
+++ b/adminer/user.inc.php
@@ -107,7 +107,7 @@ if ($_POST && !$error) {
}
}
}
-page_header((isset($_GET["host"]) ? lang('Username') . ": " . htmlspecialchars("$_GET[user]@$_GET[host]") : lang('Create user')), $error, array("privileges" => lang('Privileges')));
+page_header((isset($_GET["host"]) ? lang('Username') . ": " . htmlspecialchars("$_GET[user]@$_GET[host]") : lang('Create user')), $error, array("privileges" => array('', lang('Privileges'))));
if ($_POST) {
$row = $_POST;
diff --git a/changes.txt b/changes.txt
index 9a74275c..ba173e39 100644
--- a/changes.txt
+++ b/changes.txt
@@ -1,5 +1,7 @@
Adminer 1.12.0:
Editor: User friendly data editor
+Customization: Adminer class
+E-mail sending
Create single column foreign key in table structure
Adminer 1.11.1 (released 2009-07-03):
diff --git a/compile.php b/compile.php
index 26da6b05..73eb3b51 100644
--- a/compile.php
+++ b/compile.php
@@ -17,43 +17,23 @@ function remove_lang($match) {
}
$lang_ids = array(); // global variable simplifies usage in a callback function
+
function lang_ids($match) {
global $lang_ids;
- return 'lang(' . $lang_ids[stripslashes($match[1])] . $match[2];
+ $lang_id = &$lang_ids[stripslashes($match[1])];
+ if (!isset($lang_id)) {
+ $lang_id = count($lang_ids) - 1;
+ }
+ return ($_COOKIE["adminer_lang"] ? $match[0] : "lang($lang_id$match[2]");
}
function put_file($match) {
- global $lang_ids, $project;
+ global $project;
if (basename($match[2]) == '$LANG.inc.php') {
- if ($_COOKIE["adminer_lang"]) {
- return "";
- }
- $return = "";
- foreach (glob(dirname(__FILE__) . "/$project/lang/*.inc.php") as $filename) {
- // assign translation numbers
- include $filename;
- foreach ($translations as $key => $val) {
- if (!isset($lang_ids[$key])) {
- $lang_ids[$key] = count($lang_ids);
- }
- }
- }
- foreach (glob(dirname(__FILE__) . "/$project/lang/*.inc.php") as $filename) {
- include $filename; // reassign $translations
- $translation_ids = array_flip($lang_ids);
- foreach ($translations as $key => $val) {
- $translation_ids[$lang_ids[$key]] = $val;
- }
- $return .= 'case "' . basename($filename, '.inc.php') . '": $translations = array(';
- foreach ($translation_ids as $val) {
- $return .= (is_array($val) ? "array('" . implode("', '", array_map('add_apo_slashes', $val)) . "')" : "'" . add_apo_slashes($val) . "'") . ", ";
- }
- $return = substr($return, 0, -2) . "); break;\n";
- }
- return "switch (\$LANG) {\n$return}\n";
+ return $match[0]; // processed later
}
$return = file_get_contents(dirname(__FILE__) . "/$project/$match[2]");
- if ($match[2] != "./include/lang.inc.php" || !$_COOKIE["adminer_lang"]) {
+ if (basename($match[2]) != "lang.inc.php" || !$_COOKIE["adminer_lang"]) {
$tokens = token_get_all($return); // to find out the last token
return "?>\n$return" . (in_array($tokens[count($tokens) - 1][0], array(T_CLOSE_TAG, T_INLINE_HTML), true) ? " $val) {
+ if (isset($val)) {
+ $translation_ids[$lang_ids[$key]] = $val;
+ }
+ }
+ $return .= "\tcase \"" . basename($filename, '.inc.php') . '": $translations = array(';
+ foreach ($translation_ids as $val) {
+ $return .= (is_array($val) ? "array('" . implode("', '", array_map('add_apo_slashes', $val)) . "')" : "'" . add_apo_slashes($val) . "'") . ", ";
+ }
+ $return = substr($return, 0, -2) . "); break;\n";
+ }
+ return "switch (\$LANG) {\n$return}\n";
+}
+
function short_identifier($number, $chars) {
$return = '';
while ($number >= 0) {
@@ -113,13 +116,17 @@ function php_shrink($input) {
$space = '';
$output = '';
$in_echo = false;
+ $doc_comment = false; // include only first /**
for (reset($tokens); list($i, $token) = each($tokens); ) {
if (!is_array($token)) {
$token = array(0, $token);
}
- if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE) {
+ if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) {
$space = "\n";
} else {
+ if ($token[0] == T_DOC_COMMENT) {
+ $doc_comment = true;
+ }
if ($token[0] == T_VAR) {
$shortening = false;
} elseif (!$shortening) {
@@ -186,14 +193,15 @@ $filename = $project . ($_COOKIE["adminer_lang"] ? "-$_COOKIE[adminer_lang]" : "
$file = file_get_contents(dirname(__FILE__) . "/$project/index.php");
$file = preg_replace('(' . str_replace(' ', '\\s*', preg_quote(' if (isset($_GET["coverage"])) { include "./coverage.inc.php"; }')) . ')', '', $file);
$file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file);
+$file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php
$file = preg_replace("~if \\(isset\\(\\\$_SESSION\\[\"coverage.*\n}\n| && !isset\\(\\\$_SESSION\\[\"coverage\"\\]\\)~sU", '', $file);
+$file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file);
+$file = preg_replace_callback('~\\b(include|require) "([^"]*\\$LANG.inc.php)";~', 'put_file_lang', $file);
if ($_COOKIE["adminer_lang"]) {
// single language version
$file = preg_replace_callback("~(<\\?php\\s*echo )?lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])(;\\s*\\?>)?~s", 'remove_lang', $file);
$file = str_replace("\n", "", $file);
$file = str_replace('', $_COOKIE["adminer_lang"], $file);
-} else {
- $file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file);
}
$file = preg_replace_callback("~compile_file\\('([^']+)', '([^']+)'\\)~", 'compile_file', $file); // integrate static files
$replace = 'htmlspecialchars(preg_replace("~\\\\\\\\?.*~", "", $_SERVER["REQUEST_URI"])) . "?file=\\1&version=' . $VERSION;
diff --git a/editor/db.inc.php b/editor/db.inc.php
index 8e61d318..b8529a09 100644
--- a/editor/db.inc.php
+++ b/editor/db.inc.php
@@ -1,2 +1,2 @@
$val) {
+ $on[] = "`t0`." . idf_escape($val) . " = `t$i`." . idf_escape($foreign_key["target"][$key]);
+ }
+ //~ $join .= "\nLEFT JOIN " . idf_escape($foreign_key["table"]) . " AS `t$i` ON " . implode(" AND ", $on);
+ //! use in select
+ $i++;
}
-
- function server() {
- return "";
+ $query = preg_replace("~((?:[^'`]*|'(?:[^'\\\\]*|\\\\.)+')+)(`((?:[^`]+|``)*)`)~", '\\1`t0`.\\2', $query); // don't match ` inside ''
+ $query = preg_replace('~ FROM `t0`.(`((?:[^`]+|``)*)`) ?~', "\nFROM \\1 AS `t0`" . addcslashes($join, '\\$') . "\n", $query);
+ $return = call_adminer('select_query', "", $query);
+ if (!$return) {
+ echo "\n";
+ return $query;
}
-
- function username() {
- return "";
- }
-
- function password() {
- return "";
- }
-
- function table_name($row) {
- return htmlspecialchars(strlen($row["Comment"]) ? $row["Comment"] : $row["Name"]);
- }
-
- function field_name($fields, $key) {
- return htmlspecialchars(strlen($fields[$key]["comment"]) ? $fields[$key]["comment"] : $key);
- }
-
- function navigation($missing) {
- global $SELF;
- if ($missing != "auth") {
- ?>
+ return $return;
+}
+
+function adminer_message_query($query) {
+ return call_adminer('message_query', "", $query);
+}
+
+function adminer_navigation($missing) {
+ global $SELF;
+ if (call_adminer('navigation', true, $missing) && $missing != "auth") {
+ ?>
" . lang('No tables.') . "\n";
- } else {
- echo "\n";
- foreach ($table_status as $row) {
- echo '' . $this->table_name($row) . " \n";
+ if ($missing != "db") {
+ $table_status = table_status();
+ if (!$table_status) {
+ echo "
" . lang('No tables.') . "
\n";
+ } else {
+ echo "\n";
+ foreach ($table_status as $row) {
+ if (isset($row["Engine"])) { // ignore views
+ echo '' . adminer_table_name($row) . " \n";
}
- echo "
\n";
}
+ echo "\n";
}
}
}
}
-
-$adminer = (class_exists("Adminer") ? new Adminer : new AdminerBase);
diff --git a/editor/include/connect.inc.php b/editor/include/connect.inc.php
index d542a14f..f1d3f89d 100644
--- a/editor/include/connect.inc.php
+++ b/editor/include/connect.inc.php
@@ -1,3 +1,3 @@
select_db($_GET["db"]);
+$_GET["db"] = ""; // used here and there by Adminer
+$dbh->select_db(adminer_database());
diff --git a/editor/include/editing.inc.php b/editor/include/editing.inc.php
new file mode 100644
index 00000000..b3d9bbc7
--- /dev/null
+++ b/editor/include/editing.inc.php
@@ -0,0 +1 @@
+ array('%d row', '%d rows'),
'%d item(s) have been affected.' => array('%d item have been affected.', '%d items have been affected.'),
'%d row(s) has been imported.' => array('%d row has been imported.', '%d rows has been imported.'),
+ '%d e-mail(s) have been sent.' => array('%d e-mail has been sent.', '%d e-mails have been sent.'),
);
diff --git a/lang.php b/lang.php
index b43c277d..f7a204e5 100644
--- a/lang.php
+++ b/lang.php
@@ -14,7 +14,7 @@ if (isset($_SERVER["argv"][1])) {
}
}
-preg_match_all('~\\b(include|require) "([^"]*)";~', file_get_contents(dirname(__FILE__) . "/$project/index.php"), $matches);
+preg_match_all('~\\b(include|require) "([^"]*)";~', file_get_contents(dirname(__FILE__) . "/$project/index.php") . file_get_contents(dirname(__FILE__) . "/adminer/include/bootstrap.inc.php"), $matches);
$filenames = $matches[2];
$filenames[] = "index.php";