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

Compare commits

...

102 Commits

Author SHA1 Message Date
Peter Knut
4112aaf26f Release 4.12 2024-11-21 12:54:30 +01:00
Peter Knut
5fdc9dc427 Update docs 2024-11-21 09:59:57 +01:00
Peter Knut
cc646de4ca Remove funding config 2024-11-19 23:41:47 +01:00
Peter Knut
b6b379a8ce Improve arrays formatting in dump method 2024-11-19 23:11:36 +01:00
Peter Knut
f93db81c0e Update translations 2024-11-19 22:58:20 +01:00
Peter Knut
2cafcd7fc8 Handle the situation when no driver is found
This can happen if Adminer for MySQL with existing login is replaced by Adminer for PostgreSQL.
2024-11-19 22:58:20 +01:00
Peter Knut
53799ff6ab Update Spanish translations
Thanks to isaacpolaino (https://github.com/adminerevo/adminerevo/discussions/21#discussioncomment-11283326)
2024-11-19 22:00:12 +01:00
Peter Knut
638288cc04 Cleanup: Definition of custom PDO statement class 2024-11-19 22:00:12 +01:00
Peter Knut
99f4c22c72 MSSQL: Allow to set Encrypt and TrustServerCertificate with AdminerLoginSsl plugin (issue #5)
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/connection-string-syntax#use-trustservercertificate
2024-11-19 22:00:12 +01:00
Peter Knut
55e0c348b8 MSSQL, MongoDB: Connect to localhost with default port if server is not specified 2024-11-19 22:00:12 +01:00
Peter Knut
379003fc8d MongoDB: Fix parsing WHERE condition from SQL query
Thanks to herobank110 (https://github.com/vrana/adminer/pull/491)
2024-11-19 22:00:12 +01:00
Peter Knut
0933e4e67d MongoDB: Small cleanup 2024-11-19 22:00:12 +01:00
Peter Knut
ee26735ac6 Refactor drivers definition and compilation
- Rename 'server' driver to 'mysql'
- MySQL driver is no longer the required default
- Fix compiled SQLite single-driver Adminer
- Allow to compile only selected drivers
2024-11-19 22:00:11 +01:00
Peter Knut
214d7745a7 Compiler: Refactor languages compilation
- Allow to compile only selected languages
- Fix translations in plugins
2024-11-07 10:52:13 +01:00
Peter Knut
99b7c08e3a Compiler: Add new lines before selected keywords, not after 2024-11-05 22:16:39 +01:00
Peter Knut
b1ecb0649e Improve dumping methods if run from terminal 2024-11-05 15:56:57 +01:00
vukbgit
2430ad2702 MariaDB: Add support for UUID data type
- MariaDB >= 10.7
- UUID string data type
- uuid() function for UUID type on new/edit item form
2024-11-04 14:40:50 +01:00
Peter Knut
9eeeca6b0e Fix highlighting default submit button in indexes form 2024-11-03 22:31:45 +01:00
Peter Knut
d165cd9aec Change logo link to main page (login) 2024-11-03 22:31:45 +01:00
Peter Knut
a0a0d44c7c Update project URL and info 2024-11-03 22:31:45 +01:00
Peter Knut
316754af47 Enhance checking of new version
- Do not verify version on login page
- Do not show error from version checking
- Sync expiration of version cookie with file
- Clean up the code
2024-11-03 22:31:45 +01:00
Peter Knut
47f1f19970 Fix SQL query code direction if RTL language is used 2024-11-03 22:31:45 +01:00
Peter Knut
5c4dc82081 PostgreSQL: Fix layout of stored function parameters 2024-11-03 22:31:45 +01:00
Peter Knut
226d4ad54b MySQL: Print comments of stored procedures and functions 2024-11-03 22:31:45 +01:00
Peter Knut
85c0c8f003 Fix disappearing dragged row 2024-11-03 22:31:45 +01:00
Peter Knut
c815ea875b Fix compiling single language version 2024-11-03 22:31:45 +01:00
Peter Knut
872991fa14 Docs: Update migration section 2024-11-03 22:31:45 +01:00
Peter Knut
35411d8f4e Bump version to 4.12-dev 2024-11-03 22:31:45 +01:00
Peter Knut
81e337bed1 Release 4.11 2024-10-30 22:14:44 +01:00
Peter Knut
18ddbf1d60 MySQL: Fix highlighting current table in menu on macOS 2024-10-30 22:12:59 +01:00
Peter Knut
e4235d21e5 Clean up JS code 2024-10-30 21:16:39 +01:00
Peter Knut
10dfc54bf4 Show help popup after a short delay, refactoring 2024-10-30 21:16:39 +01:00
Peter Knut
af3c863be3 Fix drag-n-drop moving of function parameters 2024-10-30 21:16:39 +01:00
Peter Knut
6cd5495c1b PostgreSQL: Show list of schemas in database, unify lists of sequences and user types 2024-10-30 21:16:39 +01:00
Peter Knut
78ad8381ab Update CS and SK translations 2024-10-30 21:16:39 +01:00
Peter Knut
87fc82f88e Fix printing error message while validating server URL 2024-10-30 21:16:39 +01:00
Peter Knut
0519a0b985 Devel: Add modification time to CSS and JS links for easier development 2024-10-30 21:16:39 +01:00
Peter Knut
f61cf1ba0c Support drag-n-drop moving on touch screens 2024-10-30 21:16:39 +01:00
HyP3r
fc2e025603 MS SQL: Prefix Unicode strings with 'N' so they are treated correctly 2024-10-30 21:16:39 +01:00
Peter Knut
659e72b692 MariaDB: Fix several links to documentation pages 2024-10-30 21:16:39 +01:00
Peter Knut
123373ca82 Switch to custom JUSH library 2024-10-30 21:16:39 +01:00
Peter Knut
e99f2d90cf Update project information 2024-10-30 21:16:39 +01:00
Peter Knut
bdabc5aa13 Small CSS tuning 2024-10-30 21:16:39 +01:00
Peter Knut
92f3e0ca00 Reset the style of sortable row after dragging 2024-10-22 23:29:03 +02:00
Peter Knut
aa1266e4f2 Bump version to 4.10.1-dev 2024-10-22 23:29:03 +02:00
Peter Knut
b7bbd07155 Release 4.10 2024-10-22 17:10:38 +02:00
Peter Knut
1ff6f246e8 Add <div> for page footer, layout changes 2024-10-22 17:10:38 +02:00
Peter Knut
555e2e76b7 Keep backward compatibility with non-official plugins 2024-10-22 17:10:36 +02:00
Peter Knut
7883e0bd99 Update information files 2024-10-22 17:10:17 +02:00
Peter Knut
18e26a3b68 Add drag-n-drop moving of rows in table editing 2024-10-22 17:10:14 +02:00
Peter Knut
25a1ccf75b Refactor table editing, remove option to hide default values 2024-10-22 13:07:49 +02:00
Peter Knut
b9cdf52ec5 Add drag-n-drop moving of rows in table selection filter 2024-10-22 13:07:49 +02:00
Peter Knut
7997331b77 Hide arrow buttons in number input fields 2024-10-22 13:07:49 +02:00
Peter Knut
3bb75dc036 Fix missing SQL statement if warnings are printed
Regression from 4.9.
2024-10-22 13:07:49 +02:00
Adrian Jones
441e7f050c Check new version against GitHub pages 2024-10-22 13:07:49 +02:00
Peter Knut
c41cb51ede Change version layout 2024-10-22 13:07:49 +02:00
Peter Knut
42d92875c5 Print username next to the logout button 2024-10-22 13:07:49 +02:00
Peter Knut
df0e5b59bb Update readme.txt 2024-10-22 13:07:49 +02:00
Peter Knut
de9f572112 Elasticsearch: Add documentation link for regexp 2024-10-22 13:07:49 +02:00
Peter Knut
dd9a4a2b65 Remove deprecated HTML table parameters 2024-10-20 00:09:54 +02:00
Roy-Orbison
91d44f4a9f Plugin to auto-include adminer.js when present 2024-10-20 00:09:54 +02:00
Peter Knut
f993acb538 Do not display empty action links in main menu 2024-10-20 00:09:54 +02:00
Peter Knut
a87b606918 Remove a:visited style 2024-10-20 00:09:54 +02:00
Peter Knut
3e81c3871f Elasticsearch: New condition operators as the combination of query type and match type
- Support for regexp conditions.
- Proper formatting of boolean values.
2024-10-17 00:25:16 +02:00
Peter Knut
13752c0498 Define 'LIKE%%' operator in each driver 2024-10-17 00:25:16 +02:00
Peter Knut
e378f7d817 Update translations for regexp search 2024-10-17 00:25:16 +02:00
Roy-Orbison
6f789eac0a Enable regular expressions when searching data in all tables
Allows use of the database-specific regex operator and pattern syntax when searching multiple tables.
2024-10-17 00:25:16 +02:00
Roy Orbitson
9ed4c859ed Add removal buttons to table data filter 2024-10-17 00:25:16 +02:00
Peter Knut
62246338bf Add 'Home' to breadcrumb navigation 2024-10-17 00:25:16 +02:00
Peter Knut
e5a7f75807 Full width design for database select box 2024-10-17 00:25:16 +02:00
Peter Knut
279337aa65 Integrate tables-filter plugin into the base code 2024-10-17 00:25:16 +02:00
Peter Knut
bf1d16cdb7 Hide edited value if selected function will not use it 2024-10-17 00:25:16 +02:00
Peter Knut
1de9275f11 Show second link for editing a table under the table view, add table head to indexes 2024-10-17 00:25:16 +02:00
Peter Knut
0f2e04730f Show partitioning info in table structure page 2024-10-17 00:25:16 +02:00
Peter Knut
ae629f8ac7 Bump version to 4.10-dev 2024-10-17 00:25:16 +02:00
Peter Knut
0797cb6a10 Release 4.9.4 2024-10-09 22:09:31 +02:00
Peter Knut
dd122a1056 Clean up the code for PHP < 5.6 2024-10-09 22:00:13 +02:00
Peter Knut
96c0177422 Editor: Fix building links with array parameters
This solves a situation when enum data type has a foreign key to another table.
2024-10-09 09:19:37 +02:00
Peter Knut
7d6c7998d8 Editor: Fix array conversion to string (issue #3) 2024-10-08 22:59:57 +02:00
Peter Knut
3df88d4a24 Refactor opening adminer.sql[.gz] file 2024-10-07 23:58:10 +02:00
Peter Knut
2d4b73653b Refactor generating of private key and random strings
Generating of private key is atomic now.
More secure random strings on PHP 7+.
2024-10-07 23:38:33 +02:00
Peter Knut
a63fadd503 Refactor working with a locked file 2024-10-07 22:20:32 +02:00
Peter Knut
a494827dc5 Remove suppressing errors while reading local files with file_get_contents (issue #1) 2024-10-07 13:32:24 +02:00
Peter Knut
8ac486a57c Firefox: Fix opening a database to the new browser's tab with Ctrl+click 2024-10-06 00:44:02 +02:00
Peter Knut
bfcc6d8297 Better default value for object definition (*.*) while creating new database user 2024-10-04 10:03:00 +02:00
Peter Knut
29fd200ef5 Unify displaying of 'New item' action based on privileges 2024-10-04 00:44:39 +02:00
Peter Knut
b6058368d3 Fix the width of inline edit field 2024-10-03 23:33:34 +02:00
Peter Knut
fd38c4261a Bump version to 4.9.4-dev 2024-10-03 23:33:34 +02:00
Peter Knut
507f335371 Release 4.9.3 2024-10-02 17:07:09 +02:00
Peter Knut
ea314b8103 Hide invalid edit form if table record is not found 2024-10-02 09:35:59 +02:00
Peter Knut
e250470768 PostgreSQL: Fix editing record that contains a field with GENERATED ALWAYS default value
Fields with GENERATED ALWAYS default values are also disabled.

Thanks to PurpleTape (https://github.com/adminerevo/adminerevo/issues/201).
2024-10-02 00:29:24 +02:00
Peter Knut
2fa42d50eb Fix using undefined Min_DB::info property 2024-10-01 23:37:07 +02:00
Peter Knut
a366b7af09 MySQL: Fix editing user's proxy privilege, refactoring
- Uncheck all other priviledges if 'All privileges' is checked.
- Refactor related functions.
2024-10-01 23:22:26 +02:00
Peter Knut
b039a39e4d Bigger font size for code blocks 2024-10-01 09:07:21 +02:00
SeaEagle
08e48c8641 MySQL: Fix where clause for JSON column
Issue: https://github.com/adminerevo/adminerevo/issues/175
2024-10-01 09:06:20 +02:00
Peter Knut
78c2041cfd Fix background color of <pre> used as edit field 2024-10-01 00:33:47 +02:00
Peter Knut
5d7c5fa268 Do not include unchanged PARTITION BY definition into ALTER TABLE query 2024-09-22 00:33:55 +02:00
Peter Knut
8f1db4cf6f Add helper methods for dumping variable to the output 2024-09-21 22:34:38 +02:00
Peter Knut
9daa88acca MariaDB: Fix comparing CURRENT_TIMESTAMP definition while altering a table 2024-09-21 22:20:08 +02:00
Peter Knut
aa519b78ca MySQL, PostgreSQL: Fix queries splitting and string constants
Thanks to alxivnov (https://github.com/vrana/adminer/pull/490).
2024-09-21 09:28:50 +02:00
Michael Graß
aee800efed Do not limit unlimited memory, fix number conversion warning 2024-09-20 22:28:46 +02:00
Peter Knut
06d0f957d5 Bump version to 4.9.3-dev 2024-09-18 10:57:48 +02:00
113 changed files with 4512 additions and 2525 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1,2 +0,0 @@
patreon: jakubvrana
custom: ["https://sourceforge.net/p/adminer/donate/"]

1276
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

8
LICENSE.md Normal file
View File

@@ -0,0 +1,8 @@
Licenses
========
You may use Adminer under the terms of either the Apache License Version 2.0
or the GNU General Public License (GPL) version 2.
- [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)

170
README.md Normal file
View File

@@ -0,0 +1,170 @@
Adminer
=======
**Adminer** is a full-featured database management tool written in PHP. It consists of a single file ready to deploy to
the target server. As a companion, **Adminer Editor** offers data manipulation for end-users.
Supported database drivers:
- MySQL, MariaDB, PostgreSQL, SQLite, MS SQL, Oracle, MongoDB
- With plugin: SimpleDB, Elasticsearch (beta), Firebird (alpha), ClickHouse (alpha)
Requirements
------------
- PHP 5.6+ with enabled sessions.
Migration from original Adminer
-------------------------------
- Remove plugin AdminerTablesFilter (plugins/tables-filter.php).
- If you use complex custom theme, you will probably need to adjust a thing or two.
More information can be found in [Upgrade Guide](docs/upgrade.md).
Please, read also 👉 **[What to expect](#what-to-expect)** section before you decide to switch to this project.
Usage
-----
Download one for the latest [release files](https://github.com/pematon/adminer/releases), upload to the HTTP server
with PHP and enjoy 😉 If you are not satisfied with any combination of the database driver and language, you can
download the source code and compile your own Adminer:
- Download the source code.
- Run `composer install` to install dependencies.
- Run compile.php:
```shell
# Adminer
php compile.php <drivers> <languages>
# Editor
php compile.php editor <drivers> <languages>
```
For example:
```shell
php compile.php pgsql cs
php compile.php mysql,pgsql en,de,cs,sk
```
[Available drivers](https://github.com/pematon/adminer/tree/master/adminer/drivers),
[languages](https://github.com/pematon/adminer/tree/master/adminer/lang).
Security
--------
Adminer does not allow connecting to databases without a password and it rate-limits the connection attempts to protect
against brute-force attacks. Still, it is highly recommended to 🔒 **restrict access to Adminer** 🔒 by whitelisting IP
addresses allowed to connect to it, by password-protecting the access in your web server or by enabling security plugins
(e.g. to require an OTP).
Plugins
-------
* Download plugins you want and place them into the `plugins` folder.
* Create `index.php` file specifying which plugins do you want to use.
File structure will be:
```
- plugins
- drivers
- elastic.php
- dump-xml.php
- tinymce.php
- file-upload.php
- ...
- adminer.php
- index.php
```
Index.php:
```php
<?php
function adminer_object() {
// Required to run any plugin.
include_once "./plugins/plugin.php";
// Autoloader.
foreach (glob("plugins/*.php") as $filename) {
include_once "./$filename";
}
// Enable extra drivers just by including them.
include_once "./plugins/drivers/elastic.php";
// Specify enabled plugins.
$plugins = [
new AdminerDumpXml(),
new AdminerTinymce(),
new AdminerFileUpload("data/"),
// ...
];
// It is possible to combine customization and plugins.
// class AdminerCustomization extends AdminerPlugin {
// }
// return new AdminerCustomization($plugins);
return new AdminerPlugin($plugins);
}
// Include original Adminer or Adminer Editor.
include "./adminer.php";
```
[Available plugins](https://github.com/pematon/adminer/tree/master/plugins).
Main project files
------------------
- adminer/index.php - Run development version of Adminer.
- editor/index.php - Run development version of Adminer Editor.
- editor/example.php - Example customization.
- plugins/readme.txt - Plugins for Adminer and Adminer Editor.
- adminer/plugin.php - Plugin demo.
- adminer/sqlite.php - Development version of Adminer with SQLite allowed.
- editor/sqlite.php - Development version of Editor with SQLite allowed.
- adminer/designs.php - Development version of Adminer with adminer.css switcher.
- compile.php - Create a single file version.
- lang.php - Update translations.
- tests/katalon.html - Katalon Automation Recorder test suite.
Project history
---------------
Adminer was originally developed by Jakub Vrana, and it can be still found on [official pages](https://www.adminer.org/).
Unfortunately, it is not maintained for several years. In the meantime, I (@peterpp) created for my company a set of
custom plugins, modern theme, fixed some bugs and practically rewrote the Elasticsearch driver. I also looked closely
and contributed to the [AdminerEvo](https://www.adminerevo.org/) project that looked promising. However, I finally
decided to continue working on this fork and fulfill my own vision.
What to expect
--------------
Our top priority is fixing the security issues and reported bugs. But we really want to move forward and transform
Adminer to a tool that will keep its simplicity, yet looks much better, is even easier to use and can be configured
without requirement of additional plugins.
### Version 4.x
Original design and backward compatibility is kept. Many issues were fixed, and we introduced several functional and
UI improvements.
### Version 5
Bridges will be burned 🔥🔥🔥. It's in development already, so you [can check](https://github.com/pematon/adminer/tree/version-5)
what's going on. Or you can become the early adopter and help us with testing 😉
Our goals are:
- **Requirements** - Bump minimal PHP to 7.1, maybe even higher.
- **Themes** Modernize the current old-school theme, add new default theme based on our [Adminer theme](https://github.com/pematon/adminer-theme),
support dark mode, configurable color variants for production/devel environment. All current designs will be removed.
- **Plugins** - Integrate several basic plugins, enable them by optional configuration.
- **Codebase** - Prefer code readability before minimalism, use PER coding style, add namespaces.
- **Compilation** - Allow to export selected drivers, themes, languages and plugins into a single adminer.php file.
We are also thinking to change the project's name, so people will clearly distinguish between original Adminer and
other forks. Any suggestions are welcome.

View File

@@ -1,11 +1,13 @@
# Security Policy Reporting security issues
=========================
## Supported Versions To report a security issue, please [open a draft security advisory](https://github.com/pematon/adminer/security/advisories).
I support only the last published version and the last development version (last commit). Security issues are handled with top priority. Once acknowledged, a fix should be available and new version released
as soon as possible. Security advisories will be made public after a fix and new version have been released,
or the advisory has been declined.
## Reporting a Vulnerability Supported versions
------------------
To report a vulnerability, create a private bug at https://sourceforge.net/p/adminer/bugs-and-features/new/?private=1. Only the last published version and the last development version (last commit) are supported.
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.

View File

@@ -1,5 +1,6 @@
<?php <?php
$PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["call"]);
$PROCEDURE = ($_GET["name"] ?: $_GET["call"]);
page_header(lang('Call') . ": " . h($PROCEDURE), $error); page_header(lang('Call') . ": " . h($PROCEDURE), $error);
$routine = routine($_GET["call"], (isset($_GET["callf"]) ? "FUNCTION" : "PROCEDURE")); $routine = routine($_GET["call"], (isset($_GET["callf"]) ? "FUNCTION" : "PROCEDURE"));
@@ -28,13 +29,13 @@ if (!$error && $_POST) {
} }
$call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val); $call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val);
} }
$query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")"; $query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")";
$start = microtime(true); $start = microtime(true);
$result = $connection->multi_query($query); $result = $connection->multi_query($query);
$affected = $connection->affected_rows; // getting warnigns overwrites this $affected = $connection->affected_rows; // getting warnigns overwrites this
echo $adminer->selectQuery($query, $start, !$result); echo $adminer->selectQuery($query, $start, !$result);
if (!$result) { if (!$result) {
echo "<p class='error'>" . error() . "\n"; echo "<p class='error'>" . error() . "\n";
} else { } else {
@@ -42,7 +43,7 @@ if (!$error && $_POST) {
if (is_object($connection2)) { if (is_object($connection2)) {
$connection2->select_db(DB); $connection2->select_db(DB);
} }
do { do {
$result = $connection->store_result(); $result = $connection->store_result();
if (is_object($result)) { if (is_object($result)) {
@@ -53,16 +54,15 @@ if (!$error && $_POST) {
; ;
} }
} while ($connection->next_result()); } while ($connection->next_result());
if ($out) { if ($out) {
select($connection->query("SELECT " . implode(", ", $out))); select($connection->query("SELECT " . implode(", ", $out)));
} }
} }
} }
?>
<form action="" method="post"> echo "<form action='' method='post'>\n";
<?php
if ($in) { if ($in) {
echo "<table cellspacing='0' class='layout'>\n"; echo "<table cellspacing='0' class='layout'>\n";
foreach ($in as $key) { foreach ($in as $key) {
@@ -83,8 +83,28 @@ if ($in) {
} }
echo "</table>\n"; echo "</table>\n";
} }
?>
<p> echo "<p>",
<input type="submit" value="<?php echo lang('Call'); ?>"> "<input type='submit' value='", lang('Call'), "'>",
<input type="hidden" name="token" value="<?php echo $token; ?>"> "<input type='hidden' name='token' value='$token'>",
</form> "</p>\n",
"</form>\n";
$comment = $routine["comment"];
if ($comment !== null && $comment !== "") {
$comment = h(trim($routine["comment"], "\n"));
// Remove indenting of all lines (used in MySQL routines in 'sys' database).
if (preg_match('~^ +~', $comment, $matches)) {
preg_match_all("~^($matches[0]|$)~m", $comment, $linesWithIndent);
if (count($linesWithIndent[0]) == substr_count($comment, "\n")) {
$comment = preg_replace("~^($matches[0])~m", "", $comment);
}
}
// Format common headlines (used in MySQL routines in 'sys' database).
$comment = preg_replace('~(^|[^\n]\n)(Description|Parameters|Example)\n~', "$1\n<strong>$2</strong>\n", $comment);
echo "<pre class='comment'>$comment</pre>\n";
}

View File

@@ -82,20 +82,39 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
} }
$partitioning = ""; $partitioning = "";
if ($partition_by[$row["partition_by"]]) { if (support("partitioning")) {
$partitions = array(); if (isset($partition_by[$row["partition_by"]])) {
if ($row["partition_by"] == 'RANGE' || $row["partition_by"] == 'LIST') { $params = array_filter($row, function ($key) {
foreach (array_filter($row["partition_names"]) as $key => $val) { return preg_match('~^partition~', $key);
$value = $row["partition_values"][$key]; }, ARRAY_FILTER_USE_KEY);
$partitions[] = "\n PARTITION " . idf_escape($val) . " VALUES " . ($row["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
foreach ($params["partition_names"] as $key => $name) {
if ($name === "") {
unset($params["partition_names"][$key]);
unset($params["partition_values"][$key]);
}
} }
if ($params != get_partitions_info($TABLE)) {
$partitions = [];
if ($params["partition_by"] == 'RANGE' || $params["partition_by"] == 'LIST') {
foreach ($params["partition_names"] as $key => $name) {
$value = $params["partition_values"][$key];
$partitions[] = "\n PARTITION " . idf_escape($name) . " VALUES " . ($params["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
}
}
// $params["partition"] can be expression, not only column
$partitioning .= "\nPARTITION BY {$params["partition_by"]}({$params["partition"]})";
if ($partitions) {
$partitioning .= " (" . implode(",", $partitions) . "\n)";
} elseif ($params["partitions"]) {
$partitioning .= " PARTITIONS " . (int)$params["partitions"];
}
}
} elseif (preg_match("~partitioned~", $table_status["Create_options"])) {
$partitioning .= "\nREMOVE PARTITIONING";
} }
$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.'); $message = lang('Table has been altered.');
@@ -141,13 +160,9 @@ if (!$_POST) {
} }
if (support("partitioning")) { if (support("partitioning")) {
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($TABLE); $row += get_partitions_info($TABLE);
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); $row["partition_names"][] = "";
list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row(); $row["partition_values"][] = "";
$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);
} }
} }
} }
@@ -167,8 +182,8 @@ foreach ($engines as $engine) {
<p> <p>
<?php if (support("columns") || $TABLE == "") { ?> <?php if (support("columns") || $TABLE == "") { ?>
<?php echo lang('Table name'); ?>: <input name="name" data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off"> <?php echo lang('Table name'); ?>: <input name="name" data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php if ($TABLE == "" && !$_POST) { echo script("focus(qs('#form')['name']);"); } ?> <?php if ($TABLE == "" && !$_POST) { echo script("focus(gid('form')['name']);"); } ?>
<?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?> <?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . help_script_command("value", true) : ""); ?>
<?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?> <?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php } ?> <?php } ?>
@@ -184,7 +199,6 @@ edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
</div> </div>
<p> <p>
<?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>"> <?php echo lang('Auto Increment'); ?>: <input type="number" name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>">
<?php echo checkbox("defaults", 1, ($_POST ? $_POST["defaults"] : adminer_setting("defaults")), lang('Default values'), "columnShow(this.checked, 5)", "jsonly"); ?>
<?php <?php
$comments = ($_POST ? $_POST["comments"] : adminer_setting("comments")); $comments = ($_POST ? $_POST["comments"] : adminer_setting("comments"));
echo (support("comment") echo (support("comment")
@@ -207,7 +221,7 @@ if (support("partitioning")) {
print_fieldset("partition", lang('Partition by'), $row["partition_by"]); print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
?> ?>
<p> <p>
<?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?> <?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . help_script_command("value.replace(/./, 'PARTITION BY \$&')", true) . script("qsl('select').onchange = partitionByChange;"); ?>
(<input name="partition" value="<?php echo h($row["partition"]); ?>">) (<input name="partition" value="<?php echo h($row["partition"]); ?>">)
<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>"> <?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>">
<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>> <table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>

View File

@@ -66,7 +66,7 @@ echo ($_POST["add_x"] || strpos($name, "\n")
'mariadb' => "supported-character-sets-and-collations/", 'mariadb' => "supported-character-sets-and-collations/",
'mssql' => "ms187963.aspx", 'mssql' => "ms187963.aspx",
)) : ""); )) : "");
echo script("focus(qs('#name'));"); echo script("focus(gid('name'));");
?> ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php <?php

View File

@@ -47,7 +47,28 @@ if ($tables_views && !$error && !$_POST["search"]) {
page_header(($_GET["ns"] == "" ? lang('Database') . ": " . h(DB) : lang('Schema') . ": " . h($_GET["ns"])), $error, true); page_header(($_GET["ns"] == "" ? lang('Database') . ": " . h(DB) : lang('Schema') . ": " . h($_GET["ns"])), $error, true);
if ($adminer->homepage()) { if ($adminer->homepage()) {
if ($_GET["ns"] !== "") { if ($_GET["ns"] === "") {
echo "<h3 id='schemas'>" . lang('Schemas') . "</h3>\n";
$schemas = schemas();
if (!$schemas) {
echo "<p class='message'>" . lang('No schemas.') . "\n";
} else {
// TODO: Checkboxes for batch dropping of schemas.
echo "<div class='scrollable'>\n",
"<table class='nowrap'>\n",
'<thead><tr class="wrap">',
'<th>', lang('Schema'), "</th>",
'</tr></thead>';
foreach ($schemas as $name) {
echo "<tr", odd(), ">",
"<th><a href='", h(ME), "ns=" . urlencode($name), "' title='", lang('Show schema'), "'>" . h($name) . "</a></th>",
"</tr>";
}
echo '</table></div>';
}
} else {
echo "<h3 id='tables-views'>" . lang('Tables and views') . "</h3>\n"; echo "<h3 id='tables-views'>" . lang('Tables and views') . "</h3>\n";
$tables_list = tables_list(); $tables_list = tables_list();
if (!$tables_list) { if (!$tables_list) {
@@ -59,9 +80,13 @@ if ($adminer->homepage()) {
echo "<input type='search' name='query' value='" . h($_POST["query"]) . "'>"; echo "<input type='search' name='query' value='" . h($_POST["query"]) . "'>";
echo script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');", ""); echo script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');", "");
echo " <input type='submit' name='search' value='" . lang('Search') . "'>\n"; echo " <input type='submit' name='search' value='" . lang('Search') . "'>\n";
if ($adminer->operator_regexp !== null) {
echo "<p><label><input type='checkbox' name='regexp' value='1'" . (empty($_POST['regexp']) ? '' : ' checked') . '>' . lang('as a regular expression') . '</label>';
echo doc_link(['sql' => 'regexp.html', 'pgsql' => 'functions-matching.html#FUNCTIONS-POSIX-REGEXP', 'elastic' => "regexp-syntax.html"]) . "</p>\n";
}
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
if ($_POST["search"] && $_POST["query"] != "") { if ($_POST["search"] && $_POST["query"] != "") {
$_GET["where"][0]["op"] = $driver->convertOperator("LIKE %%"); $_GET["where"][0]["op"] = $adminer->operator_regexp !== null && !empty($_POST['regexp']) ? $adminer->operator_regexp : $adminer->operator_like;
search_tables(); search_tables();
} }
} }
@@ -69,7 +94,7 @@ if ($adminer->homepage()) {
echo "<table cellspacing='0' class='nowrap checkable'>\n"; echo "<table cellspacing='0' class='nowrap checkable'>\n";
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"); echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo '<thead><tr class="wrap">'; echo '<thead><tr class="wrap">';
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);", ""); echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("gid('check-all').onclick = partial(formCheck, /^(tables|views)\[/);", "");
echo '<th>' . lang('Table'); echo '<th>' . lang('Table');
echo '<td>' . lang('Engine') . doc_link(array('sql' => 'storage-engines.html')); echo '<td>' . lang('Engine') . doc_link(array('sql' => 'storage-engines.html'));
echo '<td>' . lang('Collation') . doc_link(array('sql' => 'charset-charsets.html', 'mariadb' => 'supported-character-sets-and-collations/')); echo '<td>' . lang('Collation') . doc_link(array('sql' => 'charset-charsets.html', 'mariadb' => 'supported-character-sets-and-collations/'));
@@ -122,17 +147,17 @@ if ($adminer->homepage()) {
echo "</div>\n"; echo "</div>\n";
if (!information_schema(DB)) { if (!information_schema(DB)) {
echo "<div class='footer'><div>\n"; echo "<div class='footer'><div>\n";
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . on_help("'VACUUM'"); $vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . help_script("VACUUM");
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . on_help($jush == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'"); $optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . help_script($jush == "sql" ? "OPTIMIZE TABLE" : "VACUUM OPTIMIZE");
echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>" echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>"
. ($jush == "sqlite" ? $vacuum . ($jush == "sqlite" ? $vacuum
: ($jush == "pgsql" ? $vacuum . $optimize : ($jush == "pgsql" ? $vacuum . $optimize
: ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . on_help("'ANALYZE TABLE'") . $optimize : ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . help_script("ANALYZE TABLE") . $optimize
. "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'CHECK TABLE'") . "<input type='submit' name='check' value='" . lang('Check') . "'> " . help_script("CHECK TABLE")
. "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . on_help("'REPAIR TABLE'") . "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . help_script("REPAIR TABLE")
: ""))) : "")))
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . on_help($jush == "sqlite" ? "'DELETE'" : "'TRUNCATE" . ($jush == "pgsql" ? "'" : " TABLE'")) . confirm() . "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . help_script($jush == "sqlite" ? "DELETE" : ("TRUNCATE" . ($jush == "pgsql" ? "" : " TABLE"))) . confirm()
. "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . on_help("'DROP TABLE'") . confirm() . "\n"; . "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . help_script("DROP TABLE") . confirm() . "\n";
$databases = (support("scheme") ? $adminer->schemas() : $adminer->databases()); $databases = (support("scheme") ? $adminer->schemas() : $adminer->databases());
if (count($databases) != 1 && $jush != "sqlite") { if (count($databases) != 1 && $jush != "sqlite") {
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB)); $db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
@@ -157,37 +182,59 @@ if ($adminer->homepage()) {
if (support("routine")) { if (support("routine")) {
echo "<h3 id='routines'>" . lang('Routines') . "</h3>\n"; echo "<h3 id='routines'>" . lang('Routines') . "</h3>\n";
$routines = routines(); $routines = routines();
if ($routines) { if ($routines) {
echo "<table cellspacing='0'>\n"; $commentsSupported = $routines[0]["ROUTINE_COMMENT"] !== null;
echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td></thead>\n";
echo "<table>\n";
echo '<thead><tr>',
'<th>', lang('Name'), '</th><td>', lang('Type'), '</td><td>', lang('Return type'), "</td>";
if ($commentsSupported) {
echo "<td>", lang('Comment'), "</td>";
}
echo "<td></td>",
"</tr></thead>\n";
odd(''); odd('');
foreach ($routines as $row) { 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 // not computed on the pages to be able to print the header first
echo '<tr' . odd() . '>'; $name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"]));
echo '<th><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'callf=' : 'call=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . h($row["ROUTINE_NAME"]) . '</a>';
echo '<td>' . h($row["ROUTINE_TYPE"]); echo '<tr', odd(), '>',
echo '<td>' . h($row["DTD_IDENTIFIER"]); '<th><a href="', h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'callf=' : 'call=') . urlencode($row["SPECIFIC_NAME"]) . $name), '">', h($row["ROUTINE_NAME"]), '</a></th>',
echo '<td><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'function=' : 'procedure=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . lang('Alter') . "</a>"; '<td>', h($row["ROUTINE_TYPE"]), '</td>',
'<td>', h($row["DTD_IDENTIFIER"]), '</td>';
if ($commentsSupported) {
echo '<td>', shorten_utf8(preg_replace('~\s{2,}~', " ", trim($row["ROUTINE_COMMENT"])), 50), '</td>';
}
echo '<td><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'function=' : 'procedure=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . lang('Alter') . "</a></td>";
} }
echo "</table>\n"; echo "</table>\n";
} }
echo '<p class="links">'
. (support("procedure") ? '<a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a>' : '') echo '<p class="links">',
. '<a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n" (support("procedure") ? '<a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a>' : ''),
; '<a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n";
} }
if (support("sequence")) { if (support("sequence")) {
echo "<h3 id='sequences'>" . lang('Sequences') . "</h3>\n"; echo "<h3 id='sequences'>" . lang('Sequences') . "</h3>\n";
$sequences = get_vals("SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = current_schema() ORDER BY sequence_name"); $sequences = get_vals("SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = current_schema() ORDER BY sequence_name");
if ($sequences) { if ($sequences) {
echo "<table cellspacing='0'>\n"; echo "<table>\n",
echo "<thead><tr><th>" . lang('Name') . "</thead>\n"; "<thead><tr><th>", lang('Name'), "</th><td></td></tr></thead>\n";
odd(''); odd('');
foreach ($sequences as $val) { foreach ($sequences as $val) {
echo "<tr" . odd() . "><th><a href='" . h(ME) . "sequence=" . urlencode($val) . "'>" . h($val) . "</a>\n"; echo "<tr", odd(), ">",
"<th>", h($val), "</th>",
"<td><a href='", h(ME), "sequence=", urlencode($val), "'>", lang('Alter'), "</a></td>\n";
} }
echo "</table>\n"; echo "</table>\n";
} }
echo "<p class='links'><a href='" . h(ME) . "sequence='>" . lang('Create sequence') . "</a>\n"; echo "<p class='links'><a href='" . h(ME) . "sequence='>" . lang('Create sequence') . "</a>\n";
@@ -197,12 +244,16 @@ if ($adminer->homepage()) {
echo "<h3 id='user-types'>" . lang('User types') . "</h3>\n"; echo "<h3 id='user-types'>" . lang('User types') . "</h3>\n";
$user_types = types(); $user_types = types();
if ($user_types) { if ($user_types) {
echo "<table cellspacing='0'>\n"; echo "<table>\n",
echo "<thead><tr><th>" . lang('Name') . "</thead>\n"; "<thead><tr><th>", lang('Name'), "</th><td></td></tr></thead>\n";
odd(''); odd('');
foreach ($user_types as $val) { foreach ($user_types as $val) {
echo "<tr" . odd() . "><th><a href='" . h(ME) . "type=" . urlencode($val) . "'>" . h($val) . "</a>\n"; echo "<tr", odd(), ">",
"<th>", h($val), "</th>",
"<td><a href='", h(ME), "type=", urlencode($val), "'>", lang('Alter'), "</a></td>\n";
} }
echo "</table>\n"; echo "</table>\n";
} }
echo "<p class='links'><a href='" . h(ME) . "type='>" . lang('Create type') . "</a>\n"; echo "<p class='links'><a href='" . h(ME) . "type='>" . lang('Create type') . "</a>\n";
@@ -212,7 +263,7 @@ if ($adminer->homepage()) {
echo "<h3 id='events'>" . lang('Events') . "</h3>\n"; echo "<h3 id='events'>" . lang('Events') . "</h3>\n";
$rows = get_rows("SHOW EVENTS"); $rows = get_rows("SHOW EVENTS");
if ($rows) { if ($rows) {
echo "<table cellspacing='0'>\n"; echo "<table>\n";
echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "<td></thead>\n"; echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "<td></thead>\n";
foreach ($rows as $row) { foreach ($rows as $row) {
echo "<tr>"; echo "<tr>";

View File

@@ -24,7 +24,7 @@ if (isset($_GET["mongo"])) {
$this->error = $e->getMessage(); $this->error = $e->getMessage();
} }
} }
function query($query) { function query($query) {
return false; return false;
} }
@@ -109,7 +109,7 @@ if (isset($_GET["mongo"])) {
class Min_Driver extends Min_SQL { class Min_Driver extends Min_SQL {
public $primary = "_id"; public $primary = "_id";
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) { function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
$select = ($select == array("*") $select = ($select == array("*")
? array() ? array()
@@ -127,7 +127,7 @@ if (isset($_GET["mongo"])) {
->skip($page * $limit) ->skip($page * $limit)
); );
} }
function insert($table, $set) { function insert($table, $set) {
try { try {
$return = $this->_conn->_db->selectCollection($table)->insert($set); $return = $this->_conn->_db->selectCollection($table)->insert($set);
@@ -205,8 +205,6 @@ if (isset($_GET["mongo"])) {
return $connection->_db->selectCollection($_GET["select"])->count($where); return $connection->_db->selectCollection($_GET["select"])->count($where);
} }
$operators = array("=");
} elseif (class_exists('MongoDB\Driver\Manager')) { } elseif (class_exists('MongoDB\Driver\Manager')) {
class Min_DB { class Min_DB {
var $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id; var $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id;
@@ -215,21 +213,20 @@ if (isset($_GET["mongo"])) {
var $_db, $_db_name; var $_db, $_db_name;
function connect($uri, $options) { function connect($uri, $options) {
$class = 'MongoDB\Driver\Manager';
$this->_link = new $class($uri, $options); $this->_link = new MongoDB\Driver\Manager($uri, $options);
$this->executeCommand('admin', array('ping' => 1)); $this->executeCommand('admin', array('ping' => 1));
} }
function executeCommand($db, $command) { function executeCommand($db, $command) {
$class = 'MongoDB\Driver\Command';
try { try {
return $this->_link->executeCommand($db, new $class($command)); return $this->_link->executeCommand($db, new MongoDB\Driver\Command($command));
} catch (Exception $e) { } catch (Exception $e) {
$this->error = $e->getMessage(); $this->error = $e->getMessage();
return array(); return array();
} }
} }
function executeBulkWrite($namespace, $bulk, $counter) { function executeBulkWrite($namespace, $bulk, $counter) {
try { try {
$results = $this->_link->executeBulkWrite($namespace, $bulk); $results = $this->_link->executeBulkWrite($namespace, $bulk);
@@ -340,9 +337,8 @@ if (isset($_GET["mongo"])) {
} }
$limit = min(200, max(1, (int) $limit)); $limit = min(200, max(1, (int) $limit));
$skip = $page * $limit; $skip = $page * $limit;
$class = 'MongoDB\Driver\Query';
try { try {
return new Min_Result($connection->_link->executeQuery("$connection->_db_name.$table", new $class($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort)))); return new Min_Result($connection->_link->executeQuery("$connection->_db_name.$table", new MongoDB\Driver\Query($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort))));
} catch (Exception $e) { } catch (Exception $e) {
$connection->error = $e->getMessage(); $connection->error = $e->getMessage();
return false; return false;
@@ -353,8 +349,7 @@ if (isset($_GET["mongo"])) {
global $connection; global $connection;
$db = $connection->_db_name; $db = $connection->_db_name;
$where = sql_query_where_parser($queryWhere); $where = sql_query_where_parser($queryWhere);
$class = 'MongoDB\Driver\BulkWrite'; $bulk = new MongoDB\Driver\BulkWrite(array());
$bulk = new $class(array());
if (isset($set['_id'])) { if (isset($set['_id'])) {
unset($set['_id']); unset($set['_id']);
} }
@@ -377,8 +372,7 @@ if (isset($_GET["mongo"])) {
global $connection; global $connection;
$db = $connection->_db_name; $db = $connection->_db_name;
$where = sql_query_where_parser($queryWhere); $where = sql_query_where_parser($queryWhere);
$class = 'MongoDB\Driver\BulkWrite'; $bulk = new MongoDB\Driver\BulkWrite(array());
$bulk = new $class(array());
$bulk->delete($where, array('limit' => $limit)); $bulk->delete($where, array('limit' => $limit));
return $connection->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount'); return $connection->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
} }
@@ -386,8 +380,7 @@ if (isset($_GET["mongo"])) {
function insert($table, $set) { function insert($table, $set) {
global $connection; global $connection;
$db = $connection->_db_name; $db = $connection->_db_name;
$class = 'MongoDB\Driver\BulkWrite'; $bulk = new MongoDB\Driver\BulkWrite(array());
$bulk = new $class(array());
if ($set['_id'] == '') { if ($set['_id'] == '') {
unset($set['_id']); unset($set['_id']);
} }
@@ -482,7 +475,11 @@ if (isset($_GET["mongo"])) {
} }
function sql_query_where_parser($queryWhere) { function sql_query_where_parser($queryWhere) {
$queryWhere = preg_replace('~^\sWHERE \(?\(?(.+?)\)?\)?$~', '\1', $queryWhere); $queryWhere = preg_replace('~^\s*WHERE\s*~', "", $queryWhere);
while ($queryWhere[0] == "(") {
$queryWhere = preg_replace('~^\((.*)\)$~', "$1", $queryWhere);
}
$wheres = explode(' AND ', $queryWhere); $wheres = explode(' AND ', $queryWhere);
$wheresOr = explode(') OR (', $queryWhere); $wheresOr = explode(') OR (', $queryWhere);
$where = array(); $where = array();
@@ -516,8 +513,7 @@ if (isset($_GET["mongo"])) {
$op = $match[1]; $op = $match[1];
} elseif (preg_match('~^\(date\)(.+)~', $op, $match)) { } elseif (preg_match('~^\(date\)(.+)~', $op, $match)) {
$dateTime = new DateTime($val); $dateTime = new DateTime($val);
$class = 'MongoDB\BSON\UTCDatetime'; $val = new MongoDB\BSON\UTCDatetime($dateTime->getTimestamp() * 1000);
$val = new $class($dateTime->getTimestamp() * 1000);
$op = $match[1]; $op = $match[1];
} }
switch ($op) { switch ($op) {
@@ -555,29 +551,6 @@ if (isset($_GET["mongo"])) {
} }
return $data; return $data;
} }
$operators = array(
"=",
"!=",
">",
"<",
">=",
"<=",
"regex",
"(f)=",
"(f)!=",
"(f)>",
"(f)<",
"(f)>=",
"(f)<=",
"(date)=",
"(date)!=",
"(date)>",
"(date)<",
"(date)>=",
"(date)<=",
);
} }
function table($idf) { function table($idf) {
@@ -627,6 +600,11 @@ if (isset($_GET["mongo"])) {
global $adminer; global $adminer;
$connection = new Min_DB; $connection = new Min_DB;
list($server, $username, $password) = $adminer->credentials(); list($server, $username, $password) = $adminer->credentials();
if ($server == "") {
$server = "localhost:27017";
}
$options = array(); $options = array();
if ($username . $password != "") { if ($username . $password != "") {
$options["username"] = $username; $options["username"] = $username;
@@ -734,11 +712,44 @@ if (isset($_GET["mongo"])) {
} }
function driver_config() { function driver_config() {
global $operators; if (class_exists('MongoDB')) {
$operators = ["="];
$operator_regexp = null;
} elseif (class_exists('MongoDB\Driver\Manager')) {
$operators = [
"=",
"!=",
">",
"<",
">=",
"<=",
"regex",
"(f)=",
"(f)!=",
"(f)>",
"(f)<",
"(f)>=",
"(f)<=",
"(date)=",
"(date)!=",
"(date)>",
"(date)<",
"(date)>=",
"(date)<=",
];
$operator_regexp = 'regex';
} else {
$operators = ["="];
$operator_regexp = null;
}
return array( return array(
'possible_drivers' => array("mongo", "mongodb"), 'possible_drivers' => array("mongo", "mongodb"),
'jush' => "mongo", 'jush' => "mongo",
'operators' => $operators, 'operators' => $operators,
'operator_like' => "LIKE %%", // TODO: LIKE operator is not listed in operators.
'operator_regexp' => $operator_regexp,
'functions' => array(), 'functions' => array(),
'grouping' => array(), 'grouping' => array(),
'edit_functions' => array(array("json")), 'edit_functions' => array(array("json")),

View File

@@ -24,11 +24,26 @@ if (isset($_GET["mssql"])) {
function connect($server, $username, $password) { function connect($server, $username, $password) {
global $adminer; global $adminer;
$connection_info = [
"UID" => $username,
"PWD" => $password,
"CharacterSet" => "UTF-8",
];
$ssl = $adminer->connectSsl();
if (isset($ssl["Encrypt"])) {
$connection_info["Encrypt"] = $ssl["Encrypt"];
}
if (isset($ssl["TrustServerCertificate"])) {
$connection_info["TrustServerCertificate"] = $ssl["TrustServerCertificate"];
}
$db = $adminer->database(); $db = $adminer->database();
$connection_info = array("UID" => $username, "PWD" => $password, "CharacterSet" => "UTF-8");
if ($db != "") { if ($db != "") {
$connection_info["Database"] = $db; $connection_info["Database"] = $db;
} }
$this->_link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info); $this->_link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info);
if ($this->_link) { if ($this->_link) {
$info = sqlsrv_server_info($this->_link); $info = sqlsrv_server_info($this->_link);
@@ -36,11 +51,13 @@ if (isset($_GET["mssql"])) {
} else { } else {
$this->_get_error(); $this->_get_error();
} }
return (bool) $this->_link; return (bool) $this->_link;
} }
function quote($string) { function quote($string) {
return "'" . str_replace("'", "''", $string) . "'"; $unicode = strlen($string) != strlen(utf8_decode($string));
return ($unicode ? "N" : "") . "'" . str_replace("'", "''", $string) . "'";
} }
function select_db($database) { function select_db($database) {
@@ -163,7 +180,8 @@ if (isset($_GET["mssql"])) {
} }
function quote($string) { function quote($string) {
return "'" . str_replace("'", "''", $string) . "'"; $unicode = strlen($string) != strlen(utf8_decode($string));
return ($unicode ? "N" : "") . "'" . str_replace("'", "''", $string) . "'";
} }
function select_db($database) { function select_db($database) {
@@ -301,6 +319,11 @@ if (isset($_GET["mssql"])) {
global $adminer; global $adminer;
$connection = new Min_DB; $connection = new Min_DB;
$credentials = $adminer->credentials(); $credentials = $adminer->credentials();
if ($credentials[0] == "") {
$credentials[0] = "localhost:1433";
}
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) { if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection; return $connection;
} }
@@ -432,7 +455,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
function error() { function error() {
global $connection; global $connection;
return nl_br(h(preg_replace('~^(\[[^]]*])+~m', '', $connection->error))); return nl2br(h(preg_replace('~^(\[[^]]*])+~m', '', $connection->error)));
} }
function create_database($db, $collation) { function create_database($db, $collation) {
@@ -637,6 +660,10 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
return false; return false;
} }
function is_c_style_escapes() {
return true;
}
function show_status() { function show_status() {
return array(); return array();
} }
@@ -671,6 +698,7 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
'structured_types' => $structured_types, 'structured_types' => $structured_types,
'unsigned' => array(), 'unsigned' => array(),
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"), 'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"),
'operator_like' => "LIKE %%",
'functions' => array("len", "lower", "round", "upper"), 'functions' => array("len", "lower", "round", "upper"),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"), 'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array( 'edit_functions' => array(

View File

@@ -1,8 +1,8 @@
<?php <?php
$drivers = array("server" => "MySQL") + $drivers; $drivers["mysql"] = "MySQL";
if (!defined("DRIVER")) { if (isset($_GET["mysql"])) {
define("DRIVER", "server"); // server - backwards compatibility define("DRIVER", "mysql");
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
if (extension_loaded("mysqli")) { if (extension_loaded("mysqli")) {
class Min_DB extends MySQLi { class Min_DB extends MySQLi {
@@ -14,7 +14,7 @@ if (!defined("DRIVER")) {
function connect($server = "", $username = "", $password = "", $database = null, $port = null, $socket = null) { function connect($server = "", $username = "", $password = "", $database = null, $port = null, $socket = null) {
global $adminer; global $adminer;
mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4 mysqli_report(MYSQLI_REPORT_OFF);
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
$ssl = $adminer->connectSsl(); $ssl = $adminer->connectSsl();
@@ -34,7 +34,7 @@ if (!defined("DRIVER")) {
$database, $database,
(is_numeric($port) ? $port : ini_get("mysqli.default_port")), (is_numeric($port) ? $port : ini_get("mysqli.default_port")),
(!is_numeric($port) ? $port : $socket), (!is_numeric($port) ? $port : $socket),
($ssl ? 64 : 0) // 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16) ($ssl ? MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT : 0)
); );
$this->options(MYSQLI_OPT_LOCAL_INFILE, false); $this->options(MYSQLI_OPT_LOCAL_INFILE, false);
return $return; return $return;
@@ -262,7 +262,7 @@ if (!defined("DRIVER")) {
} }
function set_charset($charset) { function set_charset($charset) {
$this->query("SET NAMES $charset"); // charset in DSN is ignored before PHP 5.3.6 $this->query("SET NAMES $charset");
} }
function select_db($database) { function select_db($database) {
@@ -371,16 +371,28 @@ if (!defined("DRIVER")) {
* @return mixed Min_DB or string for error * @return mixed Min_DB or string for error
*/ */
function connect() { function connect() {
global $adminer, $types, $structured_types; global $adminer, $types, $structured_types, $edit_functions;
$connection = new Min_DB; $connection = new Min_DB;
$credentials = $adminer->credentials(); $credentials = $adminer->credentials();
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) { if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
$connection->set_charset(charset($connection)); // available in MySQLi since PHP 5.0.5 $connection->set_charset(charset($connection));
$connection->query("SET sql_quote_show_create = 1, autocommit = 1"); $connection->query("SET sql_quote_show_create = 1, autocommit = 1");
if (min_version('5.7.8', 10.2, $connection)) {
if (min_version('5.7.8', '10.2', $connection)) {
$structured_types[lang('Strings')][] = "json"; $structured_types[lang('Strings')][] = "json";
$types["json"] = 4294967295; $types["json"] = 4294967295;
} }
// UUID data type for Mariadb >= 10.7
if (min_version('', '10.7', $connection)) {
$structured_types[lang('Strings')][] = "uuid";
$types["uuid"] = 128;
// insert/update function
$edit_functions[0]['uuid'] = 'uuid';
}
return $connection; return $connection;
} }
$return = $connection->error; $return = $connection->error;
@@ -500,11 +512,14 @@ if (!defined("DRIVER")) {
* @return array array($name => array("Name" => , "Engine" => , "Comment" => , "Oid" => , "Rows" => , "Collation" => , "Auto_increment" => , "Data_length" => , "Index_length" => , "Data_free" => )) or only inner array with $name * @return array array($name => array("Name" => , "Engine" => , "Comment" => , "Oid" => , "Rows" => , "Collation" => , "Auto_increment" => , "Data_length" => , "Index_length" => , "Data_free" => )) or only inner array with $name
*/ */
function table_status($name = "", $fast = false) { function table_status($name = "", $fast = false) {
$return = array(); if ($fast && min_version(5)) {
foreach (get_rows($fast && min_version(5) $query = "SELECT TABLE_NAME AS Name, ENGINE AS Engine, CREATE_OPTIONS AS Create_options, TABLE_COMMENT AS Comment FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() " . ($name != "" ? "AND TABLE_NAME = " . q($name) : "ORDER BY Name");
? "SELECT TABLE_NAME AS Name, ENGINE AS Engine, TABLE_COMMENT AS Comment FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() " . ($name != "" ? "AND TABLE_NAME = " . q($name) : "ORDER BY Name") } else {
: "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "") $query = "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "");
) as $row) { }
$tables = [];
foreach (get_rows($query) as $row) {
if ($row["Engine"] == "InnoDB") { if ($row["Engine"] == "InnoDB") {
// ignore internal comment, unnecessary since MySQL 5.1.21 // ignore internal comment, unnecessary since MySQL 5.1.21
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\1', $row["Comment"]); $row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\1', $row["Comment"]);
@@ -513,11 +528,15 @@ if (!defined("DRIVER")) {
$row["Comment"] = ""; $row["Comment"] = "";
} }
if ($name != "") { if ($name != "") {
// MariaDB: Table name is returned as lowercase on macOS, so we fix it here.
$row["Name"] = $name;
return $row; return $row;
} }
$return[$row["Name"]] = $row;
$tables[$row["Name"]] = $row;
} }
return $return;
return $tables;
} }
/** Find out whether the identifier is view /** Find out whether the identifier is view
@@ -894,23 +913,30 @@ if (!defined("DRIVER")) {
); );
} }
/** Get information about stored routine /**
* @param string * Gets information about stored routine.
* @param string "FUNCTION" or "PROCEDURE" *
* @return array ("fields" => array("field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ), "returns" => , "definition" => , "language" => ) * @param string $name
*/ * @param string $type "FUNCTION" or "PROCEDURE"
*
* @return array ("fields" => array("field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ), "returns" => , "definition" => , "language" => )
*/
function routine($name, $type) { function routine($name, $type) {
global $connection, $enum_length, $inout, $types; global $connection, $enum_length, $inout, $types;
$aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar");
$info = get_rows("SELECT ROUTINE_BODY, ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB) . " AND ROUTINE_NAME = " . q($name))[0];
$aliases = ["bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar"];
$space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)"; $space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
$type_pattern = "((" . implode("|", array_merge(array_keys($types), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum_length)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?"; $type_pattern = "((" . implode("|", array_merge(array_keys($types), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum_length)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : $inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern"; $pattern = "$space*(" . ($type == "FUNCTION" ? "" : $inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
$create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2); $create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match); preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match);
$fields = array(); $fields = [];
preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER); preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER);
foreach ($matches as $param) { foreach ($matches as $param) {
$fields[] = array( $fields[] = [
"field" => str_replace("``", "`", $param[2]) . $param[3], "field" => str_replace("``", "`", $param[2]) . $param[3],
"type" => strtolower($param[5]), "type" => strtolower($param[5]),
"length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]), "length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]),
@@ -919,24 +945,29 @@ if (!defined("DRIVER")) {
"full_type" => $param[4], "full_type" => $param[4],
"inout" => strtoupper($param[1]), "inout" => strtoupper($param[1]),
"collation" => strtolower($param[9]), "collation" => strtolower($param[9]),
); ];
} }
if ($type != "FUNCTION") {
return array("fields" => $fields, "definition" => $match[11]); return $type == "FUNCTION" ? [
}
return array(
"fields" => $fields, "fields" => $fields,
"returns" => array("type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]), "returns" => ["type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]],
"definition" => $match[17], "definition" => $match[17],
"language" => "SQL", // available in information_schema.ROUTINES.PARAMETER_STYLE "language" => $info["ROUTINE_BODY"],
); "comment" => $info["ROUTINE_COMMENT"],
] : [
"fields" => $fields,
"returns" => null,
"definition" => $match[11],
"language" => $info["ROUTINE_BODY"],
"comment" => $info["ROUTINE_COMMENT"],
];
} }
/** Get list of routines /** Get list of routines
* @return array ("SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => ) * @return array ("SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => )
*/ */
function routines() { function routines() {
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB)); return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER, ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB));
} }
/** Get list of available routine languages /** Get list of available routine languages
@@ -1074,6 +1105,16 @@ if (!defined("DRIVER")) {
return $strictMode; return $strictMode;
} }
function is_c_style_escapes() {
static $c_style = null;
if ($c_style === null) {
$c_style = strpos(get_key_vals("SHOW VARIABLES LIKE 'sql_mode'")["sql_mode"], 'NO_BACKSLASH_ESCAPES') === false;
}
return $c_style;
}
/** Get process list /** Get process list
* @return array ($row) * @return array ($row)
*/ */
@@ -1178,6 +1219,8 @@ if (!defined("DRIVER")) {
'structured_types' => $structured_types, 'structured_types' => $structured_types,
'unsigned' => array("unsigned", "zerofill", "unsigned zerofill"), ///< @var array number variants 'unsigned' => array("unsigned", "zerofill", "unsigned zerofill"), ///< @var array number variants
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL"), ///< @var array operators used in select 'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL"), ///< @var array operators used in select
'operator_like' => "LIKE %%",
'operator_regexp' => 'REGEXP',
'functions' => array("char_length", "date", "from_unixtime", "unix_timestamp", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper"), ///< @var array functions used in select 'functions' => array("char_length", "date", "from_unixtime", "unix_timestamp", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper"), ///< @var array functions used in select
'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"), ///< @var array grouping functions used in select 'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"), ///< @var array grouping functions used in select
'edit_functions' => array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only 'edit_functions' => array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only

View File

@@ -493,6 +493,10 @@ AND c_src.TABLE_NAME = " . q($table);
return false; return false;
} }
function is_c_style_escapes() {
return true;
}
function process_list() { function process_list() {
return get_rows('SELECT sess.process AS "process", sess.username AS "user", sess.schemaname AS "schema", sess.status AS "status", sess.wait_class AS "wait_class", sess.seconds_in_wait AS "seconds_in_wait", sql.sql_text AS "sql_text", sess.machine AS "machine", sess.port AS "port" return get_rows('SELECT sess.process AS "process", sess.username AS "user", sess.schemaname AS "schema", sess.status AS "status", sess.wait_class AS "wait_class", sess.seconds_in_wait AS "seconds_in_wait", sql.sql_text AS "sql_text", sess.machine AS "machine", sess.port AS "port"
FROM v$session sess LEFT OUTER JOIN v$sql sql FROM v$session sess LEFT OUTER JOIN v$sql sql
@@ -537,6 +541,7 @@ ORDER BY PROCESS
'structured_types' => $structured_types, 'structured_types' => $structured_types,
'unsigned' => array(), 'unsigned' => array(),
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL"), 'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL"),
'operator_like' => "LIKE %%",
'functions' => array("length", "lower", "round", "upper"), 'functions' => array("length", "lower", "round", "upper"),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"), 'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array( 'edit_functions' => array(

View File

@@ -488,7 +488,7 @@ ORDER BY connamespace, conname") as $row) {
if (preg_match('~^(.*\n)?([^\n]*)\n( *)\^(\n.*)?$~s', $return, $match)) { if (preg_match('~^(.*\n)?([^\n]*)\n( *)\^(\n.*)?$~s', $return, $match)) {
$return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\1<b>\2</b>', $match[2]) . $match[4]; $return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\1<b>\2</b>', $match[2]) . $match[4];
} }
return nl_br($return); return nl2br($return);
} }
function create_database($db, $collation) { function create_database($db, $collation) {
@@ -668,23 +668,29 @@ ORDER BY connamespace, conname") as $row) {
} }
function routine($name, $type) { function routine($name, $type) {
$rows = get_rows('SELECT routine_definition AS definition, LOWER(external_language) AS language, * $info = get_rows('SELECT routine_definition, external_language, type_udt_name
FROM information_schema.routines FROM information_schema.routines
WHERE routine_schema = current_schema() AND specific_name = ' . q($name)); WHERE routine_schema = current_schema() AND specific_name = ' . q($name))[0];
$return = $rows[0];
$return["returns"] = array("type" => $return["type_udt_name"]); $fields = get_rows('SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout
$return["fields"] = get_rows('SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout FROM information_schema.parameters
FROM information_schema.parameters WHERE specific_schema = current_schema() AND specific_name = ' . q($name) . '
WHERE specific_schema = current_schema() AND specific_name = ' . q($name) . ' ORDER BY ordinal_position');
ORDER BY ordinal_position');
return $return; return [
"fields" => $fields,
"returns" => ["type" => $info["type_udt_name"]],
"definition" => $info["routine_definition"],
"language" => strtolower($info["external_language"]),
"comment" => null, // Comments are not supported.
];
} }
function routines() { function routines() {
return get_rows('SELECT specific_name AS "SPECIFIC_NAME", routine_type AS "ROUTINE_TYPE", routine_name AS "ROUTINE_NAME", type_udt_name AS "DTD_IDENTIFIER" return get_rows('SELECT specific_name AS "SPECIFIC_NAME", routine_name AS "ROUTINE_NAME", routine_type AS "ROUTINE_TYPE", type_udt_name AS "DTD_IDENTIFIER", null AS ROUTINE_COMMENT
FROM information_schema.routines FROM information_schema.routines
WHERE routine_schema = current_schema() WHERE routine_schema = current_schema()
ORDER BY SPECIFIC_NAME'); ORDER BY SPECIFIC_NAME');
} }
function routine_languages() { function routine_languages() {
@@ -885,6 +891,16 @@ AND typelem = 0"
return false; return false;
} }
function is_c_style_escapes() {
static $c_style = null;
if ($c_style === null) {
$c_style = get_vals("SHOW standard_conforming_strings")[0] == "off";
}
return $c_style;
}
function process_list() { function process_list() {
return get_rows("SELECT * FROM pg_stat_activity ORDER BY " . (min_version(9.2) ? "pid" : "procpid")); return get_rows("SELECT * FROM pg_stat_activity ORDER BY " . (min_version(9.2) ? "pid" : "procpid"));
} }
@@ -936,7 +952,9 @@ AND typelem = 0"
'types' => $types, 'types' => $types,
'structured_types' => $structured_types, 'structured_types' => $structured_types,
'unsigned' => array(), 'unsigned' => array(),
'operators' => array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"), // no "SQL" to avoid CSRF 'operators' => array("=", "<", ">", "<=", ">=", "!=", "~", "~*", "!~", "!~*", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"), // no "SQL" to avoid CSRF
'operator_like' => "LIKE %%",
'operator_regexp' => '~*',
'functions' => array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper"), 'functions' => array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper"),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"), 'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array( 'edit_functions' => array(
@@ -949,6 +967,7 @@ AND typelem = 0"
"char|text" => "||", "char|text" => "||",
) )
), ),
'c_style_escapes' => true,
); );
} }
} }

View File

@@ -771,6 +771,10 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return false; return false;
} }
function is_c_style_escapes() {
return true;
}
function show_status() { function show_status() {
$return = array(); $return = array();
foreach (get_vals("PRAGMA compile_options") as $option) { foreach (get_vals("PRAGMA compile_options") as $option) {
@@ -800,6 +804,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
'structured_types' => array_keys($types), 'structured_types' => array_keys($types),
'unsigned' => array(), 'unsigned' => array(),
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"), // REGEXP can be user defined function 'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"), // REGEXP can be user defined function
'operator_like' => "LIKE %%",
'functions' => array("hex", "length", "lower", "round", "unixepoch", "upper"), 'functions' => array("hex", "length", "lower", "round", "unixepoch", "upper"),
'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"), 'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"),
'edit_functions' => array( 'edit_functions' => array(

View File

@@ -182,8 +182,8 @@ $prefixes = array();
if (DB != "") { if (DB != "") {
$checked = ($TABLE != "" ? "" : " checked"); $checked = ($TABLE != "" ? "" : " checked");
echo "<thead><tr>"; echo "<thead><tr>";
echo "<th style='text-align: left;'><label class='block'><input type='checkbox' id='check-tables'$checked>" . lang('Tables') . "</label>" . script("qs('#check-tables').onclick = partial(formCheck, /^tables\\[/);", ""); echo "<th style='text-align: left;'><label class='block'><input type='checkbox' id='check-tables'$checked>" . lang('Tables') . "</label>" . script("gid('check-tables').onclick = partial(formCheck, /^tables\\[/);", "");
echo "<th style='text-align: right;'><label class='block'>" . lang('Data') . "<input type='checkbox' id='check-data'$checked></label>" . script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);", ""); echo "<th style='text-align: right;'><label class='block'>" . lang('Data') . "<input type='checkbox' id='check-data'$checked></label>" . script("gid('check-data').onclick = partial(formCheck, /^data\\[/);", "");
echo "</thead>\n"; echo "</thead>\n";
$views = ""; $views = "";
@@ -208,7 +208,7 @@ if (DB != "") {
} else { } else {
echo "<thead><tr><th style='text-align: left;'>"; echo "<thead><tr><th style='text-align: left;'>";
echo "<label class='block'><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . ">" . lang('Database') . "</label>"; echo "<label class='block'><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . ">" . lang('Database') . "</label>";
echo script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);", ""); echo script("gid('check-databases').onclick = partial(formCheck, /^databases\\[/);", "");
echo "</thead>\n"; echo "</thead>\n";
$databases = $adminer->databases(); $databases = $adminer->databases();
if ($databases) { if ($databases) {

View File

@@ -3,13 +3,17 @@
class Adminer { class Adminer {
/** @var array operators used in select, null for all operators */ /** @var array operators used in select, null for all operators */
var $operators; var $operators = null;
/** @var string operator for LIKE condition */
var $operator_like = null;
/** @var string operator for regular expression condition */
var $operator_regexp = null;
/** Name in title and navigation /** Name in title and navigation
* @return string HTML code * @return string HTML code
*/ */
function name() { function name() {
return "<a href='https://www.adminer.org/'" . target_blank() . " id='h1'>Adminer</a>"; return "<a id='h1' href='" . h(HOME_URL) . "'>Adminer</a>";
} }
/** Connection parameters /** Connection parameters
@@ -25,12 +29,16 @@ class Adminer {
function connectSsl() { function connectSsl() {
} }
/** Get key used for permanent login /**
* @param bool * Gets a private key used for permanent login.
* @return string cryptic string which gets combined with password or false in case of an error *
*/ * @param bool $create
*
* @return string|false Cryptic string which gets combined with password or false in case of an error.
* @throws \Random\RandomException
*/
function permanentLogin($create = false) { function permanentLogin($create = false) {
return password_file($create); return get_private_key($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 key used to group brute force attacks; behind a reverse proxy, you want to return the last part of X-Forwarded-For
@@ -121,7 +129,7 @@ class Adminer {
echo "<table cellspacing='0' class='layout'>\n"; echo "<table cellspacing='0' class='layout'>\n";
echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);") . "\n"); echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);") . "\n");
echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">' . "\n"); echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">' . "\n");
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(qs('#username')); qs('#username').form['auth[driver]'].onchange();")); echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(gid('username')); gid('username').form['auth[driver]'].onchange();"));
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">' . "\n"); echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">' . "\n");
echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">' . "\n"); echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">' . "\n");
echo "</table>\n"; echo "</table>\n";
@@ -241,7 +249,7 @@ class Adminer {
if (!$failed && ($warnings = $driver->warnings())) { if (!$failed && ($warnings = $driver->warnings())) {
$id = "warnings"; $id = "warnings";
$result = ($supportSql ? "," : "") $result .= ($supportSql ? "," : "")
. " <a href='#$id'>" . lang('Warnings') . "</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "") . " <a href='#$id'>" . lang('Warnings') . "</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "")
. "</p>\n" . "</p>\n"
. "<div id='$id' class='hidden'>\n$warnings</div>\n"; . "<div id='$id' class='hidden'>\n$warnings</div>\n";
@@ -310,6 +318,11 @@ class Adminer {
* @return string * @return string
*/ */
function editVal($val, $field) { function editVal($val, $field) {
// Format Elasticsearch boolean value, but do not touch PostgreSQL boolean that use string value 't' or 'f'.
if ($field["type"] == "boolean" && is_bool($val)) {
return $val ? "true" : "false";
}
return $val; return $val;
} }
@@ -334,15 +347,40 @@ class Adminer {
echo "</div>\n"; echo "</div>\n";
} }
function tablePartitionsPrint($partition_info) {
$showList = $partition_info["partition_by"] == "RANGE" || $partition_info["partition_by"] == "LIST";
echo "<p>";
echo "<code>{$partition_info["partition_by"]} ({$partition_info["partition"]})</code>";
if (!$showList) {
echo " " . lang('Partitions') . ": " . h($partition_info["partitions"]);
}
echo "</p>";
if ($showList) {
echo "<table>\n";
echo "<thead><tr><th>" . lang('Partition') . "</th><td>" . lang('Values') . "</td></tr></thead>\n";
foreach ($partition_info["partition_names"] as $key => $name) {
echo "<tr><th>" . h($name) . "</th><td>" . h($partition_info["partition_values"][$key]) . "\n";
}
echo "</table>\n";
}
}
/** Print list of indexes on table in tabular format /** Print list of indexes on table in tabular format
* @param array data about all indexes on a table * @param array data about all indexes on a table
* @return null * @return null
*/ */
function tableIndexesPrint($indexes) { function tableIndexesPrint($indexes) {
echo "<table cellspacing='0'>\n"; echo "<table>\n";
echo "<thead><tr><th>" . lang('Type') . "</th><td>" . lang('Column (length)') . "</td></tr></thead>\n";
foreach ($indexes as $name => $index) { foreach ($indexes as $name => $index) {
ksort($index["columns"]); // enforce correct columns order ksort($index["columns"]); // enforce correct columns order
$print = array(); $print = [];
foreach ($index["columns"] as $key => $val) { foreach ($index["columns"] as $key => $val) {
$print[] = "<i>" . h($val) . "</i>" $print[] = "<i>" . h($val) . "</i>"
. ($index["lengths"][$key] ? "(" . $index["lengths"][$key] . ")" : "") . ($index["lengths"][$key] ? "(" . $index["lengths"][$key] . ")" : "")
@@ -351,92 +389,127 @@ class Adminer {
} }
echo "<tr title='" . h($name) . "'><th>$index[type]<td>" . implode(", ", $print) . "\n"; echo "<tr title='" . h($name) . "'><th>$index[type]<td>" . implode(", ", $print) . "\n";
} }
echo "</table>\n"; echo "</table>\n";
} }
/** Print columns box in select /**
* @param array result of selectColumnsProcess()[0] * Prints columns box in select filter.
* @param array selectable columns *
* @return null * @param array $select result of selectColumnsProcess()[0]
*/ * @param array $columns selectable columns
*/
function selectColumnsPrint($select, $columns) { function selectColumnsPrint($select, $columns) {
global $functions, $grouping; global $functions, $grouping;
print_fieldset("select", lang('Select'), $select);
print_fieldset("select", lang('Select'), $select, true);
$_GET["columns"][""] = [];
$i = 0; $i = 0;
$select[""] = array();
foreach ($select as $key => $val) { foreach ($_GET["columns"] as $key => $val) {
$val = $_GET["columns"][$key]; if ($key != "" && $val["col"] == "") continue;
$column = select_input( $column = select_input(
" name='columns[$i][col]'", "name='columns[$i][col]'",
$columns, $columns,
$val["col"], $val["col"],
($key !== "" ? "selectFieldChange" : "selectAddRow") $key !== "" ? "selectFieldChange" : "selectAddRow"
); );
echo "<div>" . ($functions || $grouping ? "<select name='columns[$i][fun]'>"
. optionlist(array(-1 => "") + array_filter(array(lang('Functions') => $functions, lang('Aggregation') => $grouping)), $val["fun"]) . "</select>" echo "<div ", ($key != "" ? "" : "class='no-sort'"), ">",
. on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1) "<span class='jsonly handle'></span>";
. script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "")
. "($column)" : $column) . "</div>\n"; if ($functions || $grouping) {
echo "<select name='columns[$i][fun]'>",
optionlist([-1 => ""] + array_filter([lang('Functions') => $functions, lang('Aggregation') => $grouping]), $val["fun"]),
"</select>",
help_script_command("value && value.replace(/ |\$/, '(') + ')'", true),
script("qsl('select').onchange = (event) => { " . ($key !== "" ? "" : " qsl('select, input:not(.remove)', event.target.parentNode).onchange();") . " };", ""),
"($column)";
} else {
echo $column;
}
echo " <input type='image' src='../adminer/static/cross.gif' class='jsonly icon remove' title='" . h(lang('Remove')) . "' alt='x'>",
script("qsl('#fieldset-select .remove').onclick = selectRemoveRow;", ""),
"</div>\n";
$i++; $i++;
} }
echo "</div></fieldset>\n";
echo "</div>", script("initSortable('#fieldset-select');"), "</fieldset>\n";
} }
/** Print search box in select /**
* @param array result of selectSearchProcess() * Prints search box in select.
* @param array selectable columns *
* @param array * @param array $where result of selectSearchProcess()
* @return null * @param array $columns selectable columns
*/ */
function selectSearchPrint($where, $columns, $indexes) { function selectSearchPrint($where, $columns, $indexes) {
print_fieldset("search", lang('Search'), $where); print_fieldset("search", lang('Search'), $where);
foreach ($indexes as $i => $index) { foreach ($indexes as $i => $index) {
if ($index["type"] == "FULLTEXT") { if ($index["type"] == "FULLTEXT") {
echo "<div>(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST"; echo "<div>(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST",
echo " <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>"; " <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>",
echo script("qsl('input').oninput = selectFieldChange;", ""); script("qsl('input').oninput = selectFieldChange;", ""),
echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL"); checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL"),
echo "</div>\n"; "</div>\n";
} }
} }
$change_next = "this.parentNode.firstChild.onchange();"; $change_next = "this.parentNode.firstChild.onchange();";
foreach (array_merge((array) $_GET["where"], array(array())) as $i => $val) { foreach (array_merge((array) $_GET["where"], array(array())) as $i => $val) {
if (!$val || ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators))) { if (!$val || ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators))) {
echo "<div>" . select_input( echo "<div>",
" name='where[$i][col]'", select_input(
$columns, " name='where[$i][col]'",
$val["col"], $columns,
($val ? "selectFieldChange" : "selectAddRow"), $val["col"],
"(" . lang('anywhere') . ")" ($val ? "selectFieldChange" : "selectAddRow"),
); "(" . lang('anywhere') . ")"
echo html_select("where[$i][op]", $this->operators, $val["op"], $change_next); ),
echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>"; html_select("where[$i][op]", $this->operators, $val["op"], $change_next),
echo script("mixin(qsl('input'), {oninput: function () { $change_next }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", ""); "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>",
echo "</div>\n"; script("mixin(qsl('input'), {oninput: function () { $change_next }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", ""),
" <input type='image' src='../adminer/static/cross.gif' class='jsonly icon remove' title='" . h(lang('Remove')) . "' alt='x'>",
script('qsl("#fieldset-search .remove").onclick = selectRemoveRow;', ""),
"</div>\n";
} }
} }
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
/** Print order box in select /**
* @param array result of selectOrderProcess() * Prints order box in select filter.
* @param array selectable columns *
* @param array * @param array $order result of selectOrderProcess()
* @return null * @param array $columns selectable columns
*/ */
function selectOrderPrint($order, $columns, $indexes) { function selectOrderPrint($order, $columns, $indexes) {
print_fieldset("sort", lang('Sort'), $order); print_fieldset("sort", lang('Sort'), $order, true);
$_GET["order"][""] = "";
$i = 0; $i = 0;
foreach ((array) $_GET["order"] as $key => $val) { foreach ((array) $_GET["order"] as $key => $val) {
if ($val != "") { if ($key != "" && $val == "") continue;
echo "<div>" . select_input(" name='order[$i]'", $columns, $val, "selectFieldChange");
echo checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')) . "</div>\n"; echo "<div ", ($key != "" ? "" : "class='no-sort'"), ">",
$i++; "<span class='jsonly handle'></span>",
} select_input("name='order[$i]'", $columns, $val, $key !== "" ? "selectFieldChange" : "selectAddRow"),
checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')),
" <input type='image' src='../adminer/static/cross.gif' class='jsonly icon remove' title='" . h(lang('Remove')) . "' alt='x'>",
script('qsl("#fieldset-sort .remove").onclick = selectRemoveRow;', ""),
"</div>\n";
$i++;
} }
echo "<div>" . select_input(" name='order[$i]'", $columns, "", "selectAddRow");
echo checkbox("desc[$i]", 1, false, lang('descending')) . "</div>\n"; echo "</div>", script("initSortable('#fieldset-sort');"), "</fieldset>\n";
echo "</div></fieldset>\n";
} }
/** Print limit box in select /** Print limit box in select
@@ -484,7 +557,7 @@ class Adminer {
json_row($key); json_row($key);
} }
echo ";\n"; echo ";\n";
echo "selectFieldChange.call(qs('#form')['select']);\n"; echo "selectFieldChange.call(gid('form')['select']);\n";
echo "</script>\n"; echo "</script>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -582,6 +655,8 @@ class Adminer {
&& (preg_match('~^[-\d.' . (preg_match('~IN$~', $op) ? ',' : '') . ']+$~', $val) || !preg_match('~' . number_type() . '|bit~', $field["type"])) && (preg_match('~^[-\d.' . (preg_match('~IN$~', $op) ? ',' : '') . ']+$~', $val) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
&& (!preg_match("~[\x80-\xFF]~", $val) || preg_match('~char|text|enum|set~', $field["type"])) && (!preg_match("~[\x80-\xFF]~", $val) || preg_match('~char|text|enum|set~', $field["type"]))
&& (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val)) && (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val))
&& (!preg_match('~^elastic~', DRIVER) || $field["type"] != "boolean" || preg_match('~true|false~', $val)) // Elasticsearch needs boolean value properly formatted.
&& (!preg_match('~^elastic~', DRIVER) || strpos($op, "regexp") === false || preg_match('~text|keyword~', $field["type"])) // Elasticsearch can use regexp only on text and keyword fields.
) { ) {
$cols[] = $prefix . $driver->convertSearch(idf_escape($name), $where, $field) . $cond; $cols[] = $prefix . $driver->convertSearch(idf_escape($name), $where, $field) . $cond;
} }
@@ -721,7 +796,7 @@ class Adminer {
* @param string * @param string
* @return string custom input field or empty string for default * @return string custom input field or empty string for default
*/ */
function editInput($table, $field, $attrs, $value) { function editInput($table, $field, $attrs, $value, $function) {
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "") return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
. ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "") . ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "")
@@ -937,9 +1012,11 @@ class Adminer {
return $ext; return $ext;
} }
/** Set the path of the file for webserver load /**
* @return string path of the sql dump file * Gets the path of the file for webserver load.
*/ *
* @return string Path of the sql import file.
*/
function importServerPath() { function importServerPath() {
return "adminer.sql"; return "adminer.sql";
} }
@@ -961,14 +1038,26 @@ class Adminer {
*/ */
function navigation($missing) { function navigation($missing) {
global $VERSION, $jush, $drivers, $connection; global $VERSION, $jush, $drivers, $connection;
?> ?>
<h1> <h1>
<?php echo $this->name(); ?> <?php echo $this->name(); ?>
<?php if ($missing != "auth"): ?>
<span class="version"><?php echo $VERSION; ?></span> <?php if ($missing != "auth"): ?>
<a href="https://www.adminer.org/#download"<?php echo target_blank(); ?> id="version"><?php echo (version_compare($VERSION, $_COOKIE["adminer_version"]) < 0 ? h($_COOKIE["adminer_version"]) : ""); ?></a> <span class="version">
<?php echo $VERSION; ?>
<a href="https://github.com/pematon/adminer/releases"<?php echo target_blank(); ?> id="version">
<?php echo (version_compare($VERSION, $_COOKIE["adminer_version"]) < 0 ? h($_COOKIE["adminer_version"]) : ""); ?>
</a>
</span>
<?php
if (!isset($_COOKIE["adminer_version"])) {
echo script("verifyVersion('" . js_escape(ME) . "', '" . get_token() . "');");
}
?>
<?php endif; ?> <?php endif; ?>
</h1> </h1>
<?php <?php
if ($missing == "auth") { if ($missing == "auth") {
$output = ""; $output = "";
@@ -978,14 +1067,21 @@ class Adminer {
if ($password !== null) { if ($password !== null) {
$dbs = $_SESSION["db"][$vendor][$server][$username]; $dbs = $_SESSION["db"][$vendor][$server][$username];
foreach (($dbs ? array_keys($dbs) : array("")) as $db) { foreach (($dbs ? array_keys($dbs) : array("")) as $db) {
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($drivers[$vendor]) " . h($username . ($server != "" ? "@" . $this->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n"; $output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>"
. h($drivers[$vendor])
. ($username != "" || $server != "" ? " - " : "")
. h($username)
. ($username != "" && $server != "" ? "@" : "")
. ($server != "" ? h($this->serverName($server)) : "")
. ($db != "" ? h(" - $db") : "")
. "</a></li>\n";
} }
} }
} }
} }
} }
if ($output) { if ($output) {
echo "<ul id='logins'>\n$output</ul>\n" . script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});"); echo "<ul id='logins'>\n$output</ul>\n" . script("mixin(gid('logins'), {onmouseover: menuOver, onmouseout: menuOut});");
} }
} else { } else {
$tables = array(); $tables = array();
@@ -1018,84 +1114,128 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
</script> </script>
<?php <?php
} }
$this->databasesPrint($missing); $this->databasesPrint($missing);
$actions = [];
if (DB == "" || !$missing) { if (DB == "" || !$missing) {
echo "<p class='links'>" . (support("sql") ? "<a href='" . h(ME) . "sql='" . bold(isset($_GET["sql"]) && !isset($_GET["import"])) . ">" . lang('SQL command') . "</a>\n<a href='" . h(ME) . "import='" . bold(isset($_GET["import"])) . ">" . lang('Import') . "</a>\n" : "") . ""; if (support("sql")) {
$actions[] = "<a href='" . h(ME) . "sql='" . bold(isset($_GET["sql"]) && !isset($_GET["import"])) . ">" . lang('SQL command') . "</a>";
$actions[] = "<a href='" . h(ME) . "import='" . bold(isset($_GET["import"])) . ">" . lang('Import') . "</a>";
}
if (support("dump")) { if (support("dump")) {
echo "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>\n"; $actions[] = "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>";
} }
} }
if ($_GET["ns"] !== "" && !$missing && DB != "") { if ($_GET["ns"] !== "" && !$missing && DB != "") {
echo '<a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create table') . "</a>\n"; $actions[] = '<a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create table') . "</a>\n";
if (!$tables) { }
echo "<p class='message'>" . lang('No tables.') . "\n"; if ($actions) {
} else { echo "<p class='links'>" . implode("\n", $actions) . "</p>";
}
if ($_GET["ns"] !== "" && !$missing && DB != "") {
if ($tables) {
$this->printTablesFilter();
$this->tablesPrint($tables); $this->tablesPrint($tables);
} else {
echo "<p class='message'>" . lang('No tables.') . "</p>\n";
} }
} }
} }
} }
/** Prints databases list in menu /**
* @param string * Prints databases select in menu.
* @return null *
*/ * @param $missing string
* @return null
*/
function databasesPrint($missing) { function databasesPrint($missing) {
global $adminer, $connection; global $adminer, $connection;
$databases = $this->databases(); $databases = $this->databases();
if (DB && $databases && !in_array(DB, $databases)) { if (DB && $databases && !in_array(DB, $databases)) {
array_unshift($databases, DB); array_unshift($databases, DB);
} }
?>
<form action=""> echo "<form action=''><p id='dbs'>";
<p id="dbs">
<?php
hidden_fields_get(); hidden_fields_get();
$db_events = script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");
echo "<span title='" . lang('database') . "'>" . lang('DB') . "</span>: " . ($databases if ($databases) {
? "<select name='db'>" . optionlist(array("" => "") + $databases, DB) . "</select>$db_events" echo "<select id='database-select' name='db'>" . optionlist(["" => lang('Database')] + $databases, DB) . "</select>"
: "<input name='db' value='" . h(DB) . "' autocapitalize='off'>\n" . script("mixin(gid('database-select'), {onmousedown: dbMouseDown, onchange: dbChange});");
); } else {
echo "<input id='database-select' name='db' value='" . h(DB) . "' autocapitalize='off'>\n";
}
echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n"; echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n";
if (support("scheme")) {
if ($missing != "db" && DB != "" && $connection->select_db(DB)) { if (support("scheme") && $missing != "db" && DB != "" && $connection->select_db(DB)) {
echo "<br>" . lang('Schema') . ": <select name='ns'>" . optionlist(array("" => "") + $adminer->schemas(), $_GET["ns"]) . "</select>$db_events"; echo "<br><select id='scheme-select' name='ns'>" . optionlist(["" => lang('Schema')] + $adminer->schemas(), $_GET["ns"]) . "</select>"
if ($_GET["ns"] != "") { . script("mixin(gid('scheme-select'), {onmousedown: dbMouseDown, onchange: dbChange});");
set_schema($_GET["ns"]);
} if ($_GET["ns"] != "") {
set_schema($_GET["ns"]);
} }
} }
foreach (array("import", "sql", "schema", "dump", "privileges") as $val) {
foreach (["import", "sql", "schema", "dump", "privileges"] as $val) {
if (isset($_GET[$val])) { if (isset($_GET[$val])) {
echo "<input type='hidden' name='$val' value=''>"; echo "<input type='hidden' name='$val' value=''>";
break; break;
} }
} }
echo "</p></form>\n"; echo "</p></form>\n";
return null;
} }
/** Prints table list in menu function printTablesFilter()
* @param array result of table_status('', true) {
* @return null global $adminer;
*/
echo "<div class='tables-filter jsonly'>"
. "<input id='tables-filter' autocomplete='off' placeholder='" . lang('Table') . "'>"
. script("initTablesFilter(" . json_encode($adminer->database()) . ");")
. "</div>\n";
}
/**
* Prints table list in menu.
*
* @param array $tables Result of table_status('', true)
* @return null
*/
function tablesPrint($tables) { function tablesPrint($tables) {
echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});"); echo "<ul id='tables'>" . script("mixin(gid('tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $table => $status) { foreach ($tables as $table => $status) {
$name = $this->tableName($status); $name = $this->tableName($status);
if ($name != "") { if ($name != "") {
$active = $table == $_GET["select"] || $table == $_GET["edit"];
echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"' echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"'
. bold($_GET["select"] == $table || $_GET["edit"] == $table, "select") . bold($active, "select")
. " title='" . lang('Select data') . "'>" . lang('select') . "</a> " . " title='" . lang('Select data') . "'>" . lang('select') . "</a> ";
;
echo (support("table") || support("indexes") if (support("table") || support("indexes")) {
? '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' $active = in_array($table, [$_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"]]);
. bold(in_array($table, array($_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"])), (is_view($status) ? "view" : "structure")) $class = is_view($status) ? "view" : "structure";
. " title='" . lang('Show structure') . "'>$name</a>"
: "<span>$name</span>" echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' . bold($active, $class)
) . "\n"; . " title='" . lang('Show structure') . "' data-main='true'>$name</a>";
} else {
echo "<span data-main='true'>$name</span>";
}
echo "</li>\n";
} }
} }
echo "</ul>\n"; echo "</ul>\n";
return null;
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
$connection = ''; $connection = '';
$has_token = $_SESSION["token"]; $has_token = $_SESSION["token"];
@@ -70,7 +71,7 @@ if (!function_exists('is_server_host_valid')) {
*/ */
function build_http_url($server, $username, $password, $defaultServer, $defaultPort = null) { function build_http_url($server, $username, $password, $defaultServer, $defaultPort = null) {
if (!preg_match('~^(https?://)?([^:]*)(:\d+)?$~', rtrim($server, '/'), $matches)) { if (!preg_match('~^(https?://)?([^:]*)(:\d+)?$~', rtrim($server, '/'), $matches)) {
$this->error = lang('Invalid server or credentials.'); auth_error(lang('Invalid server or credentials.'));
return false; return false;
} }
@@ -82,11 +83,11 @@ function build_http_url($server, $username, $password, $defaultServer, $defaultP
function add_invalid_login() { function add_invalid_login() {
global $adminer; global $adminer;
$fp = file_open_lock(get_temp_dir() . "/adminer.invalid"); $file = open_file_with_lock(get_temp_dir() . "/adminer.invalid");
if (!$fp) { if (!$file) {
return; return;
} }
$invalids = unserialize(stream_get_contents($fp)); $invalids = unserialize(stream_get_contents($file));
$time = time(); $time = time();
if ($invalids) { if ($invalids) {
foreach ($invalids as $ip => $val) { foreach ($invalids as $ip => $val) {
@@ -100,13 +101,16 @@ function add_invalid_login() {
$invalid = array($time + 30*60, 0); // active for 30 minutes $invalid = array($time + 30*60, 0); // active for 30 minutes
} }
$invalid[1]++; $invalid[1]++;
file_write_unlock($fp, serialize($invalids)); write_and_unlock_file($file, serialize($invalids));
} }
function check_invalid_login() { function check_invalid_login() {
global $adminer; global $adminer;
$invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist
$invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : array()); $filename = get_temp_dir() . "/adminer.invalid";
$invalids = file_exists($filename) ? unserialize(file_get_contents($filename)) : [];
$invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : []);
$next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts $next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts
if ($next_attempt > 0) { //! do the same with permanent login 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_error(lang('Too many unsuccessful logins, try again in %d minute(s).', ceil($next_attempt / 60)));
@@ -143,7 +147,7 @@ if ($auth) {
set_session($key, null); set_session($key, null);
} }
unset_permanent(); unset_permanent();
redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1), lang('Logout successful.') . ' ' . lang('Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.')); redirect(HOME_URL, lang('Logout successful.') . ' ' . lang('Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.'));
} elseif ($permanent && !$_SESSION["pwds"]) { } elseif ($permanent && !$_SESSION["pwds"]) {
session_regenerate_id(); session_regenerate_id();
@@ -168,9 +172,10 @@ function unset_permanent() {
} }
/** Renders an error message and a login form /** Renders an error message and a login form
* @param string plain text * @param string plain text
* @return null exits * @return null exits
*/ * @throws \Random\RandomException
*/
function auth_error($error) { function auth_error($error) {
global $adminer, $has_token; global $adminer, $has_token;
$session_name = session_name(); $session_name = session_name();
@@ -195,7 +200,7 @@ function auth_error($error) {
$error = lang('Session support must be enabled.'); $error = lang('Session support must be enabled.');
} }
$params = session_get_cookie_params(); $params = session_get_cookie_params();
cookie("adminer_key", ($_COOKIE["adminer_key"] ? $_COOKIE["adminer_key"] : rand_string()), $params["lifetime"]); cookie("adminer_key", ($_COOKIE["adminer_key"] ?: get_random_string()), $params["lifetime"]);
page_header(lang('Login'), $error, null); page_header(lang('Login'), $error, null);
echo "<form action='' method='post'>\n"; echo "<form action='' method='post'>\n";
echo "<div>"; echo "<div>";
@@ -209,6 +214,12 @@ function auth_error($error) {
exit; exit;
} }
if (isset($_GET["username"]) && !DRIVER) {
page_header(lang('No driver'), lang('Database driver not found.'), false);
page_footer("auth");
exit;
}
if (isset($_GET["username"]) && !class_exists("Min_DB")) { if (isset($_GET["username"]) && !class_exists("Min_DB")) {
unset($_SESSION["pwds"][DRIVER]); unset($_SESSION["pwds"][DRIVER]);
unset_permanent(); unset_permanent();

View File

@@ -6,6 +6,7 @@ function adminer_errors($errno, $errstr) {
error_reporting(6135); // errors and warnings error_reporting(6135); // errors and warnings
set_error_handler('adminer_errors', E_WARNING); set_error_handler('adminer_errors', E_WARNING);
include "../adminer/include/debug.inc.php";
include "../adminer/include/coverage.inc.php"; include "../adminer/include/coverage.inc.php";
// disable filter.default // disable filter.default
@@ -31,14 +32,14 @@ if (isset($_GET["file"])) {
} }
if ($_GET["script"] == "version") { if ($_GET["script"] == "version") {
$fp = file_open_lock(get_temp_dir() . "/adminer.version"); $file = open_file_with_lock(get_temp_dir() . "/adminer.version");
if ($fp) { if ($file) {
file_write_unlock($fp, serialize(array("signature" => $_POST["signature"], "version" => $_POST["version"]))); write_and_unlock_file($file, serialize(["version" => $_POST["version"]]));
} }
exit; 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 global $adminer, $connection, $driver, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $languages, $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 if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"]; $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
@@ -72,34 +73,73 @@ if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) {
@ini_set("zend.ze1_compatibility_mode", false); // @ - deprecated @ini_set("zend.ze1_compatibility_mode", false); // @ - deprecated
@ini_set("precision", 15); // @ - can be disabled, 15 - internal PHP precision @ini_set("precision", 15); // @ - can be disabled, 15 - internal PHP precision
// Migration for backward compatibility. This will keep MySQL users logged in.
if (isset($_GET["username"])) {
// Old 'server' URL param.
if (isset($_GET["server"])) {
$_GET["mysql"] = $_GET["server"];
unset($_GET["server"]);
}
// No URL param for any driver.
$driver_params = array_filter(["mysql", "pgsql", "sqlite", "sqlite2", "oracle", "mssql", "mongo", "clickhouse", "elastic", "elastic5", "firebird", "simpledb"], function ($driver) {
return isset($_GET[$driver]);
});
if (!$driver_params) {
$_GET["mysql"] = "";
}
// Migrate session data.
if (isset($_SESSION["pwds"]["server"])) {
foreach (["pwds", "db", "dbs", "queries"] as $key) {
if (isset($_SESSION[$key]["server"])) {
$_SESSION[$key]["mysql"] = $_SESSION[$key]["server"];
unset($_SESSION[$key]["server"]);
}
}
}
}
include "../adminer/include/lang.inc.php"; include "../adminer/include/lang.inc.php";
include "../adminer/lang/$LANG.inc.php"; include "../adminer/lang/$LANG.inc.php";
include "../adminer/include/pdo.inc.php"; include "../adminer/include/pdo.inc.php";
include "../adminer/include/driver.inc.php"; include "../adminer/include/driver.inc.php";
include "../adminer/drivers/sqlite.inc.php";
include "../adminer/drivers/mysql.inc.php";
include "../adminer/drivers/pgsql.inc.php"; include "../adminer/drivers/pgsql.inc.php";
include "../adminer/drivers/sqlite.inc.php";
include "../adminer/drivers/oracle.inc.php"; include "../adminer/drivers/oracle.inc.php";
include "../adminer/drivers/mssql.inc.php"; include "../adminer/drivers/mssql.inc.php";
include "../adminer/drivers/mongo.inc.php"; include "../adminer/drivers/mongo.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(); include "./include/adminer.inc.php";
$possible_drivers = $config['possible_drivers']; $adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer());
$jush = $config['jush'];
$types = $config['types']; if (defined("DRIVER")) {
$structured_types = $config['structured_types']; $config = driver_config();
$unsigned = $config['unsigned']; $possible_drivers = $config['possible_drivers'];
$operators = $config['operators']; $jush = $config['jush'];
$functions = $config['functions']; $types = $config['types'];
$grouping = $config['grouping']; $structured_types = $config['structured_types'];
$edit_functions = $config['edit_functions']; $unsigned = $config['unsigned'];
if ($adminer->operators === null) { $operators = $config['operators'];
$adminer->operators = $operators; $operator_like = $config['operator_like'];
$operator_regexp = $config['operator_regexp'];
$functions = $config['functions'];
$grouping = $config['grouping'];
$edit_functions = $config['edit_functions'];
if ($adminer->operators === null) {
$adminer->operators = $operators;
$adminer->operator_like = $operator_like;
$adminer->operator_regexp = $operator_regexp;
}
} else {
define("DRIVER", null);
} }
define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost define("SERVER", DRIVER ? $_GET[DRIVER] : null); // read from pgsql=localhost
define("DB", $_GET["db"]); // for the sake of speed and size define("DB", $_GET["db"]); // for the sake of speed and size
define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?' define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?'
. (sid() ? SID . '&' : '') . (sid() ? SID . '&' : '')
@@ -107,6 +147,7 @@ define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?'
. (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '') . (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
. (DB != "" ? 'db=' . urlencode(DB) . '&' . (isset($_GET["ns"]) ? "ns=" . urlencode($_GET["ns"]) . "&" : "") : '') . (DB != "" ? 'db=' . urlencode(DB) . '&' . (isset($_GET["ns"]) ? "ns=" . urlencode($_GET["ns"]) . "&" : "") : '')
); );
define("HOME_URL", substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1) ?: ".");
include "../adminer/include/version.inc.php"; include "../adminer/include/version.inc.php";
include "../adminer/include/design.inc.php"; include "../adminer/include/design.inc.php";

View File

@@ -0,0 +1,27 @@
<?php
function dump($value)
{
$cli = PHP_SAPI == 'cli';
if (!$cli) {
echo "<pre>";
}
$export = var_export($value, true);
$export = preg_replace('~=>\s+array\s*~', "=> array", $export);
$export = preg_replace('~\(\s+\)~', "()", $export);
echo $export;
if (!$cli) {
echo "</pre>";
}
echo "\n";
}
function dumpe($value)
{
dump($value);
exit;
}

View File

@@ -6,7 +6,7 @@
* @param string used after colon in title and heading, should be HTML escaped * @param string used after colon in title and heading, should be HTML escaped
* @return null * @return null
*/ */
function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") { function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
global $LANG, $VERSION, $adminer, $drivers, $jush; global $LANG, $VERSION, $adminer, $drivers, $jush;
page_headers(); page_headers();
if (is_ajax() && $error) { if (is_ajax() && $error) {
@@ -15,15 +15,24 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
} }
$title_all = $title . ($title2 != "" ? ": $title2" : ""); $title_all = $title . ($title2 != "" ? ": $title2" : "");
$title_page = strip_tags($title_all . (SERVER != "" && SERVER != "localhost" ? h(" - " . SERVER) : "") . " - " . $adminer->name()); $title_page = strip_tags($title_all . (SERVER != "" && SERVER != "localhost" ? h(" - " . SERVER) : "") . " - " . $adminer->name());
// Load Adminer version from file if cookie is missing.
$filename = get_temp_dir() . "/adminer.version";
if (!$_COOKIE["adminer_version"] && file_exists($filename) && ($lifetime = filemtime($filename) + 86400 - time()) > 0) { // 86400 - 1 day in seconds
$data = unserialize(file_get_contents($filename));
$_COOKIE["adminer_version"] = $data["version"];
cookie("adminer_version", $data["version"], $lifetime); // Sync expiration with the file.
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<?php echo $LANG; ?>" dir="<?php echo lang('ltr'); ?>"> <html lang="<?php echo $LANG; ?>" dir="<?php echo lang('ltr'); ?>">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
<title><?php echo $title_page; ?></title> <title><?php echo $title_page; ?></title>
<link rel="stylesheet" type="text/css" href="../adminer/static/default.css"> <link rel="stylesheet" type="text/css" href="../adminer/static/default.css?<?php echo filemtime("../adminer/static/default.css"); ?>">
<?php echo script_src("../adminer/static/functions.js"); ?> <?php echo script_src("../adminer/static/functions.js?" . filemtime("../adminer/static/functions.js")); ?>
<?php echo script_src("static/editing.js"); ?> <?php echo script_src("static/editing.js?" . filemtime("../adminer/static/editing.js")); ?>
<?php if ($adminer->head()) { ?> <?php if ($adminer->head()) { ?>
<link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico"> <link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico">
<link rel="apple-touch-icon" href="../adminer/static/favicon.ico"> <link rel="apple-touch-icon" href="../adminer/static/favicon.ico">
@@ -33,66 +42,63 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
<?php } ?> <?php } ?>
<body class="<?php echo lang('ltr'); ?> nojs"> <body class="<?php echo lang('ltr'); ?> nojs">
<?php
$filename = get_temp_dir() . "/adminer.version";
if (!$_COOKIE["adminer_version"] && function_exists('openssl_verify') && file_exists($filename) && filemtime($filename) + 86400 > 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
}
}
?>
<script<?php echo nonce(); ?>> <script<?php echo nonce(); ?>>
mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick<?php const body = document.body;
echo (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '$VERSION', '" . js_escape(ME) . "', '" . get_token() . "')"); // $token may be empty in auth.inc.php
?>}); body.onkeydown = bodyKeydown;
document.body.className = document.body.className.replace(/ nojs/, ' js'); body.onclick = bodyClick;
var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>'; body.classList.remove("nojs");
var thousandsSeparator = '<?php echo js_escape(lang(',')); ?>'; body.classList.add("js");
var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>';
var thousandsSeparator = '<?php echo js_escape(lang(',')); ?>';
</script> </script>
<div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div> <div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div>
<?php echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"); ?> <?php echo script("initHelpPopup();"); ?>
<div id="content"> <div id="content">
<?php <?php
if ($breadcrumb !== null) { if ($breadcrumb !== null) {
$link = substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1); echo '<p id="breadcrumb">';
echo '<p id="breadcrumb"><a href="' . h($link ? $link : ".") . '">' . $drivers[DRIVER] . '</a> &raquo; ';
$link = substr(preg_replace('~\b(db|ns)=[^&]*&~', '', ME), 0, -1); echo '<a href="' . h(HOME_URL) . '">' . lang('Home') . '</a> » ';
$server = $adminer->serverName(SERVER);
$server = ($server != "" ? $server : lang('Server')); $server = "";
if ($breadcrumb === false) { if ($breadcrumb === false) {
echo "$server\n"; $server .= h($drivers[DRIVER]) . ": ";
}
$server_name = $adminer->serverName(SERVER);
$server .= $server_name != "" ? h($server_name) : lang('Server');
if ($breadcrumb === false) {
echo h($server), "\n";
} else { } else {
echo "<a href='" . h($link) . "' accesskey='1' title='Alt+Shift+1'>$server</a> &raquo; "; $link = substr(preg_replace('~\b(db|ns)=[^&]*&~', '', ME), 0, -1);
echo "<a href='" . h($link) . "' accesskey='1' title='Alt+Shift+1'>$server</a> » ";
if ($_GET["ns"] != "" || (DB != "" && is_array($breadcrumb))) { if ($_GET["ns"] != "" || (DB != "" && is_array($breadcrumb))) {
echo '<a href="' . h($link . "&db=" . urlencode(DB) . (support("scheme") ? "&ns=" : "")) . '">' . h(DB) . '</a> &raquo; '; echo '<a href="' . h($link . "&db=" . urlencode(DB) . (support("scheme") ? "&ns=" : "")) . '">' . h(DB) . '</a> » ';
} }
if (is_array($breadcrumb)) { if (is_array($breadcrumb)) {
if ($_GET["ns"] != "") { if ($_GET["ns"] != "") {
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h($_GET["ns"]) . '</a> &raquo; '; echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h($_GET["ns"]) . '</a> » ';
} }
foreach ($breadcrumb as $key => $val) { foreach ($breadcrumb as $key => $val) {
$desc = (is_array($val) ? $val[1] : h($val)); $desc = (is_array($val) ? $val[1] : h($val));
if ($desc != "") { if ($desc != "") {
echo "<a href='" . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . "'>$desc</a> &raquo; "; echo "<a href='" . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . "'>$desc</a> » ";
} }
} }
} }
echo "$title\n"; echo "$title\n";
} }
} }
echo "<h2>$title_all</h2>\n"; echo "<h2>$title_all</h2>\n";
echo "<div id='ajaxstatus' class='jsonly hidden'></div>\n"; echo "<div id='ajaxstatus' class='jsonly hidden'></div>\n";
restart_session(); restart_session();
@@ -126,30 +132,40 @@ function page_headers() {
$adminer->headers(); $adminer->headers();
} }
/** Get Content Security Policy headers /**
* @return array of arrays with directive name in key, allowed sources in value * Gets Content Security Policy headers.
*/ *
* @return array of arrays with directive name in key, allowed sources in value
* @throws \Random\RandomException
*/
function csp() { function csp() {
return array( return [
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-' // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-'
"connect-src" => "'self'", "script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'",
"frame-src" => "https://www.adminer.org", "connect-src" => "'self' https://api.github.com/repos/pematon/adminer/releases/latest",
"frame-src" => "'self'",
"object-src" => "'none'", "object-src" => "'none'",
"base-uri" => "'none'", "base-uri" => "'none'",
"form-action" => "'self'", "form-action" => "'self'",
), ],
); ];
} }
/** Get a CSP nonce /**
* @return string Base64 value * Gets a CSP nonce.
*/ *
function get_nonce() { * @return string Base64 value.
* @throws \Random\RandomException
*/
function get_nonce()
{
static $nonce; static $nonce;
if (!$nonce) { if (!$nonce) {
$nonce = base64_encode(rand_string()); $nonce = base64_encode(get_random_string(true));
} }
return $nonce; return $nonce;
} }
@@ -169,27 +185,38 @@ function page_messages($error) {
} }
} }
/** Print HTML footer /**
* @param string "auth", "db", "ns" * Prints HTML footer.
* @return null *
*/ * @param ?string $missing "auth", "db", "ns"
function page_footer($missing = "") { */
function page_footer($missing = null)
{
global $adminer, $token; global $adminer, $token;
?>
</div>
<?php switch_lang(); ?> echo "</div>"; // #content
<?php if ($missing != "auth") { ?>
<form action="" method="post"> echo "<div id='footer'>\n";
<p class="logout"> language_select();
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" id="logout">
<input type="hidden" name="token" value="<?php echo $token; ?>"> if ($missing != "auth") {
</p> ?>
</form>
<?php } ?> <div class="logout">
<div id="menu"> <form action="" method="post">
<?php $adminer->navigation($missing); ?> <?php echo h($_GET["username"]); ?>
</div> <input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" id="logout">
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>
</div>
<?php <?php
}
echo "</div>\n";
echo "<div id='menu'>\n";
$adminer->navigation($missing);
echo "</div>\n";
echo script("setupSubmitHighlight(document);"); echo script("setupSubmitHighlight(document);");
} }

View File

@@ -151,14 +151,6 @@ function get_driver($id) {
return $idf; return $idf;
} }
/** Convert operator so it can be used in search
* @param string $operator
* @return string
*/
function convertOperator($operator) {
return $operator;
}
/** Convert value returned by database to actual value /** Convert value returned by database to actual value
* @param string * @param string
* @param array * @param array

View File

@@ -221,12 +221,17 @@ function process_type($field, $collate = "COLLATE") {
* @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT") * @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT")
*/ */
function process_field($field, $type_field) { function process_field($field, $type_field) {
// MariaDB exports CURRENT_TIMESTAMP as a function.
if ($field["on_update"]) {
$field["on_update"] = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $field["on_update"]);
}
return array( return array(
idf_escape(trim($field["field"])), idf_escape(trim($field["field"])),
process_type($type_field), process_type($type_field),
($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp ($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp
default_value($field), default_value($field),
(preg_match('~timestamp|datetime~', $field["type"]) && $field["on_update"] ? " ON UPDATE $field[on_update]" : ""), (preg_match('~timestamp|datetime~', $field["type"]) && $field["on_update"] ? " ON UPDATE " . $field["on_update"] : ""),
(support("comment") && $field["comment"] != "" ? " COMMENT " . q($field["comment"]) : ""), (support("comment") && $field["comment"] != "" ? " COMMENT " . q($field["comment"]) : ""),
($field["auto_increment"] ? auto_increment() : null), ($field["auto_increment"] ? auto_increment() : null),
); );
@@ -240,10 +245,13 @@ function default_value($field) {
$default = $field["default"]; $default = $field["default"];
if ($default === null) return ""; if ($default === null) return "";
if (preg_match('~^GENERATED ~i', $default)) { if (stripos($default, "GENERATED ") === 0) {
return " $default"; return " $default";
} }
// MariaDB exports CURRENT_TIMESTAMP as a function.
$default = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $default);
$quote = preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default); $quote = preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default);
return " DEFAULT " . ($quote ? q($default) : $default); return " DEFAULT " . ($quote ? q($default) : $default);
@@ -266,65 +274,106 @@ function type_class($type) {
} }
} }
/** Print table interior for fields editing /**
* @param array * Prints table interior for fields editing.
* @param array *
* @param string TABLE or PROCEDURE * @param string $type TABLE, FUNCTION or PROCEDURE
* @param array returned by referencable_primary() * @param array $foreign_keys returned by referencable_primary()
* @return null */
*/ function edit_fields(array $fields, array $collations, $type = "TABLE", $foreign_keys = []) {
function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = array()) {
global $inout; global $inout;
$fields = array_values($fields); $fields = array_values($fields);
$default_class = (($_POST ? $_POST["defaults"] : adminer_setting("defaults")) ? "" : " class='hidden'"); $comment_class = ($_POST ? $_POST["comments"] : adminer_setting("comments")) ? "" : "class='hidden'";
$comment_class = (($_POST ? $_POST["comments"] : adminer_setting("comments")) ? "" : " class='hidden'");
?> ?>
<thead><tr> <thead><tr>
<?php if ($type == "PROCEDURE") { ?><td><?php } ?> <?php
<th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?> if (support("move_col")) {
<td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("qs('#enum-edit').onblur = editingLengthBlur;"); ?> echo "<td class='jsonly'></td>";
<td id="label-length"><?php echo lang('Length'); ?> }
<td><?php echo lang('Options'); /* no label required, options have their own label */ ?> if ($type == "PROCEDURE") {
<?php if ($type == "TABLE") { ?> echo "<td></td>";
<td id="label-null">NULL }
<td><input type="radio" name="auto_increment_col" value=""><abbr id="label-ai" title="<?php echo lang('Auto Increment'); ?>">AI</abbr><?php echo doc_link(array( ?>
'sql' => "example-auto-increment.html", <th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?></th>
'mariadb' => "auto_increment/", <td id="label-type"><?php echo lang('Type'); ?><textarea id="enum-edit" rows="4" cols="12" wrap="off" style="display: none;"></textarea><?php echo script("gid('enum-edit').onblur = editingLengthBlur;"); ?></td>
'sqlite' => "autoinc.html", <td id="label-length"><?php echo lang('Length'); ?></td>
'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL", <td><?php echo lang('Options'); /* no label required, options have their own label */ ?></td>
'mssql' => "ms186775.aspx", <?php if ($type == "TABLE") { ?>
)); ?> <td id="label-null">NULL</td>
<td id="label-default"<?php echo $default_class; ?>><?php echo lang('Default value'); ?> <td><input type="radio" name="auto_increment_col" value=""><abbr id="label-ai" title="<?php echo lang('Auto Increment'); ?>">AI</abbr><?php echo doc_link([
<?php echo (support("comment") ? "<td id='label-comment'$comment_class>" . lang('Comment') : ""); ?> 'sql' => "example-auto-increment.html",
<?php } ?> 'mariadb' => "auto_increment/",
<td><?php echo "<input type='image' class='icon' name='add[" . (support("move_col") ? 0 : count($fields)) . "]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>" . script("row_count = " . count($fields) . ";"); ?> 'sqlite' => "autoinc.html",
</thead> 'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL",
<tbody> 'mssql' => "ms186775.aspx",
]); ?>
</td>
<td id="label-default"><?php echo lang('Default value'); ?></td>
<?php echo (support("comment") ? "<td id='label-comment' $comment_class>" . lang('Comment') . "</td>" : ""); ?>
<?php } ?>
<td><?php echo "<input type='image' class='icon' name='add[" . (support("move_col") ? 0 : count($fields)) . "]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>" . script("row_count = " . count($fields) . ";"); ?></td>
</tr></thead>
<?php <?php
echo script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});"); echo "<tbody>\n";
foreach ($fields as $i => $field) { foreach ($fields as $i => $field) {
$i++; $i++;
$orig = $field[($_POST ? "orig" : "field")]; $orig = $field[($_POST ? "orig" : "field")];
$display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i])) && (support("drop_col") || $orig == ""); $display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i])) && (support("drop_col") || $orig == "");
?>
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>> $style = $display ? "" : "style='display: none;'";
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $inout), $field["inout"]) : ""); ?> echo "<tr $style>\n";
<th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" data-maxlength="64" autocapitalize="off" aria-labelledby="label-name"><?php } ?>
<input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($orig); ?>"><?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?> if (support("move_col")) {
<?php if ($type == "TABLE") { ?> echo "<th class='handle jsonly'></th>";
<td><?php echo checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"); ?>
<td><label class="block"><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?> aria-labelledby="label-ai"></label><td<?php echo $default_class; ?>><?php
echo checkbox("fields[$i][has_default]", 1, $field["has_default"], "", "", "", "label-default"); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" aria-labelledby="label-default"><?php
echo (support("comment") ? "<td$comment_class><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' data-maxlength='" . (min_version(5.5) ? 1024 : 255) . "' aria-labelledby='label-comment'>" : "");
} }
if ($type == "PROCEDURE") {
echo "<td>", html_select("fields[$i][inout]", explode("|", $inout), $field["inout"]), "</td>\n";
}
echo "<th>";
if ($display) {
echo "<input name='fields[$i][field]' value='", h($field["field"]), "' data-maxlength='64' autocapitalize='off' aria-labelledby='label-name'>";
}
echo "<input type='hidden' name='fields[$i][orig]' value='", h($orig), "'>";
edit_type("fields[$i]", $field, $collations, $foreign_keys);
echo "</th>\n";
if ($type == "TABLE") {
echo "<td>", checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"), "</td>\n";
$checked = $field["auto_increment"] ? "checked" : "";
echo "<td><label class='block'><input type='radio' name='auto_increment_col' value='$i' $checked aria-labelledby='label-ai'></label></td>\n";
echo "<td>",
checkbox("fields[$i][has_default]", 1, $field["has_default"], "", "", "", "label-default"),
"<input name='fields[$i][default]' value='", h($field["default"]), "' aria-labelledby='label-default'>",
"</td>\n";
if (support("comment")) {
$max_length = min_version(5.5) ? 1024 : 255;
echo "<td $comment_class>",
"<input name='fields[$i][comment]' value='", h($field["comment"]), "' data-maxlength='$max_length' aria-labelledby='label-comment'>",
"</td>\n";
}
}
echo "<td>"; echo "<td>";
echo (support("move_col") ? if (support("move_col")) {
"<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'> " echo "<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'> ",
. "<input type='image' class='icon' name='up[$i]' src='../adminer/static/up.gif' alt='↑' title='" . lang('Move up') . "'> " "<input type='image' class='icon hidden' name='up[$i]' src='../adminer/static/up.gif' alt='↑' title='" . lang('Move up') . "'> ",
. "<input type='image' class='icon' name='down[$i]' src='../adminer/static/down.gif' alt='↓' title='" . lang('Move down') . "'> " "<input type='image' class='icon hidden' name='down[$i]' src='../adminer/static/down.gif' alt='↓' title='" . lang('Move down') . "'> ";
: ""); }
echo ($orig == "" || support("drop_col") ? "<input type='image' class='icon' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "'>" : ""); if ($orig == "" || support("drop_col")) {
echo "<input type='image' class='icon' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "'>";
}
echo "</td>\n</tr>\n";
} }
echo "</tbody>";
echo script("mixin(qs('#edit-fields tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput}); initSortable('#edit-fields tbody');");
} }
/** Move fields up and down or add field /** Move fields up and down or add field
@@ -376,25 +425,43 @@ function normalize_enum($match) {
return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0][0] . $match[0][0], $match[0][0], substr($match[0], 1, -1))), '\\')) . "'"; return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0][0] . $match[0][0], $match[0][0], substr($match[0], 1, -1))), '\\')) . "'";
} }
/** Issue grant or revoke commands /**
* @param string GRANT or REVOKE * Issue grant or revoke commands.
* @param array *
* @param string * @param bool $grant
* @param string * @param array $privileges
* @return bool * @param string $columns
*/ * @param string $on
function grant($grant, $privileges, $columns, $on) { * @param string $user
if (!$privileges) { *
return true; * @return bool
*/
function grant($grant, array $privileges, $columns, $on, $user) {
if (!$privileges) return true;
if ($privileges == ["ALL PRIVILEGES", "GRANT OPTION"]) {
if ($grant) {
return (bool) queries("GRANT ALL PRIVILEGES ON $on TO $user WITH GRANT OPTION");
} else {
return queries("REVOKE ALL PRIVILEGES ON $on FROM $user") &&
queries("REVOKE GRANT OPTION ON $on FROM $user");
}
} }
if ($privileges == array("ALL PRIVILEGES", "GRANT OPTION")) {
// can't be granted or revoked together if ($privileges == ["GRANT OPTION", "PROXY"]) {
return ($grant == "GRANT" if ($grant) {
? queries("$grant ALL PRIVILEGES$on WITH GRANT OPTION") return (bool) queries("GRANT PROXY ON $on TO $user WITH GRANT OPTION");
: queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on") } else {
); return (bool) queries("REVOKE PROXY ON $on FROM $user");
}
} }
return queries("$grant " . preg_replace('~(GRANT OPTION)\([^)]*\)~', '\1', implode("$columns, ", $privileges) . $columns) . $on);
return (bool) queries(
($grant ? "GRANT " : "REVOKE ") .
preg_replace('~(GRANT OPTION)\([^)]*\)~', '$1', implode("$columns, ", $privileges) . $columns) .
" ON $on " .
($grant ? "TO " : "FROM ") . $user
);
} }
/** Drop old object and create a new one /** Drop old object and create a new one
@@ -523,34 +590,46 @@ function tar_file($filename, $tmp_file) {
function ini_bytes($ini) { function ini_bytes($ini) {
$val = ini_get($ini); $val = ini_get($ini);
switch (strtolower(substr($val, -1))) { switch (strtolower(substr($val, -1))) {
case 'g': $val *= 1024; // no break case 'g': $val = (int)$val * 1024; // no break
case 'm': $val *= 1024; // no break case 'm': $val = (int)$val * 1024; // no break
case 'k': $val *= 1024; case 'k': $val = (int)$val * 1024;
} }
return $val; return $val;
} }
/** Create link to database documentation /**
* @param array $jush => $path * Creates link to database documentation.
* @param string HTML code *
* @return string HTML code * @param array $paths $jush => $path
*/ * @param string $text HTML code
function doc_link($paths, $text = "<sup>?</sup>") { *
* @return string HTML code
*/
function doc_link(array $paths, $text = "<sup>?</sup>") {
global $jush, $connection; global $jush, $connection;
$server_info = $connection->server_info; $server_info = $connection->server_info;
$version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits $version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits
$urls = array(
$urls = [
'sql' => "https://dev.mysql.com/doc/refman/$version/en/", 'sql' => "https://dev.mysql.com/doc/refman/$version/en/",
'sqlite' => "https://www.sqlite.org/", 'sqlite' => "https://www.sqlite.org/",
'pgsql' => "https://www.postgresql.org/docs/$version/", 'pgsql' => "https://www.postgresql.org/docs/$version/",
'mssql' => "https://msdn.microsoft.com/library/", 'mssql' => "https://msdn.microsoft.com/library/",
'oracle' => "https://www.oracle.com/pls/topic/lookup?ctx=db" . preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s', '\1\2', $server_info) . "&id=", 'oracle' => "https://www.oracle.com/pls/topic/lookup?ctx=db" . preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s', '\1\2', $server_info) . "&id=",
); 'elastic' => "https://www.elastic.co/guide/en/elasticsearch/reference/$version/",
];
if (preg_match('~MariaDB~', $server_info)) { if (preg_match('~MariaDB~', $server_info)) {
$urls['sql'] = "https://mariadb.com/kb/en/library/"; $urls['sql'] = "https://mariadb.com/kb/en/";
$paths['sql'] = (isset($paths['mariadb']) ? $paths['mariadb'] : str_replace(".html", "/", $paths['sql'])); $paths['sql'] = (isset($paths['mariadb']) ? $paths['mariadb'] : str_replace(".html", "/", $paths['sql']));
} }
return ($paths[$jush] ? "<a href='" . h($urls[$jush] . $paths[$jush]) . "'" . target_blank() . ">$text</a>" : "");
if (!isset($paths[$jush]) || !$paths[$jush] ) {
return "";
}
return "<a href='" . h($urls[$jush] . $paths[$jush]) . "'" . target_blank() . ">$text</a>";
} }
/** Wrap gzencode() for usage in ob_start() /** Wrap gzencode() for usage in ob_start()

View File

@@ -1,4 +1,5 @@
<?php <?php
/** Get database connection /** Get database connection
* @return Min_DB * @return Min_DB
*/ */
@@ -107,6 +108,9 @@ function min_version($version, $maria_db = "", $connection2 = null) {
$server_info = $match[1]; $server_info = $match[1];
$version = $maria_db; $version = $maria_db;
} }
if ($version == "") {
return false;
}
return (version_compare($server_info, $version) >= 0); return (version_compare($server_info, $version) >= 0);
} }
@@ -157,14 +161,6 @@ function h($string) {
return str_replace("\0", "&#0;", htmlspecialchars($string, ENT_QUOTES, 'utf-8')); return str_replace("\0", "&#0;", htmlspecialchars($string, ENT_QUOTES, 'utf-8'));
} }
/** Convert \n to <br>
* @param string
* @return string
*/
function nl_br($string) {
return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
}
/** Generate HTML checkbox /** Generate HTML checkbox
* @param string * @param string
* @param string * @param string
@@ -242,7 +238,7 @@ function html_select($name, $options, $value = "", $onchange = true, $labelled_b
*/ */
function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") { function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") {
$tag = ($options ? "select" : "input"); $tag = ($options ? "select" : "input");
return "<$tag$attrs" . ($options return "<$tag $attrs" . ($options
? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>" ? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
: " size='10' value='" . h($value) . "' placeholder='$placeholder'>" : " size='10' value='" . h($value) . "' placeholder='$placeholder'>"
) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input ) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input
@@ -257,18 +253,17 @@ function confirm($message = "", $selector = "qsl('input')") {
return script("$selector.onclick = function () { return confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "'); };", ""); return script("$selector.onclick = function () { return confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "'); };", "");
} }
/** Print header for hidden fieldset (close by </div></fieldset>) /**
* @param string * Prints header for hidden fieldset (close by </div></fieldset>)
* @param string * @param $id string
* @param bool * @param $legend string
* @return null */
*/ function print_fieldset($id, $legend, $visible = false, $sortable = false) {
function print_fieldset($id, $legend, $visible = false) {
echo "<fieldset><legend>"; echo "<fieldset><legend>";
echo "<a href='#fieldset-$id'>$legend</a>"; echo "<a href='#fieldset-$id'>$legend</a>";
echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", ""); echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", "");
echo "</legend>"; echo "</legend>";
echo "<div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n"; echo "<div id='fieldset-$id' class='" . ($visible ? "" : "hidden") . ($sortable ? " sortable" : "") . "'>\n";
} }
/** Return class='active' if $bold is true /** Return class='active' if $bold is true
@@ -477,24 +472,36 @@ function escape_key($key) {
*/ */
function where($where, $fields = array()) { function where($where, $fields = array()) {
global $connection, $jush; global $connection, $jush;
$return = array();
$conditions = [];
foreach ((array) $where["where"] as $key => $val) { foreach ((array) $where["where"] as $key => $val) {
$key = bracket_escape($key, 1); // 1 - back $key = bracket_escape($key, 1); // 1 - back
$column = escape_key($key); $column = escape_key($key);
$return[] = $column
. ($jush == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints if ($jush == "sql" && $fields[$key]["type"] == "json") {
: ($jush == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text $conditions[] = "$column = CAST(" . q($val) . " AS JSON)";
: " = " . unconvert_field($fields[$key], q($val)) } elseif ($jush == "sql" && is_numeric($val) && strpos($val, ".") !== false) {
)) // LIKE because of floats but slow with ints.
; //! enum and set $conditions[] = "$column LIKE " . q($val);
if ($jush == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters } elseif ($jush == "mssql") {
$return[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin"; // LIKE because of text.
$conditions[] = "$column LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val));
} else {
$conditions[] = "$column = " . unconvert_field($fields[$key], q($val));
}
// Not just [a-z] to catch non-ASCII characters.
if ($jush == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) {
$conditions[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin";
} }
} }
foreach ((array) $where["null"] as $key) { foreach ((array) $where["null"] as $key) {
$return[] = escape_key($key) . " IS NULL"; $conditions[] = escape_key($key) . " IS NULL";
} }
return implode(" AND ", $return);
return implode(" AND ", $conditions);
} }
/** Create SQL condition from query string /** Create SQL condition from query string
@@ -607,7 +614,7 @@ function auth_url($vendor, $server, $username, $db = null) {
preg_match('~([^?]*)\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . ($db !== null ? "db|" : "") . session_name()), $match); preg_match('~([^?]*)\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . ($db !== null ? "db|" : "") . session_name()), $match);
return "$match[1]?" return "$match[1]?"
. (sid() ? SID . "&" : "") . (sid() ? SID . "&" : "")
. ($vendor != "server" || $server != "" ? urlencode($vendor) . "=" . urlencode($server) . "&" : "") . urlencode($vendor) . "=" . urlencode($server) . "&"
. "username=" . urlencode($username) . "username=" . urlencode($username)
. ($db != "" ? "&db=" . urlencode($db) : "") . ($db != "" ? "&db=" . urlencode($db) : "")
. ($match[2] ? "&$match[2]" : "") . ($match[2] ? "&$match[2]" : "")
@@ -826,6 +833,8 @@ function is_utf8($val) {
* @return string escaped string with appended ... * @return string escaped string with appended ...
*/ */
function shorten_utf8($string, $length = 80, $suffix = "") { function shorten_utf8($string, $length = 80, $suffix = "") {
if ($string == "") return $suffix;
if (!preg_match("(^(" . repeat_pattern("[\t\r\n -\x{10FFFF}]", $length) . ")($)?)u", $string, $match)) { // ~s causes trash in $match[2] under some PHP versions, (.|\n) is slow if (!preg_match("(^(" . repeat_pattern("[\t\r\n -\x{10FFFF}]", $length) . ")($)?)u", $string, $match)) { // ~s causes trash in $match[2] under some PHP versions, (.|\n) is slow
preg_match("(^(" . repeat_pattern("[\t\r\n -~]", $length) . ")($)?)", $string, $match); preg_match("(^(" . repeat_pattern("[\t\r\n -~]", $length) . ")($)?)", $string, $match);
} }
@@ -886,7 +895,7 @@ function hidden_fields_get() {
*/ */
function table_status1($table, $fast = false) { function table_status1($table, $fast = false) {
$return = table_status($table, $fast); $return = table_status($table, $fast);
return ($return ? $return : array("Name" => $table)); return ($return ?: array("Name" => $table));
} }
/** Find out foreign keys for each column /** Find out foreign keys for each column
@@ -935,14 +944,15 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
*/ */
function input($field, $value, $function) { function input($field, $value, $function) {
global $types, $adminer, $jush; global $types, $adminer, $jush;
$name = h(bracket_escape($field["field"])); $name = h(bracket_escape($field["field"]));
echo "<td class='function'>";
if (is_array($value) && !$function) { if (is_array($value) && !$function) {
$args = array($value); $args = array($value);
if (version_compare(PHP_VERSION, 5.4) >= 0) { if (version_compare(PHP_VERSION, 5.4) >= 0) {
$args[] = JSON_PRETTY_PRINT; $args[] = JSON_PRETTY_PRINT;
} }
$value = call_user_func_array('json_encode', $args); //! requires PHP 5.2 $value = call_user_func_array('json_encode', $args);
$function = "json"; $function = "json";
} }
$reset = ($jush == "mssql" && $field["auto_increment"]); $reset = ($jush == "mssql" && $field["auto_increment"]);
@@ -950,18 +960,23 @@ function input($field, $value, $function) {
$function = null; $function = null;
} }
$functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field); $functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
$attrs = " name='fields[$name]'";
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
$attrs = " name='fields[$name]' $disabled";
echo "<td class='function'>";
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value); echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value, $function);
} else { } else {
$has_function = (in_array($function, $functions) || isset($functions[$function])); $has_function = (in_array($function, $functions) || isset($functions[$function]));
echo (count($functions) > 1 echo (count($functions) > 1
? "<select name='function[$name]'>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>" ? "<select name='function[$name]' $disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1) . help_script_command("value.replace(/^SQL\$/, '')", true)
. script("qsl('select').onchange = functionChange;", "") . script("qsl('select').onchange = functionChange;", "")
: h(reset($functions)) : h(reset($functions))
) . '<td>'; ) . '<td>';
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table $input = $adminer->editInput($_GET["edit"], $field, $attrs, $value, $function); // usage in call is without a table
if ($input != "") { if ($input != "") {
echo $input; echo $input;
} elseif (preg_match('~bool~', $field["type"])) { } elseif (preg_match('~bool~', $field["type"])) {
@@ -995,7 +1010,8 @@ function input($field, $value, $function) {
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator // type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
echo "<input" echo "<input"
. ((!$has_function || $function === "") && preg_match('~(?<!o)int(?!er)~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "") . ((!$has_function || $function === "") && preg_match('~(?<!o)int(?!er)~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "")
. " value='" . h($value) . "'" . ($maxlength ? " data-maxlength='$maxlength'" : "") . ($function != "now" ? " value='" . h($value) . "'" : " data-last-value='" . h($value) . "'")
. ($maxlength ? " data-maxlength='$maxlength'" : "")
. (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "") . (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "")
. "$attrs>" . "$attrs>"
; ;
@@ -1009,9 +1025,7 @@ function input($field, $value, $function) {
} }
$first++; $first++;
} }
if ($first) { echo script("mixin(qsl('td'), {onchange: partial(skipOriginal, $first), oninput: function () { this.onchange(); }});");
echo script("mixin(qsl('td'), {onchange: partial(skipOriginal, $first), oninput: function () { this.onchange(); }});");
}
} }
} }
@@ -1021,6 +1035,11 @@ function input($field, $value, $function) {
*/ */
function process_input($field) { function process_input($field) {
global $adminer, $driver; global $adminer, $driver;
if (stripos($field["default"], "GENERATED ALWAYS AS ") === 0) {
return null;
}
$idf = bracket_escape($field["field"]); $idf = bracket_escape($field["field"]);
$function = $_POST["function"][$idf]; $function = $_POST["function"][$idf];
$value = $_POST["fields"][$idf]; $value = $_POST["fields"][$idf];
@@ -1111,6 +1130,27 @@ function search_tables() {
echo ($sep ? "<p class='message'>" . lang('No tables.') : "</ul>") . "\n"; echo ($sep ? "<p class='message'>" . lang('No tables.') : "</ul>") . "\n";
} }
/**
* @param string $table
* @return array
*/
function get_partitions_info($table) {
global $connection;
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table);
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
$info = [];
list($info["partition_by"], $info["partition"], $info["partitions"]) = $result->fetch_row();
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
$info["partition_names"] = array_keys($partitions);
$info["partition_values"] = array_values($partitions);
return $info;
}
/** Send headers for export /** Send headers for export
* @param string * @param string
* @param bool * @param bool
@@ -1171,60 +1211,98 @@ function get_temp_dir() {
return $return; return $return;
} }
/** Open and exclusively lock a file /**
* @param string * Opens and exclusively lock a file.
* @return resource or null for error *
*/ * @param string $filename
function file_open_lock($filename) { * @return resource|null
$fp = @fopen($filename, "r+"); // @ - may not exist */
if (!$fp) { // c+ is available since PHP 5.2.6 function open_file_with_lock($filename)
$fp = @fopen($filename, "w"); // @ - may not be writable {
if (!$fp) { $file = fopen($filename, "c+");
return; if (!$file) {
} return null;
chmod($filename, 0660);
} }
flock($fp, LOCK_EX);
return $fp; chmod($filename, 0660);
if (!flock($file, LOCK_EX)) {
fclose($file);
return null;
}
return $file;
} }
/** Write and unlock a file /**
* @param resource * Writes and unlocks a file.
* @param string *
*/ * @param resource $file
function file_write_unlock($fp, $data) { * @param string $data
rewind($fp); */
fwrite($fp, $data); function write_and_unlock_file($file, $data)
ftruncate($fp, strlen($data)); {
flock($fp, LOCK_UN); rewind($file);
fclose($fp); fwrite($file, $data);
ftruncate($file, strlen($data));
unlock_file($file);
} }
/** Read password from file adminer.key in temporary directory or create one /**
* @param bool * Unlocks and closes the file.
* @return string or false if the file can not be created *
*/ * @param resource $file
function password_file($create) { */
function unlock_file($file)
{
flock($file, LOCK_UN);
fclose($file);
}
/**
* Reads password from file adminer.key in temporary directory or create one.
*
* @param $create bool
* @return string|false Returns false if the file can not be created.
* @throws \Random\RandomException
*/
function get_private_key($create)
{
$filename = get_temp_dir() . "/adminer.key"; $filename = get_temp_dir() . "/adminer.key";
$return = @file_get_contents($filename); // @ - may not exist
if ($return || !$create) { if (!$create && !file_exists($filename)) {
return $return; return false;
} }
$fp = @fopen($filename, "w"); // @ - can have insufficient rights //! is not atomic
if ($fp) { $file = open_file_with_lock($filename);
chmod($filename, 0660); if (!$file) {
$return = rand_string(); return false;
fwrite($fp, $return);
fclose($fp);
} }
return $return;
$key = stream_get_contents($file);
if (!$key) {
$key = get_random_string();
write_and_unlock_file($file, $key);
} else {
unlock_file($file);
}
return $key;
} }
/** Get a random string /**
* @return string 32 hexadecimal characters * Returns a random 32 characters long string.
*/ *
function rand_string() { * @param $binary bool
return md5(uniqid(mt_rand(), true)); * @return string
* @throws \Random\RandomException
*/
function get_random_string($binary = false)
{
$bytes = function_exists('random_bytes') ? random_bytes(32) : uniqid(mt_rand(), true);
return $binary ? $bytes : md5($bytes);
} }
/** Format value to use in select /** Format value to use in select
@@ -1244,7 +1322,7 @@ function select_value($val, $link, $field, $text_length) {
. "<td>" . select_value($v, $link, $field, $text_length) . "<td>" . select_value($v, $link, $field, $text_length)
; ;
} }
return "<table cellspacing='0'>$return</table>"; return "<table>$return</table>";
} }
if (!$link) { if (!$link) {
$link = $adminer->selectLink($val, $field); $link = $adminer->selectLink($val, $field);
@@ -1413,13 +1491,26 @@ function lzw_decompress($binary) {
return $return; return $return;
} }
/** Return events to display help on mouse over /**
* @param string JS expression * @param string $text Help text.
* @param bool JS expression * @param bool $side Side position.
* @return string *
*/ * @return string
function on_help($command, $side = 0) { */
return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", ""); function help_script($text, $side = false)
{
return script("initHelpFor(qsl('select, input'), '" . h($text) . "', $side);", "");
}
/**
* @param string $command JS expression for returning the help text.
* @param bool $side Side position.
*
* @return string
*/
function help_script_command($command, $side = false)
{
return script("initHelpFor(qsl('select, input'), (value) => { return $command; }, $side);", "");
} }
/** Print edit data form /** Print edit data form
@@ -1441,6 +1532,7 @@ function edit_form($table, $fields, $row, $update) {
$adminer->editRowPrint($table, $fields, $row, $update); $adminer->editRowPrint($table, $fields, $row, $update);
if ($row === false) { if ($row === false) {
echo "<p class='error'>" . lang('No rows.') . "\n"; echo "<p class='error'>" . lang('No rows.') . "\n";
return;
} }
?> ?>
<form action="" method="post" enctype="multipart/form-data" id="form"> <form action="" method="post" enctype="multipart/form-data" id="form">
@@ -1486,6 +1578,10 @@ function edit_form($table, $fields, $row, $update) {
$value = ""; $value = "";
$function = "now"; $function = "now";
} }
if ($field["type"] == "uuid" && $value == "uuid()") {
$value = "";
$function = "uuid";
}
input($field, $value, $function); input($field, $value, $function);
echo "\n"; echo "\n";
} }
@@ -1512,7 +1608,7 @@ function edit_form($table, $fields, $row, $update) {
} }
} }
echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n" echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n"
: ($_POST || !$fields ? "" : script("focus(qsa('td', qs('#form'))[1].firstChild);")) : ($_POST || !$fields ? "" : script("focus(qsa('td', gid('form'))[1].firstChild);"))
); );
if (isset($_GET["select"])) { if (isset($_GET["select"])) {
hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"])); hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"]));

View File

@@ -1,7 +1,6 @@
<?php <?php
// not used in a single language version
$langs = array( $languages = [
'en' => 'English', // Jakub Vrána - https://www.vrana.cz 'en' => 'English', // Jakub Vrána - https://www.vrana.cz
'ar' => 'العربية', // Y.M Amine - Algeria - nbr7@live.fr 'ar' => 'العربية', // Y.M Amine - Algeria - nbr7@live.fr
'bg' => 'Български', // Deyan Delchev 'bg' => 'Български', // Deyan Delchev
@@ -25,8 +24,8 @@ $langs = array(
'ja' => '日本語', // Hitoshi Ozawa - http://sourceforge.jp/projects/oss-ja-jpn/releases/ 'ja' => '日本語', // Hitoshi Ozawa - http://sourceforge.jp/projects/oss-ja-jpn/releases/
'ka' => 'ქართული', // Saba Khmaladze skhmaladze@uglt.org 'ka' => 'ქართული', // Saba Khmaladze skhmaladze@uglt.org
'ko' => '한국어', // dalli - skcha67@gmail.com 'ko' => '한국어', // dalli - skcha67@gmail.com
'lv' => 'Latviešu', // Kristaps Lediņš - https://krysits.com 'lv' => 'Latviešu', // Kristaps Lediņš - https://krysits.com
'lt' => 'Lietuvių', // Paulius Leščinskas - http://www.lescinskas.lt 'lt' => 'Lietuvių', // Paulius Leščinskas - http://www.lescinskas.lt
'ms' => 'Bahasa Melayu', // Pisyek 'ms' => 'Bahasa Melayu', // Pisyek
'nl' => 'Nederlands', // Maarten Balliauw - http://blog.maartenballiauw.be 'nl' => 'Nederlands', // Maarten Balliauw - http://blog.maartenballiauw.be
'no' => 'Norsk', // Iver Odin Kvello, mupublishing.com 'no' => 'Norsk', // Iver Odin Kvello, mupublishing.com
@@ -46,24 +45,59 @@ $langs = array(
'vi' => 'Tiếng Việt', // Giang Manh @ manhgd google mail 'vi' => 'Tiếng Việt', // Giang Manh @ manhgd google mail
'zh' => '简体中文', // Mr. Lodar, vea - urn2.net - vea.urn2@gmail.com 'zh' => '简体中文', // Mr. Lodar, vea - urn2.net - vea.urn2@gmail.com
'zh-tw' => '繁體中文', // http://tzangms.com 'zh-tw' => '繁體中文', // http://tzangms.com
); ];
/** Get current language /**
* @return string * Returns the list of available languages.
*/ * In compiled version, only selected languages are returned.
function get_lang() { *
* @return array
*/
function get_available_languages()
{
global $languages;
return $languages; // compile: available languages
}
/**
* Converts translation key into the right form.
* In compiled version, string keys used in plugins are dynamically translated to numeric keys.
*
* @param string|int $key
*
* @return string|int
*/
function convert_translation_key($key)
{
return $key; // compile: convert translation key
}
/**
* Returns current language.
*
* @return string
*/
function get_lang()
{
global $LANG; global $LANG;
return $LANG; return $LANG;
} }
/** Translate string /**
* @param string * Returns translated text.
* @param int *
* @return string * @param string|int $key Numeric key is used in compiled version.
*/ * @param ?int $number
function lang($idf, $number = null) { *
* @return string
*/
function lang($key, $number = null)
{
global $LANG, $translations; global $LANG, $translations;
$translation = ($translations[$idf] ? $translations[$idf] : $idf);
$key = convert_translation_key($key);
$translation = $translations[$key] ?: $key;
if (is_array($translation)) { if (is_array($translation)) {
$pos = ($number == 1 ? 0 $pos = ($number == 1 ? 0
: ($LANG == 'cs' || $LANG == 'sk' ? ($number && $number < 5 ? 1 : 2) // different forms for 1, 2-4, other : ($LANG == 'cs' || $LANG == 'sk' ? ($number && $number < 5 ? 1 : 2) // different forms for 1, 2-4, other
@@ -74,53 +108,77 @@ function lang($idf, $number = null) {
: ($LANG == 'bs' || $LANG == 'ru' || $LANG == 'sr' || $LANG == 'uk' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1 except 11, 2-4 except 12-14, other : ($LANG == 'bs' || $LANG == 'ru' || $LANG == 'sr' || $LANG == 'uk' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1 except 11, 2-4 except 12-14, other
: 1 // different forms for 1, other : 1 // different forms for 1, other
))))))); // http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html ))))))); // http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
$translation = $translation[$pos]; $translation = $translation[$pos];
} }
$args = func_get_args(); $args = func_get_args();
array_shift($args); array_shift($args);
$format = str_replace("%d", "%s", $translation); $format = str_replace("%d", "%s", $translation);
if ($format != $translation) { if ($format != $translation) {
$args[0] = format_number($number); $args[0] = format_number($number);
} }
return vsprintf($format, $args); return vsprintf($format, $args);
} }
function switch_lang() { function language_select()
global $LANG, $langs; {
echo "<form action='' method='post'>\n<div id='lang'>"; global $LANG, $languages;
echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();");
$available_languages = get_available_languages();
if (count($available_languages) == 1) {
return;
}
$options = [];
foreach ($languages as $language => $title) {
if (isset($available_languages[$language])) {
$options[$language] = $title;
}
}
echo "<div id='lang'><form action='' method='post'>\n";
echo lang('Language') . ": " . html_select("lang", $options, $LANG, "this.form.submit();");
echo " <input type='submit' value='" . lang('Use') . "' class='hidden'>\n"; echo " <input type='submit' value='" . lang('Use') . "' class='hidden'>\n";
echo "<input type='hidden' name='token' value='" . get_token() . "'>\n"; // $token may be empty in auth.inc.php echo "<input type='hidden' name='token' value='" . get_token() . "'>\n"; // $token may be empty in auth.inc.php
echo "</div>\n</form>\n"; echo "</form></div>\n";
} }
if (isset($_POST["lang"]) && verify_token()) { // $error not yet available if (isset($_POST["lang"]) && verify_token()) { // $error not yet available
cookie("adminer_lang", $_POST["lang"]); cookie("adminer_lang", $_POST["lang"]);
$_SESSION["lang"] = $_POST["lang"]; // cookies may be disabled $_SESSION["lang"] = $_POST["lang"]; // cookies may be disabled
$_SESSION["translations"] = array(); // used in compiled version $_SESSION["translations"] = []; // used in compiled version
redirect(remove_from_uri()); redirect(remove_from_uri());
} }
$LANG = "en"; $available_languages = get_available_languages();
if (isset($langs[$_COOKIE["adminer_lang"]])) { $LANG = $available_languages[0];
if (isset($available_languages[$_COOKIE["adminer_lang"]])) {
cookie("adminer_lang", $_COOKIE["adminer_lang"]); cookie("adminer_lang", $_COOKIE["adminer_lang"]);
$LANG = $_COOKIE["adminer_lang"]; $LANG = $_COOKIE["adminer_lang"];
} elseif (isset($langs[$_SESSION["lang"]])) { } elseif (isset($available_languages[$_SESSION["lang"]])) {
$LANG = $_SESSION["lang"]; $LANG = $_SESSION["lang"];
} else { } else {
$accept_language = array(); $accept_language = [];
preg_match_all('~([-a-z]+)(;q=([0-9.]+))?~', str_replace("_", "-", strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"])), $matches, PREG_SET_ORDER); preg_match_all('~([-a-z]+)(;q=([0-9.]+))?~', str_replace("_", "-", strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"])), $matches, PREG_SET_ORDER);
foreach ($matches as $match) { foreach ($matches as $match) {
$accept_language[$match[1]] = (isset($match[3]) ? $match[3] : 1); $accept_language[$match[1]] = (isset($match[3]) ? $match[3] : 1);
} }
arsort($accept_language); arsort($accept_language);
foreach ($accept_language as $key => $q) { foreach ($accept_language as $key => $q) {
if (isset($langs[$key])) { if (isset($available_languages[$key])) {
$LANG = $key; $LANG = $key;
break; break;
} }
$key = preg_replace('~-.*~', '', $key); $key = preg_replace('~-.*~', '', $key);
if (!isset($accept_language[$key]) && isset($langs[$key])) { if (!isset($accept_language[$key]) && isset($available_languages[$key])) {
$LANG = $key; $LANG = $key;
break; break;
} }

View File

@@ -3,7 +3,7 @@
if (extension_loaded('pdo')) { if (extension_loaded('pdo')) {
/*abstract*/ class Min_PDO { /*abstract*/ class Min_PDO {
var $_result, $server_info, $affected_rows, $errno, $error, $pdo; var $_result, $server_info, $affected_rows, $errno, $error, $pdo;
function __construct() { function __construct() {
global $adminer; global $adminer;
$pos = array_search("SQL", $adminer->operators); $pos = array_search("SQL", $adminer->operators);
@@ -11,10 +11,10 @@ if (extension_loaded('pdo')) {
unset($adminer->operators[$pos]); unset($adminer->operators[$pos]);
} }
} }
function dsn($dsn, $username, $password, $options = array()) { function dsn($dsn, $username, $password, $options = []) {
$options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT; $options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
$options[PDO::ATTR_STATEMENT_CLASS] = array('Min_PDOStatement'); $options[PDO::ATTR_STATEMENT_CLASS] = [Min_PDOStatement::class];
try { try {
$this->pdo = new PDO($dsn, $username, $password, $options); $this->pdo = new PDO($dsn, $username, $password, $options);
} catch (Exception $ex) { } catch (Exception $ex) {
@@ -22,13 +22,13 @@ if (extension_loaded('pdo')) {
} }
$this->server_info = @$this->pdo->getAttribute(PDO::ATTR_SERVER_VERSION); $this->server_info = @$this->pdo->getAttribute(PDO::ATTR_SERVER_VERSION);
} }
/*abstract function select_db($database);*/ /*abstract function select_db($database);*/
function quote($string) { function quote($string) {
return $this->pdo->quote($string); return $this->pdo->quote($string);
} }
function query($query, $unbuffered = false) { function query($query, $unbuffered = false) {
$result = $this->pdo->query($query); $result = $this->pdo->query($query);
$this->error = ""; $this->error = "";
@@ -42,11 +42,11 @@ if (extension_loaded('pdo')) {
$this->store_result($result); $this->store_result($result);
return $result; return $result;
} }
function multi_query($query) { function multi_query($query) {
return $this->_result = $this->query($query); return $this->_result = $this->query($query);
} }
function store_result($result = null) { function store_result($result = null) {
if (!$result) { if (!$result) {
$result = $this->_result; $result = $this->_result;
@@ -61,7 +61,7 @@ if (extension_loaded('pdo')) {
$this->affected_rows = $result->rowCount(); $this->affected_rows = $result->rowCount();
return true; return true;
} }
function next_result() { function next_result() {
if (!$this->_result) { if (!$this->_result) {
return false; return false;
@@ -69,7 +69,7 @@ if (extension_loaded('pdo')) {
$this->_result->_offset = 0; $this->_result->_offset = 0;
return @$this->_result->nextRowset(); // @ - PDO_PgSQL doesn't support it return @$this->_result->nextRowset(); // @ - PDO_PgSQL doesn't support it
} }
function result($query, $field = 0) { function result($query, $field = 0) {
$result = $this->query($query); $result = $this->query($query);
if (!$result) { if (!$result) {
@@ -79,18 +79,18 @@ if (extension_loaded('pdo')) {
return $row[$field]; return $row[$field];
} }
} }
class Min_PDOStatement extends PDOStatement { class Min_PDOStatement extends PDOStatement {
var $_offset = 0, $num_rows; var $_offset = 0, $num_rows;
function fetch_assoc() { function fetch_assoc() {
return $this->fetch(PDO::FETCH_ASSOC); return $this->fetch(PDO::FETCH_ASSOC);
} }
function fetch_row() { function fetch_row() {
return $this->fetch(PDO::FETCH_NUM); return $this->fetch(PDO::FETCH_NUM);
} }
function fetch_field() { function fetch_field() {
$row = (object) $this->getColumnMeta($this->_offset++); $row = (object) $this->getColumnMeta($this->_offset++);
$row->orgtable = $row->table; $row->orgtable = $row->table;

View File

@@ -1,2 +1,2 @@
<?php <?php
$VERSION = "4.9.2"; $VERSION = "4.12";

View File

@@ -1,11 +1,14 @@
<?php <?php
/** Adminer - Compact database management /**
* @link https://www.adminer.org/ * Adminer - Database management in a single PHP file
* @author Jakub Vrana, https://www.vrana.cz/ *
* @copyright 2007 Jakub Vrana * @link https://github.com/pematon/adminer
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @author Jakub Vrana (https://www.vrana.cz/)
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @author Peter Knut
*/ * @copyright 2007-2021 Jakub Vrana, 2024 Peter Knut
* @license Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
* @license GNU General Public License, version 2 (https://www.gnu.org/licenses/gpl-2.0.html)
*/
include "./include/bootstrap.inc.php"; include "./include/bootstrap.inc.php";
include "./include/tmpfile.inc.php"; include "./include/tmpfile.inc.php";

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'تسجيل الدخول', 'Login' => 'تسجيل الدخول',
'Logout successful.' => 'تم تسجيل الخروج بنجاح.', 'Logout successful.' => 'تم تسجيل الخروج بنجاح.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -30,7 +31,6 @@ $translations = array(
'Create database' => 'إنشاء قاعدة بيانات', 'Create database' => 'إنشاء قاعدة بيانات',
'SQL command' => 'استعلام SQL', 'SQL command' => 'استعلام SQL',
'Logout' => 'تسجيل الخروج', 'Logout' => 'تسجيل الخروج',
'database' => 'قاعدة بيانات',
'Use' => 'استعمال', 'Use' => 'استعمال',
'No tables.' => 'لا توجد جداول.', 'No tables.' => 'لا توجد جداول.',
'select' => 'تحديد', 'select' => 'تحديد',
@@ -67,7 +67,6 @@ $translations = array(
'Unable to select the table' => 'يتعذر اختيار الجدول', 'Unable to select the table' => 'يتعذر اختيار الجدول',
'Invalid CSRF token. Send the form again.' => 'رمز CSRF غير صالح. المرجو إرسال الاستمارة مرة أخرى.', 'Invalid CSRF token. Send the form again.' => 'رمز CSRF غير صالح. المرجو إرسال الاستمارة مرة أخرى.',
'Comment' => 'تعليق', 'Comment' => 'تعليق',
'Default values' => 'القيم الافتراضية',
'%d byte(s)' => '%d بايت', '%d byte(s)' => '%d بايت',
'No commands to execute.' => 'لا توجد أوامر للتنفيذ.', 'No commands to execute.' => 'لا توجد أوامر للتنفيذ.',
'Unable to upload a file.' => 'يتعذر رفع ملف ما.', 'Unable to upload a file.' => 'يتعذر رفع ملف ما.',
@@ -188,6 +187,7 @@ $translations = array(
'Clone' => 'نسخ', 'Clone' => 'نسخ',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'لقد تجاوزت العدد الأقصى للحقول. يرجى الرفع من %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'لقد تجاوزت العدد الأقصى للحقول. يرجى الرفع من %s.',
'Partition by' => 'مقسم بواسطة', 'Partition by' => 'مقسم بواسطة',
'Partition' => null,
'Partitions' => 'التقسيمات', 'Partitions' => 'التقسيمات',
'Partition name' => 'اسم التقسيم', 'Partition name' => 'اسم التقسيم',
'Values' => 'القيم', 'Values' => 'القيم',
@@ -223,6 +223,7 @@ $translations = array(
'Databases have been dropped.' => 'تم حذف قواعد البيانات.', 'Databases have been dropped.' => 'تم حذف قواعد البيانات.',
'Database has been dropped.' => 'تم حذف قاعدة البيانات.', 'Database has been dropped.' => 'تم حذف قاعدة البيانات.',
'Search data in tables' => 'بحث في الجداول', 'Search data in tables' => 'بحث في الجداول',
'as a regular expression' => null,
'Schema' => 'المخطط', 'Schema' => 'المخطط',
'Alter schema' => 'تعديل المخطط', 'Alter schema' => 'تعديل المخطط',
'Create schema' => 'إنشاء مخطط', 'Create schema' => 'إنشاء مخطط',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Система', 'System' => 'Система',
'Server' => 'Сървър', 'Server' => 'Сървър',
'Username' => 'Потребител', 'Username' => 'Потребител',
@@ -16,6 +17,8 @@ $translations = array(
'Language' => 'Език', 'Language' => 'Език',
'Invalid CSRF token. Send the form again.' => 'Невалиден шифроващ ключ. Попълнете и изпратете формуляра отново.', 'Invalid CSRF token. Send the form again.' => 'Невалиден шифроващ ключ. Попълнете и изпратете формуляра отново.',
'If you did not send this request from Adminer then close this page.' => 'Ако не сте изпратили тази заявка през Adminer, затворете тази страница.', 'If you did not send this request from Adminer then close this page.' => 'Ако не сте изпратили тази заявка през Adminer, затворете тази страница.',
'No driver' => null,
'Database driver not found.' => null,
'No extension' => 'Няма разширение', 'No extension' => 'Няма разширение',
'None of the supported PHP extensions (%s) are available.' => 'Никое от поддържаните PHP разширения (%s) не е налично.', 'None of the supported PHP extensions (%s) are available.' => 'Никое от поддържаните PHP разширения (%s) не е налично.',
'Session support must be enabled.' => 'Поддръжката на сесии трябва да е разрешена.', 'Session support must be enabled.' => 'Поддръжката на сесии трябва да е разрешена.',
@@ -78,7 +81,6 @@ $translations = array(
'Data' => 'Данни', 'Data' => 'Данни',
'Database' => 'База данни', 'Database' => 'База данни',
'database' => 'база данни',
'Use' => 'Избор', 'Use' => 'Избор',
'Select database' => 'Избор на база данни', 'Select database' => 'Избор на база данни',
'Invalid database.' => 'Невалидна база данни.', 'Invalid database.' => 'Невалидна база данни.',
@@ -165,7 +167,6 @@ $translations = array(
'Options' => 'Опции', 'Options' => 'Опции',
'Comment' => 'Коментар', 'Comment' => 'Коментар',
'Default value' => 'Стойност по подразбиране', 'Default value' => 'Стойност по подразбиране',
'Default values' => 'Стойности по подразбиране',
'Drop' => 'Премахване', 'Drop' => 'Премахване',
'Are you sure?' => 'Сигурни ли сте?', 'Are you sure?' => 'Сигурни ли сте?',
'Size' => 'Големина', 'Size' => 'Големина',
@@ -176,6 +177,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Максималния брой полета е превишен. Моля, увеличете %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Максималния брой полета е превишен. Моля, увеличете %s.',
'Partition by' => 'Разделяне на', 'Partition by' => 'Разделяне на',
'Partition' => null,
'Partitions' => 'Раздели', 'Partitions' => 'Раздели',
'Partition name' => 'Име на раздела', 'Partition name' => 'Име на раздела',
'Values' => 'Стойности', 'Values' => 'Стойности',
@@ -230,6 +232,7 @@ $translations = array(
'Search' => 'Търсене', 'Search' => 'Търсене',
'anywhere' => 'навсякъде', 'anywhere' => 'навсякъде',
'Search data in tables' => 'Търсене на данни в таблиците', 'Search data in tables' => 'Търсене на данни в таблиците',
'as a regular expression' => null,
'Sort' => 'Сортиране', 'Sort' => 'Сортиране',
'descending' => 'низходящо', 'descending' => 'низходящо',
'Limit' => 'Редове', 'Limit' => 'Редове',
@@ -311,12 +314,15 @@ $translations = array(
'Please use one of the extensions %s.' => 'Моля, използвайте някое от разширенията %s.', 'Please use one of the extensions %s.' => 'Моля, използвайте някое от разширенията %s.',
// PostgreSQL and MS SQL schema support // PostgreSQL and MS SQL schema support
'Schema' => 'Схема',
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'Alter schema' => 'Промяна на схемата', 'Alter schema' => 'Промяна на схемата',
'Create schema' => 'Създаване на схема', 'Create schema' => 'Създаване на схема',
'Schema has been dropped.' => 'Схемата беше премахната.', 'Schema has been dropped.' => 'Схемата беше премахната.',
'Schema has been created.' => 'Схемата беше създадена.', 'Schema has been created.' => 'Схемата беше създадена.',
'Schema has been altered.' => 'Схемата беше променена.', 'Schema has been altered.' => 'Схемата беше променена.',
'Schema' => 'Схема',
'Invalid schema.' => 'Невалидна схема.', 'Invalid schema.' => 'Невалидна схема.',
// PostgreSQL sequences support // PostgreSQL sequences support

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'লগইন', 'Login' => 'লগইন',
'Logout successful.' => 'সফলভাবে লগআউট হয়েছে।', 'Logout successful.' => 'সফলভাবে লগআউট হয়েছে।',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'ডাটাবেজ তৈরী করুন', 'Create database' => 'ডাটাবেজ তৈরী করুন',
'SQL command' => 'SQL-কমান্ড', 'SQL command' => 'SQL-কমান্ড',
'Logout' => 'লগআউট', 'Logout' => 'লগআউট',
'database' => 'ডাটাবেজ',
'Use' => 'ব্যবহার', 'Use' => 'ব্যবহার',
'No tables.' => 'কোন টেবিল নাই।', 'No tables.' => 'কোন টেবিল নাই।',
'select' => 'নির্বাচন', 'select' => 'নির্বাচন',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'টেবিল নির্বাচন করতে অক্ষম', 'Unable to select the table' => 'টেবিল নির্বাচন করতে অক্ষম',
'Invalid CSRF token. Send the form again.' => 'অবৈধ CSRF টোকেন। ফর্মটি আবার পাঠান।', 'Invalid CSRF token. Send the form again.' => 'অবৈধ CSRF টোকেন। ফর্মটি আবার পাঠান।',
'Comment' => 'মন্তব্য', 'Comment' => 'মন্তব্য',
'Default values' => 'ডিফল্ট মান',
'%d byte(s)' => array('%d বাইট', '%d বাইটসমূহ'), '%d byte(s)' => array('%d বাইট', '%d বাইটসমূহ'),
'No commands to execute.' => 'সম্পাদন করার মত কোন নির্দেশ নেই।', 'No commands to execute.' => 'সম্পাদন করার মত কোন নির্দেশ নেই।',
'Unable to upload a file.' => 'ফাইল আপলোড করা সম্ভব হচ্ছে না।', 'Unable to upload a file.' => 'ফাইল আপলোড করা সম্ভব হচ্ছে না।',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'ক্লোন', 'Clone' => 'ক্লোন',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'অনুমোদিত ফিল্ড এর সর্বাধিক সংখ্যা অতিক্রম করে গেছে। অনুগ্রহপূর্বক %s বৃদ্ধি করুন।', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'অনুমোদিত ফিল্ড এর সর্বাধিক সংখ্যা অতিক্রম করে গেছে। অনুগ্রহপূর্বক %s বৃদ্ধি করুন।',
'Partition by' => 'পার্টিশন যার মাধ্যমে', 'Partition by' => 'পার্টিশন যার মাধ্যমে',
'Partition' => null,
'Partitions' => 'পার্টিশন', 'Partitions' => 'পার্টিশন',
'Partition name' => 'পার্টিশনের নাম', 'Partition name' => 'পার্টিশনের নাম',
'Values' => 'মানসমূহ', 'Values' => 'মানসমূহ',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'স্থায়ী লগইন', 'Permanent login' => 'স্থায়ী লগইন',
'Databases have been dropped.' => 'ডাটাবেজসমূহ মুছে ফেলা হয়েছে।', 'Databases have been dropped.' => 'ডাটাবেজসমূহ মুছে ফেলা হয়েছে।',
'Search data in tables' => 'টেবিলে তথ্য খুঁজুন', 'Search data in tables' => 'টেবিলে তথ্য খুঁজুন',
'as a regular expression' => null,
'Schema' => 'স্কিমা', 'Schema' => 'স্কিমা',
'Alter schema' => 'স্কিমা পরিবর্তন করো', 'Alter schema' => 'স্কিমা পরিবর্তন করো',
'Create schema' => 'স্কিমা তৈরী করো', 'Create schema' => 'স্কিমা তৈরী করো',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem', 'System' => 'Sistem',
'Server' => 'Server', 'Server' => 'Server',
'Username' => 'Korisničko ime', 'Username' => 'Korisničko ime',
@@ -73,7 +74,6 @@ $translations = array(
'Data' => 'Podaci', 'Data' => 'Podaci',
'Database' => 'Baza podataka', 'Database' => 'Baza podataka',
'database' => 'baza podataka',
'Use' => 'Koristi', 'Use' => 'Koristi',
'Select database' => 'Izaberite bazu', 'Select database' => 'Izaberite bazu',
'Invalid database.' => 'Neispravna baza podataka.', 'Invalid database.' => 'Neispravna baza podataka.',
@@ -158,7 +158,6 @@ $translations = array(
'Auto Increment' => 'Auto-priraštaj', 'Auto Increment' => 'Auto-priraštaj',
'Options' => 'Opcije', 'Options' => 'Opcije',
'Comment' => 'Komentar', 'Comment' => 'Komentar',
'Default values' => 'Podrazumijevane vrijednosti',
'Drop' => 'Izbriši', 'Drop' => 'Izbriši',
'Are you sure?' => 'Da li ste sigurni?', 'Are you sure?' => 'Da li ste sigurni?',
'Move up' => 'Pomijeri na gore', 'Move up' => 'Pomijeri na gore',
@@ -167,6 +166,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Premašen je maksimalni broj dozvoljenih polja. Molim uvećajte %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Premašen je maksimalni broj dozvoljenih polja. Molim uvećajte %s.',
'Partition by' => 'Podijeli po', 'Partition by' => 'Podijeli po',
'Partition' => null,
'Partitions' => 'Podijele', 'Partitions' => 'Podijele',
'Partition name' => 'Ime podijele', 'Partition name' => 'Ime podijele',
'Values' => 'Vrijednosti', 'Values' => 'Vrijednosti',
@@ -221,6 +221,7 @@ $translations = array(
'Search' => 'Pretraga', 'Search' => 'Pretraga',
'anywhere' => 'bilo gdje', 'anywhere' => 'bilo gdje',
'Search data in tables' => 'Pretraži podatke u tabelama', 'Search data in tables' => 'Pretraži podatke u tabelama',
'as a regular expression' => null,
'Sort' => 'Poređaj', 'Sort' => 'Poređaj',
'descending' => 'opadajuće', 'descending' => 'opadajuće',
'Limit' => 'Granica', 'Limit' => 'Granica',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Ne', 'No' => 'Ne',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Inicia la sessió', 'Login' => 'Inicia la sessió',
'Logout successful.' => 'Desconnexió correcta.', 'Logout successful.' => 'Desconnexió correcta.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Crea una base de dades', 'Create database' => 'Crea una base de dades',
'SQL command' => 'Ordre SQL', 'SQL command' => 'Ordre SQL',
'Logout' => 'Desconnecta', 'Logout' => 'Desconnecta',
'database' => 'base de dades',
'Use' => 'Utilitza', 'Use' => 'Utilitza',
'No tables.' => 'No hi ha cap taula.', 'No tables.' => 'No hi ha cap taula.',
'select' => 'registres', 'select' => 'registres',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Impossible seleccionar la taula', 'Unable to select the table' => 'Impossible seleccionar la taula',
'Invalid CSRF token. Send the form again.' => 'Token CSRF invàlid. Torna a enviar el formulari.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF invàlid. Torna a enviar el formulari.',
'Comment' => 'Comentari', 'Comment' => 'Comentari',
'Default values' => 'Valors per defecte',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Cap comanda per executar.', 'No commands to execute.' => 'Cap comanda per executar.',
'Unable to upload a file.' => 'Impossible adjuntar el fitxer.', 'Unable to upload a file.' => 'Impossible adjuntar el fitxer.',
@@ -189,6 +188,7 @@ $translations = array(
'Tables have been dropped.' => 'S\'han suprimit les taules.', 'Tables have been dropped.' => 'S\'han suprimit les taules.',
'Clone' => 'Clona', 'Clone' => 'Clona',
'Partition by' => 'Fes particions segons', 'Partition by' => 'Fes particions segons',
'Partition' => null,
'Partitions' => 'Particions', 'Partitions' => 'Particions',
'Partition name' => 'Nom de la partició', 'Partition name' => 'Nom de la partició',
'Values' => 'Valors', 'Values' => 'Valors',
@@ -251,6 +251,7 @@ $translations = array(
'Type has been created.' => 'S\'ha creat el tipus.', 'Type has been created.' => 'S\'ha creat el tipus.',
'Alter type' => 'Modifica el tipus', 'Alter type' => 'Modifica el tipus',
'Search data in tables' => 'Cerca dades en les taules', 'Search data in tables' => 'Cerca dades en les taules',
'as a regular expression' => null,
'From server' => 'En el servidor', 'From server' => 'En el servidor',
'empty' => 'buit', 'empty' => 'buit',
'now' => 'ara', 'now' => 'ara',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => 'Domů',
'System' => 'Systém', 'System' => 'Systém',
'Server' => 'Server', 'Server' => 'Server',
'Username' => 'Uživatel', 'Username' => 'Uživatel',
@@ -20,6 +21,8 @@ $translations = array(
'Language' => 'Jazyk', 'Language' => 'Jazyk',
'Invalid CSRF token. Send the form again.' => 'Neplatný token CSRF. Odešlete formulář znovu.', 'Invalid CSRF token. Send the form again.' => 'Neplatný token CSRF. Odešlete formulář znovu.',
'If you did not send this request from Adminer then close this page.' => 'Pokud jste tento požadavek neposlali z Adminera, tak tuto stránku zavřete.', 'If you did not send this request from Adminer then close this page.' => 'Pokud jste tento požadavek neposlali z Adminera, tak tuto stránku zavřete.',
'No driver' => 'Žádný ovladač',
'Database driver not found.' => 'Databázový ovladač se nenašel.',
'No extension' => 'Žádné rozšíření', 'No extension' => 'Žádné rozšíření',
'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Není dostupné žádné z podporovaných PHP rozšíření (%s).',
'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.', 'Connecting to privileged ports is not allowed.' => 'Připojování k privilegovaným portům není povoleno.',
@@ -88,7 +91,6 @@ $translations = array(
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Databáze', 'Database' => 'Databáze',
'database' => 'databáze',
'DB' => 'DB', 'DB' => 'DB',
'Use' => 'Vybrat', 'Use' => 'Vybrat',
'Select database' => 'Vybrat databázi', 'Select database' => 'Vybrat databázi',
@@ -177,7 +179,6 @@ $translations = array(
'Options' => 'Volby', 'Options' => 'Volby',
'Comment' => 'Komentář', 'Comment' => 'Komentář',
'Default value' => 'Výchozí hodnota', 'Default value' => 'Výchozí hodnota',
'Default values' => 'Výchozí hodnoty',
'Drop' => 'Odstranit', 'Drop' => 'Odstranit',
'Drop %s?' => 'Odstranit %s?', 'Drop %s?' => 'Odstranit %s?',
'Are you sure?' => 'Opravdu?', 'Are you sure?' => 'Opravdu?',
@@ -189,6 +190,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Byl překročen maximální povolený počet polí. Zvyšte prosím %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Byl překročen maximální povolený počet polí. Zvyšte prosím %s.',
'Partition by' => 'Rozdělit podle', 'Partition by' => 'Rozdělit podle',
'Partition' => 'Oddíl',
'Partitions' => 'Oddíly', 'Partitions' => 'Oddíly',
'Partition name' => 'Název oddílu', 'Partition name' => 'Název oddílu',
'Values' => 'Hodnoty', 'Values' => 'Hodnoty',
@@ -243,6 +245,7 @@ $translations = array(
'Search' => 'Vyhledat', 'Search' => 'Vyhledat',
'anywhere' => 'kdekoliv', 'anywhere' => 'kdekoliv',
'Search data in tables' => 'Vyhledat data v tabulkách', 'Search data in tables' => 'Vyhledat data v tabulkách',
'as a regular expression' => 'jako regulární výraz',
'Sort' => 'Seřadit', 'Sort' => 'Seřadit',
'descending' => 'sestupně', 'descending' => 'sestupně',
'Limit' => 'Limit', 'Limit' => 'Limit',
@@ -256,8 +259,8 @@ $translations = array(
'%d row(s)' => array('%d řádek', '%d řádky', '%d řádků'), '%d row(s)' => array('%d řádek', '%d řádky', '%d řádků'),
'Page' => 'Stránka', 'Page' => 'Stránka',
'last' => 'poslední', 'last' => 'poslední',
'Load more data' => 'Nahrát další data', 'Load more data' => 'Načíst další data',
'Loading' => 'Nahrává se', 'Loading' => 'Načítá se',
'Whole result' => 'Celý výsledek', 'Whole result' => 'Celý výsledek',
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtů'), '%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtů'),
@@ -324,12 +327,15 @@ $translations = array(
'Please use one of the extensions %s.' => 'Prosím použijte jednu z koncovek %s.', 'Please use one of the extensions %s.' => 'Prosím použijte jednu z koncovek %s.',
// PostgreSQL and MS SQL schema support // PostgreSQL and MS SQL schema support
'Schema' => 'Schéma',
'Schemas' => 'Schémy',
'No schemas.' => 'Žádné schémy.',
'Show schema' => 'Zobrazit schéma',
'Alter schema' => 'Pozměnit schéma', 'Alter schema' => 'Pozměnit schéma',
'Create schema' => 'Vytvořit schéma', 'Create schema' => 'Vytvořit schéma',
'Schema has been dropped.' => 'Schéma bylo odstraněno.', 'Schema has been dropped.' => 'Schéma bylo odstraněno.',
'Schema has been created.' => 'Schéma bylo vytvořeno.', 'Schema has been created.' => 'Schéma bylo vytvořeno.',
'Schema has been altered.' => 'Schéma bylo změněno.', 'Schema has been altered.' => 'Schéma bylo změněno.',
'Schema' => 'Schéma',
'Invalid schema.' => 'Nesprávné schéma.', 'Invalid schema.' => 'Nesprávné schéma.',
// PostgreSQL sequences support // PostgreSQL sequences support

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'System' => 'System', 'System' => 'System',
'Server' => 'Server', 'Server' => 'Server',
'Username' => 'Brugernavn', 'Username' => 'Brugernavn',
@@ -64,7 +65,6 @@ $translations = array(
'Format' => 'Format', 'Format' => 'Format',
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Database', 'Database' => 'Database',
'database' => 'database',
'Use' => 'Brug', 'Use' => 'Brug',
'Select database' => 'Vælg database', 'Select database' => 'Vælg database',
'Invalid database.' => 'Ugyldig database.', 'Invalid database.' => 'Ugyldig database.',
@@ -143,7 +143,6 @@ $translations = array(
'Auto Increment' => 'Auto Increment', 'Auto Increment' => 'Auto Increment',
'Options' => 'Valg', 'Options' => 'Valg',
'Comment' => 'Kommentarer', 'Comment' => 'Kommentarer',
'Default values' => 'Standardværdier',
'Drop' => 'Drop', 'Drop' => 'Drop',
'Are you sure?' => 'Er du sikker?', 'Are you sure?' => 'Er du sikker?',
'Move up' => 'Flyt op', 'Move up' => 'Flyt op',
@@ -151,6 +150,7 @@ $translations = array(
'Remove' => 'Fjern', 'Remove' => 'Fjern',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimum antal feltnavne overskredet - øg venligst %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimum antal feltnavne overskredet - øg venligst %s.',
'Partition by' => 'Partition ved', 'Partition by' => 'Partition ved',
'Partition' => null,
'Partitions' => 'Partitioner', 'Partitions' => 'Partitioner',
'Partition name' => 'Partitionsnavn', 'Partition name' => 'Partitionsnavn',
'Values' => 'Værdier', 'Values' => 'Værdier',
@@ -199,6 +199,7 @@ $translations = array(
'Search' => 'Søg', 'Search' => 'Søg',
'anywhere' => 'hvorsomhelst', 'anywhere' => 'hvorsomhelst',
'Search data in tables' => 'Søg data i tabeller', 'Search data in tables' => 'Søg data i tabeller',
'as a regular expression' => null,
'Sort' => 'Sorter', 'Sort' => 'Sorter',
'descending' => 'faldende', 'descending' => 'faldende',
'Limit' => 'Limit', 'Limit' => 'Limit',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Nej', 'No' => 'Nej',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Login', 'Login' => 'Login',
'Logout successful.' => 'Abmeldung erfolgreich.', 'Logout successful.' => 'Abmeldung erfolgreich.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Danke, dass Sie Adminer genutzt haben. <a href="https://www.adminer.org/de/donation/">Spenden willkommen!</a>', 'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Danke, dass Sie Adminer genutzt haben. <a href="https://www.adminer.org/de/donation/">Spenden willkommen!</a>',
@@ -32,7 +33,6 @@ $translations = array(
'Create database' => 'Datenbank erstellen', 'Create database' => 'Datenbank erstellen',
'SQL command' => 'SQL-Kommando', 'SQL command' => 'SQL-Kommando',
'Logout' => 'Abmelden', 'Logout' => 'Abmelden',
'database' => 'Datenbank',
'Use' => 'Benutzung', 'Use' => 'Benutzung',
'No tables.' => 'Keine Tabellen.', 'No tables.' => 'Keine Tabellen.',
'select' => 'zeigen', 'select' => 'zeigen',
@@ -70,7 +70,6 @@ $translations = array(
'Unable to select the table' => 'Auswahl der Tabelle fehlgeschlagen', 'Unable to select the table' => 'Auswahl der Tabelle fehlgeschlagen',
'Invalid CSRF token. Send the form again.' => 'CSRF Token ungültig. Bitte die Formulardaten erneut abschicken.', 'Invalid CSRF token. Send the form again.' => 'CSRF Token ungültig. Bitte die Formulardaten erneut abschicken.',
'Comment' => 'Kommentar', 'Comment' => 'Kommentar',
'Default values' => 'Vorgabewerte festlegen',
'%d byte(s)' => array('%d Byte', '%d Bytes'), '%d byte(s)' => array('%d Byte', '%d Bytes'),
'No commands to execute.' => 'Kein Kommando vorhanden.', 'No commands to execute.' => 'Kein Kommando vorhanden.',
'Unable to upload a file.' => 'Hochladen von Datei fehlgeschlagen.', 'Unable to upload a file.' => 'Hochladen von Datei fehlgeschlagen.',
@@ -191,6 +190,7 @@ $translations = array(
'Clone' => 'Klonen', 'Clone' => 'Klonen',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Die maximal erlaubte Anzahl der Felder ist überschritten. Bitte %s erhöhen.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Die maximal erlaubte Anzahl der Felder ist überschritten. Bitte %s erhöhen.',
'Partition by' => 'Partitionieren um', 'Partition by' => 'Partitionieren um',
'Partition' => 'Partition',
'Partitions' => 'Partitionen', 'Partitions' => 'Partitionen',
'Partition name' => 'Name der Partition', 'Partition name' => 'Name der Partition',
'Values' => 'Werte', 'Values' => 'Werte',
@@ -225,6 +225,7 @@ $translations = array(
'Permanent login' => 'Passwort speichern', 'Permanent login' => 'Passwort speichern',
'Databases have been dropped.' => 'Datenbanken wurden entfernt.', 'Databases have been dropped.' => 'Datenbanken wurden entfernt.',
'Search data in tables' => 'Suche in Tabellen', 'Search data in tables' => 'Suche in Tabellen',
'as a regular expression' => null,
'Schema' => 'Schema', 'Schema' => 'Schema',
'Alter schema' => 'Schema ändern', 'Alter schema' => 'Schema ändern',
'Create schema' => 'Schema erstellen', 'Create schema' => 'Schema erstellen',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Nein', 'No' => 'Nein',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Σύστημα', 'System' => 'Σύστημα',
'Server' => 'Διακομιστής', 'Server' => 'Διακομιστής',
'Username' => 'Όνομα Χρήστη', 'Username' => 'Όνομα Χρήστη',
@@ -79,7 +80,6 @@ $translations = array(
'Data' => 'Δεδομένα', 'Data' => 'Δεδομένα',
'Database' => 'Β. Δεδομένων', 'Database' => 'Β. Δεδομένων',
'database' => 'β. δεδομένων',
'Use' => 'χρήση', 'Use' => 'χρήση',
'Select database' => 'Επιλέξτε Β.Δ.', 'Select database' => 'Επιλέξτε Β.Δ.',
'Invalid database.' => 'Λανθασμένη Β.Δ.', 'Invalid database.' => 'Λανθασμένη Β.Δ.',
@@ -166,7 +166,6 @@ $translations = array(
'Options' => 'Επιλογές', 'Options' => 'Επιλογές',
'Comment' => 'Σχόλιο', 'Comment' => 'Σχόλιο',
'Default value' => 'Προεπιλεγμένη τιμή', 'Default value' => 'Προεπιλεγμένη τιμή',
'Default values' => 'Προεπιλεγμένες τιμές',
'Drop' => 'Διαγραφή', 'Drop' => 'Διαγραφή',
'Are you sure?' => 'Είστε σίγουρος;', 'Are you sure?' => 'Είστε σίγουρος;',
'Size' => 'Μέγεθος', 'Size' => 'Μέγεθος',
@@ -177,6 +176,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Υπέρβαση μέγιστου επιτρεπόμενου αριθμού πεδίων. Παρακαλώ αυξήστε %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Υπέρβαση μέγιστου επιτρεπόμενου αριθμού πεδίων. Παρακαλώ αυξήστε %s.',
'Partition by' => 'Τμηματοποίηση ανά', 'Partition by' => 'Τμηματοποίηση ανά',
'Partition' => null,
'Partitions' => 'Τμήματα', 'Partitions' => 'Τμήματα',
'Partition name' => 'Όνομα Τμήματος', 'Partition name' => 'Όνομα Τμήματος',
'Values' => 'Τιμές', 'Values' => 'Τιμές',
@@ -231,6 +231,7 @@ $translations = array(
'Search' => 'Αναζήτηση', 'Search' => 'Αναζήτηση',
'anywhere' => 'παντού', 'anywhere' => 'παντού',
'Search data in tables' => 'Αναζήτηση δεδομένων στους πίνακες', 'Search data in tables' => 'Αναζήτηση δεδομένων στους πίνακες',
'as a regular expression' => null,
'Sort' => 'Ταξινόμηση', 'Sort' => 'Ταξινόμηση',
'descending' => 'Φθίνουσα', 'descending' => 'Φθίνουσα',
'Limit' => 'Όριο', 'Limit' => 'Όριο',
@@ -355,4 +356,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,8 +1,9 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Login', 'Login' => 'Login',
'Logout successful.' => 'Sesión finalizada con éxito.', 'Logout successful.' => 'Sesión finalizada con éxito.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => 'Servidor o credenciales no válidos.',
'Server' => 'Servidor', 'Server' => 'Servidor',
'Username' => 'Usuario', 'Username' => 'Usuario',
'Password' => 'Contraseña', 'Password' => 'Contraseña',
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Crear Base de datos', 'Create database' => 'Crear Base de datos',
'SQL command' => 'Comando SQL', 'SQL command' => 'Comando SQL',
'Logout' => 'Cerrar sesión', 'Logout' => 'Cerrar sesión',
'database' => 'base de datos',
'Use' => 'Usar', 'Use' => 'Usar',
'No tables.' => 'No existen tablas.', 'No tables.' => 'No existen tablas.',
'select' => 'registros', 'select' => 'registros',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'No es posible seleccionar la tabla', 'Unable to select the table' => 'No es posible seleccionar la tabla',
'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Vuelva a enviar los datos del formulario.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Vuelva a enviar los datos del formulario.',
'Comment' => 'Comentario', 'Comment' => 'Comentario',
'Default values' => 'Valores predeterminados',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'No es posible ejecutar ningún comando.', 'No commands to execute.' => 'No es posible ejecutar ningún comando.',
'Unable to upload a file.' => 'No es posible importar el archivo.', 'Unable to upload a file.' => 'No es posible importar el archivo.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'Clonar', 'Clone' => 'Clonar',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Excedida la cantidad máxima de campos permitidos. Por favor aumente %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Excedida la cantidad máxima de campos permitidos. Por favor aumente %s.',
'Partition by' => 'Particionar por', 'Partition by' => 'Particionar por',
'Partition' => null,
'Partitions' => 'Particiones', 'Partitions' => 'Particiones',
'Partition name' => 'Nombre de partición', 'Partition name' => 'Nombre de partición',
'Values' => 'Valores', 'Values' => 'Valores',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Guardar contraseña', 'Permanent login' => 'Guardar contraseña',
'Databases have been dropped.' => 'Bases de datos eliminadas.', 'Databases have been dropped.' => 'Bases de datos eliminadas.',
'Search data in tables' => 'Buscar datos en tablas', 'Search data in tables' => 'Buscar datos en tablas',
'as a regular expression' => 'como una expresión regular',
'Schema' => 'Esquema', 'Schema' => 'Esquema',
'Alter schema' => 'Modificar esquema', 'Alter schema' => 'Modificar esquema',
'Create schema' => 'Crear esquema', 'Create schema' => 'Crear esquema',
@@ -266,42 +267,42 @@ $translations = array(
'Edit all' => 'Editar todos', 'Edit all' => 'Editar todos',
'HH:MM:SS' => 'HH:MM:SS', 'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null, 'Drop %s?' => '¿Eliminar %s?',
'Tables have been optimized.' => null, 'Tables have been optimized.' => 'Tablas optimizadas.',
'Materialized view' => null, 'Materialized view' => 'Vista materializada',
'Vacuum' => null, 'Vacuum' => 'Vacio',
'Selected' => null, 'Selected' => 'Seleccionado',
'overwrite' => null, 'overwrite' => 'sobreescribir',
'DB' => null, 'DB' => 'DB',
'File must be in UTF-8 encoding.' => null, 'File must be in UTF-8 encoding.' => 'El archivo debe estar codificado en UTF-8.',
'Modify' => null, 'Modify' => 'Modificar',
'Load more data' => null, 'Load more data' => 'Cargar mas datos',
'Loading' => null, 'Loading' => 'Cargando',
'ATTACH queries are not supported.' => null, 'ATTACH queries are not supported.' => 'ATTACH consultas no está soportado.',
'Warnings' => null, 'Warnings' => 'Advertencias',
'%d / ' => array(), '%d / ' => '%d / ',
'Limit rows' => null, 'Limit rows' => 'Limitar filas',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null, 'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer no soporta el acceso a bases de datos sin contraseña, <a href="https://www.adminer.org/en/password/"%s>más informacion</a>.',
'Default value' => null, 'Default value' => 'Valor por defecto',
'Full table scan' => null, 'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(), 'Too many unsuccessful logins, try again in %d minute(s).' => array('Demasiados intentos erroneos, pruebe de nuevo en %d minuto.', 'Demasiados intentos erroneos, pruebe de nuevo en %d minutos.'),
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null, 'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => null, 'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'La contraseña Maestra ha expirado. <a href="https://www.adminer.org/en/extension/"%s>Implementar</a> %s un metodo para hacerla permanente.',
'The action will be performed after successful login with the same credentials.' => null, 'The action will be performed after successful login with the same credentials.' => 'La acción se realizará tras iniciar sesión de nuevo con las mismas credenciales.',
'Connecting to privileged ports is not allowed.' => null, 'Connecting to privileged ports is not allowed.' => 'La conexion a puertos especiales no está permitida.',
'There is a space in the input password which might be the cause.' => null, 'There is a space in the input password which might be the cause.' => 'Hay un espacio en la contraseña introducida, lo que puede ser la causa.',
'If you did not send this request from Adminer then close this page.' => null, 'If you did not send this request from Adminer then close this page.' => 'Si no mandó ésta solicitud desde Adminer entonces cierre esta página.',
'You can upload a big SQL file via FTP and import it from server.' => null, 'You can upload a big SQL file via FTP and import it from server.' => 'Puede cargar un fichero SQL grande por FTP e importarlo desde el servidor.',
'Size' => null, 'Size' => 'Tamaño',
'Compute' => null, 'Compute' => 'Procesar',
'You are offline.' => null, 'You are offline.' => 'Se encuentra desconectado.',
'You have no privileges to update this table.' => null, 'You have no privileges to update this table.' => 'No tiene privilegios para actualizar esta tabla.',
'Saving' => null, 'Saving' => 'Guardando',
'Unknown error.' => null, 'Unknown error.' => 'Error desconocido.',
'Database does not support password.' => null, 'Database does not support password.' => 'La Base de Datos no soporta el uso de contraseña.',
'Disable %s or enable %s or %s extensions.' => null, 'Disable %s or enable %s or %s extensions.' => 'Deshabilitar %s o habilitar %s o %s extensiones.',
'yes' => null, 'yes' => 'si',
'no' => null, 'no' => 'no',
'Columns' => null, 'Columns' => null,
'Nullable' => null, 'Nullable' => null,
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Logi sisse', 'Login' => 'Logi sisse',
'Logout successful.' => 'Väljalogimine õnnestus.', 'Logout successful.' => 'Väljalogimine õnnestus.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Loo uus andmebaas', 'Create database' => 'Loo uus andmebaas',
'SQL command' => 'SQL-Päring', 'SQL command' => 'SQL-Päring',
'Logout' => 'Logi välja', 'Logout' => 'Logi välja',
'database' => 'andmebaas',
'Use' => 'Kasuta', 'Use' => 'Kasuta',
'No tables.' => 'Tabeleid ei leitud.', 'No tables.' => 'Tabeleid ei leitud.',
'select' => 'kuva', 'select' => 'kuva',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Tabeli valimine ebaõnnestus', 'Unable to select the table' => 'Tabeli valimine ebaõnnestus',
'Invalid CSRF token. Send the form again.' => 'Sobimatu CSRF, palun postitage vorm uuesti.', 'Invalid CSRF token. Send the form again.' => 'Sobimatu CSRF, palun postitage vorm uuesti.',
'Comment' => 'Kommentaar', 'Comment' => 'Kommentaar',
'Default values' => 'Vaikimisi väärtused',
'%d byte(s)' => array('%d bait', '%d baiti'), '%d byte(s)' => array('%d bait', '%d baiti'),
'No commands to execute.' => 'Käsk puudub.', 'No commands to execute.' => 'Käsk puudub.',
'Unable to upload a file.' => 'Faili üleslaadimine pole võimalik.', 'Unable to upload a file.' => 'Faili üleslaadimine pole võimalik.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'Kloon', 'Clone' => 'Kloon',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimaalne väljade arv ületatud. Palun suurendage %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimaalne väljade arv ületatud. Palun suurendage %s.',
'Partition by' => 'Partitsiooni', 'Partition by' => 'Partitsiooni',
'Partition' => null,
'Partitions' => 'Partitsioonid', 'Partitions' => 'Partitsioonid',
'Partition name' => 'Partitsiooni nimi', 'Partition name' => 'Partitsiooni nimi',
'Values' => 'Väärtused', 'Values' => 'Väärtused',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Jäta mind meelde', 'Permanent login' => 'Jäta mind meelde',
'Databases have been dropped.' => 'Andmebaasid on edukalt kustutatud.', 'Databases have been dropped.' => 'Andmebaasid on edukalt kustutatud.',
'Search data in tables' => 'Otsi kogu andmebaasist', 'Search data in tables' => 'Otsi kogu andmebaasist',
'as a regular expression' => null,
'Schema' => 'Struktuur', 'Schema' => 'Struktuur',
'Alter schema' => 'Muuda struktuuri', 'Alter schema' => 'Muuda struktuuri',
'Create schema' => 'Loo struktuur', 'Create schema' => 'Loo struktuur',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'سیستم', 'System' => 'سیستم',
'Server' => 'سرور', 'Server' => 'سرور',
'Username' => 'نام کاربری', 'Username' => 'نام کاربری',
@@ -77,7 +78,6 @@ $translations = array(
'Data' => 'داده', 'Data' => 'داده',
'Database' => 'پایگاه داده', 'Database' => 'پایگاه داده',
'database' => 'پایگاه داده',
'Use' => 'استفاده', 'Use' => 'استفاده',
'Select database' => 'انتخاب پایگاه داده', 'Select database' => 'انتخاب پایگاه داده',
'Invalid database.' => 'پایگاه داده نامعتبر.', 'Invalid database.' => 'پایگاه داده نامعتبر.',
@@ -164,7 +164,6 @@ $translations = array(
'Options' => 'اختیارات', 'Options' => 'اختیارات',
'Comment' => 'توضیح', 'Comment' => 'توضیح',
'Default value' => 'مقدار پیش فرض', 'Default value' => 'مقدار پیش فرض',
'Default values' => 'مقادیر پیش فرض',
'Drop' => 'حذف', 'Drop' => 'حذف',
'Are you sure?' => 'مطمئن هستید؟', 'Are you sure?' => 'مطمئن هستید؟',
'Size' => 'حجم', 'Size' => 'حجم',
@@ -175,6 +174,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'حداکثر تعداد فیلدهای مجاز اشباع شد. لطفا %s را افزایش دهید.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'حداکثر تعداد فیلدهای مجاز اشباع شد. لطفا %s را افزایش دهید.',
'Partition by' => 'بخشبندی توسط', 'Partition by' => 'بخشبندی توسط',
'Partition' => null,
'Partitions' => 'بخشبندیها', 'Partitions' => 'بخشبندیها',
'Partition name' => 'نام بخش', 'Partition name' => 'نام بخش',
'Values' => 'مقادیر', 'Values' => 'مقادیر',
@@ -229,6 +229,7 @@ $translations = array(
'Search' => 'جستجو', 'Search' => 'جستجو',
'anywhere' => 'هرکجا', 'anywhere' => 'هرکجا',
'Search data in tables' => 'جستجوی داده در جدول', 'Search data in tables' => 'جستجوی داده در جدول',
'as a regular expression' => null,
'Sort' => 'مرتب کردن', 'Sort' => 'مرتب کردن',
'descending' => 'نزولی', 'descending' => 'نزولی',
'Limit' => 'محدودیت', 'Limit' => 'محدودیت',
@@ -355,4 +356,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Järjestelmä', 'System' => 'Järjestelmä',
'Server' => 'Palvelin', 'Server' => 'Palvelin',
'Username' => 'Käyttäjänimi', 'Username' => 'Käyttäjänimi',
@@ -79,7 +80,6 @@ $translations = array(
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Tietokanta', 'Database' => 'Tietokanta',
'database' => 'tietokanta',
'Use' => 'Käytä', 'Use' => 'Käytä',
'Select database' => 'Valitse tietokanta', 'Select database' => 'Valitse tietokanta',
'Invalid database.' => 'Tietokanta ei kelpaa.', 'Invalid database.' => 'Tietokanta ei kelpaa.',
@@ -166,7 +166,6 @@ $translations = array(
'Options' => 'Asetukset', 'Options' => 'Asetukset',
'Comment' => 'Kommentit', 'Comment' => 'Kommentit',
'Default value' => 'Oletusarvo', 'Default value' => 'Oletusarvo',
'Default values' => 'Oletusarvot',
'Drop' => 'Poista', 'Drop' => 'Poista',
'Are you sure?' => 'Oletko varma?', 'Are you sure?' => 'Oletko varma?',
'Size' => 'Koko', 'Size' => 'Koko',
@@ -177,6 +176,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Kenttien sallittu enimmäismäärä ylitetty. Kasvata arvoa %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Kenttien sallittu enimmäismäärä ylitetty. Kasvata arvoa %s.',
'Partition by' => 'Osioi arvolla', 'Partition by' => 'Osioi arvolla',
'Partition' => null,
'Partitions' => 'Osiot', 'Partitions' => 'Osiot',
'Partition name' => 'Osion nimi', 'Partition name' => 'Osion nimi',
'Values' => 'Arvot', 'Values' => 'Arvot',
@@ -231,6 +231,7 @@ $translations = array(
'Search' => 'Hae', 'Search' => 'Hae',
'anywhere' => 'kaikkialta', 'anywhere' => 'kaikkialta',
'Search data in tables' => 'Hae dataa tauluista', 'Search data in tables' => 'Hae dataa tauluista',
'as a regular expression' => null,
'Sort' => 'Lajittele', 'Sort' => 'Lajittele',
'descending' => 'alenevasti', 'descending' => 'alenevasti',
'Limit' => 'Raja', 'Limit' => 'Raja',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Ei', 'No' => 'Ei',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Authentification', 'Login' => 'Authentification',
'Logout successful.' => 'Au revoir !', 'Logout successful.' => 'Au revoir !',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -30,7 +31,6 @@ $translations = array(
'Create database' => 'Créer une base de données', 'Create database' => 'Créer une base de données',
'SQL command' => 'Requête SQL', 'SQL command' => 'Requête SQL',
'Logout' => 'Déconnexion', 'Logout' => 'Déconnexion',
'database' => 'base de données',
'Use' => 'Utiliser', 'Use' => 'Utiliser',
'No tables.' => 'Aucune table.', 'No tables.' => 'Aucune table.',
'select' => 'select', 'select' => 'select',
@@ -67,7 +67,6 @@ $translations = array(
'Unable to select the table' => 'Impossible de sélectionner la table', 'Unable to select the table' => 'Impossible de sélectionner la table',
'Invalid CSRF token. Send the form again.' => 'Token CSRF invalide. Veuillez renvoyer le formulaire.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF invalide. Veuillez renvoyer le formulaire.',
'Comment' => 'Commentaire', 'Comment' => 'Commentaire',
'Default values' => 'Valeurs par défaut',
'%d byte(s)' => array('%d octet', '%d octets'), '%d byte(s)' => array('%d octet', '%d octets'),
'No commands to execute.' => 'Aucune commande à exécuter.', 'No commands to execute.' => 'Aucune commande à exécuter.',
'Unable to upload a file.' => 'Impossible d\'importer le fichier.', 'Unable to upload a file.' => 'Impossible d\'importer le fichier.',
@@ -188,6 +187,7 @@ $translations = array(
'Clone' => 'Cloner', 'Clone' => 'Cloner',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Le nombre maximum de champs est dépassé. Veuillez augmenter %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Le nombre maximum de champs est dépassé. Veuillez augmenter %s.',
'Partition by' => 'Partitionner par', 'Partition by' => 'Partitionner par',
'Partition' => null,
'Partitions' => 'Partitions', 'Partitions' => 'Partitions',
'Partition name' => 'Nom de la partition', 'Partition name' => 'Nom de la partition',
'Values' => 'Valeurs', 'Values' => 'Valeurs',
@@ -223,6 +223,7 @@ $translations = array(
'Databases have been dropped.' => 'Les bases de données ont été supprimées.', 'Databases have been dropped.' => 'Les bases de données ont été supprimées.',
'Database has been dropped.' => 'La base de données a été supprimée.', 'Database has been dropped.' => 'La base de données a été supprimée.',
'Search data in tables' => 'Rechercher dans les tables', 'Search data in tables' => 'Rechercher dans les tables',
'as a regular expression' => 'sous forme d\'expression régulière',
'Schema' => 'Schéma', 'Schema' => 'Schéma',
'Alter schema' => 'Modifier le schéma', 'Alter schema' => 'Modifier le schéma',
'Create schema' => 'Créer un schéma', 'Create schema' => 'Créer un schéma',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Non', 'No' => 'Non',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Conectar', 'Login' => 'Conectar',
'Logout successful.' => 'Pechouse a sesión con éxito.', 'Logout successful.' => 'Pechouse a sesión con éxito.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Crear Base de datos', 'Create database' => 'Crear Base de datos',
'SQL command' => 'Comando SQL', 'SQL command' => 'Comando SQL',
'Logout' => 'Pechar sesión', 'Logout' => 'Pechar sesión',
'database' => 'base de datos',
'Use' => 'Usar', 'Use' => 'Usar',
'No tables.' => 'Nengunha táboa.', 'No tables.' => 'Nengunha táboa.',
'select' => 'selecciona', 'select' => 'selecciona',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'No é posible seleccionar a táboa', 'Unable to select the table' => 'No é posible seleccionar a táboa',
'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Envíe de novo os datos do formulario.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Envíe de novo os datos do formulario.',
'Comment' => 'Comentario', 'Comment' => 'Comentario',
'Default values' => 'Valores predeterminados',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Non hai comandos para executar.', 'No commands to execute.' => 'Non hai comandos para executar.',
'Unable to upload a file.' => 'Non é posible importar o ficheiro.', 'Unable to upload a file.' => 'Non é posible importar o ficheiro.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'Clonar', 'Clone' => 'Clonar',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Excedida o número máximo de campos permitidos. Por favor aumente %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Excedida o número máximo de campos permitidos. Por favor aumente %s.',
'Partition by' => 'Particionar por', 'Partition by' => 'Particionar por',
'Partition' => null,
'Partitions' => 'Particións', 'Partitions' => 'Particións',
'Partition name' => 'Nome da Partición', 'Partition name' => 'Nome da Partición',
'Values' => 'Valores', 'Values' => 'Valores',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Permanecer conectado', 'Permanent login' => 'Permanecer conectado',
'Databases have been dropped.' => 'Elimináronse as bases de datos.', 'Databases have been dropped.' => 'Elimináronse as bases de datos.',
'Search data in tables' => 'Buscar datos en táboas', 'Search data in tables' => 'Buscar datos en táboas',
'as a regular expression' => null,
'Schema' => 'Esquema', 'Schema' => 'Esquema',
'Alter schema' => 'Modificar esquema', 'Alter schema' => 'Modificar esquema',
'Create schema' => 'Crear esquema', 'Create schema' => 'Crear esquema',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Non', 'No' => 'Non',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'התחברות', 'Login' => 'התחברות',
'Logout successful.' => 'ההתחברות הצליחה', 'Logout successful.' => 'ההתחברות הצליחה',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -30,7 +31,6 @@ $translations = array(
'Create database' => 'צור מסד נתונים', 'Create database' => 'צור מסד נתונים',
'SQL command' => 'שאילתת SQL', 'SQL command' => 'שאילתת SQL',
'Logout' => 'התנתק', 'Logout' => 'התנתק',
'database' => 'מסד נתונים',
'Use' => 'השתמש', 'Use' => 'השתמש',
'No tables.' => 'אין טבלאות', 'No tables.' => 'אין טבלאות',
'select' => 'בחר', 'select' => 'בחר',
@@ -67,7 +67,6 @@ $translations = array(
'Unable to select the table' => 'בחירת הטבלה נכשלה', 'Unable to select the table' => 'בחירת הטבלה נכשלה',
'Invalid CSRF token. Send the form again.' => 'כשל באבטחת נתונים, שלח טופס שוב', 'Invalid CSRF token. Send the form again.' => 'כשל באבטחת נתונים, שלח טופס שוב',
'Comment' => 'הערה', 'Comment' => 'הערה',
'Default values' => 'ערכי ברירת מחדל',
'%d byte(s)' => '%d בתים', '%d byte(s)' => '%d בתים',
'No commands to execute.' => 'לא נמצאו פקודות להרצה', 'No commands to execute.' => 'לא נמצאו פקודות להרצה',
'Unable to upload a file.' => 'העלאת הקובץ נכשלה', 'Unable to upload a file.' => 'העלאת הקובץ נכשלה',
@@ -188,6 +187,7 @@ $translations = array(
'Clone' => 'שכפל', 'Clone' => 'שכפל',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'הגעת למספר השדות המרבי. בבקשה הגדל את %s', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'הגעת למספר השדות המרבי. בבקשה הגדל את %s',
'Partition by' => 'מחיצות ע"י', 'Partition by' => 'מחיצות ע"י',
'Partition' => null,
'Partitions' => 'מחיצות', 'Partitions' => 'מחיצות',
'Partition name' => 'שם מחיצה', 'Partition name' => 'שם מחיצה',
'Values' => 'ערכים', 'Values' => 'ערכים',
@@ -223,6 +223,7 @@ $translations = array(
'Databases have been dropped.' => 'מסד הנתונים הושלך', 'Databases have been dropped.' => 'מסד הנתונים הושלך',
'Database has been dropped.' => 'מסד הנתונים הושלך', 'Database has been dropped.' => 'מסד הנתונים הושלך',
'Search data in tables' => 'חפש מידע בטבלאות', 'Search data in tables' => 'חפש מידע בטבלאות',
'as a regular expression' => null,
'Schema' => 'סכמה', 'Schema' => 'סכמה',
'Alter schema' => 'שנה סכמה', 'Alter schema' => 'שנה סכמה',
'Create schema' => 'צור סכמה', 'Create schema' => 'צור סכמה',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Belépés', 'Login' => 'Belépés',
'Logout successful.' => 'Sikeres kilépés.', 'Logout successful.' => 'Sikeres kilépés.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Adatbázis létrehozása', 'Create database' => 'Adatbázis létrehozása',
'SQL command' => 'SQL parancs', 'SQL command' => 'SQL parancs',
'Logout' => 'Kilépés', 'Logout' => 'Kilépés',
'database' => 'adatbázis',
'Use' => 'Használ', 'Use' => 'Használ',
'No tables.' => 'Nincs tábla.', 'No tables.' => 'Nincs tábla.',
'select' => 'kiválasztás', 'select' => 'kiválasztás',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Nem tudom kiválasztani a táblát', 'Unable to select the table' => 'Nem tudom kiválasztani a táblát',
'Invalid CSRF token. Send the form again.' => 'Érvénytelen CSRF azonosító. Küldd újra az űrlapot.', 'Invalid CSRF token. Send the form again.' => 'Érvénytelen CSRF azonosító. Küldd újra az űrlapot.',
'Comment' => 'Megjegyzés', 'Comment' => 'Megjegyzés',
'Default values' => 'Alapértelmezett értékek',
'%d byte(s)' => array('%d bájt', '%d bájt', '%d bájt'), '%d byte(s)' => array('%d bájt', '%d bájt', '%d bájt'),
'No commands to execute.' => 'Nincs végrehajtható parancs.', 'No commands to execute.' => 'Nincs végrehajtható parancs.',
'Unable to upload a file.' => 'Nem tudom feltölteni a fájlt.', 'Unable to upload a file.' => 'Nem tudom feltölteni a fájlt.',
@@ -189,6 +188,7 @@ $translations = array(
'Tables have been dropped.' => 'Táblák eldobva.', 'Tables have been dropped.' => 'Táblák eldobva.',
'Clone' => 'Klónoz', 'Clone' => 'Klónoz',
'Partition by' => 'Particionálás ezzel', 'Partition by' => 'Particionálás ezzel',
'Partition' => null,
'Partitions' => 'Particiók', 'Partitions' => 'Particiók',
'Partition name' => 'Partició neve', 'Partition name' => 'Partició neve',
'Values' => 'Értékek', 'Values' => 'Értékek',
@@ -250,6 +250,7 @@ $translations = array(
'Type has been created.' => 'Típus létrehozva.', 'Type has been created.' => 'Típus létrehozva.',
'Alter type' => 'Típus módosítása', 'Alter type' => 'Típus módosítása',
'Search data in tables' => 'Keresés a táblákban', 'Search data in tables' => 'Keresés a táblákban',
'as a regular expression' => null,
'From server' => 'Szerverről', 'From server' => 'Szerverről',
'empty' => 'üres', 'empty' => 'üres',
'now' => 'most', 'now' => 'most',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem', 'System' => 'Sistem',
'Server' => 'Server', 'Server' => 'Server',
'Username' => 'Pengguna', 'Username' => 'Pengguna',
@@ -73,7 +74,6 @@ $translations = array(
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Basis data', 'Database' => 'Basis data',
'database' => 'basis data',
'Use' => 'Gunakan', 'Use' => 'Gunakan',
'Select database' => 'Pilih basis data', 'Select database' => 'Pilih basis data',
'Invalid database.' => 'Basis data tidak sah.', 'Invalid database.' => 'Basis data tidak sah.',
@@ -158,7 +158,6 @@ $translations = array(
'Auto Increment' => 'Inkrementasi Otomatis', 'Auto Increment' => 'Inkrementasi Otomatis',
'Options' => 'Opsi', 'Options' => 'Opsi',
'Comment' => 'Komentar', 'Comment' => 'Komentar',
'Default values' => 'Nilai bawaan',
'Drop' => 'Hapus', 'Drop' => 'Hapus',
'Are you sure?' => 'Anda yakin?', 'Are you sure?' => 'Anda yakin?',
'Move up' => 'Naik', 'Move up' => 'Naik',
@@ -167,6 +166,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Sudah lebih dumlah ruas maksimum yang diizinkan. Harap naikkan %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Sudah lebih dumlah ruas maksimum yang diizinkan. Harap naikkan %s.',
'Partition by' => 'Partisi menurut', 'Partition by' => 'Partisi menurut',
'Partition' => null,
'Partitions' => 'Partisi', 'Partitions' => 'Partisi',
'Partition name' => 'Nama partisi', 'Partition name' => 'Nama partisi',
'Values' => 'Nilai', 'Values' => 'Nilai',
@@ -220,6 +220,7 @@ $translations = array(
'Search' => 'Cari', 'Search' => 'Cari',
'anywhere' => 'di mana pun', 'anywhere' => 'di mana pun',
'Search data in tables' => 'Cari data dalam tabel', 'Search data in tables' => 'Cari data dalam tabel',
'as a regular expression' => null,
'Sort' => 'Urutkan', 'Sort' => 'Urutkan',
'descending' => 'menurun', 'descending' => 'menurun',
'Limit' => 'Batas', 'Limit' => 'Batas',
@@ -355,4 +356,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Autenticazione', 'Login' => 'Autenticazione',
'Logout successful.' => 'Uscita effettuata con successo.', 'Logout successful.' => 'Uscita effettuata con successo.',
'Invalid server or credentials.' => 'Server o credenziali non valide.', 'Invalid server or credentials.' => 'Server o credenziali non valide.',
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Crea database', 'Create database' => 'Crea database',
'SQL command' => 'Comando SQL', 'SQL command' => 'Comando SQL',
'Logout' => 'Esci', 'Logout' => 'Esci',
'database' => 'database',
'Use' => 'Usa', 'Use' => 'Usa',
'No tables.' => 'No tabelle.', 'No tables.' => 'No tabelle.',
'select' => 'seleziona', 'select' => 'seleziona',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Selezione della tabella non riuscita', 'Unable to select the table' => 'Selezione della tabella non riuscita',
'Invalid CSRF token. Send the form again.' => 'Token CSRF non valido. Reinvia la richiesta.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF non valido. Reinvia la richiesta.',
'Comment' => 'Commento', 'Comment' => 'Commento',
'Default values' => 'Valori predefiniti',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Nessun commando da eseguire.', 'No commands to execute.' => 'Nessun commando da eseguire.',
'Unable to upload a file.' => 'Caricamento del file non riuscito.', 'Unable to upload a file.' => 'Caricamento del file non riuscito.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'Clona', 'Clone' => 'Clona',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Troppi campi. Per favore aumentare %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Troppi campi. Per favore aumentare %s.',
'Partition by' => 'Partiziona per', 'Partition by' => 'Partiziona per',
'Partition' => null,
'Partitions' => 'Partizioni', 'Partitions' => 'Partizioni',
'Partition name' => 'Nome partizione', 'Partition name' => 'Nome partizione',
'Values' => 'Valori', 'Values' => 'Valori',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Login permanente', 'Permanent login' => 'Login permanente',
'Databases have been dropped.' => 'Database eliminati.', 'Databases have been dropped.' => 'Database eliminati.',
'Search data in tables' => 'Cerca nelle tabelle', 'Search data in tables' => 'Cerca nelle tabelle',
'as a regular expression' => 'come espressione regolare',
'Schema' => 'Schema', 'Schema' => 'Schema',
'Alter schema' => 'Modifica schema', 'Alter schema' => 'Modifica schema',
'Create schema' => 'Crea schema', 'Create schema' => 'Crea schema',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'No', 'No' => 'No',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'ログイン', 'Login' => 'ログイン',
'Logout successful.' => 'ログアウト', 'Logout successful.' => 'ログアウト',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'データベースを作成', 'Create database' => 'データベースを作成',
'SQL command' => 'SQLコマンド', 'SQL command' => 'SQLコマンド',
'Logout' => 'ログアウト', 'Logout' => 'ログアウト',
'database' => 'データベース',
'Use' => '使用', 'Use' => '使用',
'No tables.' => 'テーブルがありません。', 'No tables.' => 'テーブルがありません。',
'select' => '選択', 'select' => '選択',
@@ -68,7 +68,6 @@ $translations = array(
'Unable to select the table' => 'テーブルを選択できません', 'Unable to select the table' => 'テーブルを選択できません',
'Invalid CSRF token. Send the form again.' => '不正なCSRFトークン。再送信してください', 'Invalid CSRF token. Send the form again.' => '不正なCSRFトークン。再送信してください',
'Comment' => 'コメント', 'Comment' => 'コメント',
'Default values' => '規定値',
'%d byte(s)' => '%d バイト', '%d byte(s)' => '%d バイト',
'No commands to execute.' => '実行するコマンドがありません', 'No commands to execute.' => '実行するコマンドがありません',
'Unable to upload a file.' => 'ファイルをアップロードできません', 'Unable to upload a file.' => 'ファイルをアップロードできません',
@@ -189,6 +188,7 @@ $translations = array(
'Clone' => 'クローン', 'Clone' => 'クローン',
'Maximum number of allowed fields exceeded. Please increase %s.' => '定義可能な最大フィールド数を越えました。%s を増やしてください。', 'Maximum number of allowed fields exceeded. Please increase %s.' => '定義可能な最大フィールド数を越えました。%s を増やしてください。',
'Partition by' => 'パーティション', 'Partition by' => 'パーティション',
'Partition' => null,
'Partitions' => 'パーティション', 'Partitions' => 'パーティション',
'Partition name' => 'パーティション名', 'Partition name' => 'パーティション名',
'Values' => '値', 'Values' => '値',
@@ -225,6 +225,7 @@ $translations = array(
'Permanent login' => '永続的にログイン', 'Permanent login' => '永続的にログイン',
'Databases have been dropped.' => 'データベースを削除しました', 'Databases have been dropped.' => 'データベースを削除しました',
'Search data in tables' => 'データを検索する', 'Search data in tables' => 'データを検索する',
'as a regular expression' => null,
'Schema' => 'スキーマ', 'Schema' => 'スキーマ',
'Alter schema' => 'スキーマ変更', 'Alter schema' => 'スキーマ変更',
'Create schema' => 'スキーマ追加', 'Create schema' => 'スキーマ追加',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'შესვლა', 'Login' => 'შესვლა',
'Logout successful.' => 'გამოხვედით სისტემიდან.', 'Logout successful.' => 'გამოხვედით სისტემიდან.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'ბაზის შექმნა', 'Create database' => 'ბაზის შექმნა',
'SQL command' => 'SQL-ბრძანება', 'SQL command' => 'SQL-ბრძანება',
'Logout' => 'გასვლა', 'Logout' => 'გასვლა',
'database' => 'ბაზა',
'Use' => 'არჩევა', 'Use' => 'არჩევა',
'No tables.' => 'ბაზაში ცხრილი არაა.', 'No tables.' => 'ბაზაში ცხრილი არაა.',
'select' => 'არჩევა', 'select' => 'არჩევა',
@@ -68,7 +68,6 @@ $translations = array(
'Unable to select the table' => 'ცხრილიდან ინფორმაცია ვერ მოვიპოვე', 'Unable to select the table' => 'ცხრილიდან ინფორმაცია ვერ მოვიპოვე',
'Invalid CSRF token. Send the form again.' => 'უმოქმედო CSRF-ტოკენი. ფორმის კიდევ ერთხელ გაგზავნა.', 'Invalid CSRF token. Send the form again.' => 'უმოქმედო CSRF-ტოკენი. ფორმის კიდევ ერთხელ გაგზავნა.',
'Comment' => 'კომენტარები', 'Comment' => 'კომენტარები',
'Default values' => 'სტანდარტული მნიშვნელობა',
'%d byte(s)' => '%d ბაიტი', '%d byte(s)' => '%d ბაიტი',
'No commands to execute.' => 'შესასრულებელი ბრძანება არაა.', 'No commands to execute.' => 'შესასრულებელი ბრძანება არაა.',
'Unable to upload a file.' => 'ფაილი არ აიტვირთა სერვერზე.', 'Unable to upload a file.' => 'ფაილი არ აიტვირთა სერვერზე.',
@@ -187,6 +186,7 @@ $translations = array(
'Tables have been dropped.' => 'ცხრილები წაიშალა.', 'Tables have been dropped.' => 'ცხრილები წაიშალა.',
'Clone' => 'კლონირება', 'Clone' => 'კლონირება',
'Partition by' => 'დაყოფა', 'Partition by' => 'დაყოფა',
'Partition' => null,
'Partitions' => 'დანაყოფები', 'Partitions' => 'დანაყოფები',
'Partition name' => 'დანაყოფის სახელი', 'Partition name' => 'დანაყოფის სახელი',
'Values' => 'პარამეტრები', 'Values' => 'პარამეტრები',
@@ -220,6 +220,7 @@ $translations = array(
'Permanent login' => 'სისტემაში დარჩენა', 'Permanent login' => 'სისტემაში დარჩენა',
'Databases have been dropped.' => 'ბაზა წაიშალა.', 'Databases have been dropped.' => 'ბაზა წაიშალა.',
'Search data in tables' => 'ცხრილებში ძებნა', 'Search data in tables' => 'ცხრილებში ძებნა',
'as a regular expression' => null,
'Schema' => 'სქემა', 'Schema' => 'სქემა',
'Alter schema' => 'სქემის შეცვლა', 'Alter schema' => 'სქემის შეცვლა',
'Create schema' => 'ახალი სქემა', 'Create schema' => 'ახალი სქემა',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'$1-$3-$5' => '$1-$3-$5', '$1-$3-$5' => '$1-$3-$5',
'%.3f s' => '%.3f 초', '%.3f s' => '%.3f 초',
'%d byte(s)' => '%d 바이트', '%d byte(s)' => '%d 바이트',
@@ -71,11 +72,9 @@ $translations = array(
'Database has been dropped.' => '데이터베이스를 삭제했습니다.', 'Database has been dropped.' => '데이터베이스를 삭제했습니다.',
'Database has been renamed.' => '데이터베이스의 이름을 바꾸었습니다.', 'Database has been renamed.' => '데이터베이스의 이름을 바꾸었습니다.',
'Database schema' => '데이터베이스 구조', 'Database schema' => '데이터베이스 구조',
'database' => '데이터베이스',
'Database' => '데이터베이스', 'Database' => '데이터베이스',
'Databases have been dropped.' => '데이터베이스를 삭제했습니다.', 'Databases have been dropped.' => '데이터베이스를 삭제했습니다.',
'Date and time' => '시간', 'Date and time' => '시간',
'Default values' => '기본값',
'Delete' => '삭제', 'Delete' => '삭제',
'descending' => '역순', 'descending' => '역순',
'Drop' => '삭제', 'Drop' => '삭제',
@@ -172,6 +171,7 @@ $translations = array(
'Parameter name' => '매개변수 이름', 'Parameter name' => '매개변수 이름',
'Partition by' => '파티션', 'Partition by' => '파티션',
'Partition name' => '파티션 이름', 'Partition name' => '파티션 이름',
'Partition' => null,
'Partitions' => '파티션', 'Partitions' => '파티션',
'Password' => '비밀번호', 'Password' => '비밀번호',
'Permanent link' => '영구적으로 링크', 'Permanent link' => '영구적으로 링크',
@@ -204,6 +204,7 @@ $translations = array(
'Schema has been dropped.' => '스키마를 삭제했습니다.', 'Schema has been dropped.' => '스키마를 삭제했습니다.',
'Schema' => '스키마', 'Schema' => '스키마',
'Search data in tables' => '테이블 내 데이터 검색', 'Search data in tables' => '테이블 내 데이터 검색',
'as a regular expression' => null,
'Search' => '검색', 'Search' => '검색',
'Select data' => '데이터를 선택하십시오.', 'Select data' => '데이터를 선택하십시오.',
'Select database' => '데이터베이스를 선택하십시오.', 'Select database' => '데이터베이스를 선택하십시오.',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistema', 'System' => 'Sistema',
'Server' => 'Serveris', 'Server' => 'Serveris',
'Username' => 'Vartotojas', 'Username' => 'Vartotojas',
@@ -73,7 +74,6 @@ $translations = array(
'Data' => 'Duomenys', 'Data' => 'Duomenys',
'Database' => 'Duomenų bazė', 'Database' => 'Duomenų bazė',
'database' => 'duomenų bazė',
'Use' => 'Naudoti', 'Use' => 'Naudoti',
'Select database' => 'Pasirinkti duomenų bazę', 'Select database' => 'Pasirinkti duomenų bazę',
'Invalid database.' => 'Neteisinga duomenų bazė.', 'Invalid database.' => 'Neteisinga duomenų bazė.',
@@ -157,7 +157,6 @@ $translations = array(
'Auto Increment' => 'Auto Increment', 'Auto Increment' => 'Auto Increment',
'Options' => 'Nustatymai', 'Options' => 'Nustatymai',
'Comment' => 'Komentaras', 'Comment' => 'Komentaras',
'Default values' => 'Reikšmės pagal nutylėjimą',
'Drop' => 'Pašalinti', 'Drop' => 'Pašalinti',
'Are you sure?' => 'Tikrai?', 'Are you sure?' => 'Tikrai?',
'Move up' => 'Perkelti į viršų', 'Move up' => 'Perkelti į viršų',
@@ -166,6 +165,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Viršytas maksimalus leidžiamų stulpelių kiekis. Padidinkite %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Viršytas maksimalus leidžiamų stulpelių kiekis. Padidinkite %s.',
'Partition by' => 'Skirstyti pagal', 'Partition by' => 'Skirstyti pagal',
'Partition' => null,
'Partitions' => 'Skirsniai', 'Partitions' => 'Skirsniai',
'Partition name' => 'Skirsnio pavadinimas', 'Partition name' => 'Skirsnio pavadinimas',
'Values' => 'Reikšmės', 'Values' => 'Reikšmės',
@@ -219,6 +219,7 @@ $translations = array(
'Search' => 'Ieškoti', 'Search' => 'Ieškoti',
'anywhere' => 'visur', 'anywhere' => 'visur',
'Search data in tables' => 'Ieškoti duomenų lentelėse', 'Search data in tables' => 'Ieškoti duomenų lentelėse',
'as a regular expression' => null,
'Sort' => 'Rikiuoti', 'Sort' => 'Rikiuoti',
'descending' => 'mažėjimo tvarka', 'descending' => 'mažėjimo tvarka',
'Limit' => 'Limitas', 'Limit' => 'Limitas',
@@ -355,4 +356,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Ieiet', 'Login' => 'Ieiet',
'Logout successful.' => 'Jūs veiksmīgi izgājāt no sistēmas.', 'Logout successful.' => 'Jūs veiksmīgi izgājāt no sistēmas.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Izveidot datubāzi', 'Create database' => 'Izveidot datubāzi',
'SQL command' => 'SQL pieprasījums', 'SQL command' => 'SQL pieprasījums',
'Logout' => 'Iziet', 'Logout' => 'Iziet',
'database' => 'datubāze',
'Use' => 'Lietot', 'Use' => 'Lietot',
'No tables.' => 'Datubāzē nav tabulu.', 'No tables.' => 'Datubāzē nav tabulu.',
'select' => 'izvēlēties', 'select' => 'izvēlēties',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Tabula nav pieejama', 'Unable to select the table' => 'Tabula nav pieejama',
'Invalid CSRF token. Send the form again.' => 'Nederīgs CSRF žetons. Nosūtiet formu vēl vienu reizi.', 'Invalid CSRF token. Send the form again.' => 'Nederīgs CSRF žetons. Nosūtiet formu vēl vienu reizi.',
'Comment' => 'Komentārs', 'Comment' => 'Komentārs',
'Default values' => 'Noklusētā vērtība',
'%d byte(s)' => array('%d baits', '%d baiti', '%d baiti'), '%d byte(s)' => array('%d baits', '%d baiti', '%d baiti'),
'No commands to execute.' => 'Nav izpildāmu komandu.', 'No commands to execute.' => 'Nav izpildāmu komandu.',
'Unable to upload a file.' => 'Neizdevās ielādēt failu uz servera.', 'Unable to upload a file.' => 'Neizdevās ielādēt failu uz servera.',
@@ -189,6 +188,7 @@ $translations = array(
'Tables have been dropped.' => 'Tabulas dzēstas.', 'Tables have been dropped.' => 'Tabulas dzēstas.',
'Clone' => 'Klonēt', 'Clone' => 'Klonēt',
'Partition by' => 'Sadalīt pēc', 'Partition by' => 'Sadalīt pēc',
'Partition' => null,
'Partitions' => 'Partīcijas', 'Partitions' => 'Partīcijas',
'Partition name' => 'Partīcijas nosaukums', 'Partition name' => 'Partīcijas nosaukums',
'Values' => 'Vērtības', 'Values' => 'Vērtības',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Atcerēties mani', 'Permanent login' => 'Atcerēties mani',
'Databases have been dropped.' => 'Datubāzes dzēstas.', 'Databases have been dropped.' => 'Datubāzes dzēstas.',
'Search data in tables' => 'Meklēt tabulās', 'Search data in tables' => 'Meklēt tabulās',
'as a regular expression' => null,
'Schema' => 'Shēma', 'Schema' => 'Shēma',
'Alter schema' => 'Izmainīt shēmu', 'Alter schema' => 'Izmainīt shēmu',
'Create schema' => 'Jauna shēma', 'Create schema' => 'Jauna shēma',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Nē', 'No' => 'Nē',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem', 'System' => 'Sistem',
'Server' => 'Pelayan', 'Server' => 'Pelayan',
'Username' => 'Nama pengguna', 'Username' => 'Nama pengguna',
@@ -82,7 +83,6 @@ $translations = array(
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Pangkalan data', 'Database' => 'Pangkalan data',
'database' => 'pangkalan data',
'Use' => 'Guna', 'Use' => 'Guna',
'Select database' => 'Pilih pangkalan data', 'Select database' => 'Pilih pangkalan data',
'Invalid database.' => 'Pangkalan data tidak sah.', 'Invalid database.' => 'Pangkalan data tidak sah.',
@@ -169,7 +169,6 @@ $translations = array(
'Options' => 'Pilihan', 'Options' => 'Pilihan',
'Comment' => 'Komen', 'Comment' => 'Komen',
'Default value' => 'Nilai lalai', 'Default value' => 'Nilai lalai',
'Default values' => 'Nilai lalai',
'Drop' => 'Jatuh', 'Drop' => 'Jatuh',
'Drop %s?' => 'Jatuhkan %s?', 'Drop %s?' => 'Jatuhkan %s?',
'Are you sure?' => 'Anda pasti?', 'Are you sure?' => 'Anda pasti?',
@@ -181,6 +180,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Bilangan medan telah melebihi had yang dibenarkan. Sila tingkatkan %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Bilangan medan telah melebihi had yang dibenarkan. Sila tingkatkan %s.',
'Partition by' => 'Partition mengikut', 'Partition by' => 'Partition mengikut',
'Partition' => null,
'Partitions' => 'Partition', 'Partitions' => 'Partition',
'Partition name' => 'Nama partition', 'Partition name' => 'Nama partition',
'Values' => 'Nilai', 'Values' => 'Nilai',
@@ -235,6 +235,7 @@ $translations = array(
'Search' => 'Cari', 'Search' => 'Cari',
'anywhere' => 'di mana-mana', 'anywhere' => 'di mana-mana',
'Search data in tables' => 'Cari data dalam jadual', 'Search data in tables' => 'Cari data dalam jadual',
'as a regular expression' => null,
'Sort' => 'Susun', 'Sort' => 'Susun',
'descending' => 'menurun', 'descending' => 'menurun',
'Limit' => 'Had', 'Limit' => 'Had',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Tidak', 'No' => 'Tidak',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Aanmelden', 'Login' => 'Aanmelden',
'Logout successful.' => 'Successvol afgemeld.', 'Logout successful.' => 'Successvol afgemeld.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -32,7 +33,6 @@ $translations = array(
'Create database' => 'Database aanmaken', 'Create database' => 'Database aanmaken',
'SQL command' => 'SQL opdracht', 'SQL command' => 'SQL opdracht',
'Logout' => 'Afmelden', 'Logout' => 'Afmelden',
'database' => 'database',
'Use' => 'Gebruik', 'Use' => 'Gebruik',
'No tables.' => 'Geen tabellen.', 'No tables.' => 'Geen tabellen.',
'select' => 'kies', 'select' => 'kies',
@@ -70,7 +70,6 @@ $translations = array(
'Unable to select the table' => 'Onmogelijk tabel te selecteren', 'Unable to select the table' => 'Onmogelijk tabel te selecteren',
'Invalid CSRF token. Send the form again.' => 'Ongeldig CSRF token. Verstuur het formulier opnieuw.', 'Invalid CSRF token. Send the form again.' => 'Ongeldig CSRF token. Verstuur het formulier opnieuw.',
'Comment' => 'Commentaar', 'Comment' => 'Commentaar',
'Default values' => 'Standaard waarden',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Geen opdrachten uit te voeren.', 'No commands to execute.' => 'Geen opdrachten uit te voeren.',
'Unable to upload a file.' => 'Onmogelijk bestand te uploaden.', 'Unable to upload a file.' => 'Onmogelijk bestand te uploaden.',
@@ -191,6 +190,7 @@ $translations = array(
'Clone' => 'Dupliceer', 'Clone' => 'Dupliceer',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maximum aantal velden bereikt. Verhoog %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maximum aantal velden bereikt. Verhoog %s.',
'Partition by' => 'Partitioneren op', 'Partition by' => 'Partitioneren op',
'Partition' => null,
'Partitions' => 'Partities', 'Partitions' => 'Partities',
'Partition name' => 'Partitie naam', 'Partition name' => 'Partitie naam',
'Values' => 'Waarden', 'Values' => 'Waarden',
@@ -224,6 +224,7 @@ $translations = array(
'%d in total' => '%d in totaal', '%d in total' => '%d in totaal',
'Permanent login' => 'Blijf aangemeld', 'Permanent login' => 'Blijf aangemeld',
'Search data in tables' => 'Zoeken in database', 'Search data in tables' => 'Zoeken in database',
'as a regular expression' => 'als een regular expression',
'Schema' => 'Schema', 'Schema' => 'Schema',
'Alter schema' => 'Schema wijzigen', 'Alter schema' => 'Schema wijzigen',
'Create schema' => 'Schema maken', 'Create schema' => 'Schema maken',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Neen', 'No' => 'Neen',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'System' => 'System', 'System' => 'System',
'Server' => 'Server', 'Server' => 'Server',
'Username' => 'Brukernavn', 'Username' => 'Brukernavn',
@@ -64,7 +65,6 @@ $translations = array(
'Format' => 'Format', 'Format' => 'Format',
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Database', 'Database' => 'Database',
'database' => 'database',
'Use' => 'Bruk', 'Use' => 'Bruk',
'Select database' => 'Velg database', 'Select database' => 'Velg database',
'Invalid database.' => 'Ugyldig database.', 'Invalid database.' => 'Ugyldig database.',
@@ -143,7 +143,6 @@ $translations = array(
'Auto Increment' => 'Autoinkrement', 'Auto Increment' => 'Autoinkrement',
'Options' => 'Valg', 'Options' => 'Valg',
'Comment' => 'Kommentarer', 'Comment' => 'Kommentarer',
'Default values' => 'Standardverdier',
'Drop' => 'Dropp', 'Drop' => 'Dropp',
'Are you sure?' => 'Er du sikker?', 'Are you sure?' => 'Er du sikker?',
'Move up' => 'Flytt opp', 'Move up' => 'Flytt opp',
@@ -151,6 +150,7 @@ $translations = array(
'Remove' => 'Fjern', 'Remove' => 'Fjern',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimum antall feltnavn overskredet - venligst øk %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimum antall feltnavn overskredet - venligst øk %s.',
'Partition by' => 'Partisjoner ved', 'Partition by' => 'Partisjoner ved',
'Partition' => null,
'Partitions' => 'Partisjoner', 'Partitions' => 'Partisjoner',
'Partition name' => 'Partisjonsnavn', 'Partition name' => 'Partisjonsnavn',
'Values' => 'Verdier', 'Values' => 'Verdier',
@@ -199,6 +199,7 @@ $translations = array(
'Search' => 'Søk', 'Search' => 'Søk',
'anywhere' => 'hvorsomhelst', 'anywhere' => 'hvorsomhelst',
'Search data in tables' => 'Søk data i tabeller', 'Search data in tables' => 'Søk data i tabeller',
'as a regular expression' => null,
'Sort' => 'Sorter', 'Sort' => 'Sorter',
'descending' => 'minkende', 'descending' => 'minkende',
'Limit' => 'Skranke', 'Limit' => 'Skranke',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Nei', 'No' => 'Nei',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Rodzaj bazy', 'System' => 'Rodzaj bazy',
'Server' => 'Serwer', 'Server' => 'Serwer',
'Username' => 'Użytkownik', 'Username' => 'Użytkownik',
@@ -81,7 +82,6 @@ $translations = array(
'Data' => 'Dane', 'Data' => 'Dane',
'Database' => 'Baza danych', 'Database' => 'Baza danych',
'database' => 'baza danych',
'Use' => 'Wybierz', 'Use' => 'Wybierz',
'Select database' => 'Wybierz bazę danych', 'Select database' => 'Wybierz bazę danych',
'Invalid database.' => 'Nie znaleziono bazy danych.', 'Invalid database.' => 'Nie znaleziono bazy danych.',
@@ -168,7 +168,6 @@ $translations = array(
'Options' => 'Opcje', 'Options' => 'Opcje',
'Comment' => 'Komentarz', 'Comment' => 'Komentarz',
'Default value' => 'Wartość domyślna', 'Default value' => 'Wartość domyślna',
'Default values' => 'Wartości domyślne',
'Drop' => 'Usuń', 'Drop' => 'Usuń',
'Drop %s?' => 'Usunąć %s?', 'Drop %s?' => 'Usunąć %s?',
'Are you sure?' => 'Czy jesteś pewien?', 'Are you sure?' => 'Czy jesteś pewien?',
@@ -180,6 +179,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Przekroczono maksymalną liczbę pól. Zwiększ %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Przekroczono maksymalną liczbę pól. Zwiększ %s.',
'Partition by' => 'Partycjonowanie', 'Partition by' => 'Partycjonowanie',
'Partition' => null,
'Partitions' => 'Partycje', 'Partitions' => 'Partycje',
'Partition name' => 'Nazwa partycji', 'Partition name' => 'Nazwa partycji',
'Values' => 'Wartości', 'Values' => 'Wartości',
@@ -234,6 +234,7 @@ $translations = array(
'Search' => 'Szukaj', 'Search' => 'Szukaj',
'anywhere' => 'gdziekolwiek', 'anywhere' => 'gdziekolwiek',
'Search data in tables' => 'Wyszukaj we wszystkich tabelach', 'Search data in tables' => 'Wyszukaj we wszystkich tabelach',
'as a regular expression' => null,
'Sort' => 'Sortuj', 'Sort' => 'Sortuj',
'descending' => 'malejąco', 'descending' => 'malejąco',
'Limit' => 'Limit', 'Limit' => 'Limit',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Nie', 'No' => 'Nie',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Entrar', 'Login' => 'Entrar',
'Logout successful.' => 'Saída bem sucedida.', 'Logout successful.' => 'Saída bem sucedida.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Criar Base de dados', 'Create database' => 'Criar Base de dados',
'SQL command' => 'Comando SQL', 'SQL command' => 'Comando SQL',
'Logout' => 'Sair', 'Logout' => 'Sair',
'database' => 'base de dados',
'Use' => 'Usar', 'Use' => 'Usar',
'No tables.' => 'Não existem tabelas.', 'No tables.' => 'Não existem tabelas.',
'select' => 'selecionar', 'select' => 'selecionar',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Não é possível selecionar a Tabela', 'Unable to select the table' => 'Não é possível selecionar a Tabela',
'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Enviar o formulário novamente.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Enviar o formulário novamente.',
'Comment' => 'Comentário', 'Comment' => 'Comentário',
'Default values' => 'Valores padrões',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Nenhum comando para executar.', 'No commands to execute.' => 'Nenhum comando para executar.',
'Unable to upload a file.' => 'Não é possível enviar o arquivo.', 'Unable to upload a file.' => 'Não é possível enviar o arquivo.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'Clonar', 'Clone' => 'Clonar',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Quantidade máxima de campos permitidos excedidos. Por favor aumente %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Quantidade máxima de campos permitidos excedidos. Por favor aumente %s.',
'Partition by' => 'Particionar por', 'Partition by' => 'Particionar por',
'Partition' => null,
'Partitions' => 'Partições', 'Partitions' => 'Partições',
'Partition name' => 'Nome da Partição', 'Partition name' => 'Nome da Partição',
'Values' => 'Valores', 'Values' => 'Valores',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Login permanente', 'Permanent login' => 'Login permanente',
'Databases have been dropped.' => 'A Base de dados foi apagada.', 'Databases have been dropped.' => 'A Base de dados foi apagada.',
'Search data in tables' => 'Buscar dados nas Tabelas', 'Search data in tables' => 'Buscar dados nas Tabelas',
'as a regular expression' => null,
'Schema' => 'Esquema', 'Schema' => 'Esquema',
'Alter schema' => 'Alterar esquema', 'Alter schema' => 'Alterar esquema',
'Create schema' => 'Criar esquema', 'Create schema' => 'Criar esquema',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Entrar', 'Login' => 'Entrar',
'Logout successful.' => 'Sessão terminada com sucesso.', 'Logout successful.' => 'Sessão terminada com sucesso.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Criar Base de dados', 'Create database' => 'Criar Base de dados',
'SQL command' => 'Comando SQL', 'SQL command' => 'Comando SQL',
'Logout' => 'Terminar sessão', 'Logout' => 'Terminar sessão',
'database' => 'base de dados',
'Use' => 'Usar', 'Use' => 'Usar',
'No tables.' => 'Não existem tabelas.', 'No tables.' => 'Não existem tabelas.',
'select' => 'registos', 'select' => 'registos',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Não é possivel selecionar a Tabela', 'Unable to select the table' => 'Não é possivel selecionar a Tabela',
'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Enviar o formulario novamente.', 'Invalid CSRF token. Send the form again.' => 'Token CSRF inválido. Enviar o formulario novamente.',
'Comment' => 'Comentário', 'Comment' => 'Comentário',
'Default values' => 'Valores predeterminados',
'%d byte(s)' => array('%d byte', '%d bytes'), '%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Nenhum comando para executar.', 'No commands to execute.' => 'Nenhum comando para executar.',
'Unable to upload a file.' => 'Não é possível enviar o ficheiro.', 'Unable to upload a file.' => 'Não é possível enviar o ficheiro.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'Clonar', 'Clone' => 'Clonar',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Quantidade máxima de campos permitidos excedidos. Por favor aumente %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Quantidade máxima de campos permitidos excedidos. Por favor aumente %s.',
'Partition by' => 'Particionar por', 'Partition by' => 'Particionar por',
'Partition' => null,
'Partitions' => 'Partições', 'Partitions' => 'Partições',
'Partition name' => 'Nome da Partição', 'Partition name' => 'Nome da Partição',
'Values' => 'Valores', 'Values' => 'Valores',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Memorizar a senha', 'Permanent login' => 'Memorizar a senha',
'Databases have been dropped.' => 'Bases de dados eliminadas.', 'Databases have been dropped.' => 'Bases de dados eliminadas.',
'Search data in tables' => 'Pesquisar dados nas Tabelas', 'Search data in tables' => 'Pesquisar dados nas Tabelas',
'as a regular expression' => null,
'Schema' => 'Esquema', 'Schema' => 'Esquema',
'Alter schema' => 'Modificar esquema', 'Alter schema' => 'Modificar esquema',
'Create schema' => 'Criar esquema', 'Create schema' => 'Criar esquema',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Intră', 'Login' => 'Intră',
'Logout successful.' => 'Ați ieșit cu succes.', 'Logout successful.' => 'Ați ieșit cu succes.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Crează baza de date', 'Create database' => 'Crează baza de date',
'SQL command' => 'SQL query', 'SQL command' => 'SQL query',
'Logout' => 'Ieșire', 'Logout' => 'Ieșire',
'database' => 'baza de date',
'Use' => 'Alege', 'Use' => 'Alege',
'No tables.' => 'În baza de date nu sunt tabele.', 'No tables.' => 'În baza de date nu sunt tabele.',
'select' => 'selectează', 'select' => 'selectează',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Nu am putut selecta date din tabel', 'Unable to select the table' => 'Nu am putut selecta date din tabel',
'Invalid CSRF token. Send the form again.' => 'CSRF token imposibil. Retrimite forma.', 'Invalid CSRF token. Send the form again.' => 'CSRF token imposibil. Retrimite forma.',
'Comment' => 'Comentariu', 'Comment' => 'Comentariu',
'Default values' => 'Valoarea inițială',
'%d byte(s)' => array('%d octet', '%d octeți'), '%d byte(s)' => array('%d octet', '%d octeți'),
'No commands to execute.' => 'Nu sunt comenzi de executat.', 'No commands to execute.' => 'Nu sunt comenzi de executat.',
'Unable to upload a file.' => 'Nu am putut încărca fișierul pe server.', 'Unable to upload a file.' => 'Nu am putut încărca fișierul pe server.',
@@ -189,6 +188,7 @@ $translations = array(
'Tables have been dropped.' => 'Tabelele au fost șterse.', 'Tables have been dropped.' => 'Tabelele au fost șterse.',
'Clone' => 'Clonează', 'Clone' => 'Clonează',
'Partition by' => 'Împarte', 'Partition by' => 'Împarte',
'Partition' => null,
'Partitions' => 'Secțiuni', 'Partitions' => 'Secțiuni',
'Partition name' => 'Denumirea secțiunii', 'Partition name' => 'Denumirea secțiunii',
'Values' => 'Parametru', 'Values' => 'Parametru',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Logare permanentă', 'Permanent login' => 'Logare permanentă',
'Databases have been dropped.' => 'Bazele de date au fost șterse.', 'Databases have been dropped.' => 'Bazele de date au fost șterse.',
'Search data in tables' => 'Caută în tabele', 'Search data in tables' => 'Caută în tabele',
'as a regular expression' => null,
'Schema' => 'Schema', 'Schema' => 'Schema',
'Alter schema' => 'Modifică schema', 'Alter schema' => 'Modifică schema',
'Create schema' => 'Crează o schemă', 'Create schema' => 'Crează o schemă',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'Войти', 'Login' => 'Войти',
'Logout successful.' => 'Вы успешно покинули систему.', 'Logout successful.' => 'Вы успешно покинули систему.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'Создать базу данных', 'Create database' => 'Создать базу данных',
'SQL command' => 'SQL-запрос', 'SQL command' => 'SQL-запрос',
'Logout' => 'Выйти', 'Logout' => 'Выйти',
'database' => 'база данных',
'Use' => 'Выбрать', 'Use' => 'Выбрать',
'No tables.' => 'В базе данных нет таблиц.', 'No tables.' => 'В базе данных нет таблиц.',
'select' => 'выбрать', 'select' => 'выбрать',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'Не удалось получить данные из таблицы', 'Unable to select the table' => 'Не удалось получить данные из таблицы',
'Invalid CSRF token. Send the form again.' => 'Недействительный CSRF-токен. Отправите форму ещё раз.', 'Invalid CSRF token. Send the form again.' => 'Недействительный CSRF-токен. Отправите форму ещё раз.',
'Comment' => 'Комментарий', 'Comment' => 'Комментарий',
'Default values' => 'Значения по умолчанию',
'%d byte(s)' => array('%d байт', '%d байта', '%d байтов'), '%d byte(s)' => array('%d байт', '%d байта', '%d байтов'),
'No commands to execute.' => 'Нет команд для выполнения.', 'No commands to execute.' => 'Нет команд для выполнения.',
'Unable to upload a file.' => 'Не удалось загрузить файл на сервер.', 'Unable to upload a file.' => 'Не удалось загрузить файл на сервер.',
@@ -189,6 +188,7 @@ $translations = array(
'Tables have been dropped.' => 'Таблицы были удалены.', 'Tables have been dropped.' => 'Таблицы были удалены.',
'Clone' => 'Клонировать', 'Clone' => 'Клонировать',
'Partition by' => 'Разделить по', 'Partition by' => 'Разделить по',
'Partition' => null,
'Partitions' => 'Разделы', 'Partitions' => 'Разделы',
'Partition name' => 'Название раздела', 'Partition name' => 'Название раздела',
'Values' => 'Параметры', 'Values' => 'Параметры',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'Оставаться в системе', 'Permanent login' => 'Оставаться в системе',
'Databases have been dropped.' => 'Базы данных удалены.', 'Databases have been dropped.' => 'Базы данных удалены.',
'Search data in tables' => 'Поиск в таблицах', 'Search data in tables' => 'Поиск в таблицах',
'as a regular expression' => 'как регулярное выражение',
'Schema' => 'Схема', 'Schema' => 'Схема',
'Alter schema' => 'Изменить схему', 'Alter schema' => 'Изменить схему',
'Create schema' => 'Новая схема', 'Create schema' => 'Новая схема',
@@ -310,4 +311,10 @@ $translations = array(
'No' => 'Нет', 'No' => 'Нет',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => 'Domov',
'Login' => 'Prihlásiť sa', 'Login' => 'Prihlásiť sa',
'Logout successful.' => 'Odhlásenie prebehlo v poriadku.', 'Logout successful.' => 'Odhlásenie prebehlo v poriadku.',
'Invalid server or credentials.' => 'Neplatný server alebo prihlasovacie údaje.', 'Invalid server or credentials.' => 'Neplatný server alebo prihlasovacie údaje.',
@@ -32,7 +33,6 @@ $translations = array(
'Create database' => 'Vytvoriť databázu', 'Create database' => 'Vytvoriť databázu',
'SQL command' => 'SQL príkaz', 'SQL command' => 'SQL príkaz',
'Logout' => 'Odhlásiť', 'Logout' => 'Odhlásiť',
'database' => 'databáza',
'Use' => 'Vybrať', 'Use' => 'Vybrať',
'No tables.' => 'Žiadne tabuľky.', 'No tables.' => 'Žiadne tabuľky.',
'select' => 'vypísať', 'select' => 'vypísať',
@@ -70,7 +70,6 @@ $translations = array(
'Unable to select the table' => 'Tabuľku sa nepodarilo vypísať', 'Unable to select the table' => 'Tabuľku sa nepodarilo vypísať',
'Invalid CSRF token. Send the form again.' => 'Neplatný token CSRF. Odošlite formulár znova.', 'Invalid CSRF token. Send the form again.' => 'Neplatný token CSRF. Odošlite formulár znova.',
'Comment' => 'Komentár', 'Comment' => 'Komentár',
'Default values' => 'Predvolené hodnoty',
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtov'), '%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtov'),
'No commands to execute.' => 'Žiadne príkazy na vykonanie.', 'No commands to execute.' => 'Žiadne príkazy na vykonanie.',
'Unable to upload a file.' => 'Súbor sa nepodarilo nahrať.', 'Unable to upload a file.' => 'Súbor sa nepodarilo nahrať.',
@@ -78,6 +77,8 @@ $translations = array(
'File uploads are disabled.' => 'Nahrávánie súborov nie je povolené.', 'File uploads are disabled.' => 'Nahrávánie súborov nie je povolené.',
'Routine has been called, %d row(s) affected.' => array('Procedúra bola zavolaná, bol zmenený %d záznam.', 'Procedúra bola zavolaná, boli zmenené %d záznamy.', 'Procedúra bola zavolaná, bolo zmenených %d záznamov.'), 'Routine has been called, %d row(s) affected.' => array('Procedúra bola zavolaná, bol zmenený %d záznam.', 'Procedúra bola zavolaná, boli zmenené %d záznamy.', 'Procedúra bola zavolaná, bolo zmenených %d záznamov.'),
'Call' => 'Zavolať', 'Call' => 'Zavolať',
'No driver' => 'Žiadny ovládač',
'Database driver not found.' => 'Databázový ovládač sa nenašiel.',
'No extension' => 'Žiadne rozšírenie', 'No extension' => 'Žiadne rozšírenie',
'None of the supported PHP extensions (%s) are available.' => 'Nie je dostupné žiadne z podporovaných rozšírení (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Nie je dostupné žiadne z podporovaných rozšírení (%s).',
'Session support must be enabled.' => 'Session premenné musia byť povolené.', 'Session support must be enabled.' => 'Session premenné musia byť povolené.',
@@ -190,6 +191,7 @@ $translations = array(
'Whole result' => 'Celý výsledok', 'Whole result' => 'Celý výsledok',
'Clone' => 'Klonovať', 'Clone' => 'Klonovať',
'Partition by' => 'Rozdeliť podľa', 'Partition by' => 'Rozdeliť podľa',
'Partition' => 'Oddiel',
'Partitions' => 'Oddiely', 'Partitions' => 'Oddiely',
'Partition name' => 'Názov oddielu', 'Partition name' => 'Názov oddielu',
'Values' => 'Hodnoty', 'Values' => 'Hodnoty',
@@ -224,6 +226,7 @@ $translations = array(
'Permanent login' => 'Trvalé prihlásenie', 'Permanent login' => 'Trvalé prihlásenie',
'%d in total' => '%d celkom', '%d in total' => '%d celkom',
'Search data in tables' => 'Vyhľadať dáta v tabuľkách', 'Search data in tables' => 'Vyhľadať dáta v tabuľkách',
'as a regular expression' => 'ako regulárny výraz',
'Alter schema' => 'Pozmeniť schému', 'Alter schema' => 'Pozmeniť schému',
'Create schema' => 'Vytvoriť schému', 'Create schema' => 'Vytvoriť schému',
'Schema has been dropped.' => 'Schéma bola odstránená.', 'Schema has been dropped.' => 'Schéma bola odstránená.',
@@ -256,7 +259,7 @@ $translations = array(
'%d query(s) executed OK.' => array('Bol vykonaný %d dotaz.', 'Boli vykonané %d dotazy.', 'Bolo vykonaných %d dotazov.'), '%d query(s) executed OK.' => array('Bol vykonaný %d dotaz.', 'Boli vykonané %d dotazy.', 'Bolo vykonaných %d dotazov.'),
'Show only errors' => 'Zobraziť iba chyby', 'Show only errors' => 'Zobraziť iba chyby',
'Refresh' => 'Obnoviť', 'Refresh' => 'Obnoviť',
'Invalid schema.' => 'Neplatné schéma.', 'Invalid schema.' => 'Neplatná schéma.',
'Please use one of the extensions %s.' => 'Prosím vyberte jednu z koncoviek %s.', 'Please use one of the extensions %s.' => 'Prosím vyberte jednu z koncoviek %s.',
'now' => 'teraz', 'now' => 'teraz',
'ltr' => 'ltr', 'ltr' => 'ltr',
@@ -274,8 +277,8 @@ $translations = array(
'DB' => 'DB', 'DB' => 'DB',
'File must be in UTF-8 encoding.' => 'Súbor musí byť v kódovaní UTF-8.', 'File must be in UTF-8 encoding.' => 'Súbor musí byť v kódovaní UTF-8.',
'Modify' => 'Zmeniť', 'Modify' => 'Zmeniť',
'Load more data' => 'Nahráť ďalšie dáta', 'Load more data' => 'Načítať ďalšie dáta',
'Loading' => 'Nahráva sa', 'Loading' => 'Načítava sa',
'ATTACH queries are not supported.' => 'Dotazy ATTACH nie sú podporované.', 'ATTACH queries are not supported.' => 'Dotazy ATTACH nie sú podporované.',
'Warnings' => 'Varovania', 'Warnings' => 'Varovania',
'%d / ' => '%d / ', '%d / ' => '%d / ',
@@ -308,4 +311,7 @@ $translations = array(
'Default' => 'Predvolené', 'Default' => 'Predvolené',
'One Time Password' => 'Jednorázové heslo', 'One Time Password' => 'Jednorázové heslo',
'Invalid OTP code.' => 'Neplatný kód OTP.', 'Invalid OTP code.' => 'Neplatný kód OTP.',
'Schemas' => 'Schémy',
'No schemas.' => 'Žiadne schémy.',
'Show schema' => 'Zobraziť schému',
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem', 'System' => 'Sistem',
'Server' => 'Strežnik', 'Server' => 'Strežnik',
'Username' => 'Uporabniško ime', 'Username' => 'Uporabniško ime',
@@ -72,7 +73,6 @@ $translations = array(
'Data' => 'Podatki', 'Data' => 'Podatki',
'Database' => 'Baza', 'Database' => 'Baza',
'database' => 'baza',
'Use' => 'Uporabi', 'Use' => 'Uporabi',
'Select database' => 'Izberi bazo', 'Select database' => 'Izberi bazo',
'Invalid database.' => 'Neveljavna baza.', 'Invalid database.' => 'Neveljavna baza.',
@@ -153,7 +153,6 @@ $translations = array(
'Auto Increment' => 'Samodejno povečevanje', 'Auto Increment' => 'Samodejno povečevanje',
'Options' => 'Možnosti', 'Options' => 'Možnosti',
'Comment' => 'Komentar', 'Comment' => 'Komentar',
'Default values' => 'Privzete vrednosti',
'Drop' => 'Zavrzi', 'Drop' => 'Zavrzi',
'Are you sure?' => 'Ste prepričani?', 'Are you sure?' => 'Ste prepričani?',
'Move up' => 'Premakni gor', 'Move up' => 'Premakni gor',
@@ -162,6 +161,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Največje število dovoljenih polje je preseženo. Prosimo, povečajte %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Največje število dovoljenih polje je preseženo. Prosimo, povečajte %s.',
'Partition by' => 'Porazdeli po', 'Partition by' => 'Porazdeli po',
'Partition' => null,
'Partitions' => 'Porazdelitve', 'Partitions' => 'Porazdelitve',
'Partition name' => 'Ime porazdelitve', 'Partition name' => 'Ime porazdelitve',
'Values' => 'Vrednosti', 'Values' => 'Vrednosti',
@@ -215,6 +215,7 @@ $translations = array(
'Search' => 'Išči', 'Search' => 'Išči',
'anywhere' => 'kjerkoli', 'anywhere' => 'kjerkoli',
'Search data in tables' => 'Išče podatke po tabelah', 'Search data in tables' => 'Išče podatke po tabelah',
'as a regular expression' => null,
'Sort' => 'Sortiraj', 'Sort' => 'Sortiraj',
'descending' => 'padajoče', 'descending' => 'padajoče',
'Limit' => 'Limita', 'Limit' => 'Limita',
@@ -352,4 +353,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Систем', 'System' => 'Систем',
'Server' => 'Сервер', 'Server' => 'Сервер',
'Username' => 'Корисничко име', 'Username' => 'Корисничко име',
@@ -73,7 +74,6 @@ $translations = array(
'Data' => 'Податци', 'Data' => 'Податци',
'Database' => 'База података', 'Database' => 'База података',
'database' => 'база података',
'Use' => 'Користи', 'Use' => 'Користи',
'Select database' => 'Изаберите базу', 'Select database' => 'Изаберите базу',
'Invalid database.' => 'Неисправна база података.', 'Invalid database.' => 'Неисправна база података.',
@@ -158,7 +158,6 @@ $translations = array(
'Auto Increment' => 'Ауто-прираштај', 'Auto Increment' => 'Ауто-прираштај',
'Options' => 'Опције', 'Options' => 'Опције',
'Comment' => 'Коментар', 'Comment' => 'Коментар',
'Default values' => 'Подразумеване вредности',
'Drop' => 'Избриши', 'Drop' => 'Избриши',
'Are you sure?' => 'Да ли сте сигурни?', 'Are you sure?' => 'Да ли сте сигурни?',
'Move up' => 'Помери на горе', 'Move up' => 'Помери на горе',
@@ -167,6 +166,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Премашен је максимални број дозвољених поља. Молим увећајте %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Премашен је максимални број дозвољених поља. Молим увећајте %s.',
'Partition by' => 'Подели по', 'Partition by' => 'Подели по',
'Partition' => null,
'Partitions' => 'Поделе', 'Partitions' => 'Поделе',
'Partition name' => 'Име поделе', 'Partition name' => 'Име поделе',
'Values' => 'Вредности', 'Values' => 'Вредности',
@@ -220,6 +220,7 @@ $translations = array(
'Search' => 'Претрага', 'Search' => 'Претрага',
'anywhere' => 'било где', 'anywhere' => 'било где',
'Search data in tables' => 'Претражи податке у табелама', 'Search data in tables' => 'Претражи податке у табелама',
'as a regular expression' => null,
'Sort' => 'Поређај', 'Sort' => 'Поређај',
'descending' => 'опадајуће', 'descending' => 'опадајуће',
'Limit' => 'Граница', 'Limit' => 'Граница',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Не', 'No' => 'Не',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'System', 'System' => 'System',
'Server' => 'Server', 'Server' => 'Server',
'Username' => 'Användarnamn', 'Username' => 'Användarnamn',
@@ -89,7 +90,6 @@ $translations = array(
'Data' => 'Data', 'Data' => 'Data',
'Database' => 'Databas', 'Database' => 'Databas',
'database' => 'databas',
'DB' => 'DB', 'DB' => 'DB',
'Use' => 'Använd', 'Use' => 'Använd',
'Select database' => 'Välj databas', 'Select database' => 'Välj databas',
@@ -178,7 +178,6 @@ $translations = array(
'Options' => 'Inställningar', 'Options' => 'Inställningar',
'Comment' => 'Kommentar', 'Comment' => 'Kommentar',
'Default value' => 'Standardvärde', 'Default value' => 'Standardvärde',
'Default values' => 'Standardvärden',
'Drop' => 'Ta bort', 'Drop' => 'Ta bort',
'Drop %s?' => 'Ta bort %s?', 'Drop %s?' => 'Ta bort %s?',
'Are you sure?' => 'Är du säker?', 'Are you sure?' => 'Är du säker?',
@@ -190,6 +189,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Högsta nummer tillåtna fält är överskridet. Vänligen höj %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Högsta nummer tillåtna fält är överskridet. Vänligen höj %s.',
'Partition by' => 'Partitionera om', 'Partition by' => 'Partitionera om',
'Partition' => null,
'Partitions' => 'Partitioner', 'Partitions' => 'Partitioner',
'Partition name' => 'Partition', 'Partition name' => 'Partition',
'Values' => 'Värden', 'Values' => 'Värden',
@@ -244,6 +244,7 @@ $translations = array(
'Search' => 'Sök', 'Search' => 'Sök',
'anywhere' => 'överallt', 'anywhere' => 'överallt',
'Search data in tables' => 'Sök data i tabeller', 'Search data in tables' => 'Sök data i tabeller',
'as a regular expression' => null,
'Sort' => 'Sortera', 'Sort' => 'Sortera',
'descending' => 'Fallande', 'descending' => 'Fallande',
'Limit' => 'Begränsning', 'Limit' => 'Begränsning',
@@ -354,4 +355,10 @@ $translations = array(
'No' => 'Nej', 'No' => 'Nej',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'நுழை', 'Login' => 'நுழை',
'Logout successful.' => 'வெற்றிக‌ர‌மாய் வெளியேறியாயிற்று.', 'Logout successful.' => 'வெற்றிக‌ர‌மாய் வெளியேறியாயிற்று.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'த‌க‌வ‌ல்த‌ள‌த்தை உருவாக்கு', 'Create database' => 'த‌க‌வ‌ல்த‌ள‌த்தை உருவாக்கு',
'SQL command' => 'SQL க‌ட்ட‌ளை', 'SQL command' => 'SQL க‌ட்ட‌ளை',
'Logout' => 'வெளியேறு', 'Logout' => 'வெளியேறு',
'database' => 'த‌க‌வ‌ல்த‌ள‌ம்',
'Use' => 'உப‌யோகி', 'Use' => 'உப‌யோகி',
'No tables.' => 'அட்ட‌வ‌ணை இல்லை.', 'No tables.' => 'அட்ட‌வ‌ணை இல்லை.',
'select' => 'தேர்வு செய்', 'select' => 'தேர்வு செய்',
@@ -68,7 +68,6 @@ $translations = array(
'Unable to select the table' => 'அட்ட‌வ‌ணையை தேர்வு செய்ய‌ முடிய‌வில்லை', 'Unable to select the table' => 'அட்ட‌வ‌ணையை தேர்வு செய்ய‌ முடிய‌வில்லை',
'Invalid CSRF token. Send the form again.' => 'CSRF டோக்க‌ன் செல்லாது. ப‌டிவ‌த்தை மீண்டும் அனுப்ப‌வும்.', 'Invalid CSRF token. Send the form again.' => 'CSRF டோக்க‌ன் செல்லாது. ப‌டிவ‌த்தை மீண்டும் அனுப்ப‌வும்.',
'Comment' => 'குறிப்பு', 'Comment' => 'குறிப்பு',
'Default values' => 'உள்ளிருக்கும் (Default) ம‌திப்புக‌ள் ',
'%d byte(s)' => array('%d பைட்', '%d பைட்டுக‌ள்'), '%d byte(s)' => array('%d பைட்', '%d பைட்டுக‌ள்'),
'No commands to execute.' => 'செய‌ல் ப‌டுத்த‌ எந்த‌ க‌ட்ட‌ளைக‌ளும் இல்லை.', 'No commands to execute.' => 'செய‌ல் ப‌டுத்த‌ எந்த‌ க‌ட்ட‌ளைக‌ளும் இல்லை.',
'Unable to upload a file.' => 'கோப்பை மேலேற்ற‌ம் (upload) செய்ய‌ இயல‌வில்லை.', 'Unable to upload a file.' => 'கோப்பை மேலேற்ற‌ம் (upload) செய்ய‌ இயல‌வில்லை.',
@@ -187,6 +186,7 @@ $translations = array(
'Clone' => 'ந‌க‌லி (Clone)', 'Clone' => 'ந‌க‌லி (Clone)',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'அனும‌திக்க‌ப்ப‌ட்ட‌ அதிக‌ப‌ட்ச‌ கோப்புக‌ளின் எண்ணிக்கை மீற‌ப்ப‌ட்ட‌து. த‌ய‌வு செய்து %s ம‌ற்றும் %s யை அதிக‌ரிக்க‌வும்.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'அனும‌திக்க‌ப்ப‌ட்ட‌ அதிக‌ப‌ட்ச‌ கோப்புக‌ளின் எண்ணிக்கை மீற‌ப்ப‌ட்ட‌து. த‌ய‌வு செய்து %s ம‌ற்றும் %s யை அதிக‌ரிக்க‌வும்.',
'Partition by' => 'பிரித்த‌து', 'Partition by' => 'பிரித்த‌து',
'Partition' => null,
'Partitions' => 'பிரிவுக‌ள்', 'Partitions' => 'பிரிவுக‌ள்',
'Partition name' => 'பிரிவின் பெய‌ர்', 'Partition name' => 'பிரிவின் பெய‌ர்',
'Values' => 'ம‌திப்புக‌ள்', 'Values' => 'ம‌திப்புக‌ள்',
@@ -224,6 +224,7 @@ $translations = array(
'Alter schema' => 'அமைப்புமுறையை மாற்று', 'Alter schema' => 'அமைப்புமுறையை மாற்று',
'Create schema' => 'அமைப்புமுறையை உருவாக்கு', 'Create schema' => 'அமைப்புமுறையை உருவாக்கு',
'Search data in tables' => 'த‌க‌வ‌லை அட்ட‌வ‌ணையில் தேடு', 'Search data in tables' => 'த‌க‌வ‌லை அட்ட‌வ‌ணையில் தேடு',
'as a regular expression' => null,
'Sequences' => 'வ‌ரிசைமுறை', 'Sequences' => 'வ‌ரிசைமுறை',
'Create sequence' => 'வ‌ரிசைமுறையை உருவாக்கு', 'Create sequence' => 'வ‌ரிசைமுறையை உருவாக்கு',
'User types' => 'ப‌ய‌னாள‌ர் வ‌கைக‌ள்', 'User types' => 'ப‌ய‌னாள‌ர் வ‌கைக‌ள்',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,5 +1,6 @@
<?php <?php
$translations = array( $translations = array(
'Home' => null,
'Login' => 'เข้าสู่ระบบ', 'Login' => 'เข้าสู่ระบบ',
'Logout successful.' => 'ออกจากระบบเรียบร้อยแล้ว.', 'Logout successful.' => 'ออกจากระบบเรียบร้อยแล้ว.',
'Invalid server or credentials.' => null, 'Invalid server or credentials.' => null,
@@ -31,7 +32,6 @@ $translations = array(
'Create database' => 'สร้างฐานข้อมูล', 'Create database' => 'สร้างฐานข้อมูล',
'SQL command' => 'คำสั่ง SQL', 'SQL command' => 'คำสั่ง SQL',
'Logout' => 'ออกจากระบบ', 'Logout' => 'ออกจากระบบ',
'database' => 'ฐานข้อมูล',
'Use' => 'ใช้งาน', 'Use' => 'ใช้งาน',
'No tables.' => 'ไม่พบตาราง.', 'No tables.' => 'ไม่พบตาราง.',
'select' => 'เลือก', 'select' => 'เลือก',
@@ -69,7 +69,6 @@ $translations = array(
'Unable to select the table' => 'ไม่สามารถเลือกตารางได้', 'Unable to select the table' => 'ไม่สามารถเลือกตารางได้',
'Invalid CSRF token. Send the form again.' => 'เครื่องหมาย CSRF ไม่ถูกต้อง ส่งข้อมูลใหม่อีกครั้ง.', 'Invalid CSRF token. Send the form again.' => 'เครื่องหมาย CSRF ไม่ถูกต้อง ส่งข้อมูลใหม่อีกครั้ง.',
'Comment' => 'หมายเหตุ', 'Comment' => 'หมายเหตุ',
'Default values' => 'ค่าเริ่มต้น',
'%d byte(s)' => '%d ไบท์', '%d byte(s)' => '%d ไบท์',
'No commands to execute.' => 'ไม่มีคำสั่งที่จะประมวลผล.', 'No commands to execute.' => 'ไม่มีคำสั่งที่จะประมวลผล.',
'Unable to upload a file.' => 'ไม่สามารถอัปโหลดไฟล์ได้.', 'Unable to upload a file.' => 'ไม่สามารถอัปโหลดไฟล์ได้.',
@@ -190,6 +189,7 @@ $translations = array(
'Clone' => 'ทำซ้ำ', 'Clone' => 'ทำซ้ำ',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'จำนวนสูงสุดของฟิลด์อนุญาตให้เกิน กรุณาเพิ่มอีก %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'จำนวนสูงสุดของฟิลด์อนุญาตให้เกิน กรุณาเพิ่มอีก %s.',
'Partition by' => 'พาร์ทิชันโดย', 'Partition by' => 'พาร์ทิชันโดย',
'Partition' => null,
'Partitions' => 'พาร์ทิชัน', 'Partitions' => 'พาร์ทิชัน',
'Partition name' => 'ชื่อของพาร์ทิชัน', 'Partition name' => 'ชื่อของพาร์ทิชัน',
'Values' => 'ค่า', 'Values' => 'ค่า',
@@ -224,6 +224,7 @@ $translations = array(
'Permanent login' => 'จดจำการเข้าสู่ระบบตลอดไป', 'Permanent login' => 'จดจำการเข้าสู่ระบบตลอดไป',
'Databases have been dropped.' => 'ฐานข้อมูลถูกลบแล้ว.', 'Databases have been dropped.' => 'ฐานข้อมูลถูกลบแล้ว.',
'Search data in tables' => 'ค้นหาในตาราง', 'Search data in tables' => 'ค้นหาในตาราง',
'as a regular expression' => null,
'Schema' => 'Schema', 'Schema' => 'Schema',
'Alter schema' => 'เปลี่ยนแปลง schema', 'Alter schema' => 'เปลี่ยนแปลง schema',
'Create schema' => 'สร้าง schema', 'Create schema' => 'สร้าง schema',
@@ -310,4 +311,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem', 'System' => 'Sistem',
'Server' => 'Sunucu', 'Server' => 'Sunucu',
'Username' => 'Kullanıcı', 'Username' => 'Kullanıcı',
@@ -84,7 +85,6 @@ $translations = array(
'Data' => 'Veri', 'Data' => 'Veri',
'Database' => 'Veri Tabanı', 'Database' => 'Veri Tabanı',
'database' => 'veri tabanı',
'DB' => 'DB', 'DB' => 'DB',
'Use' => 'Kullan', 'Use' => 'Kullan',
'Select database' => 'Veri tabanı seç', 'Select database' => 'Veri tabanı seç',
@@ -172,7 +172,6 @@ $translations = array(
'Options' => 'Seçenekler', 'Options' => 'Seçenekler',
'Comment' => 'Yorum', 'Comment' => 'Yorum',
'Default value' => 'Varsayılan değer', 'Default value' => 'Varsayılan değer',
'Default values' => 'Varsayılan değerler',
'Drop' => 'Sil', 'Drop' => 'Sil',
'Drop %s?' => 'Sil %s?', 'Drop %s?' => 'Sil %s?',
'Are you sure?' => 'Emin misiniz?', 'Are you sure?' => 'Emin misiniz?',
@@ -184,6 +183,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'İzin verilen en fazla alan sayısııldı. Lütfen %s değerlerini artırın.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'İzin verilen en fazla alan sayısııldı. Lütfen %s değerlerini artırın.',
'Partition by' => 'Bununla bölümle', 'Partition by' => 'Bununla bölümle',
'Partition' => null,
'Partitions' => 'Bölümler', 'Partitions' => 'Bölümler',
'Partition name' => 'Bölüm adı', 'Partition name' => 'Bölüm adı',
'Values' => 'Değerler', 'Values' => 'Değerler',
@@ -238,6 +238,7 @@ $translations = array(
'Search' => 'Ara', 'Search' => 'Ara',
'anywhere' => 'hiçbir yerde', 'anywhere' => 'hiçbir yerde',
'Search data in tables' => 'Tablolarda veri ara', 'Search data in tables' => 'Tablolarda veri ara',
'as a regular expression' => null,
'Sort' => 'Sırala', 'Sort' => 'Sırala',
'descending' => 'Azalan', 'descending' => 'Azalan',
'Limit' => 'Limit', 'Limit' => 'Limit',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Hayır', 'No' => 'Hayır',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Система Бази Даних', 'System' => 'Система Бази Даних',
'Server' => 'Сервер', 'Server' => 'Сервер',
'Username' => 'Користувач', 'Username' => 'Користувач',
@@ -73,7 +74,6 @@ $translations = array(
'Data' => 'Дані', 'Data' => 'Дані',
'Database' => 'База даних', 'Database' => 'База даних',
'database' => 'база даних',
'Use' => 'Обрати', 'Use' => 'Обрати',
'Select database' => 'Обрати базу даних', 'Select database' => 'Обрати базу даних',
'Invalid database.' => 'Погана база даних.', 'Invalid database.' => 'Погана база даних.',
@@ -158,7 +158,6 @@ $translations = array(
'Auto Increment' => 'Автоматичне збільшення', 'Auto Increment' => 'Автоматичне збільшення',
'Options' => 'Опції', 'Options' => 'Опції',
'Comment' => 'Коментарі', 'Comment' => 'Коментарі',
'Default values' => 'Значення за замовчуванням',
'Drop' => 'Видалити', 'Drop' => 'Видалити',
'Are you sure?' => 'Ви впевнені?', 'Are you sure?' => 'Ви впевнені?',
'Move up' => 'Пересунути вгору', 'Move up' => 'Пересунути вгору',
@@ -167,6 +166,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Досягнута максимальна кількість доступних полів. Будь ласка, збільшіть %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Досягнута максимальна кількість доступних полів. Будь ласка, збільшіть %s.',
'Partition by' => 'Розділити по', 'Partition by' => 'Розділити по',
'Partition' => null,
'Partitions' => 'Розділи', 'Partitions' => 'Розділи',
'Partition name' => 'Назва розділу', 'Partition name' => 'Назва розділу',
'Values' => 'Значення', 'Values' => 'Значення',
@@ -220,6 +220,7 @@ $translations = array(
'Search' => 'Пошук', 'Search' => 'Пошук',
'anywhere' => 'будь-де', 'anywhere' => 'будь-де',
'Search data in tables' => 'Шукати дані в таблицях', 'Search data in tables' => 'Шукати дані в таблицях',
'as a regular expression' => null,
'Sort' => 'Сортувати', 'Sort' => 'Сортувати',
'descending' => 'по спаданню', 'descending' => 'по спаданню',
'Limit' => 'Обмеження', 'Limit' => 'Обмеження',
@@ -355,4 +356,10 @@ $translations = array(
'No' => 'Ні', 'No' => 'Ні',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Hệ thống', 'System' => 'Hệ thống',
'Server' => 'Máy chủ', 'Server' => 'Máy chủ',
'Username' => 'Tên người dùng', 'Username' => 'Tên người dùng',
@@ -76,7 +77,6 @@ $translations = array(
'Data' => 'Dữ liệu', 'Data' => 'Dữ liệu',
'Database' => 'Cơ sở dữ liệu', 'Database' => 'Cơ sở dữ liệu',
'database' => 'cơ sở dữ liệu',
'Use' => 'Sử dụng', 'Use' => 'Sử dụng',
'Select database' => 'Chọn CSDL', 'Select database' => 'Chọn CSDL',
'Invalid database.' => 'CSDL sai.', 'Invalid database.' => 'CSDL sai.',
@@ -161,7 +161,6 @@ $translations = array(
'Auto Increment' => 'Tăng tự động', 'Auto Increment' => 'Tăng tự động',
'Options' => 'Tuỳ chọn', 'Options' => 'Tuỳ chọn',
'Comment' => 'Chú thích', 'Comment' => 'Chú thích',
'Default values' => 'Giá trị mặc định',
'Drop' => 'Xoá', 'Drop' => 'Xoá',
'Are you sure?' => 'Bạn có chắc', 'Are you sure?' => 'Bạn có chắc',
'Size' => 'Kích thước', 'Size' => 'Kích thước',
@@ -172,6 +171,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Thiết lập %s cần tăng thêm. (Đã vượt giới hạnố trường tối đa cho phép trong một biểu mẫu).', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Thiết lập %s cần tăng thêm. (Đã vượt giới hạnố trường tối đa cho phép trong một biểu mẫu).',
'Partition by' => 'Phân chia bằng', 'Partition by' => 'Phân chia bằng',
'Partition' => null,
'Partitions' => 'Phân hoạch', 'Partitions' => 'Phân hoạch',
'Partition name' => 'Tên phân hoạch', 'Partition name' => 'Tên phân hoạch',
'Values' => 'Giá trị', 'Values' => 'Giá trị',
@@ -225,6 +225,7 @@ $translations = array(
'Search' => 'Tìm kiếm', 'Search' => 'Tìm kiếm',
'anywhere' => 'bất cứ đâu', 'anywhere' => 'bất cứ đâu',
'Search data in tables' => 'Tìm kiếm dữ liệu trong các bảng', 'Search data in tables' => 'Tìm kiếm dữ liệu trong các bảng',
'as a regular expression' => null,
'Sort' => 'Sắp xếp', 'Sort' => 'Sắp xếp',
'descending' => 'giảm dần', 'descending' => 'giảm dần',
'Limit' => 'Giới hạn', 'Limit' => 'Giới hạn',
@@ -354,4 +355,10 @@ $translations = array(
'No' => 'Không', 'No' => 'Không',
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => 'Xx',
'System' => 'Xx', 'System' => 'Xx',
'Server' => 'Xx', 'Server' => 'Xx',
'Username' => 'Xx', 'Username' => 'Xx',
@@ -20,6 +21,8 @@ $translations = array(
'Language' => 'Xx', 'Language' => 'Xx',
'Invalid CSRF token. Send the form again.' => 'Xx.', 'Invalid CSRF token. Send the form again.' => 'Xx.',
'If you did not send this request from Adminer then close this page.' => 'Xx.', 'If you did not send this request from Adminer then close this page.' => 'Xx.',
'No driver' => 'Xx',
'Database driver not found.' => 'Xx.',
'No extension' => 'Xx', 'No extension' => 'Xx',
'None of the supported PHP extensions (%s) are available.' => 'Xx (%s).', 'None of the supported PHP extensions (%s) are available.' => 'Xx (%s).',
'Connecting to privileged ports is not allowed.' => 'Xx.', 'Connecting to privileged ports is not allowed.' => 'Xx.',
@@ -89,7 +92,6 @@ $translations = array(
'Data' => 'Xx', 'Data' => 'Xx',
'Database' => 'Xx', 'Database' => 'Xx',
'database' => 'xx',
'DB' => 'XX', 'DB' => 'XX',
'Use' => 'Xx', 'Use' => 'Xx',
'Select database' => 'Xx', 'Select database' => 'Xx',
@@ -178,7 +180,6 @@ $translations = array(
'Options' => 'Xx', 'Options' => 'Xx',
'Comment' => 'Xx', 'Comment' => 'Xx',
'Default value' => 'Xx', 'Default value' => 'Xx',
'Default values' => 'Xx',
'Drop' => 'Xx', 'Drop' => 'Xx',
'Drop %s?' => 'Xx %s?', 'Drop %s?' => 'Xx %s?',
'Are you sure?' => 'Xx?', 'Are you sure?' => 'Xx?',
@@ -190,6 +191,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Xx %s.', 'Maximum number of allowed fields exceeded. Please increase %s.' => 'Xx %s.',
'Partition by' => 'Xx', 'Partition by' => 'Xx',
'Partition' => 'Xx',
'Partitions' => 'Xx', 'Partitions' => 'Xx',
'Partition name' => 'Xx', 'Partition name' => 'Xx',
'Values' => 'Xx', 'Values' => 'Xx',
@@ -244,6 +246,7 @@ $translations = array(
'Search' => 'Xx', 'Search' => 'Xx',
'anywhere' => 'xx', 'anywhere' => 'xx',
'Search data in tables' => 'Xx', 'Search data in tables' => 'Xx',
'as a regular expression' => 'xx',
'Sort' => 'Xx', 'Sort' => 'Xx',
'descending' => 'xx', 'descending' => 'xx',
'Limit' => 'Xx', 'Limit' => 'Xx',
@@ -324,12 +327,15 @@ $translations = array(
'Please use one of the extensions %s.' => 'Xx %s.', 'Please use one of the extensions %s.' => 'Xx %s.',
// PostgreSQL and MS SQL schema support // PostgreSQL and MS SQL schema support
'Schema' => 'Xx',
'Schemas' => 'Xx',
'No schemas.' => 'Xx.',
'Show schema' => 'Xx',
'Alter schema' => 'Xx', 'Alter schema' => 'Xx',
'Create schema' => 'Xx', 'Create schema' => 'Xx',
'Schema has been dropped.' => 'Xx.', 'Schema has been dropped.' => 'Xx.',
'Schema has been created.' => 'Xx.', 'Schema has been created.' => 'Xx.',
'Schema has been altered.' => 'Xx.', 'Schema has been altered.' => 'Xx.',
'Schema' => 'Xx',
'Invalid schema.' => 'Xx.', 'Invalid schema.' => 'Xx.',
// PostgreSQL sequences support // PostgreSQL sequences support

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => '資料庫系統', 'System' => '資料庫系統',
'Server' => '伺服器', 'Server' => '伺服器',
'Username' => '帳號', 'Username' => '帳號',
@@ -89,7 +90,6 @@ $translations = array(
'Data' => '資料', 'Data' => '資料',
'Database' => '資料庫', 'Database' => '資料庫',
'database' => '資料庫',
'DB' => '資料庫', 'DB' => '資料庫',
'Use' => '使用', 'Use' => '使用',
'Select database' => '選擇資料庫', 'Select database' => '選擇資料庫',
@@ -178,7 +178,6 @@ $translations = array(
'Options' => '選項', 'Options' => '選項',
'Comment' => '註解', 'Comment' => '註解',
'Default value' => '預設值', 'Default value' => '預設值',
'Default values' => '預設值',
'Drop' => '刪除', 'Drop' => '刪除',
'Drop %s?' => '刪除 %s?', 'Drop %s?' => '刪除 %s?',
'Are you sure?' => '你確定嗎?', 'Are you sure?' => '你確定嗎?',
@@ -190,6 +189,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => '超過允許的字段數量的最大值。請增加 %s。', 'Maximum number of allowed fields exceeded. Please increase %s.' => '超過允許的字段數量的最大值。請增加 %s。',
'Partition by' => '分區類型', 'Partition by' => '分區類型',
'Partition' => null,
'Partitions' => '分區', 'Partitions' => '分區',
'Partition name' => '分區名稱', 'Partition name' => '分區名稱',
'Values' => '值', 'Values' => '值',
@@ -244,6 +244,7 @@ $translations = array(
'Search' => '搜尋', 'Search' => '搜尋',
'anywhere' => '任意位置', 'anywhere' => '任意位置',
'Search data in tables' => '在資料庫搜尋', 'Search data in tables' => '在資料庫搜尋',
'as a regular expression' => null,
'Sort' => '排序', 'Sort' => '排序',
'descending' => '降冪 (遞減)', 'descending' => '降冪 (遞減)',
'Limit' => '限定', 'Limit' => '限定',
@@ -355,4 +356,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -1,6 +1,7 @@
<?php <?php
$translations = array( $translations = array(
// label for database system selection (MySQL, SQLite, ...) // label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => '系统', 'System' => '系统',
'Server' => '服务器', 'Server' => '服务器',
'Username' => '用户名', 'Username' => '用户名',
@@ -89,7 +90,6 @@ $translations = array(
'Data' => '数据', 'Data' => '数据',
'Database' => '数据库', 'Database' => '数据库',
'database' => '数据库',
'DB' => '数据库', 'DB' => '数据库',
'Use' => '使用', 'Use' => '使用',
'Select database' => '选择数据库', 'Select database' => '选择数据库',
@@ -178,7 +178,6 @@ $translations = array(
'Options' => '选项', 'Options' => '选项',
'Comment' => '注释', 'Comment' => '注释',
'Default value' => '默认值', 'Default value' => '默认值',
'Default values' => '默认值',
'Drop' => '删除', 'Drop' => '删除',
'Drop %s?' => '删除 %s?', 'Drop %s?' => '删除 %s?',
'Are you sure?' => '您确定吗?', 'Are you sure?' => '您确定吗?',
@@ -190,6 +189,7 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => '超过最多允许的字段数量。请增加 %s。', 'Maximum number of allowed fields exceeded. Please increase %s.' => '超过最多允许的字段数量。请增加 %s。',
'Partition by' => '分区类型', 'Partition by' => '分区类型',
'Partition' => null,
'Partitions' => '分区', 'Partitions' => '分区',
'Partition name' => '分区名', 'Partition name' => '分区名',
'Values' => '值', 'Values' => '值',
@@ -244,6 +244,7 @@ $translations = array(
'Search' => '搜索', 'Search' => '搜索',
'anywhere' => '任意位置', 'anywhere' => '任意位置',
'Search data in tables' => '在表中搜索数据', 'Search data in tables' => '在表中搜索数据',
'as a regular expression' => null,
'Sort' => '排序', 'Sort' => '排序',
'descending' => '降序', 'descending' => '降序',
'Limit' => '范围', 'Limit' => '范围',
@@ -354,4 +355,10 @@ $translations = array(
'No' => null, 'No' => null,
'One Time Password' => null, 'One Time Password' => null,
'Invalid OTP code.' => null, 'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
); );

View File

@@ -2,15 +2,15 @@
function adminer_object() { function adminer_object() {
// required to run any plugin // required to run any plugin
include_once "../plugins/plugin.php"; include_once "../plugins/plugin.php";
// autoloader // autoloader
foreach (glob("../plugins/*.php") as $filename) { foreach (glob("../plugins/*.php") as $filename) {
include_once $filename; include_once $filename;
} }
// enable extra drivers just by including them // enable extra drivers just by including them
//~ include "../plugins/drivers/simpledb.php"; //~ include "../plugins/drivers/simpledb.php";
$plugins = array( $plugins = array(
// specify enabled plugins here // specify enabled plugins here
new AdminerDatabaseHide(array('information_schema')), new AdminerDatabaseHide(array('information_schema')),
@@ -29,16 +29,16 @@ function adminer_object() {
new AdminerTranslation, new AdminerTranslation,
new AdminerForeignSystem, new AdminerForeignSystem,
new AdminerEnumOption, new AdminerEnumOption,
new AdminerTablesFilter,
new AdminerEditForeign, new AdminerEditForeign,
new AdminerLoginSsl(["TrustServerCertificate" => true]),
); );
/* It is possible to combine customization and plugins: /* It is possible to combine customization and plugins:
class AdminerCustomization extends AdminerPlugin { class AdminerCustomization extends AdminerPlugin {
} }
return new AdminerCustomization($plugins); return new AdminerCustomization($plugins);
*/ */
return new AdminerPlugin($plugins); return new AdminerPlugin($plugins);
} }

View File

@@ -14,7 +14,7 @@ echo "<form action=''><p>\n";
hidden_fields_get(); hidden_fields_get();
echo "<input type='hidden' name='db' value='" . h(DB) . "'>\n"; echo "<input type='hidden' name='db' value='" . h(DB) . "'>\n";
echo ($grant ? "" : "<input type='hidden' name='grant' value=''>\n"); echo ($grant ? "" : "<input type='hidden' name='grant' value=''>\n");
echo "<table cellspacing='0'>\n"; echo "<table>\n";
echo "<thead><tr><th>" . lang('Username') . "<th>" . lang('Server') . "<th></thead>\n"; echo "<thead><tr><th>" . lang('Username') . "<th>" . lang('Server') . "<th></thead>\n";
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {

View File

@@ -39,12 +39,17 @@ $routine_languages = routine_languages();
<?php echo ($routine_languages ? lang('Language') . ": " . html_select("language", $routine_languages, $row["language"]) . "\n" : ""); ?> <?php echo ($routine_languages ? lang('Language') . ": " . html_select("language", $routine_languages, $row["language"]) . "\n" : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<div class="scrollable"> <div class="scrollable">
<table cellspacing="0" class="nowrap"> <table cellspacing="0" class="nowrap" id="edit-fields">
<?php <?php
edit_fields($row["fields"], $collations, $routine); edit_fields($row["fields"], $collations, $routine);
if (isset($_GET["function"])) { if (isset($_GET["function"])) {
echo "<tr><td>" . lang('Return type'); echo "<tbody><tr>",
(support("move_col") ? "<th></th>" : ""),
"<th>", lang('Return type'), "</th>";
edit_type("returns", $row["returns"], $collations, array(), ($jush == "pgsql" ? array("void", "trigger") : array())); edit_type("returns", $row["returns"], $collations, array(), ($jush == "pgsql" ? array("void", "trigger") : array()));
echo "<td></td></tr></tbody>\n";
} }
?> ?>
</table> </table>

View File

@@ -50,9 +50,9 @@ foreach (table_status('', true) as $table => $table_status) {
?> ?>
<div id="schema" style="height: <?php echo $top; ?>em;"> <div id="schema" style="height: <?php echo $top; ?>em;">
<script<?php echo nonce(); ?>> <script<?php echo nonce(); ?>>
qs('#schema').onselectstart = function () { return false; }; gid('schema').onselectstart = function () { return false; };
var tablePos = {<?php echo implode(",", $table_pos_js) . "\n"; ?>}; var tablePos = {<?php echo implode(",", $table_pos_js) . "\n"; ?>};
var em = qs('#schema').offsetHeight / <?php echo $top; ?>; var em = gid('schema').offsetHeight / <?php echo $top; ?>;
document.onmousemove = schemaMousemove; document.onmousemove = schemaMousemove;
document.onmouseup = partialArg(schemaMouseup, '<?php echo js_escape(DB); ?>'); document.onmouseup = partialArg(schemaMouseup, '<?php echo js_escape(DB); ?>');
</script> </script>
@@ -61,12 +61,12 @@ foreach ($schema as $name => $table) {
echo "<div class='table' style='top: " . $table["pos"][0] . "em; left: " . $table["pos"][1] . "em;'>"; echo "<div class='table' style='top: " . $table["pos"][0] . "em; left: " . $table["pos"][1] . "em;'>";
echo '<a href="' . h(ME) . 'table=' . urlencode($name) . '"><b>' . h($name) . "</b></a>"; echo '<a href="' . h(ME) . 'table=' . urlencode($name) . '"><b>' . h($name) . "</b></a>";
echo script("qsl('div').onmousedown = schemaMousedown;"); echo script("qsl('div').onmousedown = schemaMousedown;");
foreach ($table["fields"] as $field) { foreach ($table["fields"] as $field) {
$val = '<span' . type_class($field["type"]) . ' title="' . h($field["full_type"] . ($field["null"] ? " NULL" : '')) . '">' . h($field["field"]) . '</span>'; $val = '<span' . type_class($field["type"]) . ' title="' . h($field["full_type"] . ($field["null"] ? " NULL" : '')) . '">' . h($field["field"]) . '</span>';
echo "<br>" . ($field["primary"] ? "<i>$val</i>" : $val); echo "<br>" . ($field["primary"] ? "<i>$val</i>" : $val);
} }
foreach ((array) $table["references"] as $target_name => $refs) { foreach ((array) $table["references"] as $target_name => $refs) {
foreach ($refs as $left => $ref) { foreach ($refs as $left => $ref) {
$left1 = $left - $table_pos[$name][1]; $left1 = $left - $table_pos[$name][1];
@@ -76,7 +76,7 @@ foreach ($schema as $name => $table) {
} }
} }
} }
foreach ((array) $referenced[$name] as $target_name => $refs) { foreach ((array) $referenced[$name] as $target_name => $refs) {
foreach ($refs as $left => $columns) { foreach ($refs as $left => $columns) {
$left1 = $left - $table_pos[$name][1]; $left1 = $left - $table_pos[$name][1];
@@ -86,7 +86,7 @@ foreach ($schema as $name => $table) {
} }
} }
} }
echo "\n</div>\n"; echo "\n</div>\n";
} }

View File

@@ -27,7 +27,7 @@ if (!$row) {
<form action="" method="post"> <form action="" method="post">
<p><input name="name" id="name" value="<?php echo h($row["name"]); ?>" autocapitalize="off"> <p><input name="name" id="name" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php echo script("focus(qs('#name'));"); ?> <?php echo script("focus(gid('name'));"); ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<?php <?php
if ($_GET["ns"] != "") { if ($_GET["ns"] != "") {

View File

@@ -232,14 +232,16 @@ if (is_ajax()) {
$set = null; $set = null;
if (isset($rights["insert"]) || !support("table")) { if (isset($rights["insert"]) || !support("table")) {
$set = ""; $params = [];
foreach ((array) $_GET["where"] as $val) { foreach ((array) $_GET["where"] as $val) {
if ($foreign_keys[$val["col"]] && count($foreign_keys[$val["col"]]) == 1 && ($val["op"] == "=" if (isset($foreign_keys[$val["col"]]) && count($foreign_keys[$val["col"]]) == 1
|| (!$val["op"] && !preg_match('~[_%]~', $val["val"])) // LIKE in Editor && ($val["op"] == "=" || (!$val["op"] && (is_array($val["val"]) || !preg_match('~[_%]~', $val["val"]))) // LIKE in Editor
)) { )) {
$set .= "&set" . urlencode("[" . bracket_escape($val["col"]) . "]") . "=" . urlencode($val["val"]); $params["set" . "[" . bracket_escape($val["col"]) . "]"] = $val["val"];
} }
} }
$set = $params ? "&" . http_build_query($params) : "";
} }
$adminer->selectLinks($table_status, $set); $adminer->selectLinks($table_status, $set);
@@ -251,6 +253,7 @@ if (!$columns && support("table")) {
hidden_fields_get(); hidden_fields_get();
echo (DB != "" ? '<input type="hidden" name="db" value="' . h(DB) . '">' . (isset($_GET["ns"]) ? '<input type="hidden" name="ns" value="' . h($_GET["ns"]) . '">' : "") : ""); // not used in Editor echo (DB != "" ? '<input type="hidden" name="db" value="' . h(DB) . '">' . (isset($_GET["ns"]) ? '<input type="hidden" name="ns" value="' . h($_GET["ns"]) . '">' : "") : ""); // not used in Editor
echo '<input type="hidden" name="select" value="' . h($TABLE) . '">'; echo '<input type="hidden" name="select" value="' . h($TABLE) . '">';
echo '<input type="submit" value="' . h(lang('Select')) . '">'; # hidden default submit so filter remove buttons aren't "clicked" on submission from enter key
echo "</div>\n"; echo "</div>\n";
$adminer->selectColumnsPrint($select, $columns); $adminer->selectColumnsPrint($select, $columns);
$adminer->selectSearchPrint($where, $search_columns, $indexes); $adminer->selectSearchPrint($where, $search_columns, $indexes);
@@ -319,10 +322,10 @@ if (!$columns && support("table")) {
echo "<div class='scrollable'>"; echo "<div class='scrollable'>";
echo "<table id='table' cellspacing='0' class='nowrap checkable'>"; echo "<table id='table' cellspacing='0' class='nowrap checkable'>";
echo script("mixin(qs('#table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});"); echo script("mixin(gid('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true), onkeydown: editingKeydown});");
echo "<thead><tr>" . (!$group && $select echo "<thead><tr>" . (!$group && $select
? "" ? ""
: "<td><input type='checkbox' id='all-page' class='jsonly'>" . script("qs('#all-page').onclick = partial(formCheck, /check/);", "") : "<td><input type='checkbox' id='all-page' class='jsonly'>" . script("gid('all-page').onclick = partial(formCheck, /check/);", "")
. " <a href='" . h($_GET["modify"] ? remove_from_uri("modify") : $_SERVER["REQUEST_URI"] . "&modify=1") . "'>" . lang('Modify') . "</a>"); . " <a href='" . h($_GET["modify"] ? remove_from_uri("modify") : $_SERVER["REQUEST_URI"] . "&modify=1") . "'>" . lang('Modify') . "</a>");
$names = array(); $names = array();
$functions = array(); $functions = array();
@@ -350,10 +353,10 @@ if (!$columns && support("table")) {
} }
echo "<span class='column hidden'>"; echo "<span class='column hidden'>";
if ($sortable) { if ($sortable) {
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>"; echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
} }
if (!$val["fun"] && isset($field["privileges"]["where"])) { if (!$val["fun"] && isset($field["privileges"]["where"])) {
echo '<a href="#fieldset-search" title="' . lang('Search') . '" class="text jsonly"> =</a>'; echo '<a href="#fieldset-search" title="' . lang('Search') . '" class="text jsonly"> =</a>';
echo script("qsl('a').onclick = partial(selectSearch, '" . js_escape($key) . "');"); echo script("qsl('a').onclick = partial(selectSearch, '" . js_escape($key) . "');");
} }
echo "</span>"; echo "</span>";
@@ -446,7 +449,7 @@ if (!$columns && support("table")) {
$link .= where_link($i++, $k, $v); $link .= where_link($i++, $k, $v);
} }
} }
$val = select_value($val, $link, $field, $text_length); $val = select_value($val, $link, $field, $text_length);
$id = h("val[$unique_idf][" . bracket_escape($key) . "]"); $id = h("val[$unique_idf][" . bracket_escape($key) . "]");
$value = $_POST["val"][$unique_idf][bracket_escape($key)]; $value = $_POST["val"][$unique_idf][bracket_escape($key)];
@@ -507,7 +510,7 @@ if (!$columns && support("table")) {
echo "\n"; echo "\n";
} }
} }
echo "<div class='footer'><div>\n"; echo "<div class='footer'><div>\n";
if ($rows || $page) { if ($rows || $page) {
if ($pagination) { if ($pagination) {
@@ -539,7 +542,7 @@ if (!$columns && support("table")) {
} }
echo "</fieldset>\n"; echo "</fieldset>\n";
} }
echo "<fieldset>"; echo "<fieldset>";
echo "<legend>" . lang('Whole result') . "</legend>"; echo "<legend>" . lang('Whole result') . "</legend>";
$display_rows = ($exact_count ? "" : "~ ") . $found_rows; $display_rows = ($exact_count ? "" : "~ ") . $found_rows;

View File

@@ -21,19 +21,25 @@ if (!$error && $_POST) {
if (!isset($_GET["import"])) { if (!isset($_GET["import"])) {
$query = $_POST["query"]; $query = $_POST["query"];
} elseif ($_POST["webfile"]) { } elseif ($_POST["webfile"]) {
$sql_file_path = $adminer->importServerPath(); $import_file_path = $adminer->importServerPath();
$fp = @fopen((file_exists($sql_file_path) if (!$import_file_path) {
? $sql_file_path $fp = false;
: "compress.zlib://$sql_file_path.gz" } elseif (file_exists($import_file_path)) {
), "rb"); $fp = fopen($import_file_path, "rb");
$query = ($fp ? fread($fp, 1e6) : false); } elseif (file_exists("$import_file_path.gz")) {
$fp = fopen("compress.zlib://$import_file_path.gz", "rb");
} else {
$fp = false;
}
$query = $fp ? fread($fp, 1e6) : false;
} else { } else {
$query = get_file("sql_file", true); $query = get_file("sql_file", true);
} }
if (is_string($query)) { // get_file() returns error as number, fread() as false if (is_string($query)) { // get_file() returns error as number, fread() as false
if (function_exists('memory_get_usage')) { if (function_exists('memory_get_usage') && ($memory_limit = ini_bytes("memory_limit")) != "-1") {
@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 @ini_set("memory_limit", max($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 if ($query != "" && strlen($query) < 1e6) { // don't add big queries
@@ -81,7 +87,21 @@ if (!$error && $_POST) {
$offset = $pos + strlen($found); $offset = $pos + strlen($found);
if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end 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 $c_style_escapes = is_c_style_escapes() || ($jush == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
$pattern = '(';
if ($found == '/*') {
$pattern .= '\*/';
} elseif ($found == '[') {
$pattern .= ']';
} elseif (preg_match('~^-- |^#~', $found)) {
$pattern .= "\n";
} else {
$pattern .= preg_quote($found) . ($c_style_escapes ? "|\\\\." : "");
}
$pattern .= '|$)s';
while (preg_match($pattern, $query, $match, PREG_OFFSET_CAPTURE, $offset)) {
$s = $match[0][0]; $s = $match[0][0];
if (!$s && $fp && !feof($fp)) { if (!$s && $fp && !feof($fp)) {
$query .= fread($fp, 1e5); $query .= fread($fp, 1e5);
@@ -169,7 +189,8 @@ if (!$error && $_POST) {
stop_session(); stop_session();
} }
if (!$_POST["only_errors"]) { if (!$_POST["only_errors"]) {
echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n"; $title = isset($connection->info) ? "title='" . h($connection->info) . "'" : "";
echo "<p class='message' $title>" . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n";
} }
} }
echo ($warnings ? "<div id='$warnings_id' class='hidden'>\n$warnings</div>\n" : ""); echo ($warnings ? "<div id='$warnings_id' class='hidden'>\n$warnings</div>\n" : "");
@@ -222,7 +243,7 @@ if (!isset($_GET["import"])) {
} }
echo "<p>"; echo "<p>";
textarea("query", $q, 20); 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 script(($_POST ? "" : "qs('textarea').focus();\n") . "gid('form').onsubmit = partial(sqlSubmit, gid('form'), '" . js_escape(remove_from_uri("sql|limit|error_stops|only_errors|history")) . "');");
echo "<p>$execute\n"; echo "<p>$execute\n";
echo lang('Limit rows') . ": <input type='number' name='limit' class='size' value='" . h($_POST ? $_POST["limit"] : $_GET["limit"]) . "'>\n"; echo lang('Limit rows') . ": <input type='number' name='limit' class='size' value='" . h($_POST ? $_POST["limit"] : $_GET["limit"]) . "'>\n";
@@ -234,10 +255,10 @@ if (!isset($_GET["import"])) {
: lang('File uploads are disabled.') : lang('File uploads are disabled.')
); );
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
$importServerPath = $adminer->importServerPath(); $import_file_path = $adminer->importServerPath();
if ($importServerPath) { if ($import_file_path) {
echo "<fieldset><legend>" . lang('From server') . "</legend><div>"; echo "<fieldset><legend>" . lang('From server') . "</legend><div>";
echo lang('Webserver file %s', "<code>" . h($importServerPath) . "$gz</code>"); echo lang('Webserver file %s', "<code>" . h($import_file_path) . "$gz</code>");
echo ' <input type="submit" name="webfile" value="' . lang('Run file') . '">'; echo ' <input type="submit" name="webfile" value="' . lang('Run file') . '">';
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }

View File

@@ -1,8 +1,7 @@
/** @author Ondrej Valka, http://valka.info */ /** @author Ondrej Valka, http://valka.info */
body { color: #000; background: #fff; font: 90%/1.25 Verdana, Arial, Helvetica, sans-serif; margin: 0; width: -moz-fit-content; width: fit-content; } body { color: #000; background: #fff; font: 90%/1.25 Verdana, Arial, Helvetica, sans-serif; margin: 0; width: -moz-fit-content; width: fit-content; }
a { color: blue; text-decoration: none; } a { color: blue; text-decoration: none; }
a:visited { color: navy; } a:link:hover { color: red; text-decoration: underline; }
a:link:hover, a:visited:hover { color: red; text-decoration: underline; }
a.text:hover { text-decoration: none; } a.text:hover { text-decoration: none; }
a.jush-help:hover { color: inherit; } a.jush-help:hover { color: inherit; }
h1 { font-size: 150%; margin: 0; padding: .8em 1em; border-bottom: 1px solid #999; font-weight: normal; color: #777; background: #eee; } h1 { font-size: 150%; margin: 0; padding: .8em 1em; border-bottom: 1px solid #999; font-weight: normal; color: #777; background: #eee; }
@@ -11,7 +10,7 @@ h3 { font-weight: normal; font-size: 130%; margin: 1em 0 0; }
form { margin: 0; } form { margin: 0; }
td table { width: 100%; margin: 0; } td table { width: 100%; margin: 0; }
table { margin: 1em 20px 0 0; border-collapse: collapse; font-size: 90%; } table { margin: 1em 20px 0 0; border-collapse: collapse; font-size: 90%; }
td, th { border: 1px solid #999; padding: .2em .3em; } td, th { box-sizing: border-box; border: 1px solid #999; padding: .2em .3em; }
th { background: #eee; text-align: left; } th { background: #eee; text-align: left; }
thead th { text-align: center; padding: .2em .5em; } thead th { text-align: center; padding: .2em .5em; }
thead td, thead th { background: #ddf; } /* position: sticky; causes Firefox to lose borders */ thead td, thead th { background: #ddf; } /* position: sticky; causes Firefox to lose borders */
@@ -19,20 +18,30 @@ fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: .8e
p { margin: .8em 20px 0 0; } p { margin: .8em 20px 0 0; }
img { vertical-align: middle; border: 0; } img { vertical-align: middle; border: 0; }
td img { max-width: 200px; max-height: 200px; } td img { max-width: 200px; max-height: 200px; }
code { background: #eee; }
tbody tr:hover td, tbody tr:hover th { background: #eee; } tbody tr:hover td, tbody tr:hover th { background: #eee; }
code { font-size: 110%; padding: 1px 2px; background: #eee; }
pre { margin: 1em 0 0; } pre { margin: 1em 0 0; }
pre, textarea { font: 100%/1.25 monospace; } pre code { display: block; font-size: 100%; }
input, select { vertical-align: middle; } pre, textarea { font: 110%/1.25 monospace; }
pre.jush { background: #fff; }
pre.comment { white-space: pre-wrap; }
form + pre.comment { margin-top: 2em; }
input, textarea, select { box-sizing: border-box; }
input[type="image"] { vertical-align: middle; margin-top: -3px; }
input[type="number"] { -moz-appearance: textfield; }
input::-webkit-inner-spin-button { -webkit-appearance: none; }
input.default { box-shadow: 1px 1px 1px #777; } input.default { box-shadow: 1px 1px 1px #777; }
input.required { box-shadow: 1px 1px 1px red; } input.required { box-shadow: 1px 1px 1px red; }
input.maxlength { box-shadow: 1px 1px 1px red; } input.maxlength { box-shadow: 1px 1px 1px red; }
input.wayoff { left: -1000px; position: absolute; } input.wayoff { left: -1000px; position: absolute; }
input::placeholder { color: #000; opacity: 0.4; }
.center { text-align: center; }
.block { display: block; } .block { display: block; }
.version { color: #777; font-size: 67%; } .version { color: #777; font-size: 62%; }
.js .hidden, .nojs .jsonly { display: none; } .js .hidden, .nojs .jsonly { display: none; }
.js .column { position: absolute; background: #ddf; padding: .27em 1ex .3em 0; margin-top: -.27em; } .js .column { position: absolute; background: #ddf; padding: .27em 1ex .3em 0; margin-top: -.27em; }
.nowrap td, .nowrap th, td.nowrap, p.nowrap { white-space: pre; } .nowrap { white-space: nowrap; }
p.nowrap { white-space: pre; }
.wrap td { white-space: normal; } .wrap td { white-space: normal; }
.error { color: red; background: #fee; } .error { color: red; background: #fee; }
.error b { background: #fff; font-weight: normal; } .error b { background: #fff; font-weight: normal; }
@@ -62,8 +71,19 @@ input.wayoff { left: -1000px; position: absolute; }
.footer > div { background: #fff; padding: 0 0 .5em; } .footer > div { background: #fff; padding: 0 0 .5em; }
.footer fieldset { margin-top: 0; } .footer fieldset { margin-top: 0; }
.links a { white-space: nowrap; margin-right: 20px; } .links a { white-space: nowrap; margin-right: 20px; }
.logout { margin-top: .5em; position: absolute; top: 0; right: 0; } .logout { margin: .5em 20px 0 0; position: absolute; top: 0; right: 0; }
.loadmore { margin-left: 1ex; } .loadmore { margin-left: 1ex; }
.tables-filter { padding: .8em 1em 0; }
.handle { cursor: grab; vertical-align: middle; }
.handle:before { content: "="; display: inline-block; width: 18px; height: 18px; overflow: hidden; font-size: 130%; text-align: center; line-height: 16px; opacity: 0.2; }
span.handle { display: inline-block; width: 18px; height: 18px; padding-right: .3em; }
th.handle:before { vertical-align: middle; }
.no-sort .handle { cursor: default; }
.no-sort .handle:before { content: "•"; font-size: 100%; }
.placeholder { opacity: 0; }
.dragging { position: absolute; margin: 0; background: #fff; }
.dragging * { cursor: grabbing; }
table.dragging { background: #eee; }
/* .edit used in designs */ /* .edit used in designs */
#menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; } #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; } #menu p, #logins, #tables { padding: .8em 1em; margin: 0; border-bottom: 1px solid #ccc; }
@@ -75,11 +95,13 @@ input.wayoff { left: -1000px; position: absolute; }
#lang { position: absolute; top: 0; left: 0; line-height: 1.8em; padding: .3em 1em; } #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; } #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; } #h1 { color: #777; text-decoration: none; font-style: italic; }
#version { font-size: 67%; color: red; } #version { color: red; }
#schema { margin-left: 60px; position: relative; -moz-user-select: none; -webkit-user-select: none; } #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 .table { border: 1px solid silver; padding: 0 2px; cursor: move; position: absolute; }
#schema .references { position: absolute; } #schema .references { position: absolute; }
#tables-filter, #database-select, #scheme-select { width: 100%; }
#help { position: absolute; border: 1px solid #999; background: #eee; padding: 5px; font-family: monospace; z-index: 1; } #help { position: absolute; border: 1px solid #999; background: #eee; padding: 5px; font-family: monospace; z-index: 1; }
#fieldset-select div:last-child > .remove, #fieldset-search div:last-child > .remove, #fieldset-sort div:last-child > .remove { display: none; }
.rtl h2 { margin: 0 -18px 20px 0; } .rtl h2 { margin: 0 -18px 20px 0; }
.rtl p, .rtl table, .rtl .error, .rtl .message { margin: 1em 0 0 20px; } .rtl p, .rtl table, .rtl .error, .rtl .message { margin: 1em 0 0 20px; }
@@ -89,6 +111,7 @@ input.wayoff { left: -1000px; position: absolute; }
.rtl .pages { left: auto; right: 21em; } .rtl .pages { left: auto; right: 21em; }
.rtl input.wayoff { left: auto; right: -1000px; } .rtl input.wayoff { left: auto; right: -1000px; }
.rtl #lang, .rtl #menu { left: auto; right: 0; } .rtl #lang, .rtl #menu { left: auto; right: 0; }
.rtl pre, .rtl code { direction: ltr; }
@media all and (max-width: 880px) { @media all and (max-width: 880px) {
.pages { left: auto; } .pages { left: auto; }

View File

@@ -16,17 +16,22 @@ function bodyLoad(version, maria) {
if (maria) { if (maria) {
for (var i = 1; i < obj.length; i++) { for (var i = 1; i < obj.length; i++) {
obj[i] = obj[i] obj[i] = obj[i]
.replace(/\.html/, '/') .replace('.html', '/')
.replace(/-type-syntax/, '-data-types') .replace('-type-syntax', '-data-types')
.replace(/numeric-(data-types)/, '$1-$&') .replace(/numeric-(data-types)/, '$1-$&')
.replace(/#statvar_.*/, '#$$1') .replace(/replication-options-(master|binary-log)\//, 'replication-and-binary-log-system-variables/')
.replace('server-options/', 'server-system-variables/')
.replace('innodb-parameters/', 'innodb-system-variables/')
.replace(/#(statvar|sysvar|option_mysqld)_(.*)/, '#$2')
.replace(/#sysvar_(.*)/, '#$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 obj[key] = (maria ? obj[key].replace('dev.mysql.com/doc/mysql/en/', 'mariadb.com/kb/en/') : obj[key]) // MariaDB
.replace(/\/docs\/current/, '/docs/' + version) // PostgreSQL .replace('/doc/mysql/', '/doc/refman/' + version) // MySQL
.replace('/docs/current/', '/docs/' + version) // PostgreSQL
; ;
} }
} }
@@ -83,13 +88,17 @@ function messagesPrint(el) {
/** Hide or show some login rows for selected driver /**
* @param HTMLSelectElement * Hides or shows some login rows for selected driver.
*/ *
function loginDriver(driver) { * @param {HTMLSelectElement} driverSelect
var trs = parentTag(driver, 'table').rows; */
var disabled = /sqlite/.test(selectValue(driver)); function loginDriver(driverSelect) {
alterClass(trs[1], 'hidden', disabled); // 1 - row with server const trs = parentTag(driverSelect, 'table').rows;
const disabled = /sqlite/.test(selectValue(driverSelect));
// 1 - row with server
trs[1].classList.toggle('hidden', disabled);
trs[1].getElementsByTagName('input')[0].disabled = disabled; trs[1].getElementsByTagName('input')[0].disabled = disabled;
} }
@@ -103,6 +112,11 @@ var dbPrevious = {};
* @this HTMLSelectElement * @this HTMLSelectElement
*/ */
function dbMouseDown(event) { function dbMouseDown(event) {
// Firefox: mouse-down event does not contain pressed key information for OPTION.
// Chrome: mouse-down event has inherited key information from SELECT.
// So we ignore the event for OPTION to work Ctrl+click correctly everywhere.
if (event.target.tagName === "OPTION") return;
dbCtrl = isCtrl(event); dbCtrl = isCtrl(event);
if (dbPrevious[this.name] === undefined) { if (dbPrevious[this.name] === undefined) {
dbPrevious[this.name] = this.value; dbPrevious[this.name] = this.value;
@@ -226,11 +240,13 @@ function editFields() {
els = qsa('[name$="[type]"]'); els = qsa('[name$="[type]"]');
for (var i = 0; i < els.length; i++) { for (var i = 0; i < els.length; i++) {
mixin(els[i], { mixin(els[i], {
onfocus: function () { lastType = selectValue(this); }, onfocus: () => {
lastType = selectValue(this);
},
onchange: editingTypeChange, onchange: editingTypeChange,
onmouseover: function (event) { helpMouseover.call(this, event, getTarget(event).value, 1) },
onmouseout: helpMouseout
}); });
initHelpFor(els[i], (value) => { return value; }, true);
} }
} }
@@ -239,7 +255,7 @@ function editFields() {
* @return boolean false to cancel action * @return boolean false to cancel action
*/ */
function editingClick(event) { function editingClick(event) {
var el = getTarget(event); var el = event.target;
if (!isTag(el, 'input')) { if (!isTag(el, 'input')) {
el = parentTag(el, 'label'); el = parentTag(el, 'label');
el = el && qs('input', el); el = el && qs('input', el);
@@ -248,10 +264,6 @@ function editingClick(event) {
var name = el.name; var name = el.name;
if (/^add\[/.test(name)) { if (/^add\[/.test(name)) {
editingAddRow.call(el, 1); 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)) { } else if (/^drop_col\[/.test(name)) {
editingRemoveRow.call(el, 'fields\$1[field]'); editingRemoveRow.call(el, 'fields\$1[field]');
} else { } else {
@@ -272,7 +284,7 @@ function editingClick(event) {
* @param InputEvent * @param InputEvent
*/ */
function editingInput(event) { function editingInput(event) {
var el = getTarget(event); var el = event.target;
if (/\[default]$/.test(el.name)) { if (/\[default]$/.test(el.name)) {
el.previousSibling.checked = true; el.previousSibling.checked = true;
} }
@@ -348,7 +360,10 @@ function editingAddRow(focus) {
} }
} }
tags[0].oninput = editingNameChange; tags[0].oninput = editingNameChange;
initSortableRow(row2);
row.parentNode.insertBefore(row2, row.nextSibling); row.parentNode.insertBefore(row2, row.nextSibling);
if (focus) { if (focus) {
input.oninput = editingNameChange; input.oninput = editingNameChange;
input.focus(); input.focus();
@@ -370,22 +385,6 @@ function editingRemoveRow(name) {
return false; 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 = ''; var lastType = '';
/** Clear length and hide collation or unsigned /** Clear length and hide collation or unsigned
@@ -410,26 +409,26 @@ function editingTypeChange() {
el.checked = false; el.checked = false;
} }
if (el.name === name + '[collation]') { if (el.name === name + '[collation]') {
alterClass(el, 'hidden', !/(char|text|enum|set)$/.test(text)); el.classList.toggle('hidden', !/(char|text|enum|set)$/.test(text));
} }
if (el.name === name + '[unsigned]') { if (el.name === name + '[unsigned]') {
alterClass(el, 'hidden', !/(^|[^o])int(?!er)|numeric|real|float|double|decimal|money/.test(text)); el.classList.toggle('hidden', !/(^|[^o])int(?!er)|numeric|real|float|double|decimal|money/.test(text));
} }
if (el.name === name + '[on_update]') { if (el.name === name + '[on_update]') {
alterClass(el, 'hidden', !/timestamp|datetime/.test(text)); // MySQL supports datetime since 5.6.5 // MySQL supports datetime since 5.6.5.
el.classList.toggle('hidden', !/timestamp|datetime/.test(text));
} }
if (el.name === name + '[on_delete]') { if (el.name === name + '[on_delete]') {
alterClass(el, 'hidden', !/`/.test(text)); el.classList.toggle('hidden', !/`/.test(text));
} }
} }
helpClose();
} }
/** Mark length as required /** Mark length as required
* @this HTMLInputElement * @this HTMLInputElement
*/ */
function editingLengthChange() { function editingLengthChange() {
alterClass(this, 'required', !this.value.length && /var(char|binary)$/.test(selectValue(this.parentNode.previousSibling.firstChild))); this.classList.toggle('required', !this.value.length && /var(char|binary)$/.test(selectValue(this.parentNode.previousSibling.firstChild)));
} }
/** Edit enum or set /** Edit enum or set
@@ -438,7 +437,7 @@ function editingLengthChange() {
function editingLengthFocus() { function editingLengthFocus() {
var td = this.parentNode; var td = this.parentNode;
if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) { if (/(enum|set)$/.test(selectValue(td.previousSibling.firstChild))) {
var edit = qs('#enum-edit'); var edit = gid('enum-edit');
edit.value = enumValues(this.value); edit.value = enumValues(this.value);
td.appendChild(edit); td.appendChild(edit);
this.style.display = 'none'; this.style.display = 'none';
@@ -482,9 +481,9 @@ function editingLengthBlur() {
* @param number * @param number
*/ */
function columnShow(checked, column) { function columnShow(checked, column) {
var trs = qsa('tr', qs('#edit-fields')); var trs = qsa('tr', gid('edit-fields'));
for (var i=0; i < trs.length; i++) { for (var i=0; i < trs.length; i++) {
alterClass(qsa('td', trs[i])[column], 'hidden', !checked); qsa('td', trs[i])[column].classList.toggle('hidden', !checked);
} }
} }
@@ -493,9 +492,9 @@ function columnShow(checked, column) {
*/ */
function partitionByChange() { function partitionByChange() {
var partitionTable = /RANGE|LIST/.test(selectValue(this)); var partitionTable = /RANGE|LIST/.test(selectValue(this));
alterClass(this.form['partitions'], 'hidden', partitionTable || !this.selectedIndex);
alterClass(qs('#partition-table'), 'hidden', !partitionTable); this.form['partitions'].classList.toggle('hidden', partitionTable || !this.selectedIndex);
helpClose(); gid('partition-table').classList.toggle('hidden', !partitionTable);
} }
/** Add next partition row /** Add next partition row
@@ -515,7 +514,7 @@ function partitionNameChange() {
function editingCommentsClick(el, focus) { function editingCommentsClick(el, focus) {
var comment = el.form['Comment']; var comment = el.form['Comment'];
columnShow(el.checked, 6); columnShow(el.checked, 6);
alterClass(comment, 'hidden', !el.checked); comment.classList.toggle('hidden', !el.checked);
if (focus && el.checked) { if (focus && el.checked) {
comment.focus(); comment.focus();
} }
@@ -528,7 +527,7 @@ function editingCommentsClick(el, focus) {
* @this HTMLTableElement * @this HTMLTableElement
*/ */
function dumpClick(event) { function dumpClick(event) {
var el = parentTag(getTarget(event), 'label'); var el = parentTag(event.target, 'label');
if (el) { if (el) {
el = qs('input', el); el = qs('input', el);
var match = /(.+)\[]$/.exec(el.name); var match = /(.+)\[]$/.exec(el.name);
@@ -658,7 +657,7 @@ function triggerChange(tableRe, table, form) {
if (tableRe.test(form['Trigger'].value)) { if (tableRe.test(form['Trigger'].value)) {
form['Trigger'].value = table + '_' + (selectValue(form['Timing']).charAt(0) + formEvent.charAt(0)).toLowerCase(); form['Trigger'].value = table + '_' + (selectValue(form['Timing']).charAt(0) + formEvent.charAt(0)).toLowerCase();
} }
alterClass(form['Of'], 'hidden', !/ OF/.test(formEvent)); form['Of'].classList.toggle('hidden', !/ OF/.test(formEvent));
} }
@@ -732,55 +731,114 @@ function schemaMouseup(event, db) {
s += '_' + key + ':' + Math.round(tablePos[key][0] * 10000) / 10000 + 'x' + Math.round(tablePos[key][1] * 10000) / 10000; s += '_' + key + ':' + Math.round(tablePos[key][0] * 10000) / 10000 + 'x' + Math.round(tablePos[key][1] * 10000) / 10000;
} }
s = encodeURIComponent(s.substr(1)); s = encodeURIComponent(s.substr(1));
var link = qs('#schema-link'); var link = gid('schema-link');
link.href = link.href.replace(/[^=]+$/, '') + s; link.href = link.href.replace(/[^=]+$/, '') + s;
cookie('adminer_schema-' + db + '=' + s, 30); //! special chars in db cookie('adminer_schema-' + db + '=' + s, 30); //! special chars in db
} }
} }
// Help.
(function() {
let openTimeout = null;
let closeTimeout = null;
let helpVisible = false;
var helpOpen, helpIgnore; // when mouse outs <option> then it mouse overs border of <select> - ignore it window.initHelpPopup = function () {
const help = gid("help");
/** Display help help.addEventListener("mouseenter", () => {
* @param MouseEvent clearTimeout(closeTimeout);
* @param string closeTimeout = null;
* @param bool display on left side (otherwise on top) });
* @this HTMLElement
*/
function helpMouseover(event, text, side) {
var target = getTarget(event);
if (!text) {
helpClose();
} else if (window.jush && (!helpIgnore || this !== target)) {
helpOpen = 1;
var help = qs('#help');
help.innerHTML = text;
jush.highlight_tag([ help ]);
alterClass(help, 'hidden');
var rect = target.getBoundingClientRect();
var body = document.documentElement;
help.style.top = (body.scrollTop + rect.top - (side ? (help.offsetHeight - target.offsetHeight) / 2 : help.offsetHeight)) + 'px';
help.style.left = (body.scrollLeft + rect.left - (side ? help.offsetWidth : (help.offsetWidth - target.offsetWidth) / 2)) + 'px';
}
}
/** Close help after timeout help.addEventListener("mouseleave", hideHelp);
* @param MouseEvent };
* @this HTMLElement
*/ /**
function helpMouseout(event) { * @param {HTMLElement} element
helpOpen = 0; * @param {string|function} content
helpIgnore = (this !== getTarget(event)); * @param {boolean} side Displays on left side (otherwise on top).
setTimeout(function () { */
if (!helpOpen) { window.initHelpFor = function(element, content, side = false) {
helpClose(); const withCallback = typeof content === "function";
element.addEventListener("mouseenter", (event) => {
showHelp(event.target, withCallback ? content(event.target.value) : content, side)
});
element.addEventListener("mouseleave", hideHelp);
element.addEventListener("blur", hideHelp);
if (withCallback) {
element.addEventListener("change", hideHelp);
} }
}, 200); };
}
/** Close help /**
*/ * Displays help popup after a small delay.
function helpClose() { *
alterClass(qs('#help'), 'hidden', true); * @param {HTMLElement} element
} * @param {string} text
* @param {boolean} side display on left side (otherwise on top)
*/
function showHelp(element, text, side) {
if (!text) {
hideHelp();
return;
}
if (isSorting() || !window.jush) {
return;
}
clearTimeout(openTimeout);
openTimeout = null;
clearTimeout(closeTimeout);
closeTimeout = null;
const help = gid("help");
help.innerHTML = text;
jush.highlight_tag([help]);
// Display help briefly to calculate position properly.
help.classList.remove("hidden");
const rect = element.getBoundingClientRect();
const root = document.documentElement;
help.style.top = (root.scrollTop + rect.top - (side ? (help.offsetHeight - element.offsetHeight) / 2 : help.offsetHeight)) + 'px';
help.style.left = (root.scrollLeft + rect.left - (side ? help.offsetWidth : (help.offsetWidth - element.offsetWidth) / 2)) + 'px';
if (helpVisible) {
return;
}
help.classList.add("hidden");
openTimeout = setTimeout(() => {
gid("help").classList.remove("hidden");
helpVisible = true;
openTimeout = null;
}, 600);
}
/**
* Closes the help popup after a small delay.
*/
function hideHelp() {
if (openTimeout) {
clearTimeout(openTimeout);
openTimeout = null;
return;
}
closeTimeout = setTimeout(() => {
gid("help").classList.add("hidden");
helpVisible = false;
closeTimeout = null;
}, 200);
}
})();

View File

@@ -1,4 +1,15 @@
/**
* Returns the element found by given identifier.
*
* @param {string} id
* @param {?HTMLElement} context Defaults to document.
* @return {?HTMLElement}
*/
function gid(id, context = null) {
return (context || document).getElementById(id);
}
/** Get first element by selector /** Get first element by selector
* @param string * @param string
* @param [HTMLElement] defaults to document * @param [HTMLElement] defaults to document
@@ -62,24 +73,15 @@ function mixin(target, source) {
} }
} }
/** Add or remove CSS class /**
* @param HTMLElement * Toggles visibility of element with ID.
* @param string *
* @param [bool] * @param {string} id
*/ * @return {boolean} Always false.
function alterClass(el, className, enable) { */
if (el) {
el.className = el.className.replace(RegExp('(^|\\s)' + className + '(\\s|$)'), '$2') + (enable ? ' ' + className : '');
}
}
/** Toggle visibility
* @param string
* @return boolean false
*/
function toggle(id) { function toggle(id) {
var el = qs('#' + id); gid(id).classList.toggle("hidden");
el.className = (el.className === 'hidden' ? '' : 'hidden');
return false; return false;
} }
@@ -94,34 +96,27 @@ function cookie(assign, days) {
document.cookie = assign + '; expires=' + date; document.cookie = assign + '; expires=' + date;
} }
/** Verify current Adminer version /**
* @param string * Verifies current Adminer version.
* @param string own URL base *
* @param string * @param baseUrl string
*/ * @param token string
function verifyVersion(current, url, token) { */
function verifyVersion(baseUrl, token) {
// Dummy value to prevent repeated verifications after AJAX failure.
cookie('adminer_version=0', 1); cookie('adminer_version=0', 1);
var iframe = document.createElement('iframe');
iframe.src = 'https://www.adminer.org/version/?current=' + current; ajax('https://api.github.com/repos/pematon/adminer/releases/latest', (request) => {
iframe.frameBorder = 0; const response = JSON.parse(request.responseText);
iframe.marginHeight = 0;
iframe.scrolling = 'no'; const version = response.tag_name.replace(/^\D*/, '');
iframe.style.width = '7ex'; if (!version) return;
iframe.style.height = '1.25em';
if (window.postMessage && window.addEventListener) { cookie('adminer_version=' + version, 1);
iframe.style.display = 'none';
addEventListener('message', function (event) { const data = 'version=' + version + '&token=' + token;
if (event.origin === 'https://www.adminer.org') { ajax(baseUrl + 'script=version', null, data);
var match = /version=(.+)/.exec(event.data); }, null, null, true);
if (match) {
cookie('adminer_version=' + match[1], 1);
ajax(url + 'script=version', function () {
}, event.data + '&token=' + token);
}
}
}, false);
}
qs('#version').appendChild(iframe);
} }
/** Get value of select /** Get value of select
@@ -163,7 +158,7 @@ function parentTag(el, tag) {
*/ */
function trCheck(el) { function trCheck(el) {
var tr = parentTag(el, 'tr'); var tr = parentTag(el, 'tr');
alterClass(tr, 'checked', el.checked); tr.classList.toggle('checked', el.checked);
if (el.form && el.form['all'] && el.form['all'].onclick) { // Opera treats form.all as document.all if (el.form && el.form['all'] && el.form['all'].onclick) { // Opera treats form.all as document.all
el.form['all'].onclick(); el.form['all'].onclick();
} }
@@ -176,7 +171,7 @@ function trCheck(el) {
*/ */
function selectCount(id, count) { function selectCount(id, count) {
setHtml(id, (count === '' ? '' : '(' + (count + '').replace(/\B(?=(\d{3})+$)/g, thousandsSeparator) + ')')); setHtml(id, (count === '' ? '' : '(' + (count + '').replace(/\B(?=(\d{3})+$)/g, thousandsSeparator) + ')'));
var el = qs('#' + id); var el = gid(id);
if (el) { if (el) {
var inputs = qsa('input', el.parentNode.parentNode); var inputs = qsa('input', el.parentNode.parentNode);
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
@@ -211,13 +206,21 @@ function tableCheck() {
} }
} }
/** Uncheck single element /**
* @param string * Uncheck single element.
*/ */
function formUncheck(id) { function formUncheck(id) {
var el = qs('#' + id); formUncheckAll("#" + id);
el.checked = false; }
trCheck(el);
/**
* Uncheck elements matched by selector.
*/
function formUncheckAll(selector) {
for (const element of qsa(selector)) {
element.checked = false;
trCheck(element);
}
} }
/** Get number of checked elements matching given name /** Get number of checked elements matching given name
@@ -241,7 +244,7 @@ function formChecked(el, name) {
* @param [boolean] force click * @param [boolean] force click
*/ */
function tableClick(event, click) { function tableClick(event, click) {
var td = parentTag(getTarget(event), 'td'); var td = parentTag(event.target, 'td');
var text; var text;
if (td && (text = td.getAttribute('data-text'))) { if (td && (text = td.getAttribute('data-text'))) {
if (selectClick.call(td, event, +text, td.getAttribute('data-warning'))) { if (selectClick.call(td, event, +text, td.getAttribute('data-warning'))) {
@@ -249,7 +252,7 @@ function tableClick(event, click) {
} }
} }
click = (click || !window.getSelection || getSelection().isCollapsed); click = (click || !window.getSelection || getSelection().isCollapsed);
var el = getTarget(event); var el = event.target;
while (!isTag(el, 'tr')) { while (!isTag(el, 'tr')) {
if (isTag(el, 'table|a|input|textarea')) { if (isTag(el, 'table|a|input|textarea')) {
if (el.type !== 'checkbox') { if (el.type !== 'checkbox') {
@@ -349,14 +352,85 @@ function pageClick(href, page) {
} }
} }
let tablesFilterTimeout = null;
let tablesFilterValue = '';
function initTablesFilter(dbName) {
if (sessionStorage) {
document.addEventListener('DOMContentLoaded', function () {
if (dbName === sessionStorage.getItem('adminer_tables_filter_db') && sessionStorage.getItem('adminer_tables_filter')) {
gid('tables-filter').value = sessionStorage.getItem('adminer_tables_filter');
filterTables();
} else {
sessionStorage.removeItem('adminer_tables_filter');
}
sessionStorage.setItem('adminer_tables_filter_db', dbName);
});
}
const filterInput = gid('tables-filter');
filterInput.addEventListener('input', function () {
window.clearTimeout(tablesFilterTimeout);
tablesFilterTimeout = window.setTimeout(filterTables, 200);
});
document.body.addEventListener('keydown', function(event) {
if (isCtrl(event) && event.shiftKey && event.key.toUpperCase() === 'F') {
filterInput.focus();
filterInput.select();
event.preventDefault();
}
});
}
function filterTables() {
const value = gid('tables-filter').value.toLowerCase();
if (value === tablesFilterValue) {
return;
}
tablesFilterValue = value;
let reg
if (value !== '') {
const valueExp = (`${value}`).replace(/[\\.+*?\[^\]$(){}=!<>|:]/g, '\\$&');
reg = new RegExp(`(${valueExp})`, 'gi');
}
if (sessionStorage) {
sessionStorage.setItem('adminer_tables_filter', value);
}
const tables = qsa('#tables li');
for (let i = 0; i < tables.length; i++) {
let a = qs('a[data-main="true"], span[data-main="true"]', tables[i]);
let tableName = tables[i].dataset.tableName;
if (tableName == null) {
tableName = a.innerHTML.trim();
tables[i].dataset.tableName = tableName;
}
if (value === "") {
tables[i].classList.remove('hidden');
a.innerHTML = tableName;
} else if (tableName.toLowerCase().indexOf(value) >= 0) {
tables[i].classList.remove('hidden');
a.innerHTML = tableName.replace(reg, '<strong>$1</strong>');
} else {
tables[i].classList.add('hidden');
}
}
}
/** Display items in menu /** Display items in menu
* @param MouseEvent * @param MouseEvent
* @this HTMLElement * @this HTMLElement
*/ */
function menuOver(event) { function menuOver(event) {
var a = getTarget(event); var a = event.target;
if (isTag(a, 'a|span') && a.offsetLeft + a.offsetWidth > a.parentNode.offsetWidth - 15) { // 15 - ellipsis if (isTag(a, 'a|span') && a.offsetLeft + a.offsetWidth > a.parentNode.offsetWidth - 15) { // 15 - ellipsis
this.style.overflow = 'visible'; this.style.overflow = 'visible';
} }
@@ -371,30 +445,64 @@ function menuOut() {
/** Add row in select fieldset /**
* @this HTMLSelectElement * Adds row in select fieldset.
*/ *
function selectAddRow() { * @param {Event} event
var field = this; * @this HTMLSelectElement
var row = cloneNode(field.parentNode); */
function selectAddRow(event) {
const field = this;
const row = cloneNode(field.parentNode);
field.onchange = selectFieldChange; field.onchange = selectFieldChange;
field.onchange(); field.onchange(event);
var selects = qsa('select', row);
for (var i=0; i < selects.length; i++) { const selects = qsa('select', row);
selects[i].name = selects[i].name.replace(/[a-z]\[\d+/, '$&1'); for (const select of selects) {
selects[i].selectedIndex = 0; select.name = select.name.replace(/[a-z]\[\d+/, '$&1');
select.selectedIndex = 0;
} }
var inputs = qsa('input', row);
for (var i=0; i < inputs.length; i++) { const inputs = qsa('input', row);
inputs[i].name = inputs[i].name.replace(/[a-z]\[\d+/, '$&1'); for (const input of inputs) {
inputs[i].className = ''; // Skip buttons.
if (inputs[i].type === 'checkbox') { if (input.type === 'image') {
inputs[i].checked = false; continue;
}
input.name = input.name.replace(/[a-z]\[\d+/, '$&1');
input.className = '';
if (input.type === 'checkbox') {
input.checked = false;
} else { } else {
inputs[i].value = ''; input.value = '';
} }
} }
field.parentNode.parentNode.appendChild(row);
const button = qs('.remove', row);
button.onclick = selectRemoveRow;
const parent = field.parentNode.parentNode;
if (parent.classList.contains("sortable")) {
initSortableRow(field.parentElement);
}
parent.appendChild(row);
}
/**
* Removes a row in select fieldset.
*
* @this HTMLInputElement
* @return {boolean} Always false.
*/
function selectRemoveRow() {
const row = this.parentNode;
row.parentNode.removeChild(row);
return false;
} }
/** Prevent onsearch handler on Enter /** Prevent onsearch handler on Enter
@@ -417,6 +525,159 @@ function selectSearchSearch() {
} }
} }
// Sorting.
(function() {
let placeholderRow = null, nextRow = null, dragHelper = null;
let startY, minY, maxY;
/**
* Initializes sortable list of DIV elements.
*
* @param {string} parentSelector
*/
window.initSortable = function(parentSelector) {
const parent = qs(parentSelector);
if (!parent) return;
for (const row of parent.children) {
if (!row.classList.contains("no-sort")) {
initSortableRow(row);
}
}
};
/**
* Initializes one row of sortable parent.
*
* @param {HTMLElement} row
*/
window.initSortableRow = function(row) {
row.classList.remove("no-sort");
const handle = qs(".handle", row);
handle.addEventListener("mousedown", (event) => { startSorting(row, event) });
handle.addEventListener("touchstart", (event) => { startSorting(row, event) });
};
window.isSorting = function () {
return dragHelper !== null;
};
function startSorting(row, event) {
event.preventDefault();
const pointerY = getPointerY(event);
const parent = row.parentNode;
startY = pointerY - getOffsetTop(row);
minY = getOffsetTop(parent);
maxY = minY + parent.offsetHeight - row.offsetHeight;
placeholderRow = row.cloneNode(true);
placeholderRow.classList.add("placeholder");
parent.insertBefore(placeholderRow, row);
nextRow = row.nextElementSibling;
let top = pointerY - startY;
let left = getOffsetLeft(row);
let width = row.getBoundingClientRect().width;
if (row.tagName === "TR") {
const firstChild = row.firstElementChild;
const borderWidth = (firstChild.offsetWidth - firstChild.clientWidth) / 2;
const borderHeight = (firstChild.offsetHeight - firstChild.clientHeight) / 2;
minY -= borderHeight;
maxY -= borderHeight;
top -= borderHeight;
left -= borderWidth;
width += 2 * borderWidth;
for (const child of row.children) {
child.style.width = child.getBoundingClientRect().width + "px";
}
dragHelper = document.createElement("table");
dragHelper.appendChild(row);
} else {
dragHelper = row;
}
dragHelper.style.top = `${top}px`;
dragHelper.style.left = `${left}px`;
dragHelper.style.width = `${width}px`;
dragHelper.classList.add("dragging");
document.body.appendChild(dragHelper);
window.addEventListener("mousemove", updateSorting);
window.addEventListener("touchmove", updateSorting);
window.addEventListener("mouseup", finishSorting);
window.addEventListener("touchend", finishSorting);
window.addEventListener("touchcancel", finishSorting);
}
function updateSorting(event) {
const pointerY = getPointerY(event);
let top = Math.min(Math.max(pointerY - startY, minY), maxY);
dragHelper.style.top = `${top}px`;
const parent = placeholderRow.parentNode;
top = top - minY + parent.offsetTop;
let sibling;
if (top > placeholderRow.offsetTop + placeholderRow.offsetHeight / 2) {
sibling = !nextRow.classList.contains("no-sort") ? nextRow.nextElementSibling : nextRow;
} else if (top + placeholderRow.offsetHeight < placeholderRow.offsetTop + placeholderRow.offsetHeight / 2) {
sibling = placeholderRow.previousElementSibling;
} else {
sibling = nextRow;
}
if (sibling !== nextRow) {
const parent = placeholderRow.parentNode;
nextRow = sibling;
if (sibling) {
parent.insertBefore(placeholderRow, nextRow);
} else {
parent.appendChild(placeholderRow);
}
}
}
function finishSorting() {
dragHelper.classList.remove("dragging");
dragHelper.style.top = null;
dragHelper.style.left = null;
dragHelper.style.width = null;
placeholderRow.parentNode.insertBefore(dragHelper.tagName === "TABLE" ? dragHelper.firstChild : dragHelper, placeholderRow);
placeholderRow.remove();
placeholderRow = nextRow = dragHelper = null;
window.removeEventListener("mousemove", updateSorting);
window.removeEventListener("touchmove", updateSorting);
window.removeEventListener("mouseup", finishSorting);
window.removeEventListener("touchend", finishSorting);
window.removeEventListener("touchcancel", finishSorting);
}
function getPointerY(event) {
if (event.type.includes("touch")) {
const touch = event.touches[0] || event.changedTouches[0];
return touch.clientY;
} else {
return event.clientY;
}
}
})();
/** Toggles column context menu /** Toggles column context menu
@@ -439,7 +700,7 @@ function columnMouse(className) {
* @return boolean false * @return boolean false
*/ */
function selectSearch(name) { function selectSearch(name) {
var el = qs('#fieldset-search'); var el = gid('fieldset-search');
el.className = ''; el.className = '';
var divs = qsa('div', el); var divs = qsa('div', el);
for (var i=0; i < divs.length; i++) { for (var i=0; i < divs.length; i++) {
@@ -466,16 +727,6 @@ function isCtrl(event) {
return (event.ctrlKey || event.metaKey) && !event.altKey; // shiftKey allowed return (event.ctrlKey || event.metaKey) && !event.altKey; // shiftKey allowed
} }
/** Return event target
* @param Event
* @return HTMLElement
*/
function getTarget(event) {
return event.target || event.srcElement;
}
/** Send form by Ctrl+Enter on <select> and <textarea> /** Send form by Ctrl+Enter on <select> and <textarea>
* @param KeyboardEvent * @param KeyboardEvent
* @param [string] * @param [string]
@@ -483,7 +734,7 @@ function getTarget(event) {
*/ */
function bodyKeydown(event, button) { function bodyKeydown(event, button) {
eventStop(event); eventStop(event);
var target = getTarget(event); var target = event.target;
if (target.jushTextarea) { if (target.jushTextarea) {
target = target.jushTextarea; target = target.jushTextarea;
} }
@@ -507,7 +758,7 @@ function bodyKeydown(event, button) {
* @param MouseEvent * @param MouseEvent
*/ */
function bodyClick(event) { function bodyClick(event) {
var target = getTarget(event); var target = event.target;
if ((isCtrl(event) || event.shiftKey) && target.type === 'submit' && isTag(target, 'input')) { if ((isCtrl(event) || event.shiftKey) && target.type === 'submit' && isTag(target, 'input')) {
target.form.target = '_blank'; target.form.target = '_blank';
setTimeout(function () { setTimeout(function () {
@@ -525,7 +776,7 @@ function bodyClick(event) {
*/ */
function editingKeydown(event) { function editingKeydown(event) {
if ((event.keyCode === 40 || event.keyCode === 38) && isCtrl(event)) { // 40 - Down, 38 - Up if ((event.keyCode === 40 || event.keyCode === 38) && isCtrl(event)) { // 40 - Down, 38 - Up
var target = getTarget(event); var target = event.target;
var sibling = (event.keyCode === 40 ? 'nextSibling' : 'previousSibling'); var sibling = (event.keyCode === 40 ? 'nextSibling' : 'previousSibling');
var el = target.parentNode.parentNode[sibling]; var el = target.parentNode.parentNode[sibling];
if (el && (isTag(el, 'tr') || (el = el[sibling])) && isTag(el, 'tr') && (el = el.childNodes[nodePosition(target.parentNode)]) && (el = el.childNodes[nodePosition(target)])) { if (el && (isTag(el, 'tr') || (el = el[sibling])) && isTag(el, 'tr') && (el = el.childNodes[nodePosition(target.parentNode)]) && (el = el.childNodes[nodePosition(target)])) {
@@ -539,37 +790,59 @@ function editingKeydown(event) {
return true; return true;
} }
/** Disable maxlength for functions /**
* @this HTMLSelectElement * Disables maxlength for functions and manages value visibility.
*/ *
* @this HTMLSelectElement
*/
function functionChange() { function functionChange() {
var input = this.form[this.name.replace(/^function/, 'fields')]; const input = this.form[this.name.replace(/^function/, 'fields')];
if (input) { // undefined with the set data type const value = selectValue(this);
if (selectValue(this)) {
if (input.origType === undefined) { // Undefined with the set data type.
input.origType = input.type; if (!input) {
input.origMaxLength = input.getAttribute('data-maxlength'); return;
}
input.removeAttribute('data-maxlength');
input.type = 'text';
} else if (input.origType) {
input.type = input.origType;
if (input.origMaxLength >= 0) {
input.setAttribute('data-maxlength', input.origMaxLength);
}
}
oninput({target: input});
} }
helpClose();
if (value) {
if (input.origType === undefined) {
input.origType = input.type;
input.origMaxLength = input.getAttribute('data-maxlength');
}
input.removeAttribute('data-maxlength');
input.type = 'text';
} else if (input.origType) {
input.type = input.origType;
if (input.origMaxLength >= 0) {
input.setAttribute('data-maxlength', input.origMaxLength);
}
}
// Hide input value if it will be not used by selected function.
if (value === "NULL" || value === "now") {
if (input.value !== "") {
input.dataset.lastValue = input.value;
input.value = "";
}
} else if (input.dataset.lastValue) {
input.value = input.dataset.lastValue;
}
oninput({target: input});
} }
/** Skip 'original' when typing /**
* @param number * Unset 'original', 'NULL' and 'now' functions when typing.
* @this HTMLTableCellElement *
*/ * @param first number
* @this HTMLTableCellElement
*/
function skipOriginal(first) { function skipOriginal(first) {
var fnSelect = this.previousSibling.firstChild; const fnSelect = this.previousSibling.firstChild;
if (fnSelect.selectedIndex < first) { const value = selectValue(fnSelect);
if (fnSelect.selectedIndex < first || value === "NULL" || value === "now") {
fnSelect.selectedIndex = first; fnSelect.selectedIndex = first;
} }
} }
@@ -590,41 +863,51 @@ function fieldChange() {
/** Create AJAX request /**
* @param string * Sends AJAX request.
* @param function (XMLHttpRequest) *
* @param [string] * @param {string} url
* @param [string] * @param {function|null} onSuccess (XMLHttpRequest)
* @return XMLHttpRequest or false in case of an error * @param {string|null} data POST data.
* @uses offlineMessage * @param {string|null} progressMessage
*/ * @param {boolean} failSilently
function ajax(url, callback, data, message) { * @return XMLHttpRequest or false in case of an error
var request = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false)); * @uses offlineMessage
if (request) { */
var ajaxStatus = qs('#ajaxstatus'); function ajax(url, onSuccess = null, data = null, progressMessage = null, failSilently = false) {
if (message) { const ajaxStatus = gid('ajaxstatus');
ajaxStatus.innerHTML = '<div class="message">' + message + '</div>';
ajaxStatus.className = ajaxStatus.className.replace(/ hidden/g, ''); if (progressMessage) {
} else { ajaxStatus.innerHTML = '<div class="message">' + progressMessage + '</div>';
ajaxStatus.className += ' hidden'; ajaxStatus.classList.remove("hidden");
} } else {
request.open((data ? 'POST' : 'GET'), url); ajaxStatus.classList.add("hidden");
if (data) {
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (/^2/.test(request.status)) {
callback(request);
} else {
ajaxStatus.innerHTML = (request.status ? request.responseText : '<div class="error">' + offlineMessage + '</div>');
ajaxStatus.className = ajaxStatus.className.replace(/ hidden/g, '');
}
}
};
request.send(data);
} }
const request = new XMLHttpRequest();
request.open((data ? 'POST' : 'GET'), url);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
if (data) {
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
if (onSuccess) {
onSuccess(request);
}
} else if (failSilently) {
console.error(request.status ? request.responseText : "No internet connection");
} else {
ajaxStatus.innerHTML = (request.status ? request.responseText : '<div class="error">' + offlineMessage + '</div>');
ajaxStatus.classList.remove("hidden");
}
}
};
request.send(data);
return request; return request;
} }
@@ -671,9 +954,9 @@ function ajaxForm(form, message, button) {
return ajax(url, function (request) { return ajax(url, function (request) {
setHtml('ajaxstatus', request.responseText); setHtml('ajaxstatus', request.responseText);
if (window.jush) { if (window.jush) {
jush.highlight_tag(qsa('code', qs('#ajaxstatus')), 0); jush.highlight_tag(qsa('code', gid('ajaxstatus')), 0);
} }
messagesPrint(qs('#ajaxstatus')); messagesPrint(gid('ajaxstatus'));
}, data, message); }, data, message);
} }
@@ -688,7 +971,7 @@ function ajaxForm(form, message, button) {
*/ */
function selectClick(event, text, warning) { function selectClick(event, text, warning) {
var td = this; var td = this;
var target = getTarget(event); var target = event.target;
if (!isCtrl(event) || isTag(td.firstChild, 'input|textarea') || isTag(target, 'a')) { if (!isCtrl(event) || isTag(td.firstChild, 'input|textarea') || isTag(target, 'a')) {
return; return;
} }
@@ -708,9 +991,13 @@ function selectClick(event, text, warning) {
td.innerHTML = original; td.innerHTML = original;
} }
}; };
var pos = event.rangeOffset;
var value = (td.firstChild && td.firstChild.alt) || td.textContent || td.innerText; let pos = event.rangeOffset;
input.style.width = Math.max(td.clientWidth - 14, 20) + 'px'; // 14 = 2 * (td.border + td.padding + input.border) let value = (td.firstChild && td.firstChild.alt) || td.textContent || td.innerText;
const tdStyle = window.getComputedStyle(td, null);
input.style.width = Math.max(td.clientWidth - parseFloat(tdStyle.paddingLeft) - parseFloat(tdStyle.paddingRight), 20) + 'px';
if (text) { if (text) {
var rows = 1; var rows = 1;
value.replace(/\n/g, function () { value.replace(/\n/g, function () {
@@ -771,7 +1058,7 @@ function selectLoadMore(limit, loading) {
return !ajax(href, function (request) { return !ajax(href, function (request) {
var tbody = document.createElement('tbody'); var tbody = document.createElement('tbody');
tbody.innerHTML = request.responseText; tbody.innerHTML = request.responseText;
qs('#table').appendChild(tbody); gid('table').appendChild(tbody);
if (tbody.children.length < limit) { if (tbody.children.length < limit) {
a.parentNode.removeChild(a); a.parentNode.removeChild(a);
} else { } else {
@@ -825,9 +1112,9 @@ function setupSubmitHighlightInput(input) {
* @this HTMLInputElement * @this HTMLInputElement
*/ */
function inputFocus() { function inputFocus() {
var submit = findDefaultSubmit(this); const submit = findDefaultSubmit(this);
if (submit) { if (submit) {
alterClass(submit, 'default', true); submit.classList.toggle('default', true);
} }
} }
@@ -835,16 +1122,18 @@ function inputFocus() {
* @this HTMLInputElement * @this HTMLInputElement
*/ */
function inputBlur() { function inputBlur() {
var submit = findDefaultSubmit(this); const submit = findDefaultSubmit(this);
if (submit) { if (submit) {
alterClass(submit, 'default'); submit.classList.toggle('default', false);
} }
} }
/** Find submit button used by Enter /**
* @param HTMLElement * Finds submit button used by Enter.
* @return HTMLInputElement *
*/ * @param {HTMLElement} el
* @return {HTMLInputElement}
*/
function findDefaultSubmit(el) { function findDefaultSubmit(el) {
if (el.jushTextarea) { if (el.jushTextarea) {
el = el.jushTextarea; el = el.jushTextarea;
@@ -852,10 +1141,10 @@ function findDefaultSubmit(el) {
if (!el.form) { if (!el.form) {
return null; return null;
} }
var inputs = qsa('input', el.form);
for (var i = 0; i < inputs.length; i++) { const inputs = qsa('input', el.form);
var input = inputs[i]; for (const input of inputs) {
if (input.type === 'submit' && !input.style.zIndex) { if (input.type === 'submit' && !input.classList.contains("wayoff") && !input.style.zIndex) {
return input; return input;
} }
} }
@@ -906,8 +1195,22 @@ function cloneNode(el) {
return el2; return el2;
} }
function getOffsetTop(element) {
let box = element.getBoundingClientRect();
return box.top + window.scrollY;
}
function getOffsetLeft(element) {
let box = element.getBoundingClientRect();
return box.left + window.scrollX;
}
oninput = function (event) { oninput = function (event) {
var target = event.target; const target = event.target;
var maxLength = target.getAttribute('data-maxlength'); const maxLength = target.getAttribute('data-maxlength');
alterClass(target, 'maxlength', target.value && maxLength != null && target.value.length > maxLength); // maxLength could be 0
// maxLength could be 0
target.classList.toggle('maxlength', target.value && maxLength != null && target.value.length > maxLength);
}; };

View File

@@ -7,9 +7,19 @@ if (!$fields) {
$table_status = table_status1($TABLE, true); $table_status = table_status1($TABLE, true);
$name = $adminer->tableName($table_status); $name = $adminer->tableName($table_status);
$rights = [];
foreach ($fields as $key => $field) {
$rights += $field["privileges"];
}
page_header(($fields && is_view($table_status) ? $table_status['Engine'] == 'materialized view' ? lang('Materialized view') : lang('View') : lang('Table')) . ": " . ($name != "" ? $name : h($TABLE)), $error); page_header(($fields && is_view($table_status) ? $table_status['Engine'] == 'materialized view' ? lang('Materialized view') : lang('View') : lang('Table')) . ": " . ($name != "" ? $name : h($TABLE)), $error);
$adminer->selectLinks($table_status); $set = null;
if (isset($rights["insert"]) || !support("table")) {
$set = "";
}
$adminer->selectLinks($table_status, $set);
$comment = $table_status["Comment"]; $comment = $table_status["Comment"];
if ($comment != "") { if ($comment != "") {
echo "<p class='nowrap'>" . lang('Comment') . ": " . h($comment) . "\n"; echo "<p class='nowrap'>" . lang('Comment') . ": " . h($comment) . "\n";
@@ -17,6 +27,22 @@ if ($comment != "") {
if ($fields) { if ($fields) {
$adminer->tableStructurePrint($fields); $adminer->tableStructurePrint($fields);
if (is_view($table_status)) {
$editLink = '<p class="links"><a href="' . h(ME) . 'view=' . urlencode($TABLE) . '">' . lang('Alter view') . "</a>\n";
} else {
$editLink = '<p class="links"><a href="' . h(ME) . 'create=' . urlencode($TABLE) . '">' . lang('Alter table') . "</a>\n";
}
echo $editLink;
if (support("partitioning") && preg_match("~partitioned~", $table_status["Create_options"])) {
echo "<h3 id='partition-by'>" . lang('Partition by') . "</h3>\n";
$partitions_info = get_partitions_info($TABLE);
$adminer->tablePartitionsPrint($partitions_info);
echo $editLink;
}
} }
if (!is_view($table_status)) { if (!is_view($table_status)) {
@@ -28,12 +54,12 @@ if (!is_view($table_status)) {
} }
echo '<p class="links"><a href="' . h(ME) . 'indexes=' . urlencode($TABLE) . '">' . lang('Alter indexes') . "</a>\n"; echo '<p class="links"><a href="' . h(ME) . 'indexes=' . urlencode($TABLE) . '">' . lang('Alter indexes') . "</a>\n";
} }
if (fk_support($table_status)) { if (fk_support($table_status)) {
echo "<h3 id='foreign-keys'>" . lang('Foreign keys') . "</h3>\n"; echo "<h3 id='foreign-keys'>" . lang('Foreign keys') . "</h3>\n";
$foreign_keys = foreign_keys($TABLE); $foreign_keys = foreign_keys($TABLE);
if ($foreign_keys) { if ($foreign_keys) {
echo "<table cellspacing='0'>\n"; echo "<table>\n";
echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . "<td></thead>\n"; echo "<thead><tr><th>" . lang('Source') . "<td>" . lang('Target') . "<td>" . lang('ON DELETE') . "<td>" . lang('ON UPDATE') . "<td></thead>\n";
foreach ($foreign_keys as $name => $foreign_key) { foreach ($foreign_keys as $name => $foreign_key) {
echo "<tr title='" . h($name) . "'>"; echo "<tr title='" . h($name) . "'>";
@@ -57,9 +83,9 @@ if (support(is_view($table_status) ? "view_trigger" : "trigger")) {
echo "<h3 id='triggers'>" . lang('Triggers') . "</h3>\n"; echo "<h3 id='triggers'>" . lang('Triggers') . "</h3>\n";
$triggers = triggers($TABLE); $triggers = triggers($TABLE);
if ($triggers) { if ($triggers) {
echo "<table cellspacing='0'>\n"; echo "<table>\n";
foreach ($triggers as $key => $val) { foreach ($triggers as $key => $val) {
echo "<tr valign='top'><td>" . h($val[0]) . "<td>" . h($val[1]) . "<th>" . h($key) . "<td><a href='" . h(ME . 'trigger=' . urlencode($TABLE) . '&name=' . urlencode($key)) . "'>" . lang('Alter') . "</a>\n"; echo "<tr><td>" . h($val[0]) . "<td>" . h($val[1]) . "<th>" . h($key) . "<td><a href='" . h(ME . 'trigger=' . urlencode($TABLE) . '&name=' . urlencode($key)) . "'>" . lang('Alter') . "</a>\n";
} }
echo "</table>\n"; echo "</table>\n";
} }

View File

@@ -40,7 +40,7 @@ page_header(($name != "" ? lang('Alter trigger') . ": " . h($name) : lang('Creat
<tr><th><?php echo lang('Type'); ?><td><?php echo html_select("Type", $trigger_options["Type"], $row["Type"]); ?> <tr><th><?php echo lang('Type'); ?><td><?php echo html_select("Type", $trigger_options["Type"], $row["Type"]); ?>
</table> </table>
<p><?php echo lang('Name'); ?>: <input name="Trigger" value="<?php echo h($row["Trigger"]); ?>" data-maxlength="64" autocapitalize="off"> <p><?php echo lang('Name'); ?>: <input name="Trigger" value="<?php echo h($row["Trigger"]); ?>" data-maxlength="64" autocapitalize="off">
<?php echo script("qs('#form')['Timing'].onchange();"); ?> <?php echo script("gid('form')['Timing'].onchange();"); ?>
<p><?php textarea("Statement", $row["Statement"]); ?> <p><?php textarea("Statement", $row["Statement"]); ?>
<p> <p>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">

View File

@@ -85,8 +85,8 @@ if ($_POST && !$error) {
unset($grants[$object]); unset($grants[$object]);
} }
if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && ( if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && (
!grant("REVOKE", $revoke, $match[2], " ON $match[1] FROM $new_user") //! SQL injection !grant(false, $revoke, $match[2], $match[1], $new_user) //! SQL injection
|| !grant("GRANT", $grant, $match[2], " ON $match[1] TO $new_user") || !grant(true, $grant, $match[2], $match[1], $new_user)
)) { )) {
$error = true; $error = true;
break; break;
@@ -100,7 +100,7 @@ if ($_POST && !$error) {
} elseif (!isset($_GET["grant"])) { } elseif (!isset($_GET["grant"])) {
foreach ($grants as $object => $revoke) { foreach ($grants as $object => $revoke) {
if (preg_match('~^(.+)(\(.*\))?$~U', $object, $match)) { if (preg_match('~^(.+)(\(.*\))?$~U', $object, $match)) {
grant("REVOKE", array_keys($revoke), $match[2], " ON $match[1] FROM $new_user"); grant(false, array_keys($revoke), $match[2], $match[1], $new_user);
} }
} }
} }
@@ -126,7 +126,14 @@ if ($_POST) {
if ($old_pass != "") { if ($old_pass != "") {
$row["hashed"] = true; $row["hashed"] = true;
} }
$grants[(DB == "" || $grants ? "" : idf_escape(addcslashes(DB, "%_\\"))) . ".*"] = array();
if ($grants) {
$grants[".*"] = [];
} elseif (DB != "") {
$grants[idf_escape(addcslashes(DB, "%_\\")) . ".*"] = [];
} else {
$grants["*.* "] = []; // Space is added to force editing mode.
}
} }
?> ?>
@@ -135,48 +142,86 @@ if ($_POST) {
<tr><th><?php echo lang('Server'); ?><td><input name="host" data-maxlength="60" value="<?php echo h($row["host"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Server'); ?><td><input name="host" data-maxlength="60" value="<?php echo h($row["host"]); ?>" autocapitalize="off">
<tr><th><?php echo lang('Username'); ?><td><input name="user" data-maxlength="80" value="<?php echo h($row["user"]); ?>" autocapitalize="off"> <tr><th><?php echo lang('Username'); ?><td><input name="user" data-maxlength="80" value="<?php echo h($row["user"]); ?>" autocapitalize="off">
<tr><th><?php echo lang('Password'); ?><td><input name="pass" id="pass" value="<?php echo h($row["pass"]); ?>" autocomplete="new-password"> <tr><th><?php echo lang('Password'); ?><td><input name="pass" id="pass" value="<?php echo h($row["pass"]); ?>" autocomplete="new-password">
<?php if (!$row["hashed"]) { echo script("typePassword(qs('#pass'));"); } ?> <?php if (!$row["hashed"]) { echo script("typePassword(gid('pass'));"); } ?>
<?php echo (min_version(8) ? "" : checkbox("hashed", 1, $row["hashed"], lang('Hashed'), "typePassword(this.form['pass'], this.checked);")); ?> <?php echo (min_version(8) ? "" : checkbox("hashed", 1, $row["hashed"], lang('Hashed'), "typePassword(this.form['pass'], this.checked);")); ?>
</table> </table>
<?php <?php
//! MAX_* limits, REQUIRE //! MAX_* limits, REQUIRE
echo "<table cellspacing='0'>\n"; echo "<table>\n";
echo "<thead><tr><th colspan='2'>" . lang('Privileges') . doc_link(array('sql' => "grant.html#priv_level"));
echo "<thead><tr><th colspan='2'>" . lang('Privileges') . doc_link(array('sql' => "grant.html#priv_level")) . "</th>";
$i = 0; $i = 0;
foreach ($grants as $object => $grant) { foreach ($grants as $object => $grant) {
echo '<th>' . ($object != "*.*" ? "<input name='objects[$i]' value='" . h($object) . "' size='10' autocapitalize='off'>" : "<input type='hidden' name='objects[$i]' value='*.*' size='10'>*.*"); //! separate db, table, columns, PROCEDURE|FUNCTION, routine echo "<th>";
//! separate db, table, columns, PROCEDURE|FUNCTION, routine
if ($object == "*.*") {
echo "<input type='hidden' name='objects[$i]' value='*.*' size='10'>*.*";
} else {
echo "<input name='objects[$i]' value='" . h(trim($object)) . "' size='10' autocapitalize='off'>";
}
echo "</th>";
$i++; $i++;
} }
echo "</thead>\n"; echo "</tr></thead>\n";
foreach (array( foreach ([
"" => "", "" => "",
"Server Admin" => lang('Server'), "Server Admin" => lang('Server'),
"Databases" => lang('Database'), "Databases" => lang('Database'),
"Tables" => lang('Table'), "Tables" => lang('Table'),
"Columns" => lang('Column'), "Columns" => lang('Column'),
"Procedures" => lang('Routine'), "Procedures" => lang('Routine'),
) as $context => $desc) { ] as $context => $desc) {
foreach ((array) $privileges[$context] as $privilege => $comment) { foreach ((array) $privileges[$context] as $privilege => $comment) {
echo "<tr" . odd() . "><td" . ($desc ? ">$desc<td" : " colspan='2'") . ' lang="en" title="' . h($comment) . '">' . h($privilege); echo "<tr" . odd() . ">";
if ($desc) {
echo "<td>$desc</td>";
}
echo "<td" . (!$desc ? " colspan='2'" : "") . ' lang="en" title="' . h($comment) . '">' . h($privilege) . "</td>";
$i = 0; $i = 0;
foreach ($grants as $object => $grant) { foreach ($grants as $object => $grant) {
$name = "'grants[$i][" . h(strtoupper($privilege)) . "]'"; $name = "'grants[$i][" . h(strtoupper($privilege)) . "]'";
$value = $grant[strtoupper($privilege)]; $value = $grant[strtoupper($privilege)];
if ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*")) {
echo "<td>"; $proxiedUser = strpos($object, "@") !== false;
$newObject = $object == ".*";
$allPrivileges = $privilege == "All privileges";
$grantOption = $privilege == "Grant option";
if ($object == "*.*" && $privilege == "Proxy") {
echo "<td></td>";
} elseif ($proxiedUser && $privilege != "Proxy" && !$grantOption) {
echo "<td></td>";
} elseif ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*") && !(($proxiedUser || $newObject) && $privilege == "Proxy")) {
echo "<td></td>";
} elseif (isset($_GET["grant"])) { } elseif (isset($_GET["grant"])) {
echo "<td><select name=$name><option><option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</select>"; echo "<td><select name=$name>" .
"<option></option>" .
"<option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "</option>" .
"<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</option>" .
"</select></td>";
} else { } else {
echo "<td align='center'><label class='block'>"; echo "<td class='center'><label class='block'>";
echo "<input type='checkbox' name=$name value='1'" . ($value ? " checked" : "") . ($privilege == "All privileges" echo "<input type='checkbox' name=$name value='1'" .
? " id='grants-$i-all'>" //! uncheck all except grant if all is checked ($value ? " checked" : "") .
: ">" . ($privilege == "Grant option" ? "" : script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };"))); ($allPrivileges ? " id='grants-$i-all'" : (!$grantOption ? " class='grants-$i'" : "")) .
">";
if ($allPrivileges) {
echo script("qsl('input').onclick = function () { if (this.checked) formUncheckAll('.grants-$i'); };");
} elseif (!$grantOption) {
echo script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };");
}
echo "</label>"; echo "</label>";
} }
$i++; $i++;
} }
echo "</tr>";
} }
} }

View File

@@ -6,7 +6,7 @@ $variables = ($status ? show_status() : show_variables());
if (!$variables) { if (!$variables) {
echo "<p class='message'>" . lang('No rows.') . "\n"; echo "<p class='message'>" . lang('No rows.') . "\n";
} else { } else {
echo "<table cellspacing='0'>\n"; echo "<table>\n";
foreach ($variables as $key => $val) { foreach ($variables as $key => $val) {
echo "<tr>"; echo "<tr>";
echo "<th><code class='jush-" . $jush . ($status ? "status" : "set") . "'>" . h($key) . "</code>"; echo "<th><code class='jush-" . $jush . ($status ? "status" : "set") . "'>" . h($key) . "</code>";

View File

@@ -1,995 +0,0 @@
Adminer 4.9.2 (released 2024-09-18):
- Fix textarea height for single-line inputs (used typically for SQLite text field).
- Fix undefined property in error message if driver does not support error number (e.g. PostgreSQL).
- PostgreSQL: Fix search fields configuration (regression from 4.9).
- PostgreSQL: Fix search condition for network address types, add macaddr8 type.
- PostgreSQL: Fix exporting CREATE TABLE query with GENERATED default values.
- PostgreSQL: Fix exporting CREATE TABLE query with sequence default value.
- PostgreSQL: Allow to set connection's sslmode with AdminerLoginSsl plugin.
- MySQL: Do not show 'empty' enum value in strict mode.
- Editor: Fix searching in tables.
- Function to retrieve driver name that can be used in plugins.
Adminer 4.9.1 (released 2024-09-09):
- Compatibility with PHP 8.3.
- Fix compiling jush external files.
- Improved displaying of long table names in menu.
- Replace deprecated <acronym> with <abbr>.
- Add support for translations in plugins.
- Add .editorconfig file.
- MySQL: Add unix_timestamp to functions.
- PostgreSQL: Show only accessible databases.
- PostgreSQL: Make data length calculation more accurate.
- PostgreSQL: Fix documentation link for SERIAL type.
- PostgreSQL: Fix undefined properties on PHP 8.
- Elasticsearch: Fix field selection.
- AdminerEditForeign: Refactor and fix the plugin.
- AdminerLoginOtp: Autocomplete hints for OTP input field, code refactoring.
Adminer 4.9 (released 2024-08-19):
- Validate server input in login form.
- Validate connection to server in HTTP based drivers.
- Move dependencies from submodules to Composer.
- Update hydra and pepa-lintha-dark themes.
- Elasticsearch 5: Make unusable driver usable again, move it to plugins.
- Add new Elasticsearch 7 driver.
- Set saving to file as a default export option.
- Improve URL and email detection.
- Fix AdminerVersionNoverify plugin blocking other plugins to modify HTML head.
- Fix several bugs and security issues in AdminerFileUpload plugin.
- Skip dump of generated columns.
- Update composer.json.
- Add script for exporting compiled adminer variants.
Adminer 4.8.2 (released 2024-03-16):
Support multi-line table comments
MySQL: Use ST_SRID() instead of SRID() for MySQL 8 (PR #418)
PostgreSQL: Don't reset table comments (regression from 4.2.0)
PostgreSQL PDO: Allow editing rows identified by boolean column (PR #380)
Update several translations: lv, bn, fr, it, nl, ru, cs, sk
Allow responsive styles on larger devices
Adminer 4.8.1 (released 2021-05-14):
Internet Explorer or PDO in Adminer 4.7.8-4.8.0: Fix XSS in doc_link (bug #797)
Fix more PHP 8 warnings (bug #781)
Avoid PHP warnings with PDO drivers (bug #786, regression from 4.7.8)
MySQL: Allow moving views to other DB and renaming DB with views (bug #783)
MariaDB: Do not treat sequences as views (PR #416)
PostgreSQL: Support UPDATE OF triggers (bug #789)
PostgreSQL: Support triggers with more events (OR)
PostgreSQL: Fix parsing of foreign keys with non-ASCII column names
PostgreSQL < 10 PDO: Avoid displaying GENERATED ALWAYS BY IDENTITY everywhere (bug #785, regression from 4.7.9)
SQLite: Fix displayed types (bug #784, regression from 4.8.0)
Adminer 4.8.0 (released 2021-02-10):
Support function default values in insert (bug #713)
Allow SQL pseudo-function in insert
Skip date columns for non-date values in search anywhere
Add DB version to comment in export
Support PHP 8 in create table (regression from 4.7.9)
MySQL 8: Fix EXPLAIN in SQL command
PostgreSQL: Create PRIMARY KEY for auto increment columns
PostgreSQL: Avoid exporting empty sequence last value (bug #768)
PostgreSQL: Do not show triggers from other schemas (PR #412)
PostgreSQL: Fix multi-parameter functions in default values (bug #736)
PostgreSQL: Fix displaying NULL bytea fields
PostgreSQL PDO: Do not select NULL function for false values in edit
Oracle: Alter indexes
Oracle: Count tables
Oracle: Import from CSV
Oracle: Fix column size with string type
MongoDB: Handle errors
SimpleDB, Firebird, ClickHouse: Move to plugin
Adminer 4.7.9 (released 2021-02-07):
Fix XSS in browsers which don't encode URL parameters (bug #775, regression from 4.7.0)
Elasticsearch, ClickHouse: Do not print response if HTTP code is not 200
Don't syntax highlight during IME composition (bug #747)
Quote values with leading and trailing zeroes in CSV export (bug #777)
Link URLs in SQL command (PR #411)
Fix displayed foreign key columns from other DB (bug #766)
Re-enable PHP warnings (regression from 4.7.8)
MySQL: Do not export names in quotes with sql_mode='ANSI_QUOTES' (bug #749)
MySQL: Avoid error in PHP 8 when connecting to socket (PR #409)
MySQL: Don't quote default value of text fields (bug #779)
PostgreSQL: Export all FKs after all CREATE TABLE (PR #351)
PostgreSQL: Fix dollar-quoted syntax highlighting (bug #738)
PostgreSQL: Do not show view definition from other schema (PR #392)
PostgreSQL: Use bigserial for bigint auto increment (bug #765, regression from 3.0.0)
PostgreSQL PDO: Support PgBouncer, unsupport PostgreSQL < 9.1 (bug #771)
PostgreSQL 10: Support GENERATED ALWAYS BY IDENTITY (PR #386)
PostgreSQL 10: Support partitioned tables (PR #396)
PostgreSQL 11: Create PRIMARY KEY for auto increment columns
SQLite: Set busy_timeout to 500
MS SQL: Don't truncate comments to 30 chars (PR #376)
Elasticsearch 6: Fix displaying type mapping (PR #402)
MongoDB: Fix password-less check in the mongo extension (PR #405)
Editor: Cast to string when searching (bug #325)
Editor: Avoid trailing dot in export filename
Adminer 4.7.8 (released 2020-12-06):
Support PHP 8
Disallow connecting to privileged ports (bug #769)
Adminer 4.7.7 (released 2020-05-11):
Fix open redirect if Adminer is accessible at //adminer.php%2F@
Adminer 4.7.6 (released 2020-01-31):
Speed up alter table form (regression from 4.4.0)
Fix clicking on non-input fields in alter table (regression from 4.6.2)
Display time of procedure execution
Disallow connecting to ports > 65535 (bug #730)
MySQL: Always set foreign_key_checks in export
PostgreSQL: Support exporting views
Editor: Fix focusing foreign key search in select
Adminer 4.7.5 (released 2019-11-13):
Add id="" to cells with failed inline edit (bug #708)
PostgreSQL: Fix getting default value in PostgreSQL 12 (bug #719)
PostgreSQL, Oracle: Set schema for EXPLAIN queries in SQL command (bug #706)
ClickHouse: SQL command
Swedish translation
Adminer 4.7.4 (released 2019-10-22):
Fix XSS if Adminer is accessible at URL /data:
Adminer 4.7.3 (released 2019-08-27):
Allow editing foreign keys pointing to tables in other database/schema (bug #694)
Fix blocking of concurrent instances in PHP >7.2 (bug #703)
MySQL: Speed up displaying tables in large databases (bug #700, regression from 4.7.2)
MySQL: Allow editing rows identified by negative floats (bug #695)
MySQL: Skip editing generated columns
SQLite: Quote strings stored in integer columns in export (bug #696)
SQLite: Handle error in altering table (bug #697)
SQLite: Allow setting auto increment for empty tables
SQLite: Preserve auto increment when recreating table
MS SQL: Support foreign keys to other DB
MongoDB: Allow setting authSource from environment variable
Adminer 4.7.2 (released 2019-07-18):
Do not attempt logging in without password (bug #676)
Stretch footer over the whole table width (bug #624)
Allow overwriting tables when copying them
Fix displaying SQL command after Save and continue edit
Cache busting for adminer.css
MySQL: Fix displaying multi-columns foreign keys (bug #675, regression from 4.7.0)
MySQL: Fix creating users and changing password in MySQL 8 (bug #663)
MySQL: Pass SRID to GeomFromText
PostgreSQL: Fix setting column comments on new table
PostgreSQL: Display definitions of materialized views (bug #682)
PostgreSQL: Fix table status in PostgreSQL 12 (bug #683)
MS SQL: Support comments
Elasticsearch: Fix setting number of rows
Adminer 4.7.1 (released 2019-01-24):
Display the tables scrollbar (bug #647)
Remember visible columns in Create Table form (bug #493)
Add autocomplete attributes to login form
PHP <5.4 compatibility even with ClickHouse enabled (regression from 4.7.0)
SQLite: Hide server field in login form
Editor: Allow disabling boolean fields in PostgreSQL (bug #640)
Adminer 4.7.0 (released 2018-11-24):
Simplify storing executed SQL queries to bookmarks
Warn when using password with leading or trailing spaces
Hide import from server if importServerPath() returns an empty string
Fix inline editing of empty cells (regression from 4.6.3)
Allow adding more than two indexes and forign key columns at a time (regression from 4.4.0)
Avoid overwriting existing tables when copying tables (bug #642)
Fix function change with set data type
Increase username maxlength to 80 (bug #623)
Make maxlength in all fields a soft limit
Make tables horizontally scrollable
MySQL: Support foreign keys created with ANSI quotes (bug #620)
MySQL: Recognize ON UPDATE current_timestamp() (bug #632, bug #638)
MySQL: Descending indexes in MySQL 8 (bug #643)
PostgreSQL: Quote array values in export (bug #621)
PostgreSQL: Export DESC indexes (bug #639)
PostgreSQL: Support GENERATED BY DEFAULT AS IDENTITY in PostgreSQL 10
MS SQL: Pass database when connecting
ClickHouse: Connect, databases list, tables list, select, SQL command
Georgian translation
Adminer 4.6.3 (released 2018-06-28):
Disallow using password-less databases
Copy triggers when copying table
Stop session before connecting
Simplify running slow queries
Decrease timeout for running slow queries from 5 seconds to 2 seconds
Fix displaying info about non-alphabetical objects (bug #599)
Use secure cookies on HTTP if session.cookie_secure is set
PDO: Support binary fields download
MySQL: Disallow LOAD DATA LOCAL INFILE
MySQL: Use CONVERT() only when searching for non-ASCII (bug #603)
MySQL: Order database names in MySQL 8 (bug #613)
PostgreSQL: Fix editing data in views (bug #605, regression from 4.6.0)
PostgreSQL: Do not cast date/time/number/uuid searches to text (bug #608)
PostgreSQL: Export false as 0 in PDO (bug #619)
MS SQL: Support port with sqlsrv
Editor: Do not check boolean checkboxes with false in PostgreSQL (bug #607)
Adminer 4.6.2 (released 2018-02-20):
Semi-transparent border on table actions
Shorten JSON values in select (bug #594)
Speed up alter table form (regression from 4.4.0)
Store current version without authentication and in Editor
PostgreSQL: Fix exporting string default values
PostgreSQL: Fix exporting sequences in PostgreSQL 10
PostgreSQL: Add IF EXISTS to DROP SEQUENCE in export (bug #595)
Editor: Fix displaying of true boolean values (regression from 4.5.0)
Adminer 4.6.1 (released 2018-02-09):
Sticky position of table actions
Speed up rendering of long tables (regression from 4.4.0)
Display notification about performing action after relogin
Add system tables help links
MySQL: Support non-utf8 charset in search in column
MySQL: Support geometry in MySQL 8 (bug #574)
MariaDB: Links to documentation
SQLite: Allow deleting PRIMARY KEY from tables with auto increment
PostgreSQL: Support binary files in bytea fields
PostgreSQL: Don't treat interval type as number (bug #474)
PostgreSQL: Cast to string when searching using LIKE (bug #325)
PostgreSQL: Fix condition for selecting no rows
PostgreSQL: Support TRUNCATE+INSERT export
Customization: Support connecting to MySQL via SSL
Customization: Allow specifying server name displayed in breadcrumbs
Adminer 4.6.0 (released 2018-02-05):
Fix counting selected rows after going back to select page
PHP <5.3 compatibility even with Elasticsearch enabled
Fully support functions in default values
Stop redirecting links via adminer.org
Support X-Forwarded-Prefix
Display options for timestamp columns when creating a new table
Disable autocompleting password on create user page
Use primary key to edit rows even if not selected
MySQL, PostgreSQL: Display warnings
MySQL: Add floor and ceil select functions
MySQL: Add FIND_IN_SET search operator
MariaDB: Support JSON since MariaDB 10.2
SQLite, PostgreSQL: Limit rows in data manipulation without unique key
PostgreSQL: Support routines
PostgreSQL: Allow editing views with uppercase letters (bug #467)
PostgreSQL: Allow now() as default value (bug #525)
SimpleDB: Document that allow_url_fopen is required
Malay translation
Adminer 4.5.0 (released 2018-01-24):
Display name of the object in confirmation when dropping it
Display newlines in column comments (bug #573)
Support current_timestamp() as default of time fields (bug #572)
Hide window.opener from pages opened in a new window (bug #561)
Display error when getting row to edit
Store current Adminer version server-side to avoid excessive requests
Adminer: Fix Search data in tables (regression from 4.4.0)
CSP: Allow any styles, images, media and fonts, disallow base-uri
MySQL: Support geometry in MySQL 8 (bug #574)
MySQL: Support routines with comments in parameters (bug #460)
MariaDB: Support fulltext and spatial indexes in InnoDB (bug #583)
SQLite: Enable foreign key checks
PostgreSQL: Respect NULL default value
PostgreSQL: Display foreign tables (bug #576)
PostgreSQL: Do not export triggers if not requested
PostgreSQL: Export DROP SEQUENCE if dropping table
PostgreSQL: Display boolean values as code (bug #562)
MS SQL: Support freetds
non-MySQL: Avoid CONVERT() (bug #509)
Elasticsearch: Insert, update, delete
MongoDB: Support mongodb PHP extension
Editor: Fix displaying of false values in PostgreSQL (bug #568)
Adminer 4.4.0 (released 2018-01-17):
Add Content Security Policy
Disallow scripts without nonce
Rate limit password-less login attempts from the same IP address
Disallow connecting to privileged ports
Add nosniff header
PHP 7.1: Prevent warning when using empty limit
PHP 7.2: Prevent warning when searching in select
MySQL: Remove dedicated view for replication status (added in 4.3.0)
PostgreSQL: Sort table names (regression from 4.3.1)
Editor: Don't set time zone from PHP, fixes DST
Editor: Display field comment's text inside [] only in edit form
Editor: Fix doubleclick on database page
Editor: Fix Search data in tables
Customization: Always send security headers
Hebrew translation
Adminer 4.3.1 (released 2017-04-14):
Fix permanent login after logout (bug #539)
Fix SQL command autofocus (regression from 4.0.0)
PostgreSQL: Support JSON and JSONB data types
PostgreSQL: Fix index size computation in PostgreSQL < 9.0 (regression from 4.3.0)
PostgreSQL: Fix nullable fields in export
Adminer 4.3.0 (released 2017-03-15):
Make maxlength in edit fields a soft limit
Add accessibility labels
Add Cache-Control: immutable to static files
MySQL: Support MySQL 8
MySQL: Support JSON data type
MySQL: Add dedicated view for replication status
MySQL: Support spatial indexes
PostgreSQL: Export
PostgreSQL: Don't treat partial indexes as unique
MS SQL: Support pdo_dblib
Elasticsearch: Support HTTPS by inputting https://server
Adminer 4.2.5 (released 2016-06-01):
Fix remote execution in SQLite query
SQLite: Require credentials to use
PostgreSQL: Support KILL
Adminer 4.2.4 (released 2016-02-06):
Fix remote execution in SQLite query
MySQL: Support PHP 7
Bosnian translation
Finnish translation
Adminer 4.2.3 (released 2015-11-15):
Fix XSS in indexes (non-MySQL only)
Support PHP 7
Greek translation
Galician translation
Bulgarian translation
Adminer 4.2.2 (released 2015-08-05):
Fix XSS in alter table (found by HP Fortify)
Adminer 4.2.1 (released 2015-03-10):
Send referrer header to the same domain
MySQL: Fix usage of utf8mb4 if the client library doesn't support it
MySQL: Use utf8mb4 in export only if required
SQLite: Use EXPLAIN QUERY PLAN in SQL query
Adminer 4.2.0 (released 2015-02-07):
Fix XSS in login form (bug #436)
Allow limiting number of displayed rows in SQL command
Fix reading routine column collations
Unlock session in alter database
Make master key unreadable to others (bug #410)
Fix edit by long non-utf8 string
Specify encoding for PHP 5.6 with invalid default_charset
Fix saving NULL value, bug since Adminer 4.0.3
Send 403 for auth error
Report offline and other AJAX errors (bug #419)
Don't alter table comment if not changed
Add links to documentation on table status page
Fix handling of 64 bit numbers in auto_increment
Add referrer: never meta tag
MySQL: Use utf8mb4 if available
MySQL: Support foreign keys in NDB storage
PostgreSQL: Materialized views
SQLite: Support CURRENT_* default values (bug #417)
Elasticsearch: Use where in select
Firebird: Alpha version
Danish translation
Adminer 4.1.0 (released 2014-04-18):
Provide size of all databases in the overview
Prevent against brute force login attempts from the same IP address
Compute number of tables in the overview explicitly
Display edit form after error in clone or multi-edit
Trim trailing non-breaking spaces in SQL textarea
Display time of the select command
Print elapsed time in HTML instead of SQL command comment
Improve gzip export ratio (bug #387)
Use rel="noreferrer" for external links, skip adminer.org redirect in WebKit
MySQL: Fix enum types in routines (bug #391)
MySQL: Fix editing rows by binary values, bug since Adminer 3.7.1
MySQL: Respect daylight saving time in dump, bug since Adminer 3.6.4
MySQL 5.6.5+: Support ON UPDATE on datatime column
SQLite: Support UPDATE OF triggers
SQLite: Display auto-created unique indexes, bug since Adminer 3.5.0
Editor: Fix login() method, bug since Adminer 4.0.0
Translate numbers in ar, bn, fa
Vietnamese translation
Adminer 4.0.3 (released 2014-02-01)
MongoDB: insert, truncate, indexes
SimpleDB, MongoDB: insert more fields at once
SQLite: Fix creating table and altering primary key, bug since Adminer 4.0.0
Don't store invalid credentials to session, bug since Adminer 4.0.0
Norweigan translation
Adminer 4.0.2 (released 2014-01-11):
Fix handling of long text in SQL textarea
Support paste to SQL textarea in Opera
Adminer 4.0.1 (released 2014-01-11):
Don't use type=number if a SQL function is used
Disable highlighting in textareas with long texts
Don't autofocus SQL textarea in Firefox
Don't link NULL foreign key values
Fix displaying images in Editor, bug since Adminer 3.6.0
Fix uploading files, bug since Adminer 4.0.0
MongoDB: Count tables, display ObjectIds, sort, limit, offset, count rows
Elasticsearch: Fix compiled version, create and drop DB, drop table
Adminer 4.0.0 (released 2014-01-08):
Driver for SimpleDB, MongoDB and Elasticsearch
Highlight SQL in textareas
Save and continue edit by AJAX
Split SQL command and import
Add a new column in alter table on key press
Mark length as required for strings
Add label to database selection, move logout button
Add button for dropping an index
Display number of selected rows
Add links to documentation
Disable underlining links
Differentiate views in navigation
Improve speed of CSV import
Keep form values after refresh in Firefox
Mark auto_increment fields in edit
Don't append newlines to uploaded files, bug since Adminer 3.7.0
Don't display SQL edit form on Ctrl+click on the select query, introduced in Adminer 3.6.4
Use MD5 for editing long keys only in supported drivers, bug since Adminer 3.6.4
Don't reset column when searching for an empty value with Enter, bug since Adminer 3.6.4
Encrypt passwords stored in session by a key stored in cookie
Don't execute external JavaScript when verifying version
Include JUSH in the compiled version
Protect CSRF token against BREACH
Non-MySQL: View triggers
SQLite: Allow editing primary key
SQLite: Allow editing foreign keys
PostgreSQL: Fix handling of nextval() default values
PostgreSQL: Support creating array columns
Customization: Provide schemas()
Portugal Portuguese translation
Thai translation
Adminer 3.7.1 (released 2013-06-29):
Increase click target for checkboxes
Use shadow for highlighting default button
Don't use LIMIT 1 if inline updating unique row
Don't check previous checkbox on added column in create table (bug #326)
Order table list by name
Verify UTF-8 encoding of CSV import
Notify user about expired master password for permanent login
Highlight table being altered in navigation
Send 404 for invalid database and schema
Fix title and links on invalid table pages
Display error on invalid alter table and view pages
MySQL: Speed up updating rows without numeric or UTF-8 primary key
Non-MySQL: Descending indexes
PostgreSQL: Fix detecting oid column in PDO
PostgreSQL: Handle timestamp types (bug #324)
Add Korean translation
Adminer 3.7.0 (released 2013-05-19):
Allow more SQL files to be uploaded at the same time
Print run time next to executed queries
Don't drop original view and routine before creating the new one
Highlight default submit button
Add server placeholder to login form
Disable SQL export when applying functions in select
Allow using lang() in plugins (customization)
Remove bzip2 compression support
Constraint memory used in TAR export
Allow exporting views dependent on each other (bug #214)
Fix resetting search (bug #318)
Don't use LIMIT 1 if updating unique row (bug #320)
Restrict editing rows without unique identifier to search results
Display navigation bellow main content on mobile browsers
Get number of rows on export page asynchronously
Respect 'whole result' even if some rows are checked (bug #339 since Adminer 3.7.0)
MySQL: Optimize create table page and Editor navigation
MySQL: Display bit type as binary number
MySQL: Improve export of binary data types
MySQL: Fix handling of POINT data type (bug #282)
MySQL: Don't export binary and geometry columns twice in select
MySQL: Fix EXPLAIN in MySQL < 5.1, bug since Adminer 3.6.4
SQLite: Export views
PostgreSQL: Fix swapped NULL and NOT NULL columns in PDO
Adminer 3.6.4 (released 2013-04-26):
Display pagination on a fixed position
Increase default select limit to 50
Display SQL edit form on Ctrl+click on the select query
Display SQL history from newest
Recover original view, trigger, routine if creating fails
Do not store plain text password to history in creating user
Selectable ON UPDATE CURRENT_TIMESTAMP field in create table
Open database to a new window after selecting it with Ctrl
Clear column name after resetting search (bug #296)
Explain partitions in SQL query (bug #294)
Allow loading more data with inline edit (bug #299)
Stay on the same page after deleting rows (bug #301)
Respect checked tables in export filename (bug #133)
Respect PHP configuration max_input_vars
Fix unsetting permanent login after logout
Disable autocapitalize in identifiers on mobile browsers
MySQL: Compatibility with MySQL 5.6
MySQL: Move ALTER export to plugin
MySQL: Use numeric time zone in export
MySQL: Link processlist documentation
SQLite: Export indexes
Adminer 3.6.3 (released 2013-01-23):
Display error code in SQL query
Allow specifying external links
Treat Meta key same as Ctrl
Fix XSS in displaying non-UTF-8 strings
Don't use type="number" for decimal numbers
Adminer 3.6.2 (released 2012-12-21):
Edit values by Ctrl+click instead of double click
Don't select row on double click
Support NULL in routine calls
Shorten printed values in varchar fields
Display table default values on wide screens
Display date in SQL history
HTML5 input fields
Display warning for missing UPDATE privilege
Fix switching language on first load
Support enabled mbstring.func_overload
MySQL: Prolong comment length since MySQL 5.5
PostgreSQL: Fix process list in version 9.2
MS SQL: Support databases starting with number
Adminer 3.6.1 (released 2012-09-17):
Fix compiled version on PHP with multibyte support
Adminer 3.6.0 (released 2012-09-16):
Load more data in select
Edit strings with \n in textarea
Time out long running database list and select count
Use VALUES() in INSERT+UPDATE export
Style logout button as link
Store selected database to permanent login
Ctrl+click and Shift+click on button opens form to a blank window
Switch language by POST
Compress translations
MySQL: Support geometry data types
selectQueryBuild() method (customization)
Serbian translation
Adminer 3.5.1 (released 2012-08-10):
Support same name fields in CSV export
Support Shift+click in export
Adminer 3.5.0 (released 2012-08-05):
Links for column search in select
Autohide column context menu in select
Autodisplay long table names in tables list
Display assigned auto_increment after clone
SQLite: Full alter table
SQLite: Better editing in tables without primary key
SQLite: Display number of rows in database overview
Adminer 3.4.0 (released 2012-06-30):
Link to descending order
Shift+click on checkbox to select consecutive rows
Print current time next to executed SQL queries
Warn about selecting data without index
Allow specifying database in login form
Link to original table in EXPLAIN of SELECT * FROM table t
Format numbers in translations
MySQL: inform about disabled event_scheduler
SQLite: support binary data
PostgreSQL: approximate row count in table overview
PostgreSQL: improve PDO support in SQL command
Oracle: schema, processlist, table overview numbers
Simplify work with NULL values (customization)
Use namespace in login form (customization)
Customizable export filename (customization)
Replace JSMin by better JavaScript minifier
Don't use AJAX links and forms
Indonesian translation
Ukrainian translation
Bengali translation
Adminer 3.3.4 (released 2012-03-07):
Foreign keys default actions (bug #188)
SET DEFAULT foreign key action
Fix minor parser bug in SQL command with webserver file
Ctrl+click on button opens form to a blank window
Trim table and column names (bug #195)
Error message with no response from server in AJAX
Esc to cancel AJAX request
Move AJAX loading indicator to the right
Don't quote bit type in export
Don't check row while selecting text
Fix invalid references line position on Database schema
Disable selecting text on Database schema
Ability to disable export (customization)
Extensible list of databases (customization)
MySQL: set autocommit after connect
SQLite, PostgreSQL: vacuum
SQLite, PostgreSQL: don't use LIKE for numbers (bug #202)
PostgreSQL: fix alter foreign key
PostgreSQL over PDO: connect if the eponymous database does not exist (bug #185)
Boolean search (Editor)
Persian translation
Adminer 3.3.3 (released 2011-08-12):
Highlight checked rows
Titles of links in database overview and navigation
Fix trigger export (SQLite)
Default trigger statement (SQLite, PostgreSQL)
Remove search by expression (PostgreSQL, MS SQL)
Adminer 3.3.2 (released 2011-08-08):
Display error with non-existent row in edit
Fix minor parser bug in SQL command with webserver file
Fix SQL command Stop on error
Don't scroll with AJAX select order and alter move column
Fast number of rows with big tables (PostgreSQL)
Sort databases and schemas (PostgreSQL)
Adminer 3.3.1 (released 2011-07-27):
Fix XSS introduced in Adminer 3.2.0
Fix altering default values (PostgreSQL)
Process list (PostgreSQL)
Adminer 3.3.0 (released 2011-07-19):
Use Esc to disable in-place edit
Shortcut for database privileges
Editable index names
Append new index with auto index selection (bug #138)
Preserve original timestamp value in multiple update (bug #158)
Bit type default value
Display foreign key name in tooltip
Display default column value in table overview
Display column collation in tooltip
Keyboard shortcuts: Alt+Shift+1 for homepage, Ctrl+Shift+Enter for Save and continue edit
Show only errors with Webserver file SQL command
Remember select export and import options
Link tables and indexes from SQL command EXPLAIN (MySQL)
Display error with all wrong SQL commands (MySQL)
Display foreign keys from other schemas (PostgreSQL)
Pagination support (Oracle)
Autocomplete for big foreign keys (Editor)
Display name of the referenced record in PostgreSQL (Editor)
Prefer NULL to empty string (Editor, bug #162)
Display searched columns (Editor)
Customizable favicon (customization)
Method name can return a link (customization)
Easier sending of default headers (customization)
Lithuanian and Romanian translation
Adminer 3.2.2 (released 2011-03-28):
Fix AJAX history after reload
Adminer 3.2.1 (released 2011-03-23):
Ability to save expression in edit
Respect default database collation (bug #119)
Don't export triggers without table (bug #123)
Esc to focus next field in Tab textarea
Send forms by Ctrl+Enter on <select>
Enum editor and textarea Ctrl+Enter working in IE
AJAX forms in Google Chrome
Parse UTF-16 and UTF-8 BOM in all text uploads
Display ; in history
Use DELIMITER in history
Show databases even with skip_show_database in MySQL 5
Disable maxlength with functions in edit
Better placement of AJAX icon
Table header in CSV export (Editor)
Time format hint (Editor)
Respect order after search (Editor)
Set MySQL time zone by PHP setting (Editor)
Allow own code in <head> (customization)
Polish translation
Adminer 3.2.0 (released 2011-02-24):
Get long texts and slow information by AJAX
Most links and forms by AJAX in browsers with support for history.pushState
Copy tables
Ability to search by expression in select
Export SQL command result (bug #99)
Focus first field with insert (bug #106)
Permanent link in schema
Display total time in show only errors mode in SQL command
History: edit all
MS SQL: auto primary and foreign key
SQLite: display 0
Create table default data type: int
Focus upper/lower fields by Ctrl+Up/Ctrl+Down
Hide credentials for SQLite
Utilize oids in PostgreSQL
Homepage customization
Use IN for search in numeric fields (Editor)
Use password input for _md5 and _sha1 fields (Editor)
Work without session.use_cookies (bug #107)
Fix saving schema to cookie in Opera
Portuguese, Slovenian and Turkish translation
Adminer 3.1.0 (released 2010-11-16):
TSV export and import
Customizable export
Option to show only errors in SQL command
Link to bookmark SQL command
Recognize $$ strings in SQL command (PostgreSQL)
Highlight and edit SQL command in processlist
Always display all drivers
Timestamp at the end of export
Link to refresh database cache (bug #96)
Support for virtual foreign keys
Disable XSS "protection" of IE8
Immunity against zend.ze1_compatibility_mode (bug #86)
Fix last page with empty result set
Arabic translation and RTL support
Dual licensing: Apache or GPL
Adminer 3.0.1 (released 2010-10-18):
Send the form by Ctrl+Enter in all textareas
Disable creating SQLite databases with extension other than db, sdb, sqlite
Ability to use Adminer in a frame through customization
Catalan translation
MS SQL 2005 compatibility
PostgreSQL: connect if the eponymous database does not exist
Adminer 3.0.0 (released 2010-10-15):
Drivers for MS SQL, SQLite, PostgreSQL, Oracle
Allow concurrent logins on the same server
Allow permanent login without customization
In-place editation in select
Foreign key options in Table creation
Treat binary type as hex
Show number of tables in server overview
Operator LIKE %%
Remember export parameters in cookie
Allow semicolon as CSV separator
Schemas, sequences and types support (PostgreSQL)
Autofocus username in login form
Allow to insert Tab in SQL textareas and send the form by Ctrl+Enter
Disable spellchecking in SQL textareas
Display auto_increment value of inserted item
Allow disabling auto_increment value export
Prefill auto_increment column name
Ability to jump to any page in select by JavaScript
Display comment in table overview
Link last page above data in select
Link table names in SQL queries
Hungarian, Japanese and Tamil translation
Defer table information in database overview to JavaScript (performance)
Big tables optimizations (performance)
Adminer 2.3.2 (released 2010-04-21):
Fix COUNT(*) link
Fix Save and continue edit
Adminer 2.3.1 (released 2010-04-06):
Add Drop button to Alter pages (regression from 2.0.0)
Link COUNT(*) result to listing
Newlines in select query edit
Return to referrer after edit
Respect session.auto_start (bug #42)
Adminer 2.3.0 (released 2010-02-26):
Support for permanent login (customization required)
Search in all tables
Show status variables
Print sums in tables overview
Add Delete button to Edit page (regression from 2.0.0)
Print error summary in SQL command
Simplify SQL syntax error message
Show SQL query info if available
Delete length when changing type in alter table
Ability to check table prefix in export
Adminer 2.2.1 (released 2009-11-26):
Highlight current links
Improve concurrency
Move number of tables to DB info (performance)
Search by foreign keys (Editor)
Link new item in backward keys (Editor)
Adminer 2.2.0 (released 2009-10-20):
Database list - bulk drop, number of tables
Enlarge field for enum and set definition
Display table links above table structure
Link URLs in select
Display number of manipulated rows in JS confirm
Set required memory in SQL command
Fix removed default in ALTER
Display whitespace in texts (bug #11)
ClickJacking protection in modern browsers
E-mail attachments (Editor)
Optional year in date (Editor)
Search operators (Editor)
Align numbers to right in select (Editor)
Move <h1> to $adminer->navigation (customization)
Rename get_dbh to connection (customization)
Adminer 2.1.0 (released 2009-09-12):
Edit default values directly in table creation
Execute SQL file stored on server disk
Display EXPLAIN in SQL query
Compress export and import
Display column comments in table overview
Use ON DUPLICATE KEY UPDATE for CSV import
Print ALTER export instead of executing it
Click on row selects it
Fix Editor date format
Fix long SQL query crash (bug #3)
Speed up simple alter table
Traditional Chinese translation
Adminer 2.0.0 (released 2009-08-06):
Editor: User friendly data editor
Customization: Adminer class
Create single column foreign key in table structure
Table relations (Editor)
Send e-mails (Editor)
Display images in blob (Editor)
Localize date (Editor)
Treat tinyint(1) as bool (Editor)
Divide types to groups in table creation
Link e-mails in select
Show type in field name title
Preselect now() for timestamp columns
Clear history
Prefill insert by foreign key searches
Print number of rows in SQL command
Remove Delete button from Edit page - use mass operation for it
Faster multiple update, clone and delete
Faster table list in navigation
Download version checker and syntax highlighting from HTTPS
Use HTML Strict instead of XHTML
Remove function minification in favor of performance and customization
Fix grant ALL PRIVILEGES with GRANT OPTION
Fix CSV import
Fix work with default values
Adminer 1.11.1 (released 2009-07-03):
Fix problem with enabled Filter extension
Adminer 1.11.0 (released 2009-07-02):
Connection through socket by server :/path/to/socket
Simplify export
Display execution time in SQL query
Relative date and time functions
Version checker
Save queries to history and display it on SQL page
Display MySQL variables
Ability to select all rows on current page of select
Separate JavaScript functions
Always use the default style before the external one
Always try to use the syntax highlighter
All privileges in user rights
Fix FOUND_ROWS() in SQL command
Export only selected columns in select
Bulk database creation
Include views in drop and move on database overview
Hide fieldsets in select
Automatically add new fields in table creation
Use \n in SQL commands
phpMinAdmin 1.10.1 (released 2009-05-07):
Highlight odd and hover rows
Partition editing comfort (bug #12)
Allow full length in limited int
phpMinAdmin 1.10.0 (released 2009-04-28):
Partitioning (MySQL 5.1)
CSV import
Plus and minus functions
Option to stop on error in SQL command
Cross links to select and table (bug #2236232), link new item
Suhosin compatibility
Remove max_allowed_packet from export
Read style from phpMinAdmin.css if exists
Size reduction by minification of variables and functions
Russian translation
phpMinAdmin 1.9.1 (released 2008-10-27):
Update translations
phpMinAdmin 1.9.0 (released 2008-10-16):
List of tables and views with maintenance commands
Clone rows
Bulk edit and clone
Function results in edit
NOT operators in select
Search without column restriction
Use type=password for unhashed password
Only one button for each action in select
Choose language through option-list
XHTML syntax errors
Don't set global variable in export
SHOW DATABASES can be revoked
Order by function result working also in older MySQL versions
Tested on IIS
phpMinAdmin 1.8.0 (released 2008-09-12):
Events (MySQL 5.1)
Access without login - accept ?username=
Print SQL query in select, messages and warnings
Display number of found rows
Don't wrap lines in select table
Italian and Estonian translation
Order by COUNT(*)
phpMinAdmin 1.7.0 (released 2008-08-26):
Customizable export (select objects to export, SQL or CSV)
Ability to alter existing tables and drop old tables in export
Choose columns in select, aggregation
Order rows by clicking on table heading
Truncate only search results
Automatically select name for trigger
Chinese and French translation
Preserve default values when altering table
Maintain auto_increment when moving columns
Smaller multilingual file
Cache static files
Faster checking of number of results
phpMinAdmin 1.6.1 (released 2008-05-22):
Set session parameters only if not session.auto_start
phpMinAdmin 1.6.0 (released 2008-05-16):
Order of columns in table
Set max_allowed_packet in dump and use extended insert
Spanish and German translations
Use images for editing buttons
Protection against big POST data
Logout by POST
Information about logged user
Separate stylesheet
Last-Modified header for files
Several bug fixes
phpMinAdmin 1.5.0 (released 2008-01-09):
Mass delete
Vertical privileges
Specify connection port by colon in server
Ignore length in date and time types
Boolean fulltext search for all columns in MyISAM
Shrink compiled output
Remove maxlength from server and username
Uncheck NULL by change
Mark shortened fields in select
phpMinAdmin 1.4.0 (released 2007-08-15):
Privileges
New design
Dutch translation
Use NULL for auto_increment (bug #1)
Fix dropping procedure parameters
phpMinAdmin 1.3.2 (released 2007-08-06):
Next field by JavaScript in foreign keys
Set time zone in dump
Refresh lang cookie
Remember drop result in case of faulty create
Move vertical lines in schema properly
Fix maximum page in select
phpMinAdmin 1.3.1 (released 2007-07-31):
Move references lines in schema
Fix dump
Fix update links
phpMinAdmin 1.3.0 (released 2007-07-27):
Breadcrumb navigation
Operator IN
Timestamp default values
Draggable tables in schema
Number of rows in navigation
Display MySQL version and used PHP extension
More friendly user interface
Slovak translation
phpMinAdmin 1.2.0 (released 2007-07-25):
Manipulate triggers
PDO Abstraction
Auto_increment value
JavaScript for adding rows
phpMinAdmin 1.1.0 (released 2007-07-19):
Routines manipulation
Views manipulation
Foreign keys manipulation
Database schema with references
Processlist
Index length
Dump individual tables
JavaScript for next rows in table edit
Cache databases list
phpMinAdmin 1.0.0 (released 2007-07-11):
First official release

View File

@@ -6,9 +6,18 @@ function adminer_errors($errno, $errstr) {
error_reporting(6135); // errors and warnings error_reporting(6135); // errors and warnings
set_error_handler('adminer_errors', E_WARNING); set_error_handler('adminer_errors', E_WARNING);
include dirname(__FILE__) . "/adminer/include/debug.inc.php";
include dirname(__FILE__) . "/adminer/include/version.inc.php"; include dirname(__FILE__) . "/adminer/include/version.inc.php";
include dirname(__FILE__) . "/vendor/vrana/jsshrink/jsShrink.php"; include dirname(__FILE__) . "/vendor/vrana/jsshrink/jsShrink.php";
function is_dev_version()
{
global $VERSION;
return (bool)preg_match('~-dev$~', $VERSION);
}
function add_apo_slashes($s) { function add_apo_slashes($s) {
return addcslashes($s, "\\'"); return addcslashes($s, "\\'");
} }
@@ -21,85 +30,85 @@ function add_quo_slashes($s) {
return $return; return $return;
} }
function remove_lang($match) { function replace_lang($match) {
global $translations;
$idf = strtr($match[2], array("\\'" => "'", "\\\\" => "\\"));
$s = ($translations[$idf] ? $translations[$idf] : $idf);
if ($match[3] == ",") { // lang() has parameters
return $match[1] . (is_array($s) ? "lang(array('" . implode("', '", array_map('add_apo_slashes', $s)) . "')," : "sprintf('" . add_apo_slashes($s) . "',");
}
return ($match[1] && $match[4] ? $s : "$match[1]'" . add_apo_slashes($s) . "'$match[4]");
}
function lang_ids($match) {
global $lang_ids; global $lang_ids;
$lang_id = &$lang_ids[stripslashes($match[1])];
if ($lang_id === null) { $text = stripslashes($match[1]);
$lang_id = count($lang_ids) - 1; if (!isset($lang_ids[$text])) {
$lang_ids[$text] = count($lang_ids);
} }
return ($_SESSION["lang"] ? $match[0] : "lang($lang_id$match[2]");
return "lang($lang_ids[$text]$match[2]";
} }
function put_file($match) { function put_file($match) {
global $project, $VERSION, $driver; global $project, $selected_languages, $single_driver;
if (basename($match[2]) == '$LANG.inc.php') {
return $match[0]; // processed later
}
$return = file_get_contents(dirname(__FILE__) . "/$project/$match[2]");
if (basename($match[2]) == "file.inc.php") {
$return = str_replace("\n// caching headers added in compile.php", (preg_match('~-dev$~', $VERSION) ? '' : '
if ($_SERVER["HTTP_IF_MODIFIED_SINCE"]) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 365*24*60*60) . " GMT"); $filename = basename($match[2]);
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: immutable"); // Language is processed later.
'), $return, $count); if ($filename == '$LANG.inc.php') {
return $match[0];
}
$content = file_get_contents(dirname(__FILE__) . "/$project/$match[2]");
if ($filename == "file.inc.php") {
$content = str_replace("\n// caching headers added in compile.php", (is_dev_version() ? '' : '
if ($_SERVER["HTTP_IF_MODIFIED_SINCE"]) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 365*24*60*60) . " GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: immutable");
'), $content, $count);
if (!$count) { if (!$count) {
echo "adminer/file.inc.php: Caching headers placeholder not found\n"; echo "adminer/file.inc.php: Caching headers placeholder not found\n";
} }
} }
if ($driver && dirname($match[2]) == "../adminer/drivers") {
$return = preg_replace('~^if \(isset\(\$_GET\["' . $driver . '"]\)\) \{(.*)^}~ms', '\1', $return);
}
if (basename($match[2]) != "lang.inc.php" || !$_SESSION["lang"]) {
if (basename($match[2]) == "lang.inc.php") {
$return = str_replace('function lang($idf, $number = null) {', 'function lang($idf, $number = null) {
if (is_string($idf)) { // compiled version uses numbers, string comes from a plugin
// English translation is closest to the original identifiers //! pluralized translations are not found
$pos = array_search($idf, get_translations("en")); //! this should be cached
if ($pos !== false) {
$idf = $pos;
}
}', $return, $count);
if (!$count) {
echo "lang() not found\n";
}
}
$tokens = token_get_all($return); // to find out the last token
return "?>\n$return" . (in_array($tokens[count($tokens) - 1][0], array(T_CLOSE_TAG, T_INLINE_HTML), true) ? "<?php" : "");
} elseif (preg_match('~\s*(\$pos = (.+\n).+;)~sU', $return, $match2)) {
// single language lang() is used for plural
return "function get_lang() {
return '$_SESSION[lang]';
}
function lang(\$translation, \$number = null) { if ($filename == "lang.inc.php") {
if (is_array(\$translation)) { $content = str_replace(
\$pos = $match2[2]\t\t\t: " . (preg_match("~\\\$LANG == '$_SESSION[lang]'.* \\? (.+)\n~U", $match2[1], $match3) ? $match3[1] : "1") . ' 'return $key; // compile: convert translation key',
'static $en_translations = null;
// Convert string key used in plugins to compiled numeric key.
if (is_string($key)) {
if (!$en_translations) {
$en_translations = get_translations("en");
}
// Find text in English translations or plurals map.
if (($index = array_search($key, $en_translations)) !== false) {
$key = $index;
} elseif (($index = get_plural_translation_id($key)) !== null) {
$key = $index;
}
}
return $key;',
$content, $count
); );
$translation = $translation[$pos];
} if (!$count) {
$translation = str_replace("%d", "%s", $translation); echo "function lang() not found\n";
$number = format_number($number); }
return sprintf($translation, $number);
} if ($selected_languages) {
'; $available_languages = array_fill_keys($selected_languages, true);
} else { $content = str_replace(
echo "lang() \$pos not found\n"; 'return $languages; // compile: available languages',
'return ' . var_export($available_languages, true) . ';',
$content
);
}
} }
$tokens = token_get_all($content); // to find out the last token
return "?>\n$content" . (in_array($tokens[count($tokens) - 1][0], array(T_CLOSE_TAG, T_INLINE_HTML), true) ? "<?php" : "");
} }
function lzw_compress($string) { function lzw_compress($string) {
@@ -139,45 +148,73 @@ function lzw_compress($string) {
return $return . ($rest_length ? chr($rest << (8 - $rest_length)) : ""); return $return . ($rest_length ? chr($rest << (8 - $rest_length)) : "");
} }
function put_file_lang($match) { function put_file_lang() {
global $lang_ids, $project, $langs; global $lang_ids, $selected_languages;
if ($_SESSION["lang"]) {
return ""; $languages = array_map(function ($filename) {
} preg_match('~/([^/.]+)\.inc\.php$~', $filename, $matches);
$return = ""; return $matches[1];
foreach ($langs as $lang => $val) { }, glob(dirname(__FILE__) . "/adminer/lang/*.inc.php"));
include dirname(__FILE__) . "/adminer/lang/$lang.inc.php"; // assign $translations
$cases = "";
$plurals_map = [];
foreach ($languages as $language) {
// Include only selected language and "en" into single language compilation.
// "en" is used for translations in plugins.
if ($selected_languages && !in_array($language, $selected_languages) && $language != "en") {
continue;
}
// Assign $translations
$translations = [];
include dirname(__FILE__) . "/adminer/lang/$language.inc.php";
$translation_ids = array_flip($lang_ids); // default translation $translation_ids = array_flip($lang_ids); // default translation
foreach ($translations as $key => $val) { foreach ($translations as $key => $val) {
if ($val !== null) { if ($val !== null) {
$translation_ids[$lang_ids[$key]] = implode("\t", (array) $val); $translation_ids[$lang_ids[$key]] = $val;
if ($language == "en" && is_array($val)) {
$plurals_map[$key] = $lang_ids[$key];
}
} }
} }
$return .= '
case "' . $lang . '": $compressed = "' . add_quo_slashes(lzw_compress(implode("\n", $translation_ids))) . '"; break;';
}
$translations_version = crc32($return);
return '$translations = $_SESSION["translations"];
if ($_SESSION["translations_version"] != ' . $translations_version . ') {
$translations = array();
$_SESSION["translations_version"] = ' . $translations_version . ';
}
function get_translations($lang) { $cases .= 'case "' . $language . '": $compressed = "' . add_quo_slashes(lzw_compress(json_encode($translation_ids, JSON_UNESCAPED_UNICODE))) . '"; break;';
switch ($lang) {' . $return . '
} }
$translations = array();
foreach (explode("\n", lzw_decompress($compressed)) as $val) {
$translations[] = (strpos($val, "\t") ? explode("\t", $val) : $val);
}
return $translations;
}
if (!$translations) { $translations_version = crc32($cases);
$translations = get_translations($LANG);
$_SESSION["translations"] = $translations; return '
} function get_translations($lang) {
'; switch ($lang) {' . $cases . '}
return json_decode(lzw_decompress($compressed), true);
}
function get_plural_translation_id($key) {
$plurals_map = ' . var_export($plurals_map, true) . ';
return isset($plurals_map[$key]) ? $plurals_map[$key] : null;
}
$translations = $_SESSION["translations"];
if ($_SESSION["translations_version"] != ' . $translations_version . ') {
$translations = [];
$_SESSION["translations_version"] = ' . $translations_version . ';
}
if ($_SESSION["translations_language"] != $LANG) {
$translations = [];
$_SESSION["translations_language"] = $LANG;
}
if (!$translations) {
$translations = get_translations($LANG);
$_SESSION["translations"] = $translations;
}
';
} }
function short_identifier($number, $chars) { function short_identifier($number, $chars) {
@@ -224,7 +261,7 @@ function php_shrink($input) {
} }
$tokens = array_values($tokens); $tokens = array_values($tokens);
foreach ($tokens as $i => $token) { foreach ($tokens as $token) {
if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) { if ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$short_variables[$token[1]]++; $short_variables[$token[1]]++;
} }
@@ -258,7 +295,7 @@ function php_shrink($input) {
$tokens[$i+4] = array(0, ';'); $tokens[$i+4] = array(0, ';');
} }
if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) { if ($token[0] == T_COMMENT || $token[0] == T_WHITESPACE || ($token[0] == T_DOC_COMMENT && $doc_comment)) {
$space = "\n"; $space = " ";
} else { } else {
if ($token[0] == T_DOC_COMMENT) { if ($token[0] == T_DOC_COMMENT) {
$doc_comment = true; $doc_comment = true;
@@ -287,9 +324,13 @@ function php_shrink($input) {
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) { } elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
$token[1] = '$' . $short_variables[$token[1]]; $token[1] = '$' . $short_variables[$token[1]];
} }
if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
if ($token[0] == T_FUNCTION || $token[0] == T_CLASS || $token[0] == T_INTERFACE || $token[0] == T_TRAIT) {
$space = "\n";
} elseif (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
$space = ''; $space = '';
} }
$output .= $space . $token[1]; $output .= $space . $token[1];
$space = ''; $space = '';
} }
@@ -340,60 +381,78 @@ function number_type() {
} }
$project = "adminer"; $project = "adminer";
if ($_SERVER["argv"][1] == "editor") { array_shift($argv);
if ($argv[0] == "editor") {
$project = "editor"; $project = "editor";
array_shift($_SERVER["argv"]); array_shift($argv);
} }
$driver = ""; $selected_drivers = [];
if (file_exists(dirname(__FILE__) . "/adminer/drivers/" . $_SERVER["argv"][1] . ".inc.php")) { if ($argv) {
$driver = $_SERVER["argv"][1]; $params = explode(",", $argv[0]);
array_shift($_SERVER["argv"]); if (file_exists(dirname(__FILE__) . "/adminer/drivers/" . $params[0] . ".inc.php")) {
$selected_drivers = $params;
array_shift($argv);
}
} }
$single_driver = count($selected_drivers) == 1 ? $selected_drivers[0] : null;
unset($_COOKIE["adminer_lang"]); $selected_languages = [];
$_SESSION["lang"] = $_SERVER["argv"][1]; // Adminer functions read language from session if ($argv) {
include dirname(__FILE__) . "/adminer/include/lang.inc.php"; $params = explode(",", $argv[0]);
if (isset($langs[$_SESSION["lang"]])) { if (file_exists(dirname(__FILE__) . "/adminer/lang/" . $params[0] . ".inc.php")) {
include dirname(__FILE__) . "/adminer/lang/$_SESSION[lang].inc.php"; $selected_languages = $params;
array_shift($_SERVER["argv"]); array_shift($argv);
}
} }
$single_language = count($selected_languages) == 1 ? $selected_languages[0] : null;
if ($_SERVER["argv"][1]) { if ($argv) {
echo "Usage: php compile.php [editor] [driver] [lang]\n"; echo "Usage: php compile.php [editor] [driver] [language]\n";
echo "Purpose: Compile adminer[-driver][-lang].php or editor[-driver][-lang].php.\n"; echo "Purpose: Compile adminer[-driver][-lang].php or editor[-driver][-lang].php.\n";
exit(1); exit(1);
} }
// check function definition in drivers // Check function definition in drivers.
$file = file_get_contents(dirname(__FILE__) . "/adminer/drivers/mysql.inc.php"); $file = file_get_contents(dirname(__FILE__) . "/adminer/drivers/mysql.inc.php");
$file = preg_replace('~class Min_Driver.*\n\t}~sU', '', $file); $file = preg_replace('~class Min_Driver.*\n\t}~sU', '', $file);
preg_match_all('~\bfunction ([^(]+)~', $file, $matches); //! respect context (extension, class) preg_match_all('~\bfunction ([^(]+)~', $file, $matches); //! respect context (extension, class)
$functions = array_combine($matches[1], $matches[0]); $functions = array_combine($matches[1], $matches[0]);
//! do not warn about functions without declared support() //! do not warn about functions without declared support()
unset($functions["__construct"], $functions["__destruct"], $functions["set_charset"]); unset($functions["__construct"], $functions["__destruct"], $functions["set_charset"]);
foreach (glob(dirname(__FILE__) . "/adminer/drivers/" . ($driver ? $driver : "*") . ".inc.php") as $filename) {
if ($filename != "mysql.inc.php") { foreach (glob(dirname(__FILE__) . "/adminer/drivers/*.inc.php") as $filename) {
$file = file_get_contents($filename); preg_match('~/([^/.]+)\.inc\.php$~', $filename, $matches);
foreach ($functions as $val) { if ($matches[1] == "mysql" || ($selected_drivers && !in_array($matches[1], $selected_drivers))) {
if (!strpos($file, "$val(")) { continue;
fprintf(STDERR, "Missing $val in $filename\n"); }
}
$file = file_get_contents($filename);
foreach ($functions as $function) {
if (!strpos($file, "$function(")) {
fprintf(STDERR, "Missing $function in $filename\n");
} }
} }
} }
include dirname(__FILE__) . "/adminer/include/pdo.inc.php"; include dirname(__FILE__) . "/adminer/include/pdo.inc.php";
include dirname(__FILE__) . "/adminer/include/driver.inc.php"; include dirname(__FILE__) . "/adminer/include/driver.inc.php";
$features = array("call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view");
$lang_ids = array(); // global variable simplifies usage in a callback function $features = ["call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view"];
$lang_ids = []; // global variable simplifies usage in a callback functions
// Start with index.php.
$file = file_get_contents(dirname(__FILE__) . "/$project/index.php"); $file = file_get_contents(dirname(__FILE__) . "/$project/index.php");
if ($driver) {
$_GET[$driver] = true; // to load the driver // Remove including source code for unsupported features in single-driver file.
include_once dirname(__FILE__) . "/adminer/drivers/$driver.inc.php"; if ($single_driver) {
$_GET[$single_driver] = true; // to load the driver
include_once dirname(__FILE__) . "/adminer/drivers/$single_driver.inc.php";
foreach ($features as $key => $feature) { foreach ($features as $key => $feature) {
if (!support($feature)) { if (!support($feature)) {
if (!is_int($key)) { if (is_string($key)) {
$feature = $key; $feature = $key;
} }
$file = str_replace("} elseif (isset(\$_GET[\"$feature\"])) {\n\tinclude \"./$feature.inc.php\";\n", "", $file); $file = str_replace("} elseif (isset(\$_GET[\"$feature\"])) {\n\tinclude \"./$feature.inc.php\";\n", "", $file);
@@ -403,55 +462,70 @@ if ($driver) {
$file = str_replace("if (isset(\$_GET[\"callf\"])) {\n\t\$_GET[\"call\"] = \$_GET[\"callf\"];\n}\nif (isset(\$_GET[\"function\"])) {\n\t\$_GET[\"procedure\"] = \$_GET[\"function\"];\n}\n", "", $file); $file = str_replace("if (isset(\$_GET[\"callf\"])) {\n\t\$_GET[\"call\"] = \$_GET[\"callf\"];\n}\nif (isset(\$_GET[\"function\"])) {\n\t\$_GET[\"procedure\"] = \$_GET[\"function\"];\n}\n", "", $file);
} }
} }
// Compile files included into the index.php.
$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); $file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file);
// Remove including debug files.
$file = str_replace('include "../adminer/include/debug.inc.php";', '', $file);
$file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file); $file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file);
if ($driver) {
$file = preg_replace('(include "../adminer/drivers/(?!' . preg_quote($driver) . '\.).*\s*)', '', $file); // Remove including unwanted drivers.
if ($selected_drivers) {
$file = preg_replace_callback('~include "../adminer/drivers/([^.]+).*\n~', function ($match) use ($selected_drivers) {
return in_array($match[1], $selected_drivers) ? $match[0] : "";
}, $file);
} }
$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php
if ($driver) { // Compile files included into the bootstrap.inc.php.
$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file);
if ($single_driver) {
// Remove source code for unsupported features.
foreach ($features as $feature) { foreach ($features as $feature) {
if (!support($feature)) { if (!support($feature)) {
$file = preg_replace("((\t*)" . preg_quote('if (support("' . $feature . '")') . ".*\n\\1\\})sU", '', $file); $file = preg_replace("((\t*)" . preg_quote('if (support("' . $feature . '")') . ".*\n\\1\\})sU", '', $file);
} }
} }
if (count($drivers) == 1) {
$file = str_replace('<?php echo html_select("auth[driver]", $drivers, DRIVER) . "\n"; ?>', "<input type='hidden' name='auth[driver]' value='" . ($driver == "mysql" ? "server" : $driver) . "'>" . reset($drivers), $file); $file = preg_replace('(;\.\./vendor/vrana/jush/modules/jush-(?!textarea\.|txt\.|js\.|' . preg_quote($single_driver == "mysql" ? "sql" : $single_driver) . '\.)[^.]+.js)', '', $file);
} $file = preg_replace_callback('~doc_link\(array\((.*)\)\)~sU', function ($match) use ($single_driver) {
$file = preg_replace('(;\.\./vendor/vrana/jush/modules/jush-(?!textarea\.|txt\.|js\.|' . preg_quote($driver == "mysql" ? "sql" : $driver) . '\.)[^.]+.js)', '', $file);
$file = preg_replace_callback('~doc_link\(array\((.*)\)\)~sU', function ($match) use ($driver) {
list(, $links) = $match; list(, $links) = $match;
$links = preg_replace("~'(?!(" . ($driver == "mysql" ? "sql|mariadb" : $driver) . ")')[^']*' => [^,]*,?~", '', $links); $links = preg_replace("~'(?!(" . ($single_driver == "mysql" ? "sql|mariadb" : $single_driver) . ")')[^']*' => [^,]*,?~", '', $links);
return (trim($links) ? "doc_link(array($links))" : "''"); return (trim($links) ? "doc_link(array($links))" : "''");
}, $file); }, $file);
//! strip doc_link() definition //! strip doc_link() definition
} }
if ($project == "editor") { if ($project == "editor") {
$file = preg_replace('~;\.\./vendor/vrana/jush/jush\.css~', '', $file); $file = preg_replace('~;\.\./vendor/vrana/jush/jush\.css~', '', $file);
$file = preg_replace('~compile_file\(\'\.\./(vendor/vrana/jush/modules/jush\.js|adminer/static/[^.]+\.gif)[^)]+\)~', "''", $file); $file = preg_replace('~compile_file\(\'\.\./(vendor/vrana/jush/modules/jush\.js|adminer/static/[^.]+\.gif)[^)]+\)~', "''", $file);
} }
$file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file);
$file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'replace_lang', $file);
$file = preg_replace_callback('~\b(include|require) "([^"]*\$LANG.inc.php)";~', 'put_file_lang', $file); $file = preg_replace_callback('~\b(include|require) "([^"]*\$LANG.inc.php)";~', 'put_file_lang', $file);
$file = str_replace("\r", "", $file); $file = str_replace("\r", "", $file);
if ($_SESSION["lang"]) { $file = str_replace('<?php echo script_src("static/editing.js?" . filemtime("../adminer/static/editing.js")); ?>' . "\n", "", $file);
// single language version
$file = preg_replace_callback("~(<\\?php\\s*echo )?lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])(;\\s*\\?>)?~s", 'remove_lang', $file);
$file = str_replace("<?php switch_lang(); ?>\n", "", $file);
$file = str_replace('<?php echo $LANG; ?>', $_SESSION["lang"], $file);
}
$file = str_replace('<?php echo script_src("static/editing.js"); ?>' . "\n", "", $file);
$file = preg_replace('~\s+echo script_src\("\.\./vendor/vrana/jush/modules/jush-(textarea|txt|js|\$jush)\.js"\);~', '', $file); $file = preg_replace('~\s+echo script_src\("\.\./vendor/vrana/jush/modules/jush-(textarea|txt|js|\$jush)\.js"\);~', '', $file);
$file = str_replace('<link rel="stylesheet" type="text/css" href="../vendor/vrana/jush/jush.css">' . "\n", "", $file); $file = str_replace('<link rel="stylesheet" type="text/css" href="../vendor/vrana/jush/jush.css">' . "\n", "", $file);
$file = preg_replace_callback("~compile_file\\('([^']+)'(?:, '([^']*)')?\\)~", 'compile_file', $file); // integrate static files $file = preg_replace_callback("~compile_file\\('([^']+)'(?:, '([^']*)')?\\)~", 'compile_file', $file); // integrate static files
$replace = 'preg_replace("~\\\\\\\\?.*~", "", ME) . "?file=\1&version=' . substr(md5(microtime()), 0, 8) . '"'; $replace = 'preg_replace("~\\\\\\\\?.*~", "", ME) . "?file=\1&version=' . substr(md5(microtime()), 0, 8) . '"';
$file = preg_replace('~\.\./adminer/static/(default\.css|favicon\.ico)~', '<?php echo h(' . $replace . '); ?>', $file); $file = preg_replace('~\.\./adminer/static/(favicon\.ico)~', '<?php echo h(' . $replace . '); ?>', $file);
$file = preg_replace('~"\.\./adminer/static/(functions\.js)"~', $replace, $file); $file = preg_replace('~\.\./adminer/static/(default\.css)\?.*default.css"\);\s+\?>~', '<?php echo h(' . $replace . '); ?>', $file);
$file = preg_replace('~"\.\./adminer/static/(functions\.js)\?".*functions.js"\)~', $replace, $file);
$file = preg_replace('~\.\./adminer/static/([^\'"]*)~', '" . h(' . $replace . ') . "', $file); $file = preg_replace('~\.\./adminer/static/([^\'"]*)~', '" . h(' . $replace . ') . "', $file);
$file = preg_replace('~"\.\./vendor/vrana/jush/modules/(jush\.js)"~', $replace, $file); $file = preg_replace('~"\.\./vendor/vrana/jush/modules/(jush\.js)"~', $replace, $file);
$file = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $file); $file = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $file);
$file = php_shrink($file); $file = php_shrink($file);
@mkdir("temp/export", 0777, true); @mkdir("temp", 0777, true);
$filename = "temp/export/$project" . (preg_match('~-dev$~', $VERSION) ? "" : "-$VERSION") . ($driver ? "-$driver" : "") . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php"; $filename = "temp/$project"
. (is_dev_version() ? "" : "-$VERSION")
. ($single_driver ? "-$single_driver" : "")
. ($single_language ? "-$single_language" : "")
. ".php";
file_put_contents($filename, $file); file_put_contents($filename, $file);
echo "$filename created (" . strlen($file) . " B).\n"; echo "$filename created (" . strlen($file) . " B).\n";

View File

@@ -1,19 +1,22 @@
{ {
"name": "vrana/adminer", "name": "pematon/adminer",
"description": "Database management in a single PHP file.", "description": "Database management in a single PHP file.",
"homepage": "https://www.adminer.org/", "homepage": "https://github.com/pematon/adminer",
"keywords": [ "keywords": [
"database" "database"
], ],
"support": { "support": {
"issues": "https://sourceforge.net/p/adminer/bugs-and-features/", "issues": "https://github.com/pematon/adminer/issues",
"forum": "https://sourceforge.net/p/adminer/discussion/", "forum": "https://github.com/pematon/adminer/discussions",
"source": "https://github.com/vrana/adminer/" "source": "https://github.com/pematon/adminer"
}, },
"authors": [ "authors": [
{ {
"name": "Jakub Vrána", "name": "Jakub Vrána",
"homepage": "https://www.vrana.cz/" "homepage": "https://www.vrana.cz/"
},
{
"name": "Peter Knut"
} }
], ],
"autoload": { "autoload": {
@@ -29,7 +32,7 @@
"php": "5.6 - 8.3", "php": "5.6 - 8.3",
"ext-pdo": "*", "ext-pdo": "*",
"ext-json": "*", "ext-json": "*",
"vrana/jush": "@dev", "vrana/jush": "2.0.*",
"vrana/jsshrink": "@dev" "vrana/jsshrink": "@dev"
}, },
"suggest": { "suggest": {
@@ -39,6 +42,7 @@
"ext-mysql": "*", "ext-mysql": "*",
"ext-pgsql": "*", "ext-pgsql": "*",
"ext-mongo": "*", "ext-mongo": "*",
"ext-mongodb": "*",
"ext-sqlsrv": "*", "ext-sqlsrv": "*",
"ext-mssql": "*", "ext-mssql": "*",
"ext-oci8": "*", "ext-oci8": "*",
@@ -57,7 +61,7 @@
"repositories": [ "repositories": [
{ {
"type": "vcs", "type": "vcs",
"url": "https://github.com/vrana/jush.git" "url": "https://github.com/pematon/jush.git"
}, },
{ {
"type": "vcs", "type": "vcs",

View File

@@ -62,7 +62,7 @@ if (!extension_loaded("xdebug")) {
if (file_exists($coverage_filename)) { if (file_exists($coverage_filename)) {
// display list of files // display list of files
$coverage = unserialize(file_get_contents($coverage_filename)); $coverage = unserialize(file_get_contents($coverage_filename));
echo "<table border='1' cellspacing='0'>\n"; echo "<table>\n";
foreach (array_merge(glob("adminer/*.php"), glob("adminer/include/*.php"), glob("editor/*.php"), glob("editor/include/*.php")) as $filename) { foreach (array_merge(glob("adminer/*.php"), glob("adminer/include/*.php"), glob("editor/*.php"), glob("editor/include/*.php")) as $filename) {
$cov = $coverage[realpath($filename)]; $cov = $coverage[realpath($filename)];
$ratio = 0; $ratio = 0;

14
docs/upgrade.md Normal file
View File

@@ -0,0 +1,14 @@
Upgrade guide
=============
Migrating to 4.10
-----------------
- Remove plugin AdminerTablesFilter (plugins/tables-filter.php) if you use it. Its functionality was integrated into the
base code.
- If you use complex custom theme, you will probably need to adjust a thing or two.
Migrating to 4.9
----------------
- Minimum required PHP version is 5.6.

View File

@@ -11,11 +11,11 @@ if ($adminer->homepage()) {
echo "<table cellspacing='0' class='nowrap checkable'>\n"; echo "<table cellspacing='0' class='nowrap checkable'>\n";
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});"); echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo '<thead><tr class="wrap">'; echo '<thead><tr class="wrap">';
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("qs('#check-all').onclick = partial(formCheck, /^tables\[/);", ""); echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("gid('check-all').onclick = partial(formCheck, /^tables\[/);", "");
echo '<th>' . lang('Table'); echo '<th>' . lang('Table');
echo '<td>' . lang('Rows'); echo '<td>' . lang('Rows');
echo "</thead>\n"; echo "</thead>\n";
foreach (table_status() as $table => $row) { foreach (table_status() as $table => $row) {
$name = $adminer->tableName($row); $name = $adminer->tableName($row);
if (isset($row["Engine"]) && $name != "") { if (isset($row["Engine"]) && $name != "") {
@@ -25,7 +25,7 @@ if ($adminer->homepage()) {
echo "<td align='right'><a href='" . h(ME . "edit=") . urlencode($table) . "'>" . ($row["Engine"] == "InnoDB" && $val ? "~ $val" : $val) . "</a>"; echo "<td align='right'><a href='" . h(ME . "edit=") . urlencode($table) . "'>" . ($row["Engine"] == "InnoDB" && $val ? "~ $val" : $val) . "</a>";
} }
} }
echo "</table>\n"; echo "</table>\n";
echo "</div>\n"; echo "</div>\n";
echo "</form>\n"; echo "</form>\n";

View File

@@ -1,10 +1,12 @@
<?php <?php
class Adminer { class Adminer {
var $operators = array("<=", ">="); var $operators = array("<=", ">=");
var $operator_like = null;
var $operator_regexp = null;
var $_values = array(); var $_values = array();
function name() { function name() {
return "<a href='https://www.adminer.org/editor/'" . target_blank() . " id='h1'>" . lang('Editor') . "</a>"; return "<a id='h1' href='" . h(HOME_URL) . "'>" . lang('Editor') . "</a>";
} }
//! driver, ns //! driver, ns
@@ -16,8 +18,11 @@ class Adminer {
function connectSsl() { function connectSsl() {
} }
/**
* @throws \Random\RandomException
*/
function permanentLogin($create = false) { function permanentLogin($create = false) {
return password_file($create); return get_private_key($create);
} }
function bruteForceKey() { function bruteForceKey() {
@@ -72,7 +77,7 @@ class Adminer {
function loginForm() { function loginForm() {
echo "<table cellspacing='0' class='layout'>\n"; echo "<table cellspacing='0' class='layout'>\n";
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input type="hidden" name="auth[driver]" value="server"><input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(qs('#username'));")); echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input type="hidden" name="auth[driver]" value="mysql"><input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(gid('username'));"));
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">' . "\n"); echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">' . "\n");
echo "</table>\n"; echo "</table>\n";
echo "<p><input type='submit' value='" . lang('Login') . "'>\n"; echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
@@ -259,15 +264,20 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
if (($val["col"] == "" || $columns[$val["col"]]) && "$val[col]$val[val]" != "") { if (($val["col"] == "" || $columns[$val["col"]]) && "$val[col]$val[val]" != "") {
echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>"; echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>";
echo html_select("where[$i][op]", array(-1 => "") + $this->operators, $val["op"]); echo html_select("where[$i][op]", array(-1 => "") + $this->operators, $val["op"]);
echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>" . script("mixin(qsl('input'), {onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", "") . "</div>\n"; echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>" . script("mixin(qsl('input'), {onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", "");
echo " <input type='image' src='../adminer/static/cross.gif' class='jsonly icon remove' title='" . h(lang('Remove')) . "' alt='x'>" . script('qsl("#fieldset-search .remove").onclick = selectRemoveRow;', "");
echo "</div>\n";
$i++; $i++;
} }
} }
echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>"; echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
echo script("qsl('select').onchange = selectAddRow;", ""); echo script("qsl('select').onchange = selectAddRow;", "");
echo html_select("where[$i][op]", array(-1 => "") + $this->operators); echo html_select("where[$i][op]", array(-1 => "") + $this->operators);
echo "<input type='search' name='where[$i][val]'></div>"; echo "<input type='search' name='where[$i][val]'>";
echo script("mixin(qsl('input'), {onchange: function () { this.parentNode.firstChild.onchange(); }, onsearch: selectSearchSearch});"); echo script("mixin(qsl('input'), {onchange: function () { this.parentNode.firstChild.onchange(); }, onsearch: selectSearchSearch});");
echo " <input type='image' src='../adminer/static/cross.gif' class='jsonly icon remove' title='" . h(lang('Remove')) . "' alt='x'>";
echo script('qsl("#fieldset-search .remove").onclick = selectRemoveRow;', "");
echo "</div>";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
} }
@@ -350,10 +360,10 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
$op = $where["op"]; $op = $where["op"];
$val = $where["val"]; $val = $where["val"];
if (($key < 0 ? "" : $col) . $val != "") { if (($key >= 0 && $col != "") || $val != "") {
$conds = array(); $conds = [];
foreach (($col != "" ? array($col => $fields[$col]) : $fields) as $name => $field) { foreach (($col != "" ? [$col => $fields[$col]] : $fields) as $name => $field) {
if ($col != "" || is_numeric($val) || !preg_match(number_type(), $field["type"])) { if ($col != "" || is_numeric($val) || !preg_match(number_type(), $field["type"])) {
$name = idf_escape($name); $name = idf_escape($name);
@@ -480,7 +490,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
return $return; return $return;
} }
function editInput($table, $field, $attrs, $value) { function editInput($table, $field, $attrs, $value, $function) {
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "") return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
. enum_input("radio", $attrs, $field, ($value || isset($_GET["select"]) ? $value : 0), ($field["null"] ? "" : null)) . enum_input("radio", $attrs, $field, ($value || isset($_GET["select"]) ? $value : 0), ($field["null"] ? "" : null))
@@ -508,7 +518,9 @@ qsl('div').onclick = whisperClick;", "")
$hint = lang('[yyyy]-mm-dd') . ($hint ? " [$hint]" : ""); $hint = lang('[yyyy]-mm-dd') . ($hint ? " [$hint]" : "");
} }
if ($hint) { if ($hint) {
return "<input value='" . h($value) . "'$attrs> ($hint)"; //! maxlength return "<input"
. ($function != "now" ? " value='" . h($value) . "'" : " data-last-value='" . h($value) . "'")
. "$attrs> ($hint)"; //! maxlength
} }
if (preg_match('~_(md5|sha1)$~i', $field["field"])) { if (preg_match('~_(md5|sha1)$~i', $field["field"])) {
return "<input type='password' value='" . h($value) . "'$attrs>"; return "<input type='password' value='" . h($value) . "'$attrs>";
@@ -579,6 +591,7 @@ qsl('div').onclick = whisperClick;", "")
} }
function importServerPath() { function importServerPath() {
return null;
} }
function homepage() { function homepage() {
@@ -587,14 +600,26 @@ qsl('div').onclick = whisperClick;", "")
function navigation($missing) { function navigation($missing) {
global $VERSION; global $VERSION;
?> ?>
<h1> <h1>
<?php echo $this->name(); ?> <?php echo $this->name(); ?>
<?php if ($missing != "auth"): ?>
<span class="version"><?php echo $VERSION; ?></span> <?php if ($missing != "auth"): ?>
<a href="https://www.adminer.org/editor/#download"<?php echo target_blank(); ?> id="version"><?php echo (version_compare($VERSION, $_COOKIE["adminer_version"]) < 0 ? h($_COOKIE["adminer_version"]) : ""); ?></a> <span class="version">
<?php echo $VERSION; ?>
<a href="https://github.com/pematon/adminer/releases"<?php echo target_blank(); ?> id="version">
<?php echo (version_compare($VERSION, $_COOKIE["adminer_version"]) < 0 ? h($_COOKIE["adminer_version"]) : ""); ?>
</a>
</span>
<?php
if (!isset($_COOKIE["adminer_version"])) {
echo script("verifyVersion('" . js_escape(ME) . "', '" . get_token() . "');");
}
?>
<?php endif; ?> <?php endif; ?>
</h1> </h1>
<?php <?php
if ($missing == "auth") { if ($missing == "auth") {
$first = true; $first = true;
@@ -603,7 +628,7 @@ qsl('div').onclick = whisperClick;", "")
if ($password !== null) { if ($password !== null) {
if ($first) { if ($first) {
echo "<ul id='logins'>"; echo "<ul id='logins'>";
echo script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});"); echo script("mixin(gid('logins'), {onmouseover: menuOver, onmouseout: menuOut});");
$first = false; $first = false;
} }
echo "<li><a href='" . h(auth_url($vendor, "", $username)) . "'>" . ($username != "" ? h($username) : "<i>" . lang('empty') . "</i>") . "</a>\n"; echo "<li><a href='" . h(auth_url($vendor, "", $username)) . "'>" . ($username != "" ? h($username) : "<i>" . lang('empty') . "</i>") . "</a>\n";
@@ -617,6 +642,7 @@ qsl('div').onclick = whisperClick;", "")
if (!$table_status) { if (!$table_status) {
echo "<p class='message'>" . lang('No tables.') . "\n"; echo "<p class='message'>" . lang('No tables.') . "\n";
} else { } else {
$this->printTablesFilter();
$this->tablesPrint($table_status); $this->tablesPrint($table_status);
} }
} }
@@ -626,19 +652,32 @@ qsl('div').onclick = whisperClick;", "")
function databasesPrint($missing) { function databasesPrint($missing) {
} }
function printTablesFilter()
{
global $adminer;
echo "<div class='tables-filter jsonly'>"
. "<input id='tables-filter' autocomplete='off' placeholder='" . lang('Table') . "'>"
. script("initTablesFilter(" . json_encode($adminer->database()) . ");")
. "</div>\n";
}
function tablesPrint($tables) { function tablesPrint($tables) {
echo "<ul id='tables'>"; echo "<ul id='tables'>" . script("mixin(gid('tables'), {onmouseover: menuOver, onmouseout: menuOut});");
echo script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $row) { foreach ($tables as $row) {
echo '<li>'; // Skip views and tables without a name.
$name = $this->tableName($row); if (!isset($row["Engine"]) || ($name = $this->tableName($row)) == "") {
if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name continue;
echo "<a href='" . h(ME) . 'select=' . urlencode($row["Name"]) . "'"
. bold($_GET["select"] == $row["Name"] || $_GET["edit"] == $row["Name"], "select")
. " title='" . lang('Select data') . "'>$name</a>\n"
;
} }
$active = $_GET["select"] == $row["Name"] || $_GET["edit"] == $row["Name"];
echo '<li><a href="' . h(ME) . 'select=' . urlencode($row["Name"]) . '"'
. bold($active, "select")
. " title='" . lang('Select data') . "' data-main='true'>$name</a></li>\n";
} }
echo "</ul>\n"; echo "</ul>\n";
} }
@@ -652,6 +691,8 @@ qsl('div').onclick = whisperClick;", "")
} }
} }
} }
return null;
} }
function _foreignKeyOptions($table, $column, $value = null) { function _foreignKeyOptions($table, $column, $value = null) {

View File

@@ -17,7 +17,7 @@ function email_header($header) {
* @return bool * @return bool
*/ */
function send_mail($email, $subject, $message, $from = "", $files = array()) { function send_mail($email, $subject, $message, $from = "", $files = array()) {
$eol = (DIRECTORY_SEPARATOR == "/" ? "\n" : "\r\n"); // PHP_EOL available since PHP 5.0.2 $eol = "\r\n";
$message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$message\n"))); $message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$message\n")));
$boundary = uniqid("boundary"); $boundary = uniqid("boundary");
$attachments = ""; $attachments = "";

View File

@@ -1,11 +1,14 @@
<?php <?php
/** Adminer Editor - Compact database editor /**
* @link https://www.adminer.org/ * Adminer Editor - Compact database editor for end-users
* @author Jakub Vrana, https://www.vrana.cz/ *
* @copyright 2009 Jakub Vrana * @link https://github.com/pematon/adminer
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @author Jakub Vrana (https://www.vrana.cz/)
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) * @author Peter Knut
*/ * @copyright 2009-2021 Jakub Vrana, 2024 Peter Knut
* @license Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
* @license GNU General Public License, version 2 (https://www.gnu.org/licenses/gpl-2.0.html)
*/
include "../adminer/include/bootstrap.inc.php"; include "../adminer/include/bootstrap.inc.php";
$drivers[DRIVER] = lang('Login'); $drivers[DRIVER] = lang('Login');

View File

@@ -2,16 +2,16 @@
function adminer_object() { function adminer_object() {
include_once "../plugins/plugin.php"; include_once "../plugins/plugin.php";
include_once "../plugins/login-password-less.php"; include_once "../plugins/login-password-less.php";
class AdminerCustomization extends AdminerPlugin { class AdminerCustomization extends AdminerPlugin {
function loginFormField($name, $heading, $value) { function loginFormField($name, $heading, $value) {
return parent::loginFormField($name, $heading, str_replace('value="server"', 'value="sqlite"', $value)); return parent::loginFormField($name, $heading, str_replace('value="mysql"', 'value="sqlite"', $value));
} }
function database() { function database() {
return "PATH_TO_YOUR_SQLITE_HERE"; return "PATH_TO_YOUR_SQLITE_HERE";
} }
} }
return new AdminerCustomization(array( return new AdminerCustomization(array(
// TODO: inline the result of password_hash() so that the password is not visible in source codes // TODO: inline the result of password_hash() so that the password is not visible in source codes
new AdminerLoginPasswordLess(password_hash("YOUR_PASSWORD_HERE", PASSWORD_DEFAULT)), new AdminerLoginPasswordLess(password_hash("YOUR_PASSWORD_HERE", PASSWORD_DEFAULT)),

View File

@@ -6,13 +6,14 @@ function messagesPrint() {
function selectFieldChange() { function selectFieldChange() {
} }
var helpOpen; // Help.
(function() {
window.initHelpPopup = function () {
};
function helpMouseover() { window.initHelpFor = function(element, content, side = false) {
} };
})();
function helpMouseout() {
}
/** Display typeahead /** Display typeahead
* @param string * @param string
@@ -42,7 +43,7 @@ function whisper(url) {
*/ */
function whisperClick(event) { function whisperClick(event) {
var field = this.previousSibling; var field = this.previousSibling;
var el = getTarget(event); var el = event.target;
if (isTag(el, 'a') && !(event.button || event.shiftKey || event.altKey || isCtrl(event))) { if (isTag(el, 'a') && !(event.button || event.shiftKey || event.altKey || isCtrl(event))) {
field.value = el.firstChild.data; field.value = el.firstChild.data;
field.previousSibling.value = decodeURIComponent(el.href.replace(/.*=/, '')); field.previousSibling.value = decodeURIComponent(el.href.replace(/.*=/, ''));

View File

@@ -5,7 +5,7 @@ unset($_COOKIE["adminer_lang"]);
$_SESSION["lang"] = isset($_SERVER["argv"][1]) ? $_SERVER["argv"][1] : null; // Adminer functions read language from session $_SESSION["lang"] = isset($_SERVER["argv"][1]) ? $_SERVER["argv"][1] : null; // Adminer functions read language from session
if (isset($_SESSION["lang"])) { if (isset($_SESSION["lang"])) {
include dirname(__FILE__) . "/adminer/include/lang.inc.php"; include dirname(__FILE__) . "/adminer/include/lang.inc.php";
if (isset($_SERVER["argv"][2]) || (!isset($langs[$_SESSION["lang"]]) && $_SESSION["lang"] != "xx")) { if (isset($_SERVER["argv"][2]) || (!isset($languages[$_SESSION["lang"]]) && $_SESSION["lang"] != "xx")) {
echo "Usage: php lang.php [lang]\nPurpose: Update adminer/lang/*.inc.php from source code messages.\n"; echo "Usage: php lang.php [lang]\nPurpose: Update adminer/lang/*.inc.php from source code messages.\n";
exit(1); exit(1);
} }

21
plugins/adminer.js.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
/**
* Enables auto-detection and inclusion of adminer.js, like adminer.css
*
* @author Roy Orbitson, https://github.com/Roy-Orbison
*
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerDotJs
{
const FileName = "adminer.js";
function head()
{
if (file_exists(self::FileName)) {
echo script_src(self::FileName . "?v=" . crc32(file_get_contents(self::FileName))), "\n";
}
}
}

View File

@@ -427,6 +427,7 @@ if (isset($_GET["clickhouse"])) {
'structured_types' => $structured_types, 'structured_types' => $structured_types,
'unsigned' => array(), 'unsigned' => array(),
'operators' => array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"), 'operators' => array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"),
'operator_like' => "LIKE %%",
'functions' => array(), 'functions' => array(),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"), 'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array(), 'edit_functions' => array(),

Some files were not shown because too many files have changed in this diff Show More