adminer-4.8.1/000077500000000000000000000000001404740645700131565ustar00rootroot00000000000000adminer-4.8.1/.github/000077500000000000000000000000001404740645700145165ustar00rootroot00000000000000adminer-4.8.1/.github/FUNDING.yml000066400000000000000000000001121404740645700163250ustar00rootroot00000000000000patreon: jakubvrana custom: ["https://sourceforge.net/p/adminer/donate/"] adminer-4.8.1/.github/workflows/000077500000000000000000000000001404740645700165535ustar00rootroot00000000000000adminer-4.8.1/.github/workflows/codeql-analysis.yml000066400000000000000000000044751404740645700224000ustar00rootroot00000000000000# For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: branches: [ master ] pull_request: # The branches below must be a subset of the branches above branches: [ master ] schedule: - cron: '20 16 * * 0' jobs: analyze: name: Analyze runs-on: ubuntu-latest strategy: fail-fast: false matrix: language: [ 'javascript' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - name: Checkout repository uses: actions/checkout@v2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 adminer-4.8.1/.travis.yml000066400000000000000000000003101404740645700152610ustar00rootroot00000000000000language: php php: - 5.6 - 7.1 - 7.2 - 7.3 - 7.4 - 8.0 script: git diff --name-only $TRAVIS_COMMIT_RANGE | grep '\.php$' | xargs -n1 -P8 php -l | grep -v 'No syntax errors'; test $? -eq 1 adminer-4.8.1/Makefile000066400000000000000000000011061404740645700146140ustar00rootroot00000000000000ROOT_DIRECTORY = $(shell dirname "$(realpath $(lastword $(MAKEFILE_LIST)))") PHP := $(shell which php) PORT := 8000 .DEFAULT_GOAL := default .PHONY: default default: compile .PHONY: compile compile: $(PHP) $(ROOT_DIRECTORY)/compile.php .PHONY: server server: php \ --server 127.0.0.1:$(PORT) \ --docroot $(ROOT_DIRECTORY) .PHONY: initialize initialize: git \ -C $(ROOT_DIRECTORY) \ submodule \ update \ --init \ --recursive .PHONY: clean clean: rm \ --recursive \ --force \ $(ROOT_DIRECTORY)/adminer.php .PHONY: clean.all clean.all: clean adminer-4.8.1/SECURITY.md000066400000000000000000000010601404740645700147440ustar00rootroot00000000000000# Security Policy ## Supported Versions I support only the last published version and the last development version (last commit). ## Reporting a Vulnerability To report a vulnerability, create a private bug at https://sourceforge.net/p/adminer/bugs-and-features/new/?private=1. I handle security issues with top priority. If you don't hear from me in a week then please ping the bug. Once I accept the bug, the fix should be available and new version released within days. I will mark the bug as public after releasing a new version or declining the bug. adminer-4.8.1/adminer/000077500000000000000000000000001404740645700145755ustar00rootroot00000000000000adminer-4.8.1/adminer/call.inc.php000066400000000000000000000047751404740645700170060ustar00rootroot00000000000000 $field) { if (substr($field["inout"], -3) == "OUT") { $out[$i] = "@" . idf_escape($field["field"]) . " AS " . idf_escape($field["field"]); } if (!$field["inout"] || substr($field["inout"], 0, 2) == "IN") { $in[] = $i; } } if (!$error && $_POST) { $call = array(); foreach ($routine["fields"] as $key => $field) { if (in_array($key, $in)) { $val = process_input($field); if ($val === false) { $val = "''"; } if (isset($out[$key])) { $connection->query("SET @" . idf_escape($field["field"]) . " = $val"); } } $call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val); } $query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")"; $start = microtime(true); $result = $connection->multi_query($query); $affected = $connection->affected_rows; // getting warnigns overwrites this echo $adminer->selectQuery($query, $start, !$result); if (!$result) { echo "

" . error() . "\n"; } else { $connection2 = connect(); if (is_object($connection2)) { $connection2->select_db(DB); } do { $result = $connection->store_result(); if (is_object($result)) { select($result, $connection2); } else { echo "

" . lang('Routine has been called, %d row(s) affected.', $affected) . " " . @date("H:i:s") . "\n" // @ - time zone may be not set ; } } while ($connection->next_result()); if ($out) { select($connection->query("SELECT " . implode(", ", $out))); } } } ?>

\n"; foreach ($in as $key) { $field = $routine["fields"][$key]; $name = $field["field"]; echo "" . $adminer->fieldName($field); $value = $_POST["fields"][$name]; if ($value != "") { if ($field["type"] == "enum") { $value = +$value; } if ($field["type"] == "set") { $value = array_sum($value); } } input($field, $value, (string) $_POST["function"][$name]); // param name can be empty echo "\n"; } echo "\n"; } ?>

adminer-4.8.1/adminer/create.inc.php000066400000000000000000000222601404740645700173230ustar00rootroot00000000000000 $field) { $foreign_keys[str_replace("`", "``", $table_name) . "`" . str_replace("`", "``", $field["field"])] = $table_name; // not idf_escape() - used in JS } $orig_fields = array(); $table_status = array(); if ($TABLE != "") { $orig_fields = fields($TABLE); $table_status = table_status($TABLE); if (!$table_status) { $error = lang('No tables.'); } } $row = $_POST; $row["fields"] = (array) $row["fields"]; if ($row["auto_increment_col"]) { $row["fields"][$row["auto_increment_col"]]["auto_increment"] = true; } if ($_POST) { set_adminer_settings(array("comments" => $_POST["comments"], "defaults" => $_POST["defaults"])); } if ($_POST && !process_fields($row["fields"]) && !$error) { if ($_POST["drop"]) { queries_redirect(substr(ME, 0, -1), lang('Table has been dropped.'), drop_tables(array($TABLE))); } else { $fields = array(); $all_fields = array(); $use_all_fields = false; $foreign = array(); $orig_field = reset($orig_fields); $after = " FIRST"; foreach ($row["fields"] as $key => $field) { $foreign_key = $foreign_keys[$field["type"]]; $type_field = ($foreign_key !== null ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined type if ($field["field"] != "") { if (!$field["has_default"]) { $field["default"] = null; } if ($key == $row["auto_increment_col"]) { $field["auto_increment"] = true; } $process_field = process_field($field, $type_field); $all_fields[] = array($field["orig"], $process_field, $after); if (!$orig_field || $process_field != process_field($orig_field, $orig_field)) { $fields[] = array($field["orig"], $process_field, $after); if ($field["orig"] != "" || $after) { $use_all_fields = true; } } if ($foreign_key !== null) { $foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . format_foreign_key(array( 'table' => $foreign_keys[$field["type"]], 'source' => array($field["field"]), 'target' => array($type_field["field"]), 'on_delete' => $field["on_delete"], )); } $after = " AFTER " . idf_escape($field["field"]); } elseif ($field["orig"] != "") { $use_all_fields = true; $fields[] = array($field["orig"]); } if ($field["orig"] != "") { $orig_field = next($orig_fields); if (!$orig_field) { $after = ""; } } } $partitioning = ""; if ($partition_by[$row["partition_by"]]) { $partitions = array(); if ($row["partition_by"] == 'RANGE' || $row["partition_by"] == 'LIST') { foreach (array_filter($row["partition_names"]) as $key => $val) { $value = $row["partition_values"][$key]; $partitions[] = "\n PARTITION " . idf_escape($val) . " VALUES " . ($row["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection } } $partitioning .= "\nPARTITION BY $row[partition_by]($row[partition])" . ($partitions // $row["partition"] can be expression, not only column ? " (" . implode(",", $partitions) . "\n)" : ($row["partitions"] ? " PARTITIONS " . (+$row["partitions"]) : "") ); } elseif (support("partitioning") && preg_match("~partitioned~", $table_status["Create_options"])) { $partitioning .= "\nREMOVE PARTITIONING"; } $message = lang('Table has been altered.'); if ($TABLE == "") { cookie("adminer_engine", $row["Engine"]); $message = lang('Table has been created.'); } $name = trim($row["name"]); queries_redirect(ME . (support("table") ? "table=" : "select=") . urlencode($name), $message, alter_table( $TABLE, $name, ($jush == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields), $foreign, ($row["Comment"] != $table_status["Comment"] ? $row["Comment"] : null), ($row["Engine"] && $row["Engine"] != $table_status["Engine"] ? $row["Engine"] : ""), ($row["Collation"] && $row["Collation"] != $table_status["Collation"] ? $row["Collation"] : ""), ($row["Auto_increment"] != "" ? number($row["Auto_increment"]) : ""), $partitioning )); } } page_header(($TABLE != "" ? lang('Alter table') : lang('Create table')), $error, array("table" => $TABLE), h($TABLE)); if (!$_POST) { $row = array( "Engine" => $_COOKIE["adminer_engine"], "fields" => array(array("field" => "", "type" => (isset($types["int"]) ? "int" : (isset($types["integer"]) ? "integer" : "")), "on_update" => "")), "partition_names" => array(""), ); if ($TABLE != "") { $row = $table_status; $row["name"] = $TABLE; $row["fields"] = array(); if (!$_GET["auto_increment"]) { // don't prefill by original Auto_increment for the sake of performance and not reusing deleted ids $row["Auto_increment"] = ""; } foreach ($orig_fields as $field) { $field["has_default"] = isset($field["default"]); $row["fields"][] = $field; } if (support("partitioning")) { $from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($TABLE); $result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row(); $partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION"); $partitions[""] = ""; $row["partition_names"] = array_keys($partitions); $row["partition_values"] = array_values($partitions); } } } $collations = collations(); $engines = engines(); // case of engine may differ foreach ($engines as $engine) { if (!strcasecmp($engine, $row["Engine"])) { $row["Engine"] = $engine; break; } } ?>

: " autocapitalize="off"> " . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "" . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?> "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>

: "> ' : '') ; ?>

" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?> (">) : " value=""> > $val) { echo ''; echo '

adminer-4.8.1/adminer/database.inc.php000066400000000000000000000057001404740645700176240ustar00rootroot00000000000000

' . h($name) . '
' : '' ) . "\n" . ($collations ? html_select("collation", array("" => "(" . lang('collation') . ")") + $collations, $row["collation"]) . doc_link(array( 'sql' => "charset-charsets.html", 'mariadb' => "supported-character-sets-and-collations/", 'mssql' => "ms187963.aspx", )) : ""); echo script("focus(qs('#name'));"); ?> " . confirm(lang('Drop %s?', DB)) . "\n"; } elseif (!$_POST["add_x"] && $_GET["db"] == "") { echo "\n"; } ?>

adminer-4.8.1/adminer/db.inc.php000066400000000000000000000305461404740645700164530ustar00rootroot00000000000000 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) { queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once } if ($_POST["truncate"]) { if ($_POST["tables"]) { $result = truncate_tables($_POST["tables"]); } $message = lang('Tables have been truncated.'); } elseif ($_POST["move"]) { $result = move_tables((array) $_POST["tables"], (array) $_POST["views"], $_POST["target"]); $message = lang('Tables have been moved.'); } elseif ($_POST["copy"]) { $result = copy_tables((array) $_POST["tables"], (array) $_POST["views"], $_POST["target"]); $message = lang('Tables have been copied.'); } 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 ($jush != "sql") { $result = ($jush == "sqlite" ? queries("VACUUM") : apply_queries("VACUUM" . ($_POST["optimize"] ? "" : " ANALYZE"), $_POST["tables"]) ); $message = lang('Tables have been optimized.'); } elseif (!$_POST["tables"]) { $message = lang('No tables.'); } elseif ($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"]) . ": " . h($row["Msg_text"]) . "
"; } } queries_redirect(substr(ME, 0, -1), $message, $result); } page_header(($_GET["ns"] == "" ? lang('Database') . ": " . h(DB) : lang('Schema') . ": " . h($_GET["ns"])), $error, true); if ($adminer->homepage()) { if ($_GET["ns"] !== "") { echo "

" . lang('Tables and views') . "

\n"; $tables_list = tables_list(); if (!$tables_list) { echo "

" . lang('No tables.') . "\n"; } else { echo "

\n"; if (support("table")) { echo "
" . lang('Search data in tables') . "
"; echo ""; echo script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');", ""); echo " \n"; echo "
\n"; if ($_POST["search"] && $_POST["query"] != "") { $_GET["where"][0]["op"] = "LIKE %%"; search_tables(); } } echo "
\n"; echo "\n"; echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"); echo ''; echo '\n"; $tables = 0; foreach ($tables_list as $name => $type) { $view = ($type !== null && !preg_match('~table|sequence~i', $type)); $id = h("Table-" . $name); echo '
' . script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);", ""); echo '' . lang('Table'); echo '' . lang('Engine') . doc_link(array('sql' => 'storage-engines.html')); echo '' . lang('Collation') . doc_link(array('sql' => 'charset-charsets.html', 'mariadb' => 'supported-character-sets-and-collations/')); echo '' . lang('Data Length') . doc_link(array('sql' => 'show-table-status.html', 'pgsql' => 'functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT', 'oracle' => 'REFRN20286')); echo '' . lang('Index Length') . doc_link(array('sql' => 'show-table-status.html', 'pgsql' => 'functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT')); echo '' . lang('Data Free') . doc_link(array('sql' => 'show-table-status.html')); echo '' . lang('Auto Increment') . doc_link(array('sql' => 'example-auto-increment.html', 'mariadb' => 'auto_increment/')); echo '' . lang('Rows') . doc_link(array('sql' => 'show-table-status.html', 'pgsql' => 'catalog-pg-class.html#CATALOG-PG-CLASS', 'oracle' => 'REFRN20286')); echo (support("comment") ? '' . lang('Comment') . doc_link(array('sql' => 'show-table-status.html', 'pgsql' => 'functions-info.html#FUNCTIONS-INFO-COMMENT-TABLE')) : ''); echo "
' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "", "", $id); echo '' . (support("table") || support("indexes") ? "" . h($name) . '' : h($name)); if ($view) { echo '' . (preg_match('~materialized~i', $type) ? lang('Materialized view') : lang('View')) . ''; echo '?'; } else { foreach (array( "Engine" => array(), "Collation" => array(), "Data_length" => array("create", lang('Alter table')), "Index_length" => array("indexes", lang('Alter indexes')), "Data_free" => array("edit", lang('New item')), "Auto_increment" => array("auto_increment=1&create", lang('Alter table')), "Rows" => array("select", lang('Select data')), ) as $key => $link) { $id = " id='$key-" . h($name) . "'"; echo ($link ? "" . (support("table") || $key == "Rows" || (support("indexes") && $key != "Data_length") ? "?" : "?" ) : ""); } $tables++; } echo (support("comment") ? "" : ""); } echo "
" . lang('%d in total', count($tables_list)); echo "" . h($jush == "sql" ? $connection->result("SELECT @@default_storage_engine") : ""); echo "" . h(db_collation(DB, collations())); foreach (array("Data_length", "Index_length", "Data_free") as $key) { echo ""; } echo "
\n"; echo "
\n"; if (!information_schema(DB)) { echo "\n"; } echo "
\n"; echo script("tableCheck();"); } echo '

" . lang('Routines') . "

\n"; $routines = routines(); if ($routines) { echo "\n"; echo '\n"; odd(''); foreach ($routines as $row) { $name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"])); // not computed on the pages to be able to print the header first echo ''; echo '
' . lang('Name') . '' . lang('Type') . '' . lang('Return type') . "
' . h($row["ROUTINE_NAME"]) . ''; echo '' . h($row["ROUTINE_TYPE"]); echo '' . h($row["DTD_IDENTIFIER"]); echo '' . lang('Alter') . ""; } echo "
\n"; } echo '

" . lang('Sequences') . "

\n"; $sequences = get_vals("SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = current_schema() ORDER BY sequence_name"); if ($sequences) { echo "\n"; echo "\n"; odd(''); foreach ($sequences as $val) { echo "
" . lang('Name') . "
" . h($val) . "\n"; } echo "
\n"; } echo "

" . lang('User types') . "

\n"; $user_types = types(); if ($user_types) { echo "\n"; echo "\n"; odd(''); foreach ($user_types as $val) { echo "
" . lang('Name') . "
" . h($val) . "\n"; } echo "
\n"; } echo "

" . lang('Events') . "

\n"; $rows = get_rows("SHOW EVENTS"); if ($rows) { echo "\n"; echo "\n"; foreach ($rows as $row) { echo ""; echo "
" . lang('Name') . "" . lang('Schedule') . "" . lang('Start') . "" . lang('End') . "
" . h($row["Name"]); echo "" . ($row["Execute at"] ? lang('At given time') . "" . $row["Execute at"] : lang('Every') . " " . $row["Interval value"] . " " . $row["Interval field"] . "$row[Starts]"); echo "$row[Ends]"; echo '' . lang('Alter') . ''; } echo "
\n"; $event_scheduler = $connection->result("SELECT @@event_scheduler"); if ($event_scheduler && $event_scheduler != "ON") { echo "

event_scheduler: " . h($event_scheduler) . "\n"; } } echo '

"text", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT"); } if (!isset($row["events"])) { // backwards compatibility $row["routines"] = $row["events"] = ($_GET["dump"] == ""); $row["triggers"] = $row["table_style"]; } echo "
" . lang('Output') . "" . html_select("output", $adminer->dumpOutput(), $row["output"], 0) . "\n"; // 0 - radio echo "
" . lang('Format') . "" . html_select("format", $adminer->dumpFormat(), $row["format"], 0) . "\n"; // 0 - radio echo ($jush == "sqlite" ? "" : "
" . lang('Database') . "" . html_select('db_style', $db_style, $row["db_style"]) . (support("routine") ? checkbox("routines", 1, $row["routines"], lang('Routines')) : "") . (support("event") ? checkbox("events", 1, $row["events"], lang('Events')) : "") ); echo "
" . lang('Tables') . "" . html_select('table_style', $table_style, $row["table_style"]) . checkbox("auto_increment", 1, $row["auto_increment"], lang('Auto Increment')) . (support("trigger") ? checkbox("triggers", 1, $row["triggers"], lang('Triggers')) : "") ; echo "
" . lang('Data') . "" . html_select('data_style', $data_style, $row["data_style"]); ?>

"; echo "\n"; $databases = $adminer->databases(); if ($databases) { foreach ($databases as $db) { if (!information_schema($db)) { $prefix = preg_replace('~_.*~', '', $db); echo "
" . script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);", ""); echo "" . script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);", ""); echo "\n"; $views = ""; $tables_list = tables_list(); foreach ($tables_list as $name => $type) { $prefix = preg_replace('~_.*~', '', $name); $checked = ($TABLE == "" || $TABLE == (substr($TABLE, -1) == "%" ? "$prefix%" : $name)); //! % may be part of table name $print = "
" . checkbox("tables[]", $name, $checked, $name, "", "block"); if ($type !== null && !preg_match('~table~i', $type)) { $views .= "$print\n"; } else { echo "$print\n"; } $prefixes[$prefix]++; } echo $views; if ($tables_list) { echo script("ajaxSetHtml('" . js_escape(ME) . "script=db');"); } } else { echo "
"; echo ""; echo script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);", ""); echo "
" . checkbox("databases[]", $db, $TABLE == "" || $TABLE == "$prefix%", $db, "", "block") . "\n"; $prefixes[$prefix]++; } } } else { echo "
"; } } ?>

$val) { if ($key != "" && $val > 1) { echo ($first ? "

" : " ") . "" . h($key) . ""; $first = false; } } adminer-4.8.1/adminer/edit.inc.php000066400000000000000000000063031404740645700170050ustar00rootroot00000000000000 $field) { if (!isset($field["privileges"][$update ? "update" : "insert"]) || $adminer->fieldName($field) == "" || $field["generated"]) { unset($fields[$name]); } } if ($_POST && !$error && !isset($_GET["select"])) { $location = $_POST["referer"]; if ($_POST["insert"]) { // continue edit or insert $location = ($update ? null : $_SERVER["REQUEST_URI"]); } elseif (!preg_match('~^.+&select=.+$~', $location)) { $location = ME . "select=" . urlencode($TABLE); } $indexes = indexes($TABLE); $unique_array = unique_array($_GET["where"], $indexes); $query_where = "\nWHERE $where"; if (isset($_POST["delete"])) { queries_redirect( $location, lang('Item has been deleted.'), $driver->delete($TABLE, $query_where, !$unique_array) ); } else { $set = array(); foreach ($fields as $name => $field) { $val = process_input($field); if ($val !== false && $val !== null) { $set[idf_escape($name)] = $val; } } if ($update) { if (!$set) { redirect($location); } queries_redirect( $location, lang('Item has been updated.'), $driver->update($TABLE, $set, $query_where, !$unique_array) ); if (is_ajax()) { page_headers(); page_messages($error); exit; } } else { $result = $driver->insert($TABLE, $set); $last_id = ($result ? last_id() : 0); queries_redirect($location, lang('Item%s has been inserted.', ($last_id ? " $last_id" : "")), $result); //! link } } } $row = null; if ($_POST["save"]) { $row = (array) $_POST["fields"]; } elseif ($where) { $select = array(); foreach ($fields as $name => $field) { if (isset($field["privileges"]["select"])) { $as = convert_field($field); if ($_POST["clone"] && $field["auto_increment"]) { $as = "''"; } if ($jush == "sql" && preg_match("~enum|set~", $field["type"])) { $as = "1*" . idf_escape($name); } $select[] = ($as ? "$as AS " : "") . idf_escape($name); } } $row = array(); if (!support("table")) { $select = array("*"); } if ($select) { $result = $driver->select($TABLE, $select, array($where), $select, array(), (isset($_GET["select"]) ? 2 : 1)); if (!$result) { $error = error(); } else { $row = $result->fetch_assoc(); if (!$row) { // MySQLi returns null $row = false; } } if (isset($_GET["select"]) && (!$row || $result->fetch_assoc())) { // $result->num_rows != 1 isn't available in all drivers $row = null; } } } if (!support("table") && !$fields) { if (!$where) { // insert $result = $driver->select($TABLE, array("*"), $where, array("*")); $row = ($result ? $result->fetch_assoc() : false); if (!$row) { $row = array($driver->primary => ""); } } if ($row) { foreach ($row as $key => $val) { if (!$where) { $row[$key] = null; } $fields[$key] = array("field" => $key, "null" => ($key != $driver->primary), "auto_increment" => ($key == $driver->primary)); } } } edit_form($TABLE, $fields, $row, $update); adminer-4.8.1/adminer/event.inc.php000066400000000000000000000062451404740645700172060ustar00rootroot00000000000000 "ENABLE", "DISABLED" => "DISABLE", "SLAVESIDE_DISABLED" => "DISABLE ON SLAVE"); $row = $_POST; if ($_POST && !$error) { if ($_POST["drop"]) { query_redirect("DROP EVENT " . idf_escape($EVENT), substr(ME, 0, -1), lang('Event has been dropped.')); } elseif (in_array($row["INTERVAL_FIELD"], $intervals) && isset($statuses[$row["STATUS"]])) { $schedule = "\nON SCHEDULE " . ($row["INTERVAL_VALUE"] ? "EVERY " . q($row["INTERVAL_VALUE"]) . " $row[INTERVAL_FIELD]" . ($row["STARTS"] ? " STARTS " . q($row["STARTS"]) : "") . ($row["ENDS"] ? " ENDS " . q($row["ENDS"]) : "") //! ALTER EVENT doesn't drop ENDS - MySQL bug #39173 : "AT " . q($row["STARTS"]) ) . " ON COMPLETION" . ($row["ON_COMPLETION"] ? "" : " NOT") . " PRESERVE" ; queries_redirect(substr(ME, 0, -1), ($EVENT != "" ? lang('Event has been altered.') : lang('Event has been created.')), queries(($EVENT != "" ? "ALTER EVENT " . idf_escape($EVENT) . $schedule . ($EVENT != $row["EVENT_NAME"] ? "\nRENAME TO " . idf_escape($row["EVENT_NAME"]) : "") : "CREATE EVENT " . idf_escape($row["EVENT_NAME"]) . $schedule ) . "\n" . $statuses[$row["STATUS"]] . " COMMENT " . q($row["EVENT_COMMENT"]) . rtrim(" DO\n$row[EVENT_DEFINITION]", ";") . ";" )); } } page_header(($EVENT != "" ? lang('Alter event') . ": " . h($EVENT) : lang('Create event')), $error); if (!$row && $EVENT != "") { $rows = get_rows("SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA = " . q(DB) . " AND EVENT_NAME = " . q($EVENT)); $row = reset($rows); } ?>

" data-maxlength="64" autocapitalize="off">
">
">
" class="size">
" data-maxlength="64">

adminer-4.8.1/adminer/file.inc.php000066400000000000000000000031211404740645700167720ustar00rootroot00000000000000 $val) { $target[$key] = $row["target"][$key]; } $row["target"] = $target; } if ($jush == "sqlite") { queries_redirect($location, $message, recreate_table($TABLE, $TABLE, array(), array(), array(" $name" => ($_POST["drop"] ? "" : " " . format_foreign_key($row))))); } else { $alter = "ALTER TABLE " . table($TABLE); $drop = "\nDROP " . ($jush == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name); if ($_POST["drop"]) { query_redirect($alter . $drop, $location, $message); } else { query_redirect($alter . ($name != "" ? "$drop," : "") . "\nADD" . format_foreign_key($row), $location, $message); $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.') . "
$error"; //! no partitioning } } } page_header(lang('Foreign key'), $error, array("table" => $TABLE), h($TABLE)); if ($_POST) { ksort($row["source"]); if ($_POST["add"]) { $row["source"][] = ""; } elseif ($_POST["change"] || $_POST["change-js"]) { $row["target"] = array(); } } elseif ($name != "") { $foreign_keys = foreign_keys($TABLE); $row = $foreign_keys[$name]; $row["source"][] = ""; } else { $row["table"] = $TABLE; $row["source"] = array(""); } ?>
select_db($row["db"]); } if ($row["ns"] != "") { set_schema($row["ns"]); } $referencable = array_keys(array_filter(table_status('', true), 'fk_support')); $target = array_keys(fields(in_array($row["table"], $referencable) ? $row["table"] : reset($referencable))); $onchange = "this.form['change-js'].value = '1'; this.form.submit();"; echo "

" . lang('Target table') . ": " . html_select("table", $referencable, $row["table"], $onchange) . "\n"; if ($jush == "pgsql") { echo lang('Schema') . ": " . html_select("ns", $adminer->schemas(), $row["ns"] != "" ? $row["ns"] : $_GET["ns"], $onchange); } elseif ($jush != "sqlite") { $dbs = array(); foreach ($adminer->databases() as $db) { if (!information_schema($db)) { $dbs[] = $db; } } echo lang('DB') . ": " . html_select("db", $dbs, $row["db"] != "" ? $row["db"] : $_GET["db"], $onchange); } ?>

$val) { echo ""; echo "
" . html_select("source[" . (+$key) . "]", array(-1 => "") + $source, $val, ($j == count($row["source"]) - 1 ? "foreignAddRow.call(this);" : 1), "label-source"); echo "" . html_select("target[" . (+$key) . "]", $target, $row["target"][$key], 1, "label-target"); $j++; } ?>

: "") + explode("|", $on_actions), $row["on_delete"]); ?> : "") + explode("|", $on_actions), $row["on_update"]); ?> "innodb-foreign-key-constraints.html", 'mariadb' => "foreign-keys/", 'pgsql' => "sql-createtable.html#SQL-CREATETABLE-REFERENCES", 'mssql' => "ms174979.aspx", 'oracle' => "https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm#sthref2903", )); ?>

adminer-4.8.1/adminer/include/000077500000000000000000000000001404740645700162205ustar00rootroot00000000000000adminer-4.8.1/adminer/include/adminer.inc.php000066400000000000000000001100201404740645700211120ustar00rootroot00000000000000Adminer"; } /** Connection parameters * @return array ($server, $username, $password) */ function credentials() { return array(SERVER, $_GET["username"], get_password()); } /** Get SSL connection options * @return array array("key" => filename, "cert" => filename, "ca" => filename) or null */ function connectSsl() { } /** Get key used for permanent login * @param bool * @return string cryptic string which gets combined with password or false in case of an error */ function permanentLogin($create = false) { return password_file($create); } /** Return key used to group brute force attacks; behind a reverse proxy, you want to return the last part of X-Forwarded-For * @return string */ function bruteForceKey() { return $_SERVER["REMOTE_ADDR"]; } /** Get server name displayed in breadcrumbs * @param string * @return string HTML code or null */ function serverName($server) { return h($server); } /** Identifier of selected database * @return string */ function database() { // should be used everywhere instead of DB return DB; } /** Get cached list of databases * @param bool * @return array */ function databases($flush = true) { return get_databases($flush); } /** Get list of schemas * @return array */ function schemas() { return schemas(); } /** Specify limit for waiting on some slow queries like DB list * @return float number of seconds */ function queryTimeout() { return 2; } /** Headers to send before HTML output * @return null */ function headers() { } /** Get Content Security Policy headers * @return array of arrays with directive name in key, allowed sources in value */ function csp() { return csp(); } /** Print HTML code inside * @return bool true to link favicon.ico and adminer.css if exists */ function head() { ?> \n"; echo $this->loginFormField('driver', '' . lang('System') . '', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);") . "\n"); echo $this->loginFormField('server', '' . lang('Server') . '', '' . "\n"); echo $this->loginFormField('username', '' . lang('Username') . '', '' . script("focus(qs('#username')); qs('#username').form['auth[driver]'].onchange();")); echo $this->loginFormField('password', '' . lang('Password') . '', '' . "\n"); echo $this->loginFormField('db', '' . lang('Database') . '', '' . "\n"); echo "\n"; echo "

\n"; echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n"; } /** Get login form field * @param string * @param string HTML * @param string HTML * @return string */ function loginFormField($name, $heading, $value) { return $heading . $value; } /** Authorize the user * @param string * @param string * @return mixed true for success, string for error message, false for unknown error */ function login($login, $password) { if ($password == "") { return lang('Adminer does not support accessing a database without a password, more information.', target_blank()); } return true; } /** Table caption used in navigation and headings * @param array result of SHOW TABLE STATUS * @return string HTML code, "" to ignore table */ function tableName($tableStatus) { return h($tableStatus["Name"]); } /** Field caption used in select and edit * @param array single field returned from fields() * @param int order of column in select * @return string HTML code, "" to ignore field */ function fieldName($field, $order = 0) { return '' . h($field["field"]) . ''; } /** Print links after select heading * @param array result of SHOW TABLE STATUS * @param string new item options, NULL for no new item * @return null */ function selectLinks($tableStatus, $set = "") { global $jush, $driver; echo '

\n"; // required for IE9 inline edit if (!$failed && ($warnings = $driver->warnings())) { $id = "warnings"; $return = ", " . lang('Warnings') . "" . script("qsl('a').onclick = partial(toggle, '$id');", "") . "$return\n" ; } return "

" . h(str_replace("\n", " ", $query)) . " (" . format_time($start) . ")" . (support("sql") ? " " . lang('Edit') . "" : "") . $return ; } /** Query printed in SQL command before execution * @param string query to be executed * @return string escaped query to be printed */ function sqlCommandQuery($query) { return shorten_utf8(trim($query), 1000); } /** Description of a row in a table * @param string * @return string SQL expression, empty string for no description */ function rowDescription($table) { return ""; } /** Get descriptions of selected data * @param array all data to print * @param array * @return array */ function rowDescriptions($rows, $foreignKeys) { return $rows; } /** Get a link to use in select table * @param string raw value of the field * @param array single field returned from fields() * @return string or null to create the default link */ function selectLink($val, $field) { } /** Value printed in select table * @param string HTML-escaped value to print * @param string link to foreign key * @param array single field returned from fields() * @param array original value before applying editVal() and escaping * @return string */ function selectVal($val, $link, $field, $original) { $return = ($val === null ? "NULL" : (preg_match("~char|binary|boolean~", $field["type"]) && !preg_match("~var~", $field["type"]) ? "$val" : $val)); if (preg_match('~blob|bytea|raw|file~', $field["type"]) && !is_utf8($val)) { $return = "" . lang('%d byte(s)', strlen($original)) . ""; } if (preg_match('~json~', $field["type"])) { $return = "$return"; } return ($link ? "$return" : $return); } /** Value conversion used in select and edit * @param string * @param array single field returned from fields() * @return string */ function editVal($val, $field) { return $val; } /** Print table structure in tabular format * @param array data about individual fields * @return null */ function tableStructurePrint($fields) { echo "

\n"; echo "\n"; echo "\n"; foreach ($fields as $field) { echo "
" . lang('Column') . "" . lang('Type') . (support("comment") ? "" . lang('Comment') : "") . "
" . h($field["field"]); echo "" . h($field["full_type"]) . ""; echo ($field["null"] ? " NULL" : ""); echo ($field["auto_increment"] ? " " . lang('Auto Increment') . "" : ""); echo (isset($field["default"]) ? " [" . h($field["default"]) . "]" : ""); echo (support("comment") ? "" . h($field["comment"]) : ""); echo "\n"; } echo "
\n"; echo "
\n"; } /** Print list of indexes on table in tabular format * @param array data about all indexes on a table * @return null */ function tableIndexesPrint($indexes) { echo "\n"; foreach ($indexes as $name => $index) { ksort($index["columns"]); // enforce correct columns order $print = array(); foreach ($index["columns"] as $key => $val) { $print[] = "" . h($val) . "" . ($index["lengths"][$key] ? "(" . $index["lengths"][$key] . ")" : "") . ($index["descs"][$key] ? " DESC" : "") ; } echo "
$index[type]" . implode(", ", $print) . "\n"; } echo "
\n"; } /** Print columns box in select * @param array result of selectColumnsProcess()[0] * @param array selectable columns * @return null */ function selectColumnsPrint($select, $columns) { global $functions, $grouping; print_fieldset("select", lang('Select'), $select); $i = 0; $select[""] = array(); foreach ($select as $key => $val) { $val = $_GET["columns"][$key]; $column = select_input( " name='columns[$i][col]'", $columns, $val["col"], ($key !== "" ? "selectFieldChange" : "selectAddRow") ); echo "
" . ($functions || $grouping ? "" . on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1) . script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "") . "($column)" : $column) . "
\n"; $i++; } echo "\n"; } /** Print search box in select * @param array result of selectSearchProcess() * @param array selectable columns * @param array * @return null */ function selectSearchPrint($where, $columns, $indexes) { print_fieldset("search", lang('Search'), $where); foreach ($indexes as $i => $index) { if ($index["type"] == "FULLTEXT") { echo "
(" . implode(", ", array_map('h', $index["columns"])) . ") AGAINST"; echo " "; echo script("qsl('input').oninput = selectFieldChange;", ""); echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL"); echo "
\n"; } } $change_next = "this.parentNode.firstChild.onchange();"; foreach (array_merge((array) $_GET["where"], array(array())) as $i => $val) { if (!$val || ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators))) { echo "
" . select_input( " name='where[$i][col]'", $columns, $val["col"], ($val ? "selectFieldChange" : "selectAddRow"), "(" . lang('anywhere') . ")" ); echo html_select("where[$i][op]", $this->operators, $val["op"], $change_next); echo ""; echo script("mixin(qsl('input'), {oninput: function () { $change_next }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", ""); echo "
\n"; } } echo "\n"; } /** Print order box in select * @param array result of selectOrderProcess() * @param array selectable columns * @param array * @return null */ function selectOrderPrint($order, $columns, $indexes) { print_fieldset("sort", lang('Sort'), $order); $i = 0; foreach ((array) $_GET["order"] as $key => $val) { if ($val != "") { echo "
" . select_input(" name='order[$i]'", $columns, $val, "selectFieldChange"); echo checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')) . "
\n"; $i++; } } echo "
" . select_input(" name='order[$i]'", $columns, "", "selectAddRow"); echo checkbox("desc[$i]", 1, false, lang('descending')) . "
\n"; echo "\n"; } /** Print limit box in select * @param string result of selectLimitProcess() * @return null */ function selectLimitPrint($limit) { echo "
" . lang('Limit') . "
"; //
for easy styling echo ""; echo script("qsl('input').oninput = selectFieldChange;", ""); echo "
\n"; } /** Print text length box in select * @param string result of selectLengthProcess() * @return null */ function selectLengthPrint($text_length) { if ($text_length !== null) { echo "
" . lang('Text length') . "
"; echo ""; echo "
\n"; } } /** Print action box in select * @param array * @return null */ function selectActionPrint($indexes) { echo "
" . lang('Action') . "
"; echo ""; echo " "; echo "\n"; echo "var indexColumns = "; $columns = array(); foreach ($indexes as $index) { $current_key = reset($index["columns"]); if ($index["type"] != "FULLTEXT" && $current_key) { $columns[$current_key] = 1; } } $columns[""] = 1; foreach ($columns as $key => $val) { json_row($key); } echo ";\n"; echo "selectFieldChange.call(qs('#form')['select']);\n"; echo "\n"; echo "
\n"; } /** Print command box in select * @return bool whether to print default commands */ function selectCommandPrint() { return !information_schema(DB); } /** Print import box in select * @return bool whether to print default import */ function selectImportPrint() { return !information_schema(DB); } /** Print extra text in the end of a select form * @param array fields holding e-mails * @param array selectable columns * @return null */ function selectEmailPrint($emailFields, $columns) { } /** Process columns box in select * @param array selectable columns * @param array * @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" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) { $select[$key] = apply_sql_function($val["fun"], ($val["col"] != "" ? idf_escape($val["col"]) : "*")); if (!in_array($val["fun"], $grouping)) { $group[] = $select[$key]; } } } return array($select, $group); } /** Process search box in select * @param array * @param array * @return array expressions to join by AND */ function selectSearchProcess($fields, $indexes) { global $connection, $driver; $return = array(); foreach ($indexes as $i => $index) { if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") { $return[] = "MATCH (" . implode(", ", array_map('idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")"; } } foreach ((array) $_GET["where"] as $key => $val) { if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) { $prefix = ""; $cond = " $val[op]"; if (preg_match('~IN$~', $val["op"])) { $in = process_length($val["val"]); $cond .= " " . ($in != "" ? $in : "(NULL)"); } elseif ($val["op"] == "SQL") { $cond = " $val[val]"; // SQL injection } elseif ($val["op"] == "LIKE %%") { $cond = " LIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%"); } elseif ($val["op"] == "ILIKE %%") { $cond = " ILIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%"); } elseif ($val["op"] == "FIND_IN_SET") { $prefix = "$val[op](" . q($val["val"]) . ", "; $cond = ")"; } elseif (!preg_match('~NULL$~', $val["op"])) { $cond .= " " . $this->processInput($fields[$val["col"]], $val["val"]); } if ($val["col"] != "") { $return[] = $prefix . $driver->convertSearch(idf_escape($val["col"]), $val, $fields[$val["col"]]) . $cond; } else { // find anywhere $cols = array(); foreach ($fields as $name => $field) { if ((preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"])) && (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"])) && (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val["val"])) ) { $cols[] = $prefix . $driver->convertSearch(idf_escape($name), $val, $field) . $cond; } } $return[] = ($cols ? "(" . implode(" OR ", $cols) . ")" : "1 = 0"); } } } return $return; } /** Process order box in select * @param array * @param array * @return array expressions to join by comma */ function selectOrderProcess($fields, $indexes) { $return = array(); foreach ((array) $_GET["order"] as $key => $val) { if ($val != "") { $return[] = (preg_match('~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~', $val) ? $val : idf_escape($val)) //! MS SQL uses [] . (isset($_GET["desc"][$key]) ? " DESC" : "") ; } } return $return; } /** Process limit box in select * @return string expression to use in LIMIT, will be escaped */ function selectLimitProcess() { return (isset($_GET["limit"]) ? $_GET["limit"] : "50"); } /** Process length box in select * @return string number of characters to shorten texts, will be escaped */ function selectLengthProcess() { return (isset($_GET["text_length"]) ? $_GET["text_length"] : "100"); } /** Process extras in select form * @param array AND conditions * @param array * @return bool true if processed, false to process other parts of form */ function selectEmailProcess($where, $foreignKeys) { return false; } /** Build SQL query used in select * @param array result of selectColumnsProcess()[0] * @param array result of selectSearchProcess() * @param array result of selectColumnsProcess()[1] * @param array result of selectOrderProcess() * @param int result of selectLimitProcess() * @param int index of page starting at zero * @return string empty string to use default query */ function selectQueryBuild($select, $where, $group, $order, $limit, $page) { return ""; } /** Query printed after execution in the message * @param string executed query * @param string elapsed time * @param bool * @return string */ function messageQuery($query, $time, $failed = false) { global $jush, $driver; restart_session(); $history = &get_session("queries"); if (!$history[$_GET["db"]]) { $history[$_GET["db"]] = array(); } if (strlen($query) > 1e6) { $query = preg_replace('~[\x80-\xFF]+$~', '', substr($query, 0, 1e6)) . "\nâ€Ļ"; // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment } $history[$_GET["db"]][] = array($query, time(), $time); // not DB - $_GET["db"] is changed in database.inc.php //! respect $_GET["ns"] $sql_id = "sql-" . count($history[$_GET["db"]]); $return = "" . lang('SQL command') . "\n"; if (!$failed && ($warnings = $driver->warnings())) { $id = "warnings-" . count($history[$_GET["db"]]); $return = "" . lang('Warnings') . ", $return\n"; } return " " . @date("H:i:s") . "" // @ - time zone may be not set . " $return' ; } /** Print before edit form * @param string * @param array * @param mixed * @param bool * @return null */ function editRowPrint($table, $fields, $row, $update) { } /** Functions displayed in edit form * @param array single field from fields() * @return array */ function editFunctions($field) { global $edit_functions; $return = ($field["null"] ? "NULL/" : ""); $update = isset($_GET["select"]) || where($_GET); foreach ($edit_functions as $key => $functions) { if (!$key || (!isset($_GET["call"]) && $update)) { // relative functions foreach ($functions as $pattern => $val) { if (!$pattern || preg_match("~$pattern~", $field["type"])) { $return .= "/$val"; } } } if ($key && !preg_match('~set|blob|bytea|raw|file|bool~', $field["type"])) { $return .= "/SQL"; } } if ($field["auto_increment"] && !$update) { $return = lang('Auto Increment'); } return explode("/", $return); } /** Get options to display edit field * @param string table name * @param array single field from fields() * @param string attributes to use inside the tag * @param string * @return string custom input field or empty string for default */ function editInput($table, $field, $attrs, $value) { if ($field["type"] == "enum") { return (isset($_GET["select"]) ? " " : "") . ($field["null"] ? " " : "") . enum_input("radio", $attrs, $field, $value, 0) // 0 - empty ; } return ""; } /** Get hint for edit field * @param string table name * @param array single field from fields() * @param string * @return string */ function editHint($table, $field, $value) { return ""; } /** Process sent input * @param array single field from fields() * @param string * @param string * @return string expression to use in a query */ function processInput($field, $value, $function = "") { if ($function == "SQL") { return $value; // SQL injection } $name = $field["field"]; $return = q($value); if (preg_match('~^(now|getdate|uuid)$~', $function)) { $return = "$function()"; } elseif (preg_match('~^current_(date|timestamp)$~', $function)) { $return = $function; } elseif (preg_match('~^([+-]|\|\|)$~', $function)) { $return = idf_escape($name) . " $function $return"; } elseif (preg_match('~^[+-] interval$~', $function)) { $return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) ? $value : $return); } elseif (preg_match('~^(addtime|subtime|concat)$~', $function)) { $return = "$function(" . idf_escape($name) . ", $return)"; } elseif (preg_match('~^(md5|sha1|password|encrypt)$~', $function)) { $return = "$function($return)"; } return unconvert_field($field, $return); } /** Returns export output options * @return array */ function dumpOutput() { $return = array('text' => lang('open'), 'file' => lang('save')); if (function_exists('gzencode')) { $return['gz'] = 'gzip'; } return $return; } /** Returns export format options * @return array empty to disable export */ function dumpFormat() { return array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV'); } /** Export database structure * @param string * @return null prints data */ function dumpDatabase($db) { } /** Export table structure * @param string * @param string * @param int 0 table, 1 view, 2 temporary view table * @return null prints data */ function dumpTable($table, $style, $is_view = 0) { if ($_POST["format"] != "sql") { echo "\xef\xbb\xbf"; // UTF-8 byte order mark if ($style) { dump_csv(array_keys(fields($table))); } } else { if ($is_view == 2) { $fields = array(); foreach (fields($table) as $name => $field) { $fields[] = idf_escape($name) . " $field[full_type]"; } $create = "CREATE TABLE " . table($table) . " (" . implode(", ", $fields) . ")"; } else { $create = create_sql($table, $_POST["auto_increment"], $style); } set_utf8mb4($create); if ($style && $create) { if ($style == "DROP+CREATE" || $is_view == 1) { echo "DROP " . ($is_view == 2 ? "VIEW" : "TABLE") . " IF EXISTS " . table($table) . ";\n"; } if ($is_view == 1) { $create = remove_definer($create); } echo "$create;\n\n"; } } } /** Export table data * @param string * @param string * @param string * @return null prints data */ function dumpData($table, $style, $query) { global $connection, $jush; $max_packet = ($jush == "sqlite" ? 0 : 1048576); // default, minimum is 1024 if ($style) { if ($_POST["format"] == "sql") { if ($style == "TRUNCATE+INSERT") { echo truncate_sql($table) . ";\n"; } $fields = fields($table); } $result = $connection->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers if ($result) { $insert = ""; $buffer = ""; $keys = array(); $suffix = ""; $fetch_function = ($table != '' ? 'fetch_assoc' : 'fetch_row'); while ($row = $result->$fetch_function()) { if (!$keys) { $values = array(); foreach ($row as $val) { $field = $result->fetch_field(); $keys[] = $field->name; $key = idf_escape($field->name); $values[] = "$key = VALUES($key)"; } $suffix = ($style == "INSERT+UPDATE" ? "\nON DUPLICATE KEY UPDATE " . implode(", ", $values) : "") . ";\n"; } if ($_POST["format"] != "sql") { if ($style == "table") { dump_csv($keys); $style = "INSERT"; } dump_csv($row); } else { if (!$insert) { $insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('idf_escape', $keys)) . ") VALUES"; } foreach ($row as $key => $val) { $field = $fields[$key]; $row[$key] = ($val !== null ? unconvert_field($field, preg_match(number_type(), $field["type"]) && !preg_match('~\[~', $field["full_type"]) && is_numeric($val) ? $val : q(($val === false ? 0 : $val))) : "NULL" ); } $s = ($max_packet ? "\n" : " ") . "(" . implode(",\t", $row) . ")"; if (!$buffer) { $buffer = $insert . $s; } elseif (strlen($buffer) + 4 + strlen($s) + strlen($suffix) < $max_packet) { // 4 - length specification $buffer .= ",$s"; } else { echo $buffer . $suffix; $buffer = $insert . $s; } } } if ($buffer) { echo $buffer . $suffix; } } elseif ($_POST["format"] == "sql") { echo "-- " . str_replace("\n", " ", $connection->error) . "\n"; } } } /** Set export filename * @param string * @return string filename without extension */ function dumpFilename($identifier) { return friendly_url($identifier != "" ? $identifier : (SERVER != "" ? SERVER : "localhost")); } /** Send headers for export * @param string * @param bool * @return string extension */ function dumpHeaders($identifier, $multi_table = false) { $output = $_POST["output"]; $ext = (preg_match('~sql~', $_POST["format"]) ? "sql" : ($multi_table ? "tar" : "csv")); // multiple CSV packed to TAR header("Content-Type: " . ($output == "gz" ? "application/x-gzip" : ($ext == "tar" ? "application/x-tar" : ($ext == "sql" || $output != "file" ? "text/plain" : "text/csv") . "; charset=utf-8" ))); if ($output == "gz") { ob_start('ob_gzencode', 1e6); } return $ext; } /** Set the path of the file for webserver load * @return string path of the sql dump file */ function importServerPath() { return "adminer.sql"; } /** Print homepage * @return bool whether to print default homepage */ function homepage() { echo '

name(); ?> id="version">

$servers) { foreach ($servers as $server => $usernames) { foreach ($usernames as $username => $password) { if ($password !== null) { $dbs = $_SESSION["db"][$vendor][$server][$username]; foreach (($dbs ? array_keys($dbs) : array("")) as $db) { $output .= "
  • ($drivers[$vendor]) " . h($username . ($server != "" ? "@" . $this->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "\n"; } } } } } if ($output) { echo "\n" . script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});"); } } else { $tables = array(); if ($_GET["ns"] !== "" && !$missing && DB != "") { $connection->select_db(DB); $tables = table_status('', true); } echo script_src("../externals/jush/modules/jush.js"); echo script_src("../externals/jush/modules/jush-textarea.js"); echo script_src("../externals/jush/modules/jush-txt.js"); echo script_src("../externals/jush/modules/jush-js.js"); if (support("sql")) { echo script_src("../externals/jush/modules/jush-$jush.js"); ?> > $type) { $links[] = preg_quote($table, '/'); } echo "var jushLinks = { $jush: [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n"; foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) { echo "jushLinks.$val = jushLinks.$jush;\n"; } } $server_info = $connection->server_info; ?> bodyLoad(''); databasesPrint($missing); if (DB == "" || !$missing) { echo "

    " . lang('No tables.') . "\n"; } else { $this->tablesPrint($tables); } } } } /** Prints databases list in menu * @param string * @return null */ function databasesPrint($missing) { global $adminer, $connection; $databases = $this->databases(); if (DB && $databases && !in_array(DB, $databases)) { array_unshift($databases, DB); } ?>

    " . lang('DB') . ": " . ($databases ? "$db_events" : "\n" ); echo "\n"; if (support("scheme")) { if ($missing != "db" && DB != "" && $connection->select_db(DB)) { echo "
    " . lang('Schema') . ": $db_events"; if ($_GET["ns"] != "") { set_schema($_GET["ns"]); } } } foreach (array("import", "sql", "schema", "dump", "privileges") as $val) { if (isset($_GET[$val])) { echo ""; break; } } echo "

    \n"; } /** Prints table list in menu * @param array result of table_status('', true) * @return null */ function tablesPrint($tables) { echo "\n"; } } adminer-4.8.1/adminer/include/auth.inc.php000066400000000000000000000166731404740645700204570ustar00rootroot00000000000000 $val) { if ($val[0] < $time) { unset($invalids[$ip]); } } } $invalid = &$invalids[$adminer->bruteForceKey()]; if (!$invalid) { $invalid = array($time + 30*60, 0); // active for 30 minutes } $invalid[1]++; file_write_unlock($fp, serialize($invalids)); } function check_invalid_login() { global $adminer; $invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist $invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : array()); $next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts if ($next_attempt > 0) { //! do the same with permanent login auth_error(lang('Too many unsuccessful logins, try again in %d minute(s).', ceil($next_attempt / 60))); } } $auth = $_POST["auth"]; if ($auth) { session_regenerate_id(); // defense against session fixation $vendor = $auth["driver"]; $server = $auth["server"]; $username = $auth["username"]; $password = (string) $auth["password"]; $db = $auth["db"]; set_password($vendor, $server, $username, $password); $_SESSION["db"][$vendor][$server][$username][$db] = true; if ($auth["permanent"]) { $key = base64_encode($vendor) . "-" . base64_encode($server) . "-" . base64_encode($username) . "-" . base64_encode($db); $private = $adminer->permanentLogin(true); $permanent[$key] = "$key:" . base64_encode($private ? encrypt_string($password, $private) : ""); cookie("adminer_permanent", implode(" ", $permanent)); } if (count($_POST) == 1 // 1 - auth || DRIVER != $vendor || SERVER != $server || $_GET["username"] !== $username // "0" == "00" || DB != $db ) { redirect(auth_url($vendor, $server, $username, $db)); } } elseif ($_POST["logout"] && (!$has_token || verify_token())) { foreach (array("pwds", "db", "dbs", "queries") as $key) { set_session($key, null); } unset_permanent(); redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1), lang('Logout successful.') . ' ' . lang('Thanks for using Adminer, consider donating.')); } elseif ($permanent && !$_SESSION["pwds"]) { session_regenerate_id(); $private = $adminer->permanentLogin(); foreach ($permanent as $key => $val) { list(, $cipher) = explode(":", $val); list($vendor, $server, $username, $db) = array_map('base64_decode', explode("-", $key)); set_password($vendor, $server, $username, decrypt_string(base64_decode($cipher), $private)); $_SESSION["db"][$vendor][$server][$username][$db] = true; } } function unset_permanent() { global $permanent; foreach ($permanent as $key => $val) { list($vendor, $server, $username, $db) = array_map('base64_decode', explode("-", $key)); if ($vendor == DRIVER && $server == SERVER && $username == $_GET["username"] && $db == DB) { unset($permanent[$key]); } } cookie("adminer_permanent", implode(" ", $permanent)); } /** Renders an error message and a login form * @param string plain text * @return null exits */ function auth_error($error) { global $adminer, $has_token; $session_name = session_name(); if (isset($_GET["username"])) { header("HTTP/1.1 403 Forbidden"); // 401 requires sending WWW-Authenticate header if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$has_token) { $error = lang('Session expired, please login again.'); } else { restart_session(); add_invalid_login(); $password = get_password(); if ($password !== null) { if ($password === false) { $error .= ($error ? '
    ' : '') . lang('Master password expired. Implement %s method to make it permanent.', target_blank(), 'permanentLogin()'); } set_password(DRIVER, SERVER, $_GET["username"], null); } unset_permanent(); } } if (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_bool("session.use_only_cookies")) { $error = lang('Session support must be enabled.'); } $params = session_get_cookie_params(); cookie("adminer_key", ($_COOKIE["adminer_key"] ? $_COOKIE["adminer_key"] : rand_string()), $params["lifetime"]); page_header(lang('Login'), $error, null); echo "
    \n"; echo "
    "; if (hidden_fields($_POST, array("auth"))) { // expired session echo "

    " . lang('The action will be performed after successful login with the same credentials.') . "\n"; } echo "

    \n"; $adminer->loginForm(); echo "
    \n"; page_footer("auth"); exit; } if (isset($_GET["username"]) && !class_exists("Min_DB")) { unset($_SESSION["pwds"][DRIVER]); unset_permanent(); page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), false); page_footer("auth"); exit; } stop_session(true); if (isset($_GET["username"]) && is_string(get_password())) { list($host, $port) = explode(":", SERVER, 2); if (preg_match('~^\s*([-+]?\d+)~', $port, $match) && ($match[1] < 1024 || $match[1] > 65535)) { // is_numeric('80#') would still connect to port 80 auth_error(lang('Connecting to privileged ports is not allowed.')); } check_invalid_login(); $connection = connect(); $driver = new Min_Driver($connection); } $login = null; if (!is_object($connection) || ($login = $adminer->login($_GET["username"], get_password())) !== true) { $error = (is_string($connection) ? h($connection) : (is_string($login) ? $login : lang('Invalid credentials.'))); auth_error($error . (preg_match('~^ | $~', get_password()) ? '
    ' . lang('There is a space in the input password which might be the cause.') : '')); } if ($_POST["logout"] && $has_token && !verify_token()) { page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.')); page_footer("db"); exit; } if ($auth && $_POST["token"]) { $_POST["token"] = $token; // reset token after explicit login } $error = ''; ///< @var string if ($_POST) { if (!verify_token()) { $ini = "max_input_vars"; $max_vars = ini_get($ini); if (extension_loaded("suhosin")) { foreach (array("suhosin.request.max_vars", "suhosin.post.max_vars") as $key) { $val = ini_get($key); if ($val && (!$max_vars || $val < $max_vars)) { $ini = $key; $max_vars = $val; } } } $error = (!$_POST["token"] && $max_vars ? lang('Maximum number of allowed fields exceeded. Please increase %s.', "'$ini'") : lang('Invalid CSRF token. Send the form again.') . ' ' . lang('If you did not send this request from Adminer then close this page.') ); } } elseif ($_SERVER["REQUEST_METHOD"] == "POST") { // posted form with no data means that post_max_size exceeded because Adminer always sends token at least $error = lang('Too big POST data. Reduce the data or increase the %s configuration directive.', "'post_max_size'"); if (isset($_GET["sql"])) { $error .= ' ' . lang('You can upload a big SQL file via FTP and import it from server.'); } } adminer-4.8.1/adminer/include/bootstrap.inc.php000066400000000000000000000114201404740645700215140ustar00rootroot00000000000000 $_POST["signature"], "version" => $_POST["version"]))); } exit; } global $adminer, $connection, $driver, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $permanent, $structured_types, $has_token, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"]; } if (!strpos($_SERVER["REQUEST_URI"], '?') && $_SERVER["QUERY_STRING"] != "") { // IIS 7 compatibility $_SERVER["REQUEST_URI"] .= "?$_SERVER[QUERY_STRING]"; } if ($_SERVER["HTTP_X_FORWARDED_PREFIX"]) { $_SERVER["REQUEST_URI"] = $_SERVER["HTTP_X_FORWARDED_PREFIX"] . $_SERVER["REQUEST_URI"]; } $HTTPS = ($_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")) || ini_bool("session.cookie_secure"); // session.cookie_secure could be set on HTTP if we are behind a reverse proxy @ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled if (!defined("SID")) { session_cache_limiter(""); // to allow restarting session session_name("adminer_sid"); // use specific session name to get own namespace $params = array(0, preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS); if (version_compare(PHP_VERSION, '5.2.0') >= 0) { $params[] = true; // HttpOnly } call_user_func_array('session_set_cookie_params', $params); // ini_set() may be disabled session_start(); } // disable magic quotes to be able to use database escaping function remove_slashes(array(&$_GET, &$_POST, &$_COOKIE), $filter); if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) { set_magic_quotes_runtime(false); } @set_time_limit(0); // @ - can be disabled @ini_set("zend.ze1_compatibility_mode", false); // @ - deprecated @ini_set("precision", 15); // @ - can be disabled, 15 - internal PHP precision include "../adminer/include/lang.inc.php"; include "../adminer/lang/$LANG.inc.php"; include "../adminer/include/pdo.inc.php"; include "../adminer/include/driver.inc.php"; include "../adminer/drivers/sqlite.inc.php"; include "../adminer/drivers/pgsql.inc.php"; include "../adminer/drivers/oracle.inc.php"; include "../adminer/drivers/mssql.inc.php"; include "../adminer/drivers/mongo.inc.php"; include "../adminer/drivers/elastic.inc.php"; include "./include/adminer.inc.php"; $adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer); include "../adminer/drivers/mysql.inc.php"; // must be included as last driver $config = driver_config(); $possible_drivers = $config['possible_drivers']; $jush = $config['jush']; $types = $config['types']; $structured_types = $config['structured_types']; $unsigned = $config['unsigned']; $operators = $config['operators']; $functions = $config['functions']; $grouping = $config['grouping']; $edit_functions = $config['edit_functions']; if ($adminer->operators === null) { $adminer->operators = $operators; } define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost define("DB", $_GET["db"]); // for the sake of speed and size define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?' . (sid() ? SID . '&' : '') . (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '') . (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '') . (DB != "" ? 'db=' . urlencode(DB) . '&' . (isset($_GET["ns"]) ? "ns=" . urlencode($_GET["ns"]) . "&" : "") : '') ); include "../adminer/include/version.inc.php"; include "../adminer/include/design.inc.php"; include "../adminer/include/xxtea.inc.php"; include "../adminer/include/auth.inc.php"; include "./include/editing.inc.php"; include "./include/connect.inc.php"; $on_actions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys() adminer-4.8.1/adminer/include/connect.inc.php000066400000000000000000000104131404740645700211310ustar00rootroot00000000000000\n"; foreach (array( 'database' => lang('Create database'), 'privileges' => lang('Privileges'), 'processlist' => lang('Process list'), 'variables' => lang('Variables'), 'status' => lang('Status'), ) as $key => $val) { if (support($key)) { echo "$val\n"; } } echo "

    " . lang('%s version: %s through PHP extension %s', $drivers[DRIVER], "" . h($connection->server_info) . "", "$connection->extension") . "\n"; echo "

    " . lang('Logged as: %s', "" . h(logged_user()) . "") . "\n"; $databases = $adminer->databases(); if ($databases) { $scheme = support("scheme"); $collations = collations(); echo "

    \n"; echo "\n"; echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"); echo "" . (support("database") ? "\n" ; $databases = ($_GET["dbsize"] ? count_tables($databases) : array_flip($databases)); foreach ($databases as $db => $tables) { $root = h(ME) . "db=" . urlencode($db); $id = h("Db-" . $db); echo "" . (support("database") ? "
    " : "") . "" . lang('Database') . " - " . lang('Refresh') . "" . "" . lang('Collation') . "" . lang('Tables') . "" . lang('Size') . " - " . lang('Compute') . "" . script("qsl('a').onclick = partial(ajaxSetHtml, '" . js_escape(ME) . "script=connect');", "") . "
    " . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : ""); echo "" . h($db) . ""; $collation = h(db_collation($db, $collations)); echo "" . (support("database") ? "$collation" : $collation); echo "" . ($_GET["dbsize"] ? $tables : "?") . ""; echo "" . ($_GET["dbsize"] ? db_size($db) : "?"); echo "\n"; } echo "
    \n"; echo (support("database") ? "\n" : "" ); echo "\n"; echo "
    \n"; echo script("tableCheck();"); } } page_footer("db"); } if (isset($_GET["status"])) { $_GET["variables"] = $_GET["status"]; } if (isset($_GET["import"])) { $_GET["sql"] = $_GET["import"]; } 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"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) { if (DB != "" || $_GET["refresh"]) { restart_session(); set_session("dbs", null); } connect_error(); // separate function to catch SQLite error exit; } if (support("scheme")) { if (DB != "" && $_GET["ns"] !== "") { if (!isset($_GET["ns"])) { redirect(preg_replace('~ns=[^&]*&~', '', ME) . "ns=" . get_schema()); } if (!set_schema($_GET["ns"])) { header("HTTP/1.1 404 Not Found"); page_header(lang('Schema') . ": " . h($_GET["ns"]), lang('Invalid schema.'), true); page_footer("ns"); exit; } } } adminer-4.8.1/adminer/include/coverage.inc.php000066400000000000000000000013021404740645700212700ustar00rootroot00000000000000 $lines) { foreach ($lines as $l => $val) { if (!$coverage[$filename][$l] || $val > 0) { $coverage[$filename][$l] = $val; } } file_put_contents($coverage_filename, serialize($coverage)); } } xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); register_shutdown_function('save_coverage'); } adminer-4.8.1/adminer/include/design.inc.php000066400000000000000000000157541404740645700207660ustar00rootroot00000000000000 "link", "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, should be HTML escaped * @return null */ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") { global $LANG, $VERSION, $adminer, $drivers, $jush; page_headers(); if (is_ajax() && $error) { page_messages($error); exit; } $title_all = $title . ($title2 != "" ? ": $title2" : ""); $title_page = strip_tags($title_all . (SERVER != "" && SERVER != "localhost" ? h(" - " . SERVER) : "") . " - " . $adminer->name()); ?> <?php echo $title_page; ?> head()) { ?> css() as $css) { ?> time()) { // 86400 - 1 day in seconds $version = unserialize(file_get_contents($filename)); $public = "-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqWOVuF5uw7/+Z70djoK RlHIZFZPO0uYRezq90+7Amk+FDNd7KkL5eDve+vHRJBLAszF/7XKXe11xwliIsFs DFWQlsABVZB3oisKCBEuI71J4kPH8dKGEWR9jDHFw3cWmoH3PmqImX6FISWbG3B8 h7FIx3jEaw5ckVPVTeo5JRm/1DZzJxjyDenXvBQ/6o9DgZKeNDgxwKzH+sw9/YCO jHnq1cFpOIISzARlrHMa/43YfeNRAm/tsBXjSxembBPo7aQZLAWHmaj5+K19H10B nCpz9Y++cipkVEiKRGih4ZEvjoFysEOdRLj6WiD/uUNky4xGeA6LaJqh5XpkFkcQ fQIDAQAB -----END PUBLIC KEY----- "; if (openssl_verify($version["version"], base64_decode($version["signature"]), $public) == 1) { $_COOKIE["adminer_version"] = $version["version"]; // doesn't need to send to the browser } } ?> > mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick}); document.body.className = document.body.className.replace(/ nojs/, ' js'); var offlineMessage = ''; var thousandsSeparator = '';
    ' . $drivers[DRIVER] . ' » '; $link = substr(preg_replace('~\b(db|ns)=[^&]*&~', '', ME), 0, -1); $server = $adminer->serverName(SERVER); $server = ($server != "" ? $server : lang('Server')); if ($breadcrumb === false) { echo "$server\n"; } else { echo "$server » "; if ($_GET["ns"] != "" || (DB != "" && is_array($breadcrumb))) { echo '' . h(DB) . ' » '; } if (is_array($breadcrumb)) { if ($_GET["ns"] != "") { echo '' . h($_GET["ns"]) . ' » '; } foreach ($breadcrumb as $key => $val) { $desc = (is_array($val) ? $val[1] : h($val)); if ($desc != "") { echo "$desc » "; } } } echo "$title\n"; } } echo "

    $title_all

    \n"; echo "\n"; restart_session(); page_messages($error); $databases = &get_session("dbs"); if (DB != "" && $databases && !in_array(DB, $databases, true)) { $databases = null; } stop_session(); define("PAGE_HEADER", 1); } /** Send HTTP headers * @return null */ function page_headers() { global $adminer; header("Content-Type: text/html; charset=utf-8"); header("Cache-Control: no-cache"); header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, Firefox 3.6.9 header("X-XSS-Protection: 0"); // prevents introducing XSS in IE8 by removing safe parts of the page header("X-Content-Type-Options: nosniff"); header("Referrer-Policy: origin-when-cross-origin"); foreach ($adminer->csp() as $csp) { $header = array(); foreach ($csp as $key => $val) { $header[] = "$key $val"; } header("Content-Security-Policy: " . implode("; ", $header)); } $adminer->headers(); } /** Get Content Security Policy headers * @return array of arrays with directive name in key, allowed sources in value */ function csp() { return array( array( "script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'", // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-' "connect-src" => "'self'", "frame-src" => "https://www.adminer.org", "object-src" => "'none'", "base-uri" => "'none'", "form-action" => "'self'", ), ); } /** Get a CSP nonce * @return string Base64 value */ function get_nonce() { static $nonce; if (!$nonce) { $nonce = base64_encode(rand_string()); } return $nonce; } /** Print flash and error messages * @param string * @return null */ function page_messages($error) { $uri = preg_replace('~^[^?]*~', '', $_SERVER["REQUEST_URI"]); $messages = $_SESSION["messages"][$uri]; if ($messages) { echo "
    " . implode("
    \n
    ", $messages) . "
    " . script("messagesPrint();"); unset($_SESSION["messages"][$uri]); } if ($error) { echo "
    $error
    \n"; } } /** Print HTML footer * @param string "auth", "db", "ns" * @return null */ function page_footer($missing = "") { global $adminer, $token; ?>

    _conn = $connection; } /** Select data from table * @param string * @param array result of $adminer->selectColumnsProcess()[0] * @param array result of $adminer->selectSearchProcess() * @param array result of $adminer->selectColumnsProcess()[1] * @param array result of $adminer->selectOrderProcess() * @param int result of $adminer->selectLimitProcess() * @param int index of page starting at zero * @param bool whether to print the query * @return Min_Result */ function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) { global $adminer, $jush; $is_group = (count($group) < count($select)); $query = $adminer->selectQueryBuild($select, $where, $group, $order, $limit, $page); if (!$query) { $query = "SELECT" . limit( ($_GET["page"] != "last" && $limit != "" && $group && $is_group && $jush == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table), ($where ? "\nWHERE " . implode(" AND ", $where) : "") . ($group && $is_group ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : ""), ($limit != "" ? +$limit : null), ($page ? $limit * $page : 0), "\n" ); } $start = microtime(true); $return = $this->_conn->query($query); if ($print) { echo $adminer->selectQuery($query, $start, !$return); } return $return; } /** Delete data from table * @param string * @param string " WHERE ..." * @param int 0 or 1 * @return bool */ function delete($table, $queryWhere, $limit = 0) { $query = "FROM " . table($table); return queries("DELETE" . ($limit ? limit1($table, $query, $queryWhere) : " $query$queryWhere")); } /** Update data in table * @param string * @param array escaped columns in keys, quoted data in values * @param string " WHERE ..." * @param int 0 or 1 * @param string * @return bool */ function update($table, $set, $queryWhere, $limit = 0, $separator = "\n") { $values = array(); foreach ($set as $key => $val) { $values[] = "$key = $val"; } $query = table($table) . " SET$separator" . implode(",$separator", $values); return queries("UPDATE" . ($limit ? limit1($table, $query, $queryWhere, $separator) : " $query$queryWhere")); } /** Insert data into table * @param string * @param array escaped columns in keys, quoted data in values * @return bool */ function insert($table, $set) { return queries("INSERT INTO " . table($table) . ($set ? " (" . implode(", ", array_keys($set)) . ")\nVALUES (" . implode(", ", $set) . ")" : " DEFAULT VALUES" )); } /** Insert or update data in table * @param string * @param array * @param array of arrays with escaped columns in keys and quoted data in values * @return bool */ /*abstract*/ function insertUpdate($table, $rows, $primary) { return false; } /** Begin transaction * @return bool */ function begin() { return queries("BEGIN"); } /** Commit transaction * @return bool */ function commit() { return queries("COMMIT"); } /** Rollback transaction * @return bool */ function rollback() { return queries("ROLLBACK"); } /** Return query with a timeout * @param string * @param int seconds * @return string or null if the driver doesn't support query timeouts */ function slowQuery($query, $timeout) { } /** Convert column to be searchable * @param string escaped column name * @param array array("op" => , "val" => ) * @param array * @return string */ function convertSearch($idf, $val, $field) { return $idf; } /** Convert value returned by database to actual value * @param string * @param array * @return string */ function value($val, $field) { return (method_exists($this->_conn, 'value') ? $this->_conn->value($val, $field) : (is_resource($val) ? stream_get_contents($val) : $val) ); } /** Quote binary string * @param string * @return string */ function quoteBinary($s) { return q($s); } /** Get warnings about the last command * @return string HTML */ function warnings() { return ''; } /** Get help link for table * @param string * @return string relative URL or null */ function tableHelp($name) { } } adminer-4.8.1/adminer/include/editing.inc.php000066400000000000000000000531431404740645700211320ustar00rootroot00000000000000 orgtable - create links from these columns $indexes = array(); // orgtable => array(column => colno) - primary keys $columns = array(); // orgtable => array(column => ) - not selected columns in primary key $blobs = array(); // colno => bool - display bytes for blobs $types = array(); // colno => type - display char in $return = array(); // table => orgtable - mapping to use in EXPLAIN odd(''); // reset odd for each result for ($i=0; (!$limit || $i < $limit) && ($row = $result->fetch_row()); $i++) { if (!$i) { echo "
    \n"; echo "\n"; echo ""; for ($j=0; $j < count($row); $j++) { $field = $result->fetch_field(); $name = $field->name; $orgtable = $field->orgtable; $orgname = $field->orgname; $return[$field->table] = $orgtable; if ($orgtables && $jush == "sql") { // MySQL EXPLAIN $links[$j] = ($name == "table" ? "table=" : ($name == "possible_keys" ? "indexes=" : null)); } elseif ($orgtable != "") { if (!isset($indexes[$orgtable])) { // find primary key in each table $indexes[$orgtable] = array(); foreach (indexes($orgtable, $connection2) as $index) { if ($index["type"] == "PRIMARY") { $indexes[$orgtable] = array_flip($index["columns"]); break; } } $columns[$orgtable] = $indexes[$orgtable]; } if (isset($columns[$orgtable][$orgname])) { unset($columns[$orgtable][$orgname]); $indexes[$orgtable][$orgname] = $j; $links[$j] = $orgtable; } } if ($field->charsetnr == 63) { // 63 - binary $blobs[$j] = true; } $types[$j] = $field->type; echo "name != $orgname ? " title='" . h(($orgtable != "" ? "$orgtable." : "") . $orgname) . "'" : "") . ">" . h($name) . ($orgtables ? doc_link(array( 'sql' => "explain-output.html#explain_" . strtolower($name), 'mariadb' => "explain/#the-columns-in-explain-select", )) : "") ; } echo "\n"; } echo ""; foreach ($row as $key => $val) { $link = ""; if (isset($links[$key]) && !$columns[$links[$key]]) { if ($orgtables && $jush == "sql") { // MySQL EXPLAIN $table = $row[array_search("table=", $links)]; $link = ME . $links[$key] . urlencode($orgtables[$table] != "" ? $orgtables[$table] : $table); } else { $link = ME . "edit=" . urlencode($links[$key]); foreach ($indexes[$links[$key]] as $col => $j) { $link .= "&where" . urlencode("[" . bracket_escape($col) . "]") . "=" . urlencode($row[$j]); } } } elseif (is_url($val)) { $link = $val; } if ($val === null) { $val = "NULL"; } elseif ($blobs[$key] && !is_utf8($val)) { $val = "" . lang('%d byte(s)', strlen($val)) . ""; //! link to download } else { $val = h($val); if ($types[$key] == 254) { // 254 - char $val = "$val"; } } if ($link) { $val = "$val"; } echo "
    $val"; } } echo ($i ? "
    \n
    " : "

    " . lang('No rows.')) . "\n"; return $return; } /** Get referencable tables with single column primary key except self * @param string * @return array ($table_name => $field) */ function referencable_primary($self) { $return = array(); // table_name => field foreach (table_status('', true) 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 unset($return[$table_name]); break; } $return[$table_name] = $field; } } } } return $return; } /** Get settings stored in a cookie * @return array */ function adminer_settings() { parse_str($_COOKIE["adminer_settings"], $settings); return $settings; } /** Get setting stored in a cookie * @param string * @return array */ function adminer_setting($key) { $settings = adminer_settings(); return $settings[$key]; } /** Store settings to a cookie * @param array * @return bool */ function set_adminer_settings($settings) { return cookie("adminer_settings", http_build_query($settings + adminer_settings())); } /** Print SQL "; } /** Print table columns for type edit * @param string * @param array * @param array * @param array returned by referencable_primary() * @param array extra types to prepend * @return null */ function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_types = array()) { global $structured_types, $types, $unsigned, $on_actions; $type = $field["type"]; ?> " size="3" aria-labelledby="label-length">

    "; echo "$legend"; echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", ""); echo ""; echo "
    dumpFormat(); foreach ((array) $_GET["columns"] as $column) { if ($column["fun"]) { unset($format['sql']); break; } } if ($format) { print_fieldset("export", lang('Export') . " "); $output = $adminer->dumpOutput(); echo ($output ? html_select("output", $output, $adminer_import["output"]) . " " : ""); echo html_select("format", $format, $adminer_import["format"]); echo " \n"; echo "\n"; } $adminer->selectEmailPrint(array_filter($email_fields, 'strlen'), $columns); } echo "\n"; if ($adminer->selectImportPrint()) { echo "
    "; echo "" . lang('Import') . ""; echo script("qsl('a').onclick = partial(toggle, 'import');", ""); echo ""; echo "
    "; } echo "\n"; echo "\n"; echo (!$group && $select ? "" : script("tableCheck();")); } } } if (is_ajax()) { ob_end_clean(); exit; } adminer-4.8.1/adminer/sequence.inc.php000066400000000000000000000022031404740645700176630ustar00rootroot00000000000000

    " autocapitalize="off"> " . confirm(lang('Drop %s?', $SEQUENCE)) . "\n"; } ?>

    adminer-4.8.1/adminer/sql.inc.php000066400000000000000000000262161404740645700166640ustar00rootroot00000000000000dumpTable("", ""); $adminer->dumpData("", "table", $_POST["query"]); exit; } restart_session(); $history_all = &get_session("queries"); $history = &$history_all[DB]; if (!$error && $_POST["clear"]) { $history = array(); redirect(remove_from_uri("history")); } page_header((isset($_GET["import"]) ? lang('Import') : lang('SQL command')), $error); if (!$error && $_POST) { $fp = false; if (!isset($_GET["import"])) { $query = $_POST["query"]; } elseif ($_POST["webfile"]) { $sql_file_path = $adminer->importServerPath(); $fp = @fopen((file_exists($sql_file_path) ? $sql_file_path : "compress.zlib://$sql_file_path.gz" ), "rb"); $query = ($fp ? fread($fp, 1e6) : false); } else { $query = get_file("sql_file", true); } if (is_string($query)) { // get_file() returns error as number, fread() as false if (function_exists('memory_get_usage')) { @ini_set("memory_limit", max(ini_bytes("memory_limit"), 2 * strlen($query) + memory_get_usage() + 8e6)); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables } if ($query != "" && strlen($query) < 1e6) { // don't add big queries $q = $query . (preg_match("~;[ \t\r\n]*\$~", $query) ? "" : ";"); //! doesn't work with DELIMITER | if (!$history || reset(end($history)) != $q) { // no repeated queries restart_session(); $history[] = array($q, time()); //! add elapsed time set_session("queries", $history_all); // required because reference is unlinked by stop_session() stop_session(); } } $space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)"; $delimiter = ";"; $offset = 0; $empty = true; $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); if ($_GET["ns"] != "") { set_schema($_GET["ns"], $connection2); } } $commands = 0; $errors = array(); $parse = '[\'"' . ($jush == "sql" ? '`#' : ($jush == "sqlite" ? '`[' : ($jush == "mssql" ? '[' : ''))) . ']|/\*|-- |$' . ($jush == "pgsql" ? '|\$[^$]*\$' : ''); $total_start = microtime(true); parse_str($_COOKIE["adminer_export"], $adminer_export); $dump_format = $adminer->dumpFormat(); unset($dump_format["sql"]); while ($query != "") { if (!$offset && preg_match("~^$space*+DELIMITER\\s+(\\S+)~i", $query, $match)) { $delimiter = $match[1]; $query = substr($query, strlen($match[0])); } else { preg_match('(' . preg_quote($delimiter) . "\\s*|$parse)", $query, $match, PREG_OFFSET_CAPTURE, $offset); // should always match list($found, $pos) = $match[0]; if (!$found && $fp && !feof($fp)) { $query .= fread($fp, 1e5); } else { if (!$found && rtrim($query) == "") { break; } $offset = $pos + strlen($found); if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end while (preg_match('(' . ($found == '/*' ? '\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset)) { //! respect sql_mode NO_BACKSLASH_ESCAPES $s = $match[0][0]; if (!$s && $fp && !feof($fp)) { $query .= fread($fp, 1e5); } else { $offset = $match[0][1] + strlen($s); if ($s[0] != "\\") { break; } } } } else { // end of a query $empty = false; $q = substr($query, 0, $pos); $commands++; $print = "
    " . $adminer->sqlCommandQuery($q) . "
    \n"; if ($jush == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) { // PHP doesn't support setting SQLITE_LIMIT_ATTACHED echo $print; echo "

    " . lang('ATTACH queries are not supported.') . "\n"; $errors[] = " $commands"; if ($_POST["error_stops"]) { break; } } else { if (!$_POST["only_errors"]) { echo $print; ob_flush(); flush(); // can take a long time - show the running query } $start = microtime(true); //! don't allow changing of character_set_results, convert encoding of displayed query if ($connection->multi_query($q) && is_object($connection2) && preg_match("~^$space*+USE\\b~i", $q)) { $connection2->query($q); } do { $result = $connection->store_result(); if ($connection->error) { echo ($_POST["only_errors"] ? $print : ""); echo "

    " . lang('Error in query') . ($connection->errno ? " ($connection->errno)" : "") . ": " . error() . "\n"; $errors[] = " $commands"; if ($_POST["error_stops"]) { break 2; } } else { $time = " (" . format_time($start) . ")" . (strlen($q) < 1000 ? " " . lang('Edit') . "" : "") // 1000 - maximum length of encoded URL in IE is 2083 characters ; $affected = $connection->affected_rows; // getting warnigns overwrites this $warnings = ($_POST["only_errors"] ? "" : $driver->warnings()); $warnings_id = "warnings-$commands"; if ($warnings) { $time .= ", " . lang('Warnings') . "" . script("qsl('a').onclick = partial(toggle, '$warnings_id');", ""); } $explain = null; $explain_id = "explain-$commands"; if (is_object($result)) { $limit = $_POST["limit"]; $orgtables = select($result, $connection2, array(), $limit); if (!$_POST["only_errors"]) { echo "

    \n"; $num_rows = $result->num_rows; echo "

    " . ($num_rows ? ($limit && $num_rows > $limit ? lang('%d / ', $limit) : "") . lang('%d row(s)', $num_rows) : ""); echo $time; if ($connection2 && preg_match("~^($space|\\()*+SELECT\\b~i", $q) && ($explain = explain($connection2, $q))) { echo ", Explain" . script("qsl('a').onclick = partial(toggle, '$explain_id');", ""); } $id = "export-$commands"; echo ", " . lang('Export') . "" . script("qsl('a').onclick = partial(toggle, '$id');", "") . "\n" . "

    \n" ; } } else { if (preg_match("~^$space*+(CREATE|DROP|ALTER)$space++(DATABASE|SCHEMA)\\b~i", $q)) { restart_session(); set_session("dbs", null); // clear cache stop_session(); } if (!$_POST["only_errors"]) { echo "

    " . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n"; } } echo ($warnings ? "

    \n" : ""); if ($explain) { echo "\n"; } } $start = microtime(true); } while ($connection->next_result()); } $query = substr($query, $offset); $offset = 0; } } } } if ($empty) { echo "

    " . lang('No commands to execute.') . "\n"; } elseif ($_POST["only_errors"]) { echo "

    " . lang('%d query(s) executed OK.', $commands - count($errors)); echo " (" . format_time($total_start) . ")\n"; } elseif ($errors && $commands > 1) { echo "

    " . lang('Error in query') . ": " . implode("", $errors) . "\n"; } //! MS SQL - SET SHOWPLAN_ALL OFF } else { echo "

    " . upload_error($query) . "\n"; } } ?>

    "; if (!isset($_GET["import"])) { $q = $_GET["sql"]; // overwrite $q from if ($_POST) to save memory if ($_POST) { $q = $_POST["query"]; } elseif ($_GET["history"] == "all") { $q = $history; } elseif ($_GET["history"] != "") { $q = $history[$_GET["history"]][0]; } echo "

    "; textarea("query", $q, 20); echo script(($_POST ? "" : "qs('textarea').focus();\n") . "qs('#form').onsubmit = partial(sqlSubmit, qs('#form'), '" . js_escape(remove_from_uri("sql|limit|error_stops|only_errors|history")) . "');"); echo "

    $execute\n"; echo lang('Limit rows') . ": \n"; } else { echo "

    " . lang('File upload') . "
    "; $gz = (extension_loaded("zlib") ? "[.gz]" : ""); echo (ini_bool("file_uploads") ? "SQL$gz (< " . ini_get("upload_max_filesize") . "B): \n$execute" // ignore post_max_size because it is for all form fields together and bytes computing would be necessary : lang('File uploads are disabled.') ); echo "
    \n"; $importServerPath = $adminer->importServerPath(); if ($importServerPath) { echo "
    " . lang('From server') . "
    "; echo lang('Webserver file %s', "" . h($importServerPath) . "$gz"); echo ' '; echo "
    \n"; } echo "

    "; } echo checkbox("error_stops", 1, ($_POST ? $_POST["error_stops"] : isset($_GET["import"]) || $_GET["error_stops"]), lang('Stop on error')) . "\n"; echo checkbox("only_errors", 1, ($_POST ? $_POST["only_errors"] : isset($_GET["import"]) || $_GET["only_errors"]), lang('Show only errors')) . "\n"; echo "\n"; if (!isset($_GET["import"]) && $history) { print_fieldset("history", lang('History'), $_GET["history"] != ""); for ($val = end($history); $val; $val = prev($history)) { // not array_reverse() to save memory $key = key($history); list($q, $time, $elapsed) = $val; echo '' . lang('Edit') . "" . " " . @date("H:i:s", $time) . "" // @ - time zone may be not set . " " . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $q)))), 80, "") . ($elapsed ? " ($elapsed)" : "") . "
    \n" ; } echo "\n"; echo "" . lang('Edit all') . "\n"; echo "\n"; } ?>

    adminer-4.8.1/adminer/sqlite.php000066400000000000000000000005701404740645700166110ustar00rootroot00000000000000 div { background: #fff; padding: 0 0 .5em; } .footer fieldset { margin-top: 0; } .links a { white-space: nowrap; margin-right: 20px; } .logout { margin-top: .5em; position: absolute; top: 0; right: 0; } .loadmore { margin-left: 1ex; } /* .edit used in designs */ #menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; } #menu p, #logins, #tables { padding: .8em 1em; margin: 0; border-bottom: 1px solid #ccc; } #logins li, #tables li { list-style: none; } #dbs { overflow: hidden; } #logins, #tables { white-space: nowrap; overflow: auto; } #logins a, #tables a, #tables span { background: #fff; } #content { margin: 2em 0 0 21em; padding: 10px 20px 20px 0; } #lang { position: absolute; top: 0; left: 0; line-height: 1.8em; padding: .3em 1em; } #breadcrumb { white-space: nowrap; position: absolute; top: 0; left: 21em; background: #eee; height: 2em; line-height: 1.8em; padding: 0 1em; margin: 0 0 0 -18px; } #h1 { color: #777; text-decoration: none; font-style: italic; } #version { font-size: 67%; color: red; } #schema { margin-left: 60px; position: relative; -moz-user-select: none; -webkit-user-select: none; } #schema .table { border: 1px solid silver; padding: 0 2px; cursor: move; position: absolute; } #schema .references { position: absolute; } #help { position: absolute; border: 1px solid #999; background: #eee; padding: 5px; font-family: monospace; z-index: 1; } .rtl h2 { margin: 0 -18px 20px 0; } .rtl p, .rtl table, .rtl .error, .rtl .message { margin: 1em 0 0 20px; } .rtl .logout { left: 0; right: auto; } .rtl #content { margin: 2em 21em 0 0; padding: 10px 0 20px 20px; } .rtl #breadcrumb { left: auto; right: 21em; margin: 0 -18px 0 0; } .rtl .pages { left: auto; right: 21em; } .rtl input.wayoff { left: auto; right: -1000px; } .rtl #lang, .rtl #menu { left: auto; right: 0; } @media all and (max-device-width: 880px) { .pages { left: auto; } #menu { position: static; width: auto; } #content { margin-left: 10px; } #lang { position: static; border-top: 1px solid #999; } #breadcrumb { left: auto; } .rtl .pages { right: auto; } .rtl #content { margin-right: 10px; } .rtl #breadcrumb { right: auto; } } @media print { #lang, #menu { display: none; } #content { margin-left: 1em; } #breadcrumb { left: 1em; } .nowrap td, .nowrap th, td.nowrap { white-space: normal; } } adminer-4.8.1/adminer/static/down.gif000066400000000000000000000001171404740645700175210ustar00rootroot00000000000000GIF89a1îî™™!ų, „ŠËíMņĖ*)ž[Wū\ĸĮL&؜Æļ•Įō;adminer-4.8.1/adminer/static/editing.js000066400000000000000000000505211404740645700200500ustar00rootroot00000000000000// Adminer specific functions /** Load syntax highlighting * @param string first three characters of database system version * @param [boolean] */ function bodyLoad(version, maria) { if (window.jush) { jush.create_links = ' target="_blank" rel="noreferrer noopener"'; if (version) { for (var key in jush.urls) { var obj = jush.urls; if (typeof obj[key] != 'string') { obj = obj[key]; key = 0; if (maria) { for (var i = 1; i < obj.length; i++) { obj[i] = obj[i] .replace(/\.html/, '/') .replace(/-type-syntax/, '-data-types') .replace(/numeric-(data-types)/, '$1-$&') .replace(/#statvar_.*/, '#$$1') ; } } } obj[key] = (maria ? obj[key].replace(/dev\.mysql\.com\/doc\/mysql\/en\//, 'mariadb.com/kb/en/library/') : obj[key]) // MariaDB .replace(/\/doc\/mysql/, '/doc/refman/' + version) // MySQL .replace(/\/docs\/current/, '/docs/' + version) // PostgreSQL ; } } if (window.jushLinks) { jush.custom_links = jushLinks; } jush.highlight_tag('code', 0); var tags = qsa('textarea'); for (var i = 0; i < tags.length; i++) { if (/(^|\s)jush-/.test(tags[i].className)) { var pre = jush.textarea(tags[i]); if (pre) { setupSubmitHighlightInput(pre); } } } } } /** Get value of dynamically created form field * @param HTMLFormElement * @param string * @return HTMLElement */ function formField(form, name) { // required in IE < 8, form.elements[name] doesn't work for (var i=0; i < form.length; i++) { if (form[i].name == name) { return form[i]; } } } /** Try to change input type to password or to text * @param HTMLInputElement * @param boolean */ function typePassword(el, disable) { try { el.type = (disable ? 'text' : 'password'); } catch (e) { } } /** Install toggle handler * @param [HTMLElement] */ function messagesPrint(el) { var els = qsa('.toggle', el); for (var i = 0; i < els.length; i++) { els[i].onclick = partial(toggle, els[i].getAttribute('href').substr(1)); } } /** Hide or show some login rows for selected driver * @param HTMLSelectElement */ function loginDriver(driver) { var trs = parentTag(driver, 'table').rows; var disabled = /sqlite/.test(selectValue(driver)); alterClass(trs[1], 'hidden', disabled); // 1 - row with server trs[1].getElementsByTagName('input')[0].disabled = disabled; } var dbCtrl; var dbPrevious = {}; /** Check if database should be opened to a new window * @param MouseEvent * @this HTMLSelectElement */ function dbMouseDown(event) { dbCtrl = isCtrl(event); if (dbPrevious[this.name] == undefined) { dbPrevious[this.name] = this.value; } } /** Load database after selecting it * @this HTMLSelectElement */ function dbChange() { if (dbCtrl) { this.form.target = '_blank'; } this.form.submit(); this.form.target = ''; if (dbCtrl && dbPrevious[this.name] != undefined) { this.value = dbPrevious[this.name]; dbPrevious[this.name] = undefined; } } /** Check whether the query will be executed with index * @this HTMLElement */ function selectFieldChange() { var form = this.form; var ok = (function () { var inputs = qsa('input', form); for (var i=0; i < inputs.length; i++) { if (inputs[i].value && /^fulltext/.test(inputs[i].name)) { return true; } } var ok = form.limit.value; var selects = qsa('select', form); var group = false; var columns = {}; for (var i=0; i < selects.length; i++) { var select = selects[i]; var col = selectValue(select); var match = /^(where.+)col\]/.exec(select.name); if (match) { var op = selectValue(form[match[1] + 'op]']); var val = form[match[1] + 'val]'].value; if (col in indexColumns && (!/LIKE|REGEXP/.test(op) || (op == 'LIKE' && val.charAt(0) != '%'))) { return true; } else if (col || val) { ok = false; } } if ((match = /^(columns.+)fun\]/.exec(select.name))) { if (/^(avg|count|count distinct|group_concat|max|min|sum)$/.test(col)) { group = true; } var val = selectValue(form[match[1] + 'col]']); if (val) { columns[col && col != 'count' ? '' : val] = 1; } } if (col && /^order/.test(select.name)) { if (!(col in indexColumns)) { ok = false; } break; } } if (group) { for (var col in columns) { if (!(col in indexColumns)) { ok = false; } } } return ok; })(); setHtml('noindex', (ok ? '' : '!')); } var added = '.', rowCount; /** Check if val is equal to a-delimiter-b where delimiter is '_', '' or big letter * @param string * @param string * @param string * @return boolean */ function delimiterEqual(val, a, b) { return (val == a + '_' + b || val == a + b || val == a + b.charAt(0).toUpperCase() + b.substr(1)); } /** Escape string to use as identifier * @param string * @return string */ function idfEscape(s) { return s.replace(/`/, '``'); } /** Set up event handlers for edit_fields(). */ function editFields() { var els = qsa('[name$="[field]"]'); for (var i = 0; i < els.length; i++) { els[i].oninput = function () { editingNameChange.call(this); if (!this.defaultValue) { editingAddRow.call(this); } } } els = qsa('[name$="[length]"]'); for (var i = 0; i < els.length; i++) { mixin(els[i], {onfocus: editingLengthFocus, oninput: editingLengthChange}); } els = qsa('[name$="[type]"]'); for (var i = 0; i < els.length; i++) { mixin(els[i], { onfocus: function () { lastType = selectValue(this); }, onchange: editingTypeChange, onmouseover: function (event) { helpMouseover.call(this, event, getTarget(event).value, 1) }, onmouseout: helpMouseout }); } } /** Handle clicks on fields editing * @param MouseEvent * @return boolean false to cancel action */ function editingClick(event) { var el = getTarget(event); if (!isTag(el, 'input')) { el = parentTag(el, 'label'); el = el && qs('input', el); } if (el) { var name = el.name; if (/^add\[/.test(name)) { editingAddRow.call(el, 1); } else if (/^up\[/.test(name)) { editingMoveRow.call(el, 1); } else if (/^down\[/.test(name)) { editingMoveRow.call(el); } else if (/^drop_col\[/.test(name)) { editingRemoveRow.call(el, 'fields\$1[field]'); } else { if (name == 'auto_increment_col') { var field = el.form['fields[' + el.value + '][field]']; if (!field.value) { field.value = 'id'; field.oninput(); } } return; } return false; } } /** Handle input on fields editing * @param InputEvent */ function editingInput(event) { var el = getTarget(event); if (/\[default\]$/.test(el.name)) { el.previousSibling.checked = true; } } /** Detect foreign key * @this HTMLInputElement */ function editingNameChange() { var name = this.name.substr(0, this.name.length - 7); var type = formField(this.form, name + '[type]'); var opts = type.options; var candidate; // don't select anything with ambiguous match (like column `id`) var val = this.value; for (var i = opts.length; i--; ) { var match = /(.+)`(.+)/.exec(opts[i].value); if (!match) { // common type if (candidate && i == opts.length - 2 && val == opts[candidate].value.replace(/.+`/, '') && name == 'fields[1]') { // single target table, link to column, first field - probably `id` return; } break; } var table = match[1]; var column = match[2]; var tables = [ table, table.replace(/s$/, ''), table.replace(/es$/, '') ]; for (var j=0; j < tables.length; j++) { table = tables[j]; if (val == column || val == table || delimiterEqual(val, table, column) || delimiterEqual(val, column, table)) { if (candidate) { return; } candidate = i; break; } } } if (candidate) { type.selectedIndex = candidate; type.onchange(); } } /** Add table row for next field * @param [boolean] * @return boolean false * @this HTMLInputElement */ function editingAddRow(focus) { var match = /(\d+)(\.\d+)?/.exec(this.name); var x = match[0] + (match[2] ? added.substr(match[2].length) : added) + '1'; var row = parentTag(this, 'tr'); var row2 = cloneNode(row); var tags = qsa('select', row); var tags2 = qsa('select', row2); for (var i=0; i < tags.length; i++) { tags2[i].name = tags[i].name.replace(/[0-9.]+/, x); tags2[i].selectedIndex = tags[i].selectedIndex; } tags = qsa('input', row); tags2 = qsa('input', row2); var input = tags2[0]; // IE loose tags2 after insertBefore() for (var i=0; i < tags.length; i++) { if (tags[i].name == 'auto_increment_col') { tags2[i].value = x; tags2[i].checked = false; } tags2[i].name = tags[i].name.replace(/([0-9.]+)/, x); if (/\[(orig|field|comment|default)/.test(tags[i].name)) { tags2[i].value = ''; } if (/\[(has_default)/.test(tags[i].name)) { tags2[i].checked = false; } } tags[0].oninput = editingNameChange; row.parentNode.insertBefore(row2, row.nextSibling); if (focus) { input.oninput = editingNameChange; input.focus(); } added += '0'; rowCount++; return false; } /** Remove table row for field * @param string regular expression replacement * @return boolean false * @this HTMLInputElement */ function editingRemoveRow(name) { var field = formField(this.form, this.name.replace(/[^\[]+(.+)/, name)); field.parentNode.removeChild(field); parentTag(this, 'tr').style.display = 'none'; return false; } /** Move table row for field * @param [boolean] * @return boolean false for success * @this HTMLInputElement */ function editingMoveRow(up){ var row = parentTag(this, 'tr'); if (!('nextElementSibling' in row)) { return true; } row.parentNode.insertBefore(row, up ? row.previousElementSibling : row.nextElementSibling ? row.nextElementSibling.nextElementSibling : row.parentNode.firstChild); return false; } var lastType = ''; /** Clear length and hide collation or unsigned * @this HTMLSelectElement */ function editingTypeChange() { var type = this; var name = type.name.substr(0, type.name.length - 6); var text = selectValue(type); for (var i=0; i < type.form.elements.length; i++) { var el = type.form.elements[i]; if (el.name == name + '[length]') { if (!( (/(char|binary)$/.test(lastType) && /(char|binary)$/.test(text)) || (/(enum|set)$/.test(lastType) && /(enum|set)$/.test(text)) )) { el.value = ''; } el.oninput.apply(el); } if (lastType == 'timestamp' && el.name == name + '[has_default]' && /timestamp/i.test(formField(type.form, name + '[default]').value)) { el.checked = false; } if (el.name == name + '[collation]') { alterClass(el, 'hidden', !/(char|text|enum|set)$/.test(text)); } if (el.name == name + '[unsigned]') { alterClass(el, 'hidden', !/(^|[^o])int(?!er)|numeric|real|float|double|decimal|money/.test(text)); } if (el.name == name + '[on_update]') { alterClass(el, 'hidden', !/timestamp|datetime/.test(text)); // MySQL supports datetime since 5.6.5 } if (el.name == name + '[on_delete]') { alterClass(el, 'hidden', !/`/.test(text)); } } helpClose(); } /** Mark length as required * @this HTMLInputElement */ function editingLengthChange() { alterClass(this, 'required', !this.value.length && /var(char|binary)$/.test(selectValue(this.parentNode.previousSibling.firstChild))); } /** Edit enum or set * @this HTMLInputElement */ function editingLengthFocus() { var td = this.parentNode; if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) { var edit = qs('#enum-edit'); edit.value = enumValues(this.value); td.appendChild(edit); this.style.display = 'none'; edit.style.display = 'inline'; edit.focus(); } } /** Get enum values * @param string * @return string values separated by newlines */ function enumValues(s) { var re = /(^|,)\s*'(([^\\']|\\.|'')*)'\s*/g; var result = []; var offset = 0; var match; while (match = re.exec(s)) { if (offset != match.index) { break; } result.push(match[2].replace(/'(')|\\(.)/g, '$1$2')); offset += match[0].length; } return (offset == s.length ? result.join('\n') : s); } /** Finish editing of enum or set * @this HTMLTextAreaElement */ function editingLengthBlur() { var field = this.parentNode.firstChild; var val = this.value; field.value = (/^'[^\n]+'$/.test(val) ? val : val && "'" + val.replace(/\n+$/, '').replace(/'/g, "''").replace(/\\/g, '\\\\').replace(/\n/g, "','") + "'"); field.style.display = 'inline'; this.style.display = 'none'; } /** Show or hide selected table column * @param boolean * @param number */ function columnShow(checked, column) { var trs = qsa('tr', qs('#edit-fields')); for (var i=0; i < trs.length; i++) { alterClass(qsa('td', trs[i])[column], 'hidden', !checked); } } /** Display partition options * @this HTMLSelectElement */ function partitionByChange() { var partitionTable = /RANGE|LIST/.test(selectValue(this)); alterClass(this.form['partitions'], 'hidden', partitionTable || !this.selectedIndex); alterClass(qs('#partition-table'), 'hidden', !partitionTable); helpClose(); } /** Add next partition row * @this HTMLInputElement */ function partitionNameChange() { var row = cloneNode(parentTag(this, 'tr')); row.firstChild.firstChild.value = ''; parentTag(this, 'table').appendChild(row); this.oninput = function () {}; } /** Show or hide comment fields * @param HTMLInputElement * @param [boolean] whether to focus Comment if checked */ function editingCommentsClick(el, focus) { var comment = el.form['Comment']; columnShow(el.checked, 6); alterClass(comment, 'hidden', !el.checked); if (focus && el.checked) { comment.focus(); } } /** Uncheck 'all' checkbox * @param MouseEvent * @this HTMLTableElement */ function dumpClick(event) { var el = parentTag(getTarget(event), 'label'); if (el) { el = qs('input', el); var match = /(.+)\[\]$/.exec(el.name); if (match) { checkboxClick.call(el, event); formUncheck('check-' + match[1]); } } } /** Add row for foreign key * @this HTMLSelectElement */ function foreignAddRow() { var row = cloneNode(parentTag(this, 'tr')); this.onchange = function () { }; var selects = qsa('select', row); for (var i=0; i < selects.length; i++) { selects[i].name = selects[i].name.replace(/\]/, '1$&'); selects[i].selectedIndex = 0; } parentTag(this, 'table').appendChild(row); } /** Add row for indexes * @this HTMLSelectElement */ function indexesAddRow() { var row = cloneNode(parentTag(this, 'tr')); this.onchange = function () { }; var selects = qsa('select', row); for (var i=0; i < selects.length; i++) { selects[i].name = selects[i].name.replace(/indexes\[\d+/, '$&1'); selects[i].selectedIndex = 0; } var inputs = qsa('input', row); for (var i=0; i < inputs.length; i++) { inputs[i].name = inputs[i].name.replace(/indexes\[\d+/, '$&1'); inputs[i].value = ''; } parentTag(this, 'table').appendChild(row); } /** Change column in index * @param string name prefix * @this HTMLSelectElement */ function indexesChangeColumn(prefix) { var names = []; for (var tag in { 'select': 1, 'input': 1 }) { var columns = qsa(tag, parentTag(this, 'td')); for (var i=0; i < columns.length; i++) { if (/\[columns\]/.test(columns[i].name)) { var value = selectValue(columns[i]); if (value) { names.push(value); } } } } this.form[this.name.replace(/\].*/, '][name]')].value = prefix + names.join('_'); } /** Add column for index * @param string name prefix * @this HTMLSelectElement */ function indexesAddColumn(prefix) { var field = this; var select = field.form[field.name.replace(/\].*/, '][type]')]; if (!select.selectedIndex) { while (selectValue(select) != "INDEX" && select.selectedIndex < select.options.length) { select.selectedIndex++; } select.onchange(); } var column = cloneNode(field.parentNode); var selects = qsa('select', column); for (var i = 0; i < selects.length; i++) { select = selects[i]; select.name = select.name.replace(/\]\[\d+/, '$&1'); select.selectedIndex = 0; } field.onchange = partial(indexesChangeColumn, prefix); var inputs = qsa('input', column); for (var i = 0; i < inputs.length; i++) { var input = inputs[i]; input.name = input.name.replace(/\]\[\d+/, '$&1'); if (input.type != 'checkbox') { input.value = ''; } } parentTag(field, 'td').appendChild(column); field.onchange(); } /** Updates the form action * @param HTMLFormElement * @param string */ function sqlSubmit(form, root) { if (encodeURIComponent(form['query'].value).length < 2e3) { form.action = root + '&sql=' + encodeURIComponent(form['query'].value) + (form['limit'].value ? '&limit=' + +form['limit'].value : '') + (form['error_stops'].checked ? '&error_stops=1' : '') + (form['only_errors'].checked ? '&only_errors=1' : '') ; } } /** Handle changing trigger time or event * @param RegExp * @param string * @param HTMLFormElement */ function triggerChange(tableRe, table, form) { var formEvent = selectValue(form['Event']); if (tableRe.test(form['Trigger'].value)) { form['Trigger'].value = table + '_' + (selectValue(form['Timing']).charAt(0) + formEvent.charAt(0)).toLowerCase(); } alterClass(form['Of'], 'hidden', !/ OF/.test(formEvent)); } var that, x, y; // em and tablePos defined in schema.inc.php /** Get mouse position * @param MouseEvent * @this HTMLElement */ function schemaMousedown(event) { if ((event.which ? event.which : event.button) == 1) { that = this; x = event.clientX - this.offsetLeft; y = event.clientY - this.offsetTop; } } /** Move object * @param MouseEvent */ function schemaMousemove(event) { if (that !== undefined) { var left = (event.clientX - x) / em; var top = (event.clientY - y) / em; var divs = qsa('div', that); var lineSet = { }; for (var i=0; i < divs.length; i++) { if (divs[i].className == 'references') { var div2 = qs('[id="' + (/^refs/.test(divs[i].id) ? 'refd' : 'refs') + divs[i].id.substr(4) + '"]'); var ref = (tablePos[divs[i].title] ? tablePos[divs[i].title] : [ div2.parentNode.offsetTop / em, 0 ]); var left1 = -1; var id = divs[i].id.replace(/^ref.(.+)-.+/, '$1'); if (divs[i].parentNode != div2.parentNode) { left1 = Math.min(0, ref[1] - left) - 1; divs[i].style.left = left1 + 'em'; divs[i].querySelector('div').style.width = -left1 + 'em'; var left2 = Math.min(0, left - ref[1]) - 1; div2.style.left = left2 + 'em'; div2.querySelector('div').style.width = -left2 + 'em'; } if (!lineSet[id]) { var line = qs('[id="' + divs[i].id.replace(/^....(.+)-.+$/, 'refl$1') + '"]'); var top1 = top + divs[i].offsetTop / em; var top2 = top + div2.offsetTop / em; if (divs[i].parentNode != div2.parentNode) { top2 += ref[0] - top; line.querySelector('div').style.height = Math.abs(top1 - top2) + 'em'; } line.style.left = (left + left1) + 'em'; line.style.top = Math.min(top1, top2) + 'em'; lineSet[id] = true; } } } that.style.left = left + 'em'; that.style.top = top + 'em'; } } /** Finish move * @param MouseEvent * @param string */ function schemaMouseup(event, db) { if (that !== undefined) { tablePos[that.firstChild.firstChild.firstChild.data] = [ (event.clientY - y) / em, (event.clientX - x) / em ]; that = undefined; var s = ''; for (var key in tablePos) { s += '_' + key + ':' + Math.round(tablePos[key][0] * 10000) / 10000 + 'x' + Math.round(tablePos[key][1] * 10000) / 10000; } s = encodeURIComponent(s.substr(1)); var link = qs('#schema-link'); link.href = link.href.replace(/[^=]+$/, '') + s; cookie('adminer_schema-' + db + '=' + s, 30); //! special chars in db } } var helpOpen, helpIgnore; // when mouse outs