1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-31 10:01:50 +02:00

Compare commits

..

396 Commits

Author SHA1 Message Date
Jakub Vrana
100a1f49bc Release 5.0.2 2025-03-10 07:18:15 +01:00
Jakub Vrana
47ccd9b44d Add comment 2025-03-09 18:29:02 +01:00
Dragsio
7512bc2d51 Wrap username in <span>
Username enclosed in tags for better use of custom themes (eg. vertical padding).
2025-03-09 18:28:50 +01:00
Jakub Vrana
4991817b0d Extract variable 2025-03-08 23:12:08 +01:00
Peter Knut
e883ad428e Add support for "order" field privilege
In Elasticsearch, text fields are not sortable.
2025-03-08 23:12:00 +01:00
Peter Knut
87d87248c1 Add support for "where" field privilege
In Elasticsearch, only indexed fields are searchable.
2025-03-08 23:05:16 +01:00
Jakub Vrana
862e5b4aa4 Move variable initialization 2025-03-08 21:45:21 +01:00
Jakub Vrana
ad2cbbf26e Use helper function 2025-03-08 19:59:32 +01:00
Jakub Vrana
afe7dd9ad9 Display explain on first click
Also remove extra newlines in explain
2025-03-08 18:18:58 +01:00
Jakub Vrana
3b2ef32349 Add missing namespace to plugin 2025-03-08 17:32:52 +01:00
Jakub Vrana
47b64f4752 Composer: Add script for cleaning 2025-03-08 17:10:21 +01:00
Jakub Vrana
a1c3e34e04 Translations: check fullstops in 'ja' and 'he' 2025-03-08 17:06:30 +01:00
Jakub Vrana
608eec89dd Translations: Add missing placeholders 2025-03-08 10:05:14 +01:00
Jakub Vrana
cfe39e48ca Update xx translation 2025-03-08 10:05:11 +01:00
Jakub Vrana
900a3c0d6a Translations: Fix fullstops 2025-03-08 08:09:29 +01:00
Jakub Vrana
ead6a9a36f Polish: Change link to web 2025-03-08 06:49:32 +01:00
Matthaiks
d05a758a88 Update Polish translation 2025-03-08 06:47:52 +01:00
Jakub Vrana
b0450d0d2a PostgreSQL: Fix setting NULL and original value on enum (bug #884) 2025-03-08 06:44:12 +01:00
Jakub Vrana
e7c3a046a7 Oracle: Fix Db::result 2025-03-08 06:14:26 +01:00
Jakub Vrana
d35c896b92 Add helper function 2025-03-08 06:13:18 +01:00
Jakub Vrana
4b71549ca0 CockroachDB: Add support via PostgreSQL driver
This fixes cockroachdb/cockroach#40391.
2025-03-08 05:56:49 +01:00
Jakub Vrana
ab0f07dd81 Don't create Driver with connection error 2025-03-08 05:37:01 +01:00
Jakub Vrana
c19e6f27f1 Move issues to GitHub 2025-03-07 19:42:21 +01:00
Jakub Vrana
14b257784b Develop 2025-03-07 13:19:34 +01:00
Jakub Vrana
b93d4e2882 Release 5.0.1 2025-03-07 13:17:55 +01:00
Jakub Vrana
28c171f681 PostgreSQL: Support indexes on materialized views (PR #467) 2025-03-07 13:13:58 +01:00
Jakub Vrana
22a544f71c Add missing namespace 2025-03-07 12:50:23 +01:00
Jakub Vrana
2c9f380c64 Elastic: Remove plugin for version 5 2025-03-07 12:17:14 +01:00
Jakub Vrana
9918f4155e Pass credentials to connect() 2025-03-07 12:03:29 +01:00
Jakub Vrana
95e6a65999 Remove duplicate columns from select (bug #670) 2025-03-07 11:36:36 +01:00
Jakub Vrana
94ed6f0e98 MariaDB: Fix link to status variable doc (bug #658) 2025-03-07 11:05:31 +01:00
Jakub Vrana
99eb2f95a5 Develop 2025-03-07 09:41:01 +01:00
Jakub Vrana
8d7cb5954d Release 5.0.0 2025-03-07 09:40:15 +01:00
Jakub Vrana
47700f2763 PostgreSQL: Fix exporting foreign keys 2025-03-07 08:02:06 +01:00
Jakub Vrana
a4a8f48a9c PHPCS: Ignore compiled files 2025-03-07 07:56:35 +01:00
Jakub Vrana
770a77ac33 Wrap long lines 2025-03-07 07:44:26 +01:00
Jakub Vrana
8ceaf36de7 Editor: Fix getting fields 2025-03-07 07:17:05 +01:00
Jakub Vrana
517d2d1c2f MS SQL: Support computed columns 2025-03-07 06:42:27 +01:00
Jakub Vrana
af5d519266 SQLite: Support generated columns 2025-03-07 06:07:25 +01:00
Jakub Vrana
c045b20a8e Allow creating generated columns (bug #857) 2025-03-07 05:18:56 +01:00
Jakub Vrana
874307a27f Fix undefined variable 2025-03-07 04:56:31 +01:00
Jakub Vrana
c27b91a167 MySQL: Drop support for MySQL 4 2025-03-07 03:58:42 +01:00
Jakub Vrana
afe03ef720 MySQL: Display generated value in table structure 2025-03-07 03:58:33 +01:00
Jakub Vrana
c0e2ab22d5 Syntax highlight generated expressions 2025-03-06 19:47:05 +01:00
Jakub Vrana
7351980beb Skip generated columns in multi-edit (bug #882) 2025-03-06 19:32:19 +01:00
Jakub Vrana
7b5a20334d Don't allow inline edit of generated columns 2025-03-06 18:59:20 +01:00
Jakub Vrana
6262b120f5 PostgreSQL: Skip editing generated columns 2025-03-06 18:44:18 +01:00
Jakub Vrana
bd27ca0b2b Add comment 2025-03-06 18:36:26 +01:00
Jakub Vrana
aa7cf70d25 JS: Use || 2025-03-06 18:23:20 +01:00
Jakub Vrana
94a4f61db2 PHP: Use ?: 2025-03-06 18:12:22 +01:00
Jakub Vrana
dc50bf17ea SQLite: Remove useless condition 2025-03-06 17:55:45 +01:00
Jakub Vrana
f05f4b4cbc Change $jush to constant 2025-03-06 17:51:20 +01:00
Jakub Vrana
0541680d73 Move constants to namespace 2025-03-06 17:34:21 +01:00
Jakub Vrana
5a84ff7647 PostgreSQL: Display ? instead of -1 rows in table overview (bug #883) 2025-03-06 17:08:32 +01:00
Jakub Vrana
edd7c67797 Delete incorporated plugin 2025-03-06 14:59:48 +01:00
Jakub Vrana
c6f825a786 Move $enum_length to Driver 2025-03-06 14:51:24 +01:00
Jakub Vrana
f711135574 Move $inout to Driver 2025-03-06 14:49:08 +01:00
Jakub Vrana
2b16f51933 PDO: Support search by expression.
This reverts b848764.
2025-03-06 14:40:13 +01:00
Jakub Vrana
d268e0ebb4 ClickHouse: Check for allow_url_fopen 2025-03-06 14:30:50 +01:00
Jakub Vrana
5fdaae27dc Move possible drivers and JUSH to Driver 2025-03-06 14:27:58 +01:00
Jakub Vrana
049536da90 Mongo: Use $this->_conn 2025-03-06 14:10:05 +01:00
Jakub Vrana
bddce074fa Mongo: Add Driver outside of if 2025-03-06 14:08:19 +01:00
Jakub Vrana
347d9f1f55 Move on_actions to Driver 2025-03-06 14:04:47 +01:00
Jakub Vrana
a8feb00098 Move unsigned to Driver 2025-03-06 13:58:15 +01:00
Jakub Vrana
69d7d76dc5 Move operators, functions and grouping to Driver 2025-03-06 13:51:49 +01:00
Jakub Vrana
2f0cd4185b Move edit functions to Driver 2025-03-06 13:28:04 +01:00
Jakub Vrana
37a75f3759 Move types to Driver 2025-03-06 12:35:20 +01:00
Takashi SHIRAI
d2add4dd72 Fix the primary key for MS SQL
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-03-06 08:54:59 +01:00
Jakub Vrana
f5d47d46a0 Use anonymous function 2025-03-05 17:08:29 +01:00
Jakub Vrana
e8d9a126be Rely on PHP 5.3 2025-03-05 17:05:19 +01:00
Jakub Vrana
12f0a4bc9a Inform about namespace use 2025-03-05 16:54:53 +01:00
Jakub Vrana
d9df9693e3 Code style: Add more checks 2025-03-05 16:33:22 +01:00
Jakub Vrana
873d6d50fd Code style: explain rules 2025-03-05 15:55:33 +01:00
Jakub Vrana
c873ceba17 Use PHP 5.3 functions 2025-03-05 15:54:13 +01:00
Jakub Vrana
0bf8861dd1 Plugins: Use namespace for driver functions 2025-03-05 15:54:08 +01:00
Jakub Vrana
137ac2396b Fix plugin autoloading 2025-03-05 15:39:48 +01:00
Jakub Vrana
755d7b47ac Code style: Check camel caps except in drivers 2025-03-05 15:37:16 +01:00
Jakub Vrana
dd947fc1ee Don't check code style in compiled files 2025-03-05 15:36:25 +01:00
Jakub Vrana
105999f62e Code style: Indent long statements 2025-03-05 15:01:21 +01:00
Jakub Vrana
ed5de27dd3 Code style: Indent long statements 2025-03-05 14:59:13 +01:00
Jakub Vrana
293e031498 Plugins: Add missing namespaces 2025-03-05 14:51:55 +01:00
Jakub Vrana
a7f097e78c Code style: Indent long statements 2025-03-05 14:51:17 +01:00
Jakub Vrana
af68e30742 Code style: Remove newline before } 2025-03-05 14:38:48 +01:00
Jakub Vrana
f820fa1c26 Mark abstract classes 2025-03-05 14:31:53 +01:00
Jakub Vrana
f468c095ae Make root namespace explicit 2025-03-05 14:25:09 +01:00
Jakub Vrana
c10b614ee1 Mongo: inline class names 2025-03-05 14:20:54 +01:00
Jakub Vrana
f5b255230b Don't require namespace in example 2025-03-05 14:15:32 +01:00
Jakub Vrana
54568ddef6 PDO: Support namespaces 2025-03-05 14:15:17 +01:00
Jakub Vrana
3da09dd31a Rename Min_ classes 2025-03-05 14:12:42 +01:00
Jakub Vrana
45ac930e06 Update todo 2025-03-05 13:45:42 +01:00
Jakub Vrana
e801753519 Remove extra newline 2025-03-05 13:45:23 +01:00
Jakub Vrana
a4e9f7b87b Fix tests 2025-03-05 13:31:50 +01:00
Jakub Vrana
35829eedaf Use namespace 2025-03-05 13:31:03 +01:00
Jakub Vrana
44c2e979f7 Compile: Support else after if (support) 2025-03-05 13:19:17 +01:00
Jakub Vrana
2a8b4009b1 Namespaces in compile 2025-03-05 13:14:21 +01:00
Jakub Vrana
6ceebc99df Add namespace in lang.php 2025-03-05 13:10:41 +01:00
Jakub Vrana
2f49bfb67e Return accidentally removed error message 2025-03-05 13:10:41 +01:00
Jakub Vrana
e1e085f312 Use namespace in callbacks 2025-03-05 13:10:40 +01:00
Jakub Vrana
50e7a65e6e Use namespaces in plugins 2025-03-05 13:10:40 +01:00
Jakub Vrana
52c5392089 PHP: Use namespace 2025-03-05 13:10:40 +01:00
Jakub Vrana
5a708df6ca Coding style: Check newline at {} 2025-03-05 13:10:40 +01:00
Jakub Vrana
c52ba0308e Specify coding style and follow it 2025-03-05 13:10:37 +01:00
Jakub Vrana
422668f2d7 Composer: Exclude drivers from classmap 2025-03-05 06:35:54 +01:00
Jakub Vrana
f0335f7f8b Hide Refresh link if it does nothing 2025-03-04 19:58:26 +01:00
Jakub Vrana
cc635acd20 Remove unnecessary function 2025-03-04 19:52:07 +01:00
Jakub Vrana
63dd38c44d PostgreSQL: Compute size of all databases (bug #881) 2025-03-04 19:40:42 +01:00
Jakub Vrana
e411c229ab Fix enum alignment 2025-03-04 18:53:01 +01:00
Jakub Vrana
b9d6529442 Remove margin from td pre 2025-03-04 18:46:28 +01:00
Jakub Vrana
0426bd4610 Designs: Fix logout button 2025-03-04 18:44:40 +01:00
Jakub Vrana
c7d283d262 Designs: Fix background of pre.jush 2025-03-04 18:34:07 +01:00
Jakub Vrana
d61678f5cb Reapply "Fix background color of <pre> used as edit field"
This reverts commit 9b25969fb2.
2025-03-04 18:11:32 +01:00
Jakub Vrana
94088474dd Design bilal-dark: Add missing icons 2025-03-04 18:10:23 +01:00
Jakub Vrana
9b25969fb2 Revert "Fix background color of <pre> used as edit field"
This reverts commit 0717bce535.
2025-03-04 11:04:26 +01:00
Jakub Vrana
996b178406 MySQL: Fix connecting with self-signed cert 2025-03-03 16:06:10 +01:00
Jakub Vrana
116827060f PostgreSQL, MS SQL, Oracle: Hide table actions for information_schema 2025-03-03 15:54:08 +01:00
Jakub Vrana
af87336116 Add TODO 2025-03-03 15:43:04 +01:00
jfonsato
17939b56c4 PostgreSQL: Show only accessible databases 2025-03-03 15:34:43 +01:00
Christian Weiske
d5a17835ff Elastic: Fix text search on boolean fields
When searching in all fields for a text value, an error was thrown
with ElasticSearch 7.17.23 when the index contains boolean fields:

> query_shard_exception: failed to create query:
> Can't parse boolean value [textvalue], expected [true] or [false]

This patch fixes that problem by skipping boolean fields when the
search word is not the string "true" or "false".
2025-03-03 10:40:38 +01:00
Matrixman
4967a40410 New version of design rmSOFT
New version of design rmSOFT
2025-03-03 09:36:21 +01:00
Jan Tojnar
4cdcb44bee Use more [] in doc-comments
Follow up to 42de70d032
2025-03-03 08:39:17 +01:00
Jakub Vrana
160beb726a MS SQL: Link help from sys tables 2025-03-03 08:18:20 +01:00
Jakub Vrana
fb3b23617d Don't autofocus computed fields in insert form 2025-03-03 06:34:02 +01:00
Jakub Vrana
dfe3cc1888 Warn about failed type export 2025-03-03 05:17:00 +01:00
Jakub Vrana
c1704d83c1 Add comment 2025-03-03 05:16:15 +01:00
Jakub Vrana
364a4bce1f Update todo 2025-02-28 17:28:35 +01:00
Jakub Vrana
d9bca2df37 Speed up with disabled output buffering 2025-02-28 15:37:18 +01:00
Jakub Vrana
315ffc9d8b CSV import: Don't unquote " in unquoted values 2025-02-28 14:40:31 +01:00
Denitz
530b3dd1e5 Add Reset button for tables-filter plugin 2025-02-28 13:52:32 +01:00
Jakub Vrana
980c22fe8d MS SQL: Don't insert identity without IDENTITY_INSERT 2025-02-27 09:42:33 +01:00
Jakub Vrana
26d1e51916 PostgreSQL: Display ENUM types 2025-02-27 09:41:31 +01:00
Jakub Vrana
6d889b9f99 Add test for check constraints 2025-02-27 08:26:05 +01:00
Jakub Vrana
7e4ee77cc0 Fix Create table test 2025-02-27 08:10:44 +01:00
Jakub Vrana
742fd7dcb6 Remove <datalist> from tests 2025-02-27 08:09:45 +01:00
Jakub Vrana
d23a0eb77e PostgreSQL: Export ENUM types (bug #587) 2025-02-26 23:55:17 +01:00
Jakub Vrana
5eac6a44bd PostgreSQL: Link enum doc 2025-02-26 23:38:07 +01:00
Jakub Vrana
db300bc38b MS SQL: Specify columns in CSV import 2025-02-26 22:49:22 +01:00
Jakub Vrana
48a680658c MS SQL: Do not update primary key in CSV import 2025-02-26 22:47:16 +01:00
Jakub Vrana
70f9ff75fc MS SQL: Fix CSV import (bug #859) 2025-02-26 22:40:28 +01:00
Jakub Vrana
81340ff7e5 MS SQL: Compute arrays in insertUpdate only once 2025-02-26 22:35:00 +01:00
Jakub Vrana
89b097c699 Don't hide import if there was an error 2025-02-26 22:28:01 +01:00
Jakub Vrana
e075f4bd8b MS SQL: Import all CSV rows with one command 2025-02-26 22:27:43 +01:00
Jakub Vrana
e8fa48a257 MS SQL: Set identity_insert in CSV import 2025-02-26 22:11:41 +01:00
Takashi SHIRAI
0ed3c5cb19 Fix insertUpdate for mssql
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-02-26 22:04:58 +01:00
Jakub Vrana
2f237dfa04 MS SQL export: Create foreign keys after all tables 2025-02-26 21:39:45 +01:00
Jakub Vrana
afdc78a07b PostgreSQL: Sort PRIMARY and UNIQUE indexes first 2025-02-26 21:28:02 +01:00
Jakub Vrana
3dc87c1811 PostgreSQL: Do not alter indexes with expressions 2025-02-26 21:24:47 +01:00
Jakub Vrana
de7bb79132 Remove empty string 2025-02-26 20:01:56 +01:00
Jakub Vrana
f81658ecfe PostgreSQL: Add missing CHECK in export 2025-02-26 19:56:16 +01:00
Jakub Vrana
a603de853d PostgreSQL: Move primary key in export back to table 2025-02-26 19:55:49 +01:00
Jakub Vrana
2998db57d4 PostgreSQL: Print errors in export 2025-02-26 19:37:18 +01:00
Jakub Vrana
9aaa429528 PostgreSQL: Fix export of indexes with expressions (bug #768) 2025-02-26 19:27:19 +01:00
Jakub Vrana
ba70be12a4 PostgreSQL: Fix help link to pg_catalog views 2025-02-26 19:21:13 +01:00
Jakub Vrana
4b47326ffa Use use_sql 2025-02-26 18:47:25 +01:00
Jakub Vrana
848cd482e2 MS SQL: Add support for PDO_SQLSRV extension 2025-02-26 18:08:18 +01:00
Takashi SHIRAI
15cd83fc39 Add seek() to Min_PDOStatement for mssql.
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-02-26 17:43:35 +01:00
Jakub Vrana
4de6e47c0a Use \W in friendly_url() 2025-02-26 16:48:02 +01:00
Jakub Vrana
45f24a8f62 Delete unused functions 2025-02-26 16:48:02 +01:00
Jakub Vrana
cf835515b1 Support compiling Elastic driver 2025-02-26 16:48:02 +01:00
Jakub Vrana
c38b967fc4 Foreign keys: Switch schema back after getting the tables 2025-02-26 16:48:02 +01:00
Jakub Vrana
efb1eb9d6b MS SQL: Remove support for MSSQL extension 2025-02-26 16:48:02 +01:00
Jakub Vrana
ce1031e017 MS SQL: Split altering foreign key to two commands 2025-02-26 16:48:02 +01:00
Jakub Vrana
d54be5ac2e MS SQL: Display foreign keys ON UPDATE and ON DELETE 2025-02-26 16:47:55 +01:00
Jakub Vrana
76cc7c6614 MS SQL: Set identity_insert in export 2025-02-26 16:47:24 +01:00
Jakub Vrana
54dd702763 Fix bug number 2025-02-26 16:47:24 +01:00
Jakub Vrana
dfd26d0704 MS SQL: Support export 2025-02-26 16:47:18 +01:00
Jakub Vrana
0f8460b5e8 PostgreSQL: Use function for exporting constraints 2025-02-26 12:35:25 +01:00
Jakub Vrana
09883aa2f5 SQLite: Remove support for SQLite version 2 2025-02-26 12:20:37 +01:00
Jakub Vrana
e3a2b1b57a SQLite: Support CHECK constraint 2025-02-26 12:20:37 +01:00
Jakub Vrana
a28d95a023 SQLite: Constraint getting view by name to views only 2025-02-26 12:20:37 +01:00
Jakub Vrana
ab025e74a3 SQLite: Display all rows of variable values 2025-02-26 12:20:37 +01:00
Jakub Vrana
8077ef41c1 SQLite: Add command Check tables 2025-02-26 12:20:36 +01:00
Jakub Vrana
9d8864a6c7 Compile: Fix removing single driver login form field 2025-02-26 12:20:36 +01:00
Jakub Vrana
e107ef52d5 Move \n to loginFormField 2025-02-26 12:20:36 +01:00
Jakub Vrana
57ec1f924d Allow compiling driver from plugins 2025-02-26 12:20:36 +01:00
Jakub Vrana
491b481b7f Use __DIR__ 2025-02-26 12:20:36 +01:00
Jakub Vrana
e327d31a08 Hide SQL export if driver doesn't support it 2025-02-26 12:20:34 +01:00
Denitz
708a4e9494 Update table-structure.php 2025-02-25 16:44:25 +01:00
Jakub Vrana
c55ad679ac Use Default setup for CodeQL analysis 2025-02-25 16:41:08 +01:00
Jakub Vrana
dccbdfde97 MongoDB: Remove support for deprecated extension mongo 2025-02-25 15:59:04 +01:00
Jakub Vrana
09091c0dac Develop 2025-02-25 07:32:48 +01:00
Jakub Vrana
bb22a965b2 Release 4.17.1 2025-02-25 07:31:42 +01:00
Jakub Vrana
4f0da70733 Move is_c_style_escapes to Min_Driver 2025-02-25 07:26:08 +01:00
Jakub Vrana
a1235f68ff SQLite: Disable backslash escapes 2025-02-25 07:15:57 +01:00
Jakub Vrana
0138f3b0a5 Oracle: Fix foreign key doc link 2025-02-25 07:09:10 +01:00
Jakub Vrana
192ae38d57 MS SQL: Link doc with current version 2025-02-25 06:58:10 +01:00
Jakub Vrana
620e147b8c Check: Add doc link 2025-02-25 06:54:07 +01:00
Jakub Vrana
644cde4855 MS SQL: Update doc_links 2025-02-25 06:52:27 +01:00
Jakub Vrana
c15576bbf8 Use get_rows() 2025-02-25 06:36:32 +01:00
Jakub Vrana
0d8028ddc5 Compile: Do not warn about functions without declared support 2025-02-25 06:30:22 +01:00
Jakub Vrana
242f5a1ed8 MySQL: Fix typo in the date type (regression from 4.17.0) 2025-02-25 05:41:41 +01:00
Jakub Vrana
d12ea17b17 Remove bogus comment 2025-02-25 05:41:12 +01:00
Jakub Vrana
a7365a50b1 Remove border-collapse: separate in designs after removing cellspacing 2025-02-24 16:41:35 +01:00
Jakub Vrana
b5beffb37c Develop 2025-02-24 12:21:15 +01:00
Jakub Vrana
6b20230d50 Release 4.17.0 2025-02-24 12:20:55 +01:00
Jakub Vrana
836dba07af Warn about missing functions only in single-driver compile 2025-02-24 10:05:31 +01:00
Jakub Vrana
883e0a6619 MySQL 9+: Support vector type 2025-02-23 23:01:43 +01:00
Jakub Vrana
5000e7dc16 Inline function 2025-02-23 18:48:50 +01:00
Jakub Vrana
798432935d PostgreSQL 8+: Fix exporting table constraints 2025-02-23 18:47:11 +01:00
Jakub Vrana
08060f3253 PostgreSQL: Export functions 2025-02-23 18:28:33 +01:00
Jakub Vrana
6d59ed6d7e Fix comment 2025-02-23 18:17:11 +01:00
Jakub Vrana
eb0d5c3c5e Print SQL errors as comments in export 2025-02-23 17:42:23 +01:00
Jakub Vrana
04d707ef94 Anonymous functions require PHP 5.3 2025-02-23 17:07:01 +01:00
Jakub Vrana
004ac1c782 Use less brackets 2025-02-23 17:04:43 +01:00
Jakub Vrana
3ad62d55c8 Show comments at routine call (bug #874) 2025-02-23 16:35:23 +01:00
Jakub Vrana
42de70d032 Use [] in doc-comments 2025-02-23 14:39:14 +01:00
Jakub Vrana
aa2907190e MS SQL: Don't support C-style escapes 2025-02-23 14:39:14 +01:00
Jakub Vrana
5c8b6a3408 Use $connection->result 2025-02-23 14:39:13 +01:00
Jakub Vrana
7f883b9302 Fit number 100 in .size (text length) 2025-02-23 13:40:41 +01:00
Jakub Vrana
27db0914ca Style auto_increment value 2025-02-23 13:40:14 +01:00
Jakub Vrana
483cbf1616 Fix indent 2025-02-23 13:36:37 +01:00
Jakub Vrana
08a956cf2a Offer original values in multi-row editing (regression from 4.16.0) 2025-02-23 13:28:21 +01:00
Jakub Vrana
9d992e4be6 MySQL: Don't offer empty enum value in edit
MySQL errors if there's an invalid value on the first row of INSERT or
UPDATE, regardless of the sql_mode variable.
2025-02-23 13:24:30 +01:00
Jakub Vrana
7ece69a8c4 Remove unused HTLM attribute 2025-02-23 11:42:05 +01:00
Jakub Vrana
1838df9465 Narrows screens: Move lang and logout under h1 2025-02-23 11:25:07 +01:00
Jakub Vrana
4e6ad13eac Move Logout button on narrow screens
This avoids overlapping Logout and breadcrumb.
The button also didn't display on far right due to width: fit-content.
2025-02-23 10:59:56 +01:00
Jakub Vrana
ba35e11bae Ignore error in dropping old constraint 2025-02-23 08:41:33 +01:00
Jakub Vrana
834f4b6c5b Specify viewport width 2025-02-23 08:35:09 +01:00
Jakub Vrana
176f2923cd Fix comment 2025-02-22 23:18:18 +01:00
Jakub Vrana
aaaca731cd MS SQL: Support CHECK constraint 2025-02-22 21:21:47 +01:00
Jakub Vrana
ee9932a0dd PostgreSQL: Support CHECK constraint 2025-02-22 21:08:23 +01:00
Jakub Vrana
c34c672df9 Support constraint checks in compile 2025-02-22 20:40:14 +01:00
Joe Koop
550289de51 MySQL: Support CHECK constraint
added list of check constraints to mysql table view

added create, alter, drop check constraints (mysql)

chore: use the correct function to sql-escape

fix: feature detection for check constraints (mysql)

fix: get check constraint info (mysql)

correct the capitalization of a section title

to be consistent with the other section titles

added a missing `</thead>`
2025-02-22 20:37:59 +01:00
Jakub Vrana
f652ff807e Update CodeQL 2025-02-22 19:01:06 +01:00
Jakub Vrana
746603bdc7 Update tests 2025-02-22 16:31:02 +01:00
Jakub Vrana
e9d9a30844 Use password in example 2025-02-22 16:21:07 +01:00
Jakub Vrana
4d5de895e2 Use new Katalon format 2025-02-22 16:20:31 +01:00
Jakub Vrana
e282ced59e PostgreSQL: Constraint enum values in editing (bug #270) 2025-02-22 13:42:28 +01:00
Jakub Vrana
20d722b882 PostgreSQL: Link user defined types 2025-02-22 12:36:58 +01:00
Jakub Vrana
c1c3b84fff Fix links to PostgreSQL docs 2025-02-22 12:18:14 +01:00
Jakub Vrana
b176a0fbd4 Add TODO 2025-02-22 12:16:15 +01:00
Jakub Vrana
8456779e18 MS SQL: Allow changing default values 2025-02-22 11:08:23 +01:00
Jakub Vrana
3b69ff4ce2 MS SQL: Fix length of nvarchar columns 2025-02-22 10:39:14 +01:00
Jakub Vrana
3a101e873f MS SQL: Allow adding default values 2025-02-22 10:36:44 +01:00
Jakub Vrana
6ecef5eca6 MS SQL: Display default values (bug #732) 2025-02-22 10:11:03 +01:00
Jakub Vrana
707958c63d Remove (beta) from MS SQL 2025-02-22 09:50:20 +01:00
Jakub Vrana
5d18df1d82 MS SQL: Allow altering table in non-default schema (bug #405) 2025-02-22 09:42:36 +01:00
Jakub Vrana
8602304d86 Hide index column options by default 2025-02-22 09:25:39 +01:00
Jakub Vrana
e744fecd98 Make space for the Use button 2025-02-22 08:12:04 +01:00
Jakub Vrana
b58e03f5fc Editor: PDO: Select value of foreign key in edit (bug #847) 2025-02-22 07:56:22 +01:00
Jakub Vrana
40a86bffa2 Add HTML newlines 2025-02-21 21:40:59 +01:00
Jakub Vrana
b7b22486b2 Fix undefined variable in SQL export 2025-02-21 21:35:25 +01:00
Jakub Vrana
cbf7373b54 Wrap long lines in designs 2025-02-21 21:31:58 +01:00
Jakub Vrana
b29767dcfb Use CSS to highlight odd rows 2025-02-21 21:27:41 +01:00
Jakub Vrana
db75be9ba7 Add TODO 2025-02-21 18:40:07 +01:00
Jakub Vrana
67c991846e Hide collations if empty 2025-02-21 18:21:41 +01:00
Jakub Vrana
7d3266b369 MySQL: Fix links to information_schema help 2025-02-21 17:31:56 +01:00
Sebastian Butsch
5f3a820571 Set body width to auto 2025-02-21 17:20:17 +01:00
Jakub Vrana
e7df6bf616 Remove CSS vendor prefixes 2025-02-21 17:01:54 +01:00
Jakub Vrana
1d8bd0a210 Wrap connection error message 2025-02-21 14:29:22 +01:00
Jakub Vrana
6fe9827eea Trim trailing whitespace 2025-02-21 13:59:17 +01:00
Jakub Vrána
7900062d4d Update funding 2025-02-21 11:57:52 +01:00
Jakub Vrana
63cffbbc8a Fix style 2025-02-21 10:57:11 +01:00
Jakub Vrana
0b3baa1e23 Fix Latvian plurals 2025-02-21 09:40:31 +01:00
Jakub Vrana
e3fbc56b6f SQLite: Show all supported pragmas in Variables 2025-02-20 18:11:18 +01:00
Jakub Vrana
00607012af Update TODO 2025-02-20 17:59:02 +01:00
Jakub Vrana
e4e5941b90 Wrap long lines 2025-02-20 17:58:00 +01:00
Jakub Vrana
097f2a1242 Develop 2025-02-20 16:40:14 +01:00
Jakub Vrana
c81bed0baa Fix indent 2025-02-20 16:27:39 +01:00
Jakub Vrana
9c9fc4a85b Release 4.16.0 2025-02-20 15:58:15 +01:00
Jakub Vrana
b46b1dd574 Fix typo in comment 2025-02-20 11:47:38 +01:00
Jakub Vrana
f248fb29b1 PostgreSQL: Support adding auto_increment (bug #761) 2025-02-20 11:13:50 +01:00
Jakub Vrana
94f75f9798 PostgreSQL: Support dropping auto_increment 2025-02-20 11:12:39 +01:00
Jakub Vrana
f2e2c6e4ac SQLite: Fix expressions in default values (bug #860) 2025-02-20 09:37:43 +01:00
Jakub Vrana
e321a26ee5 Move functions unused in Editor 2025-02-20 09:11:59 +01:00
Jakub Vrana
f35dd89c65 Fix style 2025-02-20 08:37:13 +01:00
Bilal Yameen
8f2b4ced62 Dark theme for Adminer 2025-02-19 21:22:57 +01:00
Peter Knut
5eb3446908 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
2025-02-19 21:20:53 +01:00
Peter Knut
a685d414ad Change version layout 2025-02-19 20:47:36 +01:00
Pavel Železný
7c9fec4e6b Fix mysqli ssl without server certificate 2025-02-19 20:17:48 +01:00
araisch
224cbfed56 MySQL SSL: Allow disabling cert verification 2025-02-19 19:20:37 +01:00
Jakub Vrana
490d274662 Update TODO 2025-02-19 19:10:36 +01:00
Peter Knut
3a27c4f64c Editor: Fix searching in tables
Thanks to ytetsuro (https://github.com/vrana/adminer/pull/473)
2025-02-19 19:04:47 +01:00
Jakub Vrana
bd6ebcaab9 Remove spaces 2025-02-19 19:00:47 +01:00
Peter Knut
1f97968e65 PostgreSQL: Allow to set connection's sslmode with AdminerLoginSsl plugin
Thanks to wodka (https://github.com/vrana/adminer/pull/427/files)
2025-02-19 18:54:24 +01:00
Vladimir
dfb33a323d Add .gitattributes, exclude tests from archive 2025-02-19 17:03:34 +01:00
Jakub Vrana
869c2b92ea Remove design submodules 2025-02-19 15:13:46 +01:00
Jakub Vrana
675dbaad73 SQLite: Fix getting result of queries with no rows 2025-02-19 15:06:55 +01:00
Jakub Vrana
a001a3a061 SQLite: Fix altering forign keys (bug #841) 2025-02-19 15:02:11 +01:00
Jakub Vrana
df451f4374 MySQL: Fix saving bit(64) values (bug #839) 2025-02-19 14:57:41 +01:00
Jakub Vrana
9def8d7f95 MS SQL: Foreign keys in non-default schema (bug #833) 2025-02-19 14:36:54 +01:00
Vladimir Goncharov
2385bf72bd support for array values in clickhouse driver 2025-02-19 14:36:07 +01:00
Jakub Vrana
12427467f7 Fix lowercase title 2025-02-19 14:36:07 +01:00
Jakub Vrana
2bec4ca11b Avoid global variables in plugins drivers 2025-02-19 14:36:07 +01:00
panji
e676303a26 MongoDB: Execute commands against the selected DB 2025-02-19 14:36:04 +01:00
Jakub Vrana
9261abc415 PostgreSQL: Preserve whitespace in EXPLAIN (bug #827) 2025-02-19 14:35:19 +01:00
Jakub Vrana
e5c05fe26c Elastic 5: Do not set Content-Type without content 2025-02-19 12:31:44 +01:00
Tim Alexander
21bf7e0570 Fix German Translation Errors 2025-02-19 12:07:19 +01:00
Jakub Vrana
93f04464a2 Oracle: Remove NOT REGEXP (bug #804) 2025-02-19 11:16:46 +01:00
Jakub Vrana
e03713ce2d Add LICENSE 2025-02-19 11:16:46 +01:00
Takashi SHIRAI
2da5683b99 Support to access tablespaces of granted tables
Signed-off-by: Takashi SHIRAI <shirai@nintendo.co.jp>
2025-02-19 11:16:46 +01:00
Jakub Vrana
8ff20622fb Develop 2025-02-19 11:16:46 +01:00
Jakub Vrana
9ef14dbf77 Release 2025-02-19 11:16:46 +01:00
Jakub Vrana
274fa2259b Escape unknown field in select 2025-02-19 11:16:45 +01:00
Jakub Vrana
7541149522 Use Unicode 2025-02-19 11:16:45 +01:00
Jakub Vrana
2a3626faae SimpleDB: Disable XML entity loader 2025-02-19 11:16:45 +01:00
Jakub Vrana
d94e348f57 Use a better random string 2025-02-19 11:16:45 +01:00
Jakub Vrana
51dbfb6987 Hide error message from HTTP servers 2025-02-19 11:16:45 +01:00
Jakub Vrana
578c9fca92 Don't allow path in HTTP servers 2025-02-19 11:16:45 +01:00
Jakub Vrana
d9289355d7 Fix style 2025-02-19 11:16:45 +01:00
Jakub Vrana
874b9ee746 Use autofocus HTML attribute 2025-02-19 11:16:45 +01:00
Jakub Vrana
17974cdf76 VersionNoverify plugin: Do not block other plugins 2025-02-19 11:16:44 +01:00
Jakub Vrana
2d8b6ec771 Add PHP 8.1-8.4 2025-02-19 11:16:44 +01:00
Adrian Jones
5982060f3b Fix links to MySQL docs
It was directing to https://dev.mysql.com/doc/refman/9.2en/select.html instead of https://dev.mysql.com/doc/refman/9.2/en/select.html
2025-02-19 11:16:44 +01:00
Saiful Alam Rakib
6496ff5a47 Fix the UI of pappu687 for latest version 2025-02-19 11:16:44 +01:00
Jakub Vrana
6aa55d806b Bump version 2025-02-19 11:16:44 +01:00
Peter Knut
0ef358a6b5 Release 4.14.0 2025-02-19 11:16:44 +01:00
Peter Knut
882e9d02a0 PostgreSQL: Fix renaming database 2025-02-19 11:16:44 +01:00
Peter Knut
e346f47384 PostgreSQL: Fix starting value of exported autoincrement
Thanks to @OmlineEditor (https://github.com/adminerevo/adminerevo/issues/113)
2025-02-19 11:16:44 +01:00
Peter Knut
fdd02a5485 Modify naming of new foreign rows
Regexp is used to unify implementation with other similar situations. This also prevents false detection in CodeQL security scanning.
2025-02-19 11:16:43 +01:00
Lucas Sandery
7238bc7900 Update lucas-sandery theme
::file-selector-button got standardised.
2025-02-19 11:16:43 +01:00
Peter Knut
15ac0889c0 Bump version to 4.14-dev 2025-02-19 11:16:43 +01:00
Peter Knut
ab40931365 Fix main visual glitches in designs, remove broken designs 2025-02-19 11:16:43 +01:00
Peter Knut
5d6e9fff65 Bump version to 4.12.1-dev 2025-02-19 11:16:43 +01:00
Kian-Meng Ang
d6d86fa26a Fix some typos
https://github.com/adminerevo/adminerevo/pull/210
2025-02-19 11:16:43 +01:00
Peter Knut
f25ffb36f9 Update German translation
Thanks to wintstar (https://github.com/adminerevo/adminerevo/issues/219)
2025-02-19 11:16:43 +01:00
Peter Knut
49fd7858ac Release 4.12 2025-02-19 11:16:43 +01:00
Peter Knut
0628b8de02 MSSQL, MongoDB: Connect to localhost with default port if server is not specified 2025-02-19 11:16:42 +01:00
Peter Knut
99434644ef MongoDB: Fix parsing WHERE condition from SQL query
Thanks to herobank110 (https://github.com/vrana/adminer/pull/491)
2025-02-19 11:16:42 +01:00
vukbgit
5492b3e055 MariaDB: Add support for UUID data type
- MariaDB >= 10.7
- UUID string data type
- uuid() function for UUID type on new/edit item form
2025-02-19 11:16:42 +01:00
Peter Knut
84b69da58d Fix SQL query code direction if RTL language is used 2025-02-19 11:16:42 +01:00
Peter Knut
a51d0f4701 Bump version to 4.12.0-dev 2025-02-19 11:16:42 +01:00
Peter Knut
7cd82c8fd7 Release 4.11 2025-02-19 11:16:42 +01:00
Peter Knut
d065c9ba51 MySQL: Fix highlighting current table in menu on macOS 2025-02-19 11:16:41 +01:00
Peter Knut
f79340a0b5 Update CS and SK translations 2025-02-19 11:16:41 +01:00
HyP3r
4bc9a29f3e MS SQL: Prefix Unicode strings with 'N' so they are treated correctly 2025-02-19 11:16:41 +01:00
Peter Knut
81530227c2 MariaDB: Fix several links to documentation pages 2025-02-19 11:16:41 +01:00
Peter Knut
d8217d6ee2 Bump version to 4.10.1-dev 2025-02-19 11:16:41 +01:00
Peter Knut
02c13131e3 Release 4.10.0 2025-02-19 11:16:41 +01:00
Jakub Vrana
21c339901c PHP <5.6 compatibility 2025-02-19 11:16:41 +01:00
Peter Knut
06c4fd4855 Print username next to the logout button 2025-02-19 11:16:41 +01:00
Peter Knut
0a473cef18 Update readme.txt 2025-02-19 11:16:41 +01:00
Roy-Orbison
652a09bb91 Plugin to auto-include adminer.js when present 2025-02-19 11:16:40 +01:00
Peter Knut
47a9453ace Do not display empty action links in main menu 2025-02-19 11:16:40 +01:00
Peter Knut
d4f99d5cdc Bump version to 4.10-dev 2025-02-19 11:16:40 +01:00
Peter Knut
72ed1b5cdc Release 4.9.4 2025-02-19 11:16:40 +01:00
Peter Knut
4e825a36d3 Editor: Fix building links with array parameters
This solves a situation when enum data type has a foreign key to another table.
2025-02-19 11:16:40 +01:00
Peter Knut
927444ffdd Editor: Fix array conversion to string (issue #3) 2025-02-19 11:16:40 +01:00
Peter Knut
d9976c25fc Firefox: Fix opening a database to the new browser's tab with Ctrl+click 2025-02-19 11:16:40 +01:00
Peter Knut
c5fa212b26 Unify displaying of 'New item' action based on privileges 2025-02-19 11:16:40 +01:00
Peter Knut
edef2b1a3d Fix the width of inline edit field 2025-02-19 11:16:39 +01:00
Peter Knut
7eccd59856 Bump version to 4.9.4-dev 2025-02-19 11:16:39 +01:00
Peter Knut
476b957565 Release 4.9.3 2025-02-19 11:16:39 +01:00
Peter Knut
8e43fffe53 Hide invalid edit form if table record is not found 2025-02-19 11:16:39 +01:00
Peter Knut
d2c6ea21b6 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).
2025-02-19 11:16:39 +01:00
SeaEagle
a310d52327 MySQL: Fix where clause for JSON column
Issue: https://github.com/adminerevo/adminerevo/issues/175
2025-02-19 11:16:39 +01:00
Peter Knut
0717bce535 Fix background color of <pre> used as edit field 2025-02-19 11:16:39 +01:00
Peter Knut
53aad3bb62 Do not include unchanged PARTITION BY definition into ALTER TABLE query 2025-02-19 11:16:39 +01:00
Peter Knut
99cd514a29 MariaDB: Fix comparing CURRENT_TIMESTAMP definition while altering a table 2025-02-19 11:16:39 +01:00
Peter Knut
8ea4892523 MySQL, PostgreSQL: Fix queries splitting and string constants
Thanks to alxivnov (https://github.com/vrana/adminer/pull/490).
2025-02-19 11:16:38 +01:00
Michael Graß
74e4bb9a6f Do not limit unlimited memory, fix number conversion warning 2025-02-19 11:16:38 +01:00
Peter Knut
3d2d39e7d0 Bump version to 4.9.3-dev 2025-02-19 11:16:38 +01:00
Peter Knut
06a4d294bd Release 4.9.2 2025-02-19 11:16:38 +01:00
Peter Knut
0d5e5819a0 Basic JS code cleanup 2025-02-19 11:16:38 +01:00
khoazero123
b17ffcc512 PostgreSQL: Fix exporting CREATE TABLE with sequence default value 2025-02-19 11:16:38 +01:00
Roy-Orbison
d91bd659a5 Function to retrieve driver name
Plugins cannot access $drivers global after compilation.
2025-02-19 11:16:38 +01:00
Peter Knut
1efb87fcbe PostgreSQL: Fix exporting CREATE TABLE query with GENERATED default values
Thanks to GottfriedCP (https://github.com/adminerevo/adminerevo/issues/157)
2025-02-19 11:16:38 +01:00
Peter Knut
d8f1521b60 PostreSQL: Fix search condition for network address types, add macaddr8 type
This fixes issue https://github.com/adminerevo/adminerevo/issues/115
2025-02-19 11:16:38 +01:00
Peter Knut
cb6e2f9a86 Bump version to 4.9.2-dev 2025-02-19 11:16:37 +01:00
Peter Knut
4824c578bf Release 4.9.1 2025-02-19 11:16:37 +01:00
Jakub Vrana
f4607d763c Ignore undefined property PHP warning 2025-02-19 11:16:37 +01:00
Peter Knut
12293ce215 PostgreSQL: Fix documentation link for SERIAL type
Thanks to leggiero (https://github.com/vrana/adminer/pull/432)
2025-02-19 11:16:37 +01:00
caltong
c47d933ab0 PostgreSQL: Make data length calculation more accurate 2025-02-19 11:16:37 +01:00
Thomas Daniels
6e6785ebc4 PostgreSQL: Show only accessible databases 2025-02-19 11:16:37 +01:00
Peter Knut
6d848bf165 Replace deprecated <acronym> with <abbr> 2025-02-19 11:16:37 +01:00
Peter Knut
2189947c43 AdminerLoginOtp: Autocomplete hints for OTP input field, code refactoring
Tanks to SGCBB (https://github.com/vrana/adminer/pull/488)
2025-02-19 11:16:37 +01:00
Sneda8
b6f9f58712 PHP 8.3 error suppression
PHP 8.3 has shortened the array access on null error message to "Trying to access array offset on null". This commit changes the regular expression used to circumvent errors.
2025-02-19 11:16:36 +01:00
Peter Knut
fdeb9557cd Improved displaying of long table names in menu 2025-02-19 11:16:36 +01:00
Peter Knut
11e1290b5b Add .editorconfig file
Thanks to cweiske (https://github.com/adminerevo/adminerevo/pull/163).
2025-02-19 11:16:36 +01:00
Peter Knut
ac9fd04f87 Fix field selection in Elasticsearch
Thanks to cweiske: https://github.com/adminerevo/adminerevo/pull/159
2025-02-19 11:16:36 +01:00
Peter Knut
2128c05e53 Bump version to 4.9.1-dev 2025-02-19 11:16:36 +01:00
Peter Knut
550db0691e Release 4.9 2025-02-19 11:16:36 +01:00
Adrian Jones
4484f5f620 Fix uninitialized string offset
This can happen if you include an unpaired single or double quote, eg: SELECT * FROM table_name WHERE field_name = 'test
2025-02-19 11:16:36 +01:00
Denitz
c2f8ccc8d8 Skip dump of generated columns 2025-02-19 11:16:36 +01:00
Peter Knut
bd279b2758 Update changes.txt 2025-02-19 11:16:36 +01:00
Peter Knut
76575a95f1 Move Elastic drivers to plugins, driver for Elastic 7+ is the default 2025-02-19 11:16:35 +01:00
Peter Knut
95bab4c077 Modify tables hierarchy for Elasticsearch 7
- Properly display list of databases, indexes, aliases and fields.
- Fix search and delete queries.
2025-02-19 11:16:35 +01:00
Peter Knut
e85af88227 New Elasticsearch 7 plugin as a copy of the old one 2025-02-19 11:16:35 +01:00
Peter Knut
c6bb98ad22 Improve code readability by using of empty lines 2025-02-19 11:16:35 +01:00
Peter Knut
2a0f17b6d9 Compatibility with Elasticsearch 7.14
- Removed empty body from requests.
- Fix deleting records.
2025-02-19 11:16:35 +01:00
Peter Knut
dc1ad9e8ed Fix global search in all tables 2025-02-19 11:16:35 +01:00
Peter Knut
1270748f74 Fix version condition for deprecated mapping types
Mapping types are still supported in version 6, but only one mapping type can be created.
In version 7, mapping types are deprecated and there is only one system '_doc' mapping type.
See: https://www.elastic.co/guide/en/elasticsearch/reference/6.0/removal-of-types.html
2025-02-19 11:16:35 +01:00
Peter Knut
266fda37a1 Fix searching if "anywhere" field is selected
- Allow to search only in fields with index.
2025-02-19 11:16:35 +01:00
Peter Knut
1f14ab470f Replace deprecated "filtered" query with "bool" query
- Allow to choose "must", "should", "must_not" condition.
- Add system "_id" column to the field list. So it can be used in search condition.
2025-02-19 11:16:35 +01:00
Peter Knut
501234c2d1 Fix undefined $sql variable 2025-02-19 11:16:34 +01:00
Peter Knut
197ab976b8 Update changes.txt 2025-02-16 18:03:17 +01:00
Peter Knut
b2759df1f9 Disable redirections in HTTP based drivers 2025-02-16 18:03:17 +01:00
Peter Knut
de07f00ccb Bump version to 4.9.0-dev 2025-02-16 18:03:16 +01:00
Peter Knut
031d2c6a34 Make jush and JsShring submodules available 2025-02-16 18:03:16 +01:00
Lucas Sandery
e2810adc05 Allow responsive styles on larger devices
and fix a media query.

Signed-off-by: Lucas Sandery <lucas-sandery@users.noreply.github.com>
(cherry picked from commit 4b0b011b93f9b684e5ab81f493f239f478fc3f2b)
2025-02-16 18:03:16 +01:00
Peter Knut
baeeb362f7 Fix and complete Slovak translation 2025-02-16 18:03:16 +01:00
Lukáš Rajchl
347ac77bab Update Czech translation
(cherry picked from commit 7338eadd7c)
2025-02-16 18:03:16 +01:00
Anastasia
6b9eb3f446 Update Russian translation
(cherry picked from commit 33fcfbc13b)
2025-02-16 18:03:16 +01:00
Gerry Demaret
f58b13e994 Update Dutch translation
(cherry picked from commit 6024d73ae6)
2025-02-16 18:03:16 +01:00
Lionel Laffineur
fe295bc78a Update French and Italian translations
(cherry picked from commit 496ab9a262)
2025-02-16 18:03:09 +01:00
Hossain Ahmed Saiman
b39469eb9f Bangla language corrections
Some informal words has been replaced with formal words. Some incorrect words has been corrected.

(cherry picked from commit a4ebae8706)

(cherry picked from commit 965598b640)
2025-02-15 14:05:39 +01:00
@krysits.COM
20684a5166 Add Latvian language translation
(cherry picked from commit fad4ce785b)
2025-02-15 14:04:34 +01:00
206 changed files with 8517 additions and 12325 deletions

View File

@@ -7,7 +7,7 @@ end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{php,css,js}]
[*.{php,css,js,xml}]
indent_style = tab
[*.json]

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/.gitmodules export-ignore
/.travis.yml export-ignore
/tests export-ignore

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
github: vrana
patreon: jakubvrana
custom: ["https://www.paypal.com/donate/?item_name=Donation+to+Adminer&business=jakub%40vrana.cz"]

View File

@@ -1,67 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '20 16 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

2
.gitignore vendored
View File

@@ -2,5 +2,3 @@
/adminer*.php
/editor*.php
/vendor/
/composer.lock
/temp

12
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "designs/hydra"]
path = designs/hydra
url = https://github.com/Niyko/Hydra-Dark-Theme-for-Adminer
[submodule "designs/pepa-linha-dark"]
path = designs/pepa-linha-dark
url = https://github.com/pepa-linha/Adminer-Design-Dark/
[submodule "jush"]
path = externals/jush
url = https://github.com/vrana/jush
[submodule "JsShrink"]
path = externals/JsShrink
url = https://github.com/vrana/JsShrink

View File

@@ -6,4 +6,8 @@ php:
- 7.3
- 7.4
- 8.0
- 8.1
- 8.2
- 8.3
- 8.4
script: git diff --name-only $TRAVIS_COMMIT_RANGE | grep '\.php$' | xargs -n1 -P8 php -l | grep -v 'No syntax errors'; test $? -eq 1

File diff suppressed because it is too large Load Diff

1
LICENSE Normal file
View File

@@ -0,0 +1 @@
Apache License 2.0 or GPL 2

View File

@@ -1,8 +0,0 @@
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
View File

@@ -1,170 +0,0 @@
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,13 +1,11 @@
Reporting security issues
=========================
# Security Policy
To report a security issue, please [open a draft security advisory](https://github.com/pematon/adminer/security/advisories).
## Supported Versions
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.
I support only the last published version and the last development version (last commit).
Supported versions
------------------
## Reporting a Vulnerability
Only the last published version and the last development version (last commit) are supported.
To report a vulnerability, add a new draft security advisory at https://github.com/vrana/adminer/security/advisories/new.
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,4 +1,5 @@
<?php
namespace Adminer;
$PROCEDURE = ($_GET["name"] ?: $_GET["call"]);
page_header(lang('Call') . ": " . h($PROCEDURE), $error);
@@ -33,13 +34,13 @@ if (!$error && $_POST) {
$query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")";
$start = microtime(true);
$result = $connection->multi_query($query);
$affected = $connection->affected_rows; // getting warnigns overwrites this
$affected = $connection->affected_rows; // getting warnings overwrites this
echo $adminer->selectQuery($query, $start, !$result);
if (!$result) {
echo "<p class='error'>" . error() . "\n";
} else {
$connection2 = connect();
$connection2 = connect($adminer->credentials());
if (is_object($connection2)) {
$connection2->select_db(DB);
}
@@ -60,11 +61,12 @@ if (!$error && $_POST) {
}
}
}
?>
echo "<form action='' method='post'>\n";
<form action="" method="post">
<?php
if ($in) {
echo "<table cellspacing='0' class='layout'>\n";
echo "<table class='layout'>\n";
foreach ($in as $key) {
$field = $routine["fields"][$key];
$name = $field["field"];
@@ -83,28 +85,30 @@ if ($in) {
}
echo "</table>\n";
}
?>
<p>
<input type="submit" value="<?php echo lang('Call'); ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>
echo "<p>",
"<input type='submit' value='", lang('Call'), "'>",
"<input type='hidden' name='token' value='$token'>",
"</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";
<pre>
<?php
function pre_tr($s) {
return preg_replace('~^~m', '<tr>', preg_replace('~\|~', '<td>', preg_replace('~\|$~m', "", rtrim($s))));
}
$table = '(\+--[-+]+\+\n)';
$row = '(\| .* \|\n)';
echo preg_replace_callback(
"~^$table?$row$table?($row*)$table?~m",
function ($match) {
$first_row = pre_tr($match[2]);
return "<table>\n" . ($match[1] ? "<thead>$first_row</thead>\n" : $first_row) . pre_tr($match[4]) . "\n</table>";
},
preg_replace(
'~(\n( -|mysql)&gt; )(.+)~',
"\\1<code class='jush-sql'>\\3</code>",
preg_replace('~(.+)\n---+\n~', "<b>\\1</b>\n", h($routine['comment']))
)
);
?>
</pre>

51
adminer/check.inc.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
namespace Adminer;
$TABLE = $_GET["check"];
$name = $_GET["name"];
$row = $_POST;
if ($row && !$error) {
if (JUSH == "sqlite") {
$result = recreate_table($TABLE, $TABLE, array(), array(), array(), 0, array(), $name, ($row["drop"] ? "" : $row["clause"]));
} else {
$result = ($name == "" || queries("ALTER TABLE " . table($TABLE) . " DROP CONSTRAINT " . idf_escape($name)));
if (!$row["drop"]) {
$result = queries("ALTER TABLE " . table($TABLE) . " ADD" . ($row["name"] != "" ? " CONSTRAINT " . idf_escape($row["name"]) : "") . " CHECK ($row[clause])"); //! SQL injection
}
}
queries_redirect(
ME . "table=" . urlencode($TABLE),
($row["drop"] ? lang('Check has been dropped.') : ($name != "" ? lang('Check has been altered.') : lang('Check has been created.'))),
$result
);
}
page_header(($name != "" ? lang('Alter check') . ": " . h($name) : lang('Create check')), $error, array("table" => $TABLE));
if (!$row) {
$checks = $driver->checkConstraints($TABLE);
$row = array("name" => $name, "clause" => $checks[$name]);
}
?>
<form action="" method="post">
<p><?php
if (JUSH != "sqlite") {
echo lang('Name') . ': <input name="name" value="' . h($row["name"]) . '" data-maxlength="64" autocapitalize="off"> ';
}
echo doc_link(array(
'sql' => "create-table-check-constraints.html",
'mariadb' => "constraint/",
'pgsql' => "ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS",
'mssql' => "relational-databases/tables/create-check-constraints",
'sqlite' => "lang_createtable.html#check_constraints",
), "?");
?>
<p><?php textarea("clause", $row["clause"]); ?>
<p><input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($name != "") { ?>
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?>
<?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$TABLE = $_GET["create"];
$partition_by = array();
foreach (array('HASH', 'LINEAR HASH', 'KEY', 'LINEAR KEY', 'RANGE', 'LIST') as $key) {
@@ -46,22 +48,19 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
$foreign_key = $foreign_keys[$field["type"]];
$type_field = ($foreign_key !== null ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined type
if ($field["field"] != "") {
if (!$field["has_default"]) {
if (!$field["generated"]) {
$field["default"] = null;
}
if ($key == $row["auto_increment_col"]) {
$field["auto_increment"] = true;
}
$process_field = process_field($field, $type_field);
$all_fields[] = array($field["orig"], $process_field, $after);
if (!$orig_field || $process_field != process_field($orig_field, $orig_field)) {
if (!$orig_field || $process_field !== process_field($orig_field, $orig_field)) {
$fields[] = array($field["orig"], $process_field, $after);
if ($field["orig"] != "" || $after) {
$use_all_fields = true;
}
}
if ($foreign_key !== null) {
$foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . format_foreign_key(array(
$foreign[idf_escape($field["field"])] = ($TABLE != "" && JUSH != "sqlite" ? "ADD" : " ") . format_foreign_key(array(
'table' => $foreign_keys[$field["type"]],
'source' => array($field["field"]),
'target' => array($type_field["field"]),
@@ -89,14 +88,14 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
}, ARRAY_FILTER_USE_KEY);
foreach ($params["partition_names"] as $key => $name) {
if ($name === "") {
if ($name == "") {
unset($params["partition_names"][$key]);
unset($params["partition_values"][$key]);
}
}
if ($params != get_partitions_info($TABLE)) {
$partitions = [];
$partitions = array();
if ($params["partition_by"] == 'RANGE' || $params["partition_by"] == 'LIST') {
foreach ($params["partition_names"] as $key => $name) {
$value = $params["partition_values"][$key];
@@ -105,11 +104,11 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
}
// $params["partition"] can be expression, not only column
$partitioning .= "\nPARTITION BY {$params["partition_by"]}({$params["partition"]})";
$partitioning .= "\nPARTITION BY $params[partition_by]($params[partition])";
if ($partitions) {
$partitioning .= " (" . implode(",", $partitions) . "\n)";
} elseif ($params["partitions"]) {
$partitioning .= " PARTITIONS " . (int)$params["partitions"];
$partitioning .= " PARTITIONS " . (+$params["partitions"]);
}
}
} elseif (preg_match("~partitioned~", $table_status["Create_options"])) {
@@ -127,7 +126,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
queries_redirect(ME . (support("table") ? "table=" : "select=") . urlencode($name), $message, alter_table(
$TABLE,
$name,
($jush == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields),
(JUSH == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields),
$foreign,
($row["Comment"] != $table_status["Comment"] ? $row["Comment"] : null),
($row["Engine"] && $row["Engine"] != $table_status["Engine"] ? $row["Engine"] : ""),
@@ -141,6 +140,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
page_header(($TABLE != "" ? lang('Alter table') : lang('Create table')), $error, array("table" => $TABLE), h($TABLE));
if (!$_POST) {
$types = $driver->types();
$row = array(
"Engine" => $_COOKIE["adminer_engine"],
"fields" => array(array("field" => "", "type" => (isset($types["int"]) ? "int" : (isset($types["integer"]) ? "integer" : "")), "on_update" => "")),
@@ -155,7 +155,7 @@ if (!$_POST) {
$row["Auto_increment"] = "";
}
foreach ($orig_fields as $field) {
$field["has_default"] = isset($field["default"]);
$field["generated"] = $field["generated"] ?: (isset($field["default"]) ? "DEFAULT" : "");
$row["fields"][] = $field;
}
@@ -181,16 +181,15 @@ foreach ($engines as $engine) {
<form action="" method="post" id="form">
<p>
<?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 if ($TABLE == "" && !$_POST) { echo script("focus(gid('form')['name']);"); } ?>
<?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 lang('Table name'); ?>: <input name="name"<?php echo ($TABLE == "" && !$_POST ? " autofocus" : ""); ?> data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?>
<?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'); ?>">
<?php } ?>
<?php if (support("columns")) { ?>
<div class="scrollable">
<table cellspacing="0" id="edit-fields" class="nowrap">
<table id="edit-fields" class="nowrap">
<?php
edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
?>
@@ -198,7 +197,8 @@ edit_fields($row["fields"], $collations, "TABLE", $foreign_keys);
<?php echo script("editFields();"); ?>
</div>
<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" class="size" 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
$comments = ($_POST ? $_POST["comments"] : adminer_setting("comments"));
echo (support("comment")
@@ -214,17 +214,19 @@ echo (support("comment")
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php } ?>
<?php if ($TABLE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $TABLE)); ?><?php } ?>
<?php if ($TABLE != "") { ?>
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $TABLE)); ?>
<?php } ?>
<?php
if (support("partitioning")) {
$partition_table = preg_match('~RANGE|LIST~', $row["partition_by"]);
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
?>
<p>
<?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;"); ?>
<?php echo html_select("partition_by", array("" => "") + $partition_by, $row["partition_by"]) . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?>
(<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"]); ?>">
<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
<table id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
<thead><tr><th><?php echo lang('Partition name'); ?><th><?php echo lang('Values'); ?></thead>
<?php
foreach ($row["partition_names"] as $key => $val) {

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$row = $_POST;
if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x
@@ -44,7 +46,7 @@ if ($_POST) {
$name = $row["name"];
} elseif (DB != "") {
$row["collation"] = db_collation(DB, $collations);
} elseif ($jush == "sql") {
} elseif (JUSH == "sql") {
// propose database name with limited privileges
foreach (get_vals("SHOW GRANTS") as $grant) {
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\.\*)?~', $grant, $match) && $match[1]) {
@@ -59,14 +61,13 @@ if ($_POST) {
<p>
<?php
echo ($_POST["add_x"] || strpos($name, "\n")
? '<textarea id="name" name="name" rows="10" cols="40">' . h($name) . '</textarea><br>'
: '<input name="name" id="name" value="' . h($name) . '" data-maxlength="64" autocapitalize="off">'
? '<textarea autofocus name="name" rows="10" cols="40">' . h($name) . '</textarea><br>'
: '<input name="name" autofocus value="' . h($name) . '" data-maxlength="64" autocapitalize="off">'
) . "\n" . ($collations ? html_select("collation", array("" => "(" . lang('collation') . ")") + $collations, $row["collation"]) . doc_link(array(
'sql' => "charset-charsets.html",
'mariadb' => "supported-character-sets-and-collations/",
'mssql' => "ms187963.aspx",
'mssql' => "relational-databases/system-functions/sys-fn-helpcollations-transact-sql",
)) : "");
echo script("focus(gid('name'));");
?>
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php

View File

@@ -1,10 +1,12 @@
<?php
namespace Adminer;
$tables_views = array_merge((array) $_POST["tables"], (array) $_POST["views"]);
if ($tables_views && !$error && !$_POST["search"]) {
$result = true;
$message = "";
if ($jush == "sql" && $_POST["tables"] && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) {
if (JUSH == "sql" && $_POST["tables"] && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"] || $_POST["copy"])) {
queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once
}
@@ -27,15 +29,21 @@ if ($tables_views && !$error && !$_POST["search"]) {
$result = drop_tables($_POST["tables"]);
}
$message = lang('Tables have been dropped.');
} elseif ($jush != "sql") {
$result = ($jush == "sqlite"
} elseif (JUSH == "sqlite" && $_POST["check"]) {
foreach ((array) $_POST["tables"] as $table) {
foreach (get_rows("PRAGMA integrity_check(" . q($table) . ")") as $row) {
$message .= "<b>" . h($table) . "</b>: " . h($row["integrity_check"]) . "<br>";
}
}
} elseif (JUSH != "sql") {
$result = (JUSH == "sqlite"
? queries("VACUUM")
: apply_queries("VACUUM" . ($_POST["optimize"] ? "" : " ANALYZE"), $_POST["tables"])
);
$message = lang('Tables have been optimized.');
} elseif (!$_POST["tables"]) {
$message = lang('No tables.');
} elseif ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"])))) {
} elseif ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('Adminer\idf_escape', $_POST["tables"])))) {
while ($row = $result->fetch_assoc()) {
$message .= "<b>" . h($row["Table"]) . "</b>: " . h($row["Msg_text"]) . "<br>";
}
@@ -47,28 +55,7 @@ if ($tables_views && !$error && !$_POST["search"]) {
page_header(($_GET["ns"] == "" ? lang('Database') . ": " . h(DB) : lang('Schema') . ": " . h($_GET["ns"])), $error, true);
if ($adminer->homepage()) {
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 {
if ($_GET["ns"] !== "") {
echo "<h3 id='tables-views'>" . lang('Tables and views') . "</h3>\n";
$tables_list = tables_list();
if (!$tables_list) {
@@ -80,21 +67,17 @@ if ($adminer->homepage()) {
echo "<input type='search' name='query' value='" . h($_POST["query"]) . "'>";
echo script("qsl('input').onkeydown = partialArg(bodyKeydown, 'search');", "");
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";
if ($_POST["search"] && $_POST["query"] != "") {
$_GET["where"][0]["op"] = $adminer->operator_regexp !== null && !empty($_POST['regexp']) ? $adminer->operator_regexp : $adminer->operator_like;
$_GET["where"][0]["op"] = $driver->convertOperator("LIKE %%");
search_tables();
}
}
echo "<div class='scrollable'>\n";
echo "<table cellspacing='0' class='nowrap checkable'>\n";
echo "<table class='nowrap checkable odds'>\n";
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo '<thead><tr class="wrap">';
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("gid('check-all').onclick = partial(formCheck, /^(tables|views)\[/);", "");
echo '<td><input id="check-all" type="checkbox" class="jsonly">' . script("qs('#check-all').onclick = partial(formCheck, /^(tables|views)\[/);", "");
echo '<th>' . lang('Table');
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/'));
@@ -110,13 +93,14 @@ if ($adminer->homepage()) {
foreach ($tables_list as $name => $type) {
$view = ($type !== null && !preg_match('~table|sequence~i', $type));
$id = h("Table-" . $name);
echo '<tr' . odd() . '><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "", "", $id);
echo '<tr><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "", "", $id);
echo '<th>' . (support("table") || support("indexes") ? "<a href='" . h(ME) . "table=" . urlencode($name) . "' title='" . lang('Show structure') . "' id='$id'>" . h($name) . '</a>' : h($name));
if ($view) {
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '" title="' . lang('Alter view') . '">' . (preg_match('~materialized~i', $type) ? lang('Materialized view') : lang('View')) . '</a>';
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '" title="' . lang('Select data') . '">?</a>';
} else {
foreach (array(
foreach (
array(
"Engine" => array(),
"Collation" => array(),
"Data_length" => array("create", lang('Alter table')),
@@ -124,7 +108,8 @@ if ($adminer->homepage()) {
"Data_free" => array("edit", lang('New item')),
"Auto_increment" => array("auto_increment=1&create", lang('Alter table')),
"Rows" => array("select", lang('Select data')),
) as $key => $link) {
) as $key => $link
) {
$id = " id='$key-" . h($name) . "'";
echo ($link ? "<td align='right'>" . (support("table") || $key == "Rows" || (support("indexes") && $key != "Data_length")
? "<a href='" . h(ME . "$link[0]=") . urlencode($name) . "'$id title='$link[1]'>?</a>"
@@ -134,32 +119,35 @@ if ($adminer->homepage()) {
$tables++;
}
echo (support("comment") ? "<td id='Comment-" . h($name) . "'>" : "");
echo "\n";
}
echo "<tr><td><th>" . lang('%d in total', count($tables_list));
echo "<td>" . h($jush == "sql" ? $connection->result("SELECT @@default_storage_engine") : "");
echo "<td>" . h(JUSH == "sql" ? get_val("SELECT @@default_storage_engine") : "");
echo "<td>" . h(db_collation(DB, collations()));
foreach (array("Data_length", "Index_length", "Data_free") as $key) {
echo "<td align='right' id='sum-$key'>";
}
echo "\n";
echo "</table>\n";
echo "</div>\n";
if (!information_schema(DB)) {
echo "<div class='footer'><div>\n";
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . help_script("VACUUM");
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . help_script($jush == "sql" ? "OPTIMIZE TABLE" : "VACUUM OPTIMIZE");
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . on_help("'VACUUM'");
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . on_help(JUSH == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'");
echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>"
. ($jush == "sqlite" ? $vacuum
: ($jush == "pgsql" ? $vacuum . $optimize
: ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . help_script("ANALYZE TABLE") . $optimize
. "<input type='submit' name='check' value='" . lang('Check') . "'> " . help_script("CHECK TABLE")
. "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . help_script("REPAIR TABLE")
. (JUSH == "sqlite" ? $vacuum . "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'PRAGMA integrity_check'")
: (JUSH == "pgsql" ? $vacuum . $optimize
: (JUSH == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . on_help("'ANALYZE TABLE'")
. $optimize
. "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'CHECK TABLE'")
. "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . on_help("'REPAIR TABLE'")
: "")))
. "<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') . "'>" . help_script("DROP TABLE") . confirm() . "\n";
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . on_help(JUSH == "sqlite" ? "'DELETE'" : "'TRUNCATE" . (JUSH == "pgsql" ? "'" : " TABLE'")) . confirm()
. "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . on_help("'DROP TABLE'") . confirm() . "\n";
$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));
echo "<p>" . lang('Move to other database') . ": ";
echo ($databases ? html_select("target", $databases, $db) : '<input name="target" value="' . h($db) . '" autocapitalize="off">');
@@ -182,59 +170,35 @@ if ($adminer->homepage()) {
if (support("routine")) {
echo "<h3 id='routines'>" . lang('Routines') . "</h3>\n";
$routines = routines();
if ($routines) {
$commentsSupported = $routines[0]["ROUTINE_COMMENT"] !== null;
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('');
echo "<table class='odds'>\n";
echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td></thead>\n";
foreach ($routines as $row) {
// not computed on the pages to be able to print the header first
$name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"]));
echo '<tr', odd(), '>',
'<th><a href="', h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'callf=' : 'call=') . urlencode($row["SPECIFIC_NAME"]) . $name), '">', h($row["ROUTINE_NAME"]), '</a></th>',
'<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>';
$name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"])); // not computed on the pages to be able to print the header first
echo '<tr>';
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 '<td>' . h($row["DTD_IDENTIFIER"]);
echo '<td><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'function=' : 'procedure=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . lang('Alter') . "</a>";
}
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 '<p class="links">',
(support("procedure") ? '<a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a>' : ''),
'<a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n";
echo '<p class="links">'
. (support("procedure") ? '<a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a>' : '')
. '<a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n"
;
}
if (support("sequence")) {
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");
if ($sequences) {
echo "<table>\n",
"<thead><tr><th>", lang('Name'), "</th><td></td></tr></thead>\n";
odd('');
echo "<table class='odds'>\n";
echo "<thead><tr><th>" . lang('Name') . "</thead>\n";
foreach ($sequences as $val) {
echo "<tr", odd(), ">",
"<th>", h($val), "</th>",
"<td><a href='", h(ME), "sequence=", urlencode($val), "'>", lang('Alter'), "</a></td>\n";
echo "<tr><th><a href='" . h(ME) . "sequence=" . urlencode($val) . "'>" . h($val) . "</a>\n";
}
echo "</table>\n";
}
echo "<p class='links'><a href='" . h(ME) . "sequence='>" . lang('Create sequence') . "</a>\n";
@@ -244,16 +208,11 @@ if ($adminer->homepage()) {
echo "<h3 id='user-types'>" . lang('User types') . "</h3>\n";
$user_types = types();
if ($user_types) {
echo "<table>\n",
"<thead><tr><th>", lang('Name'), "</th><td></td></tr></thead>\n";
odd('');
echo "<table class='odds'>\n";
echo "<thead><tr><th>" . lang('Name') . "</thead>\n";
foreach ($user_types as $val) {
echo "<tr", odd(), ">",
"<th>", h($val), "</th>",
"<td><a href='", h(ME), "type=", urlencode($val), "'>", lang('Alter'), "</a></td>\n";
echo "<tr><th><a href='" . h(ME) . "type=" . urlencode($val) . "'>" . h($val) . "</a>\n";
}
echo "</table>\n";
}
echo "<p class='links'><a href='" . h(ME) . "type='>" . lang('Create type') . "</a>\n";
@@ -273,7 +232,7 @@ if ($adminer->homepage()) {
echo '<td><a href="' . h(ME) . 'event=' . urlencode($row["Name"]) . '">' . lang('Alter') . '</a>';
}
echo "</table>\n";
$event_scheduler = $connection->result("SELECT @@event_scheduler");
$event_scheduler = get_val("SELECT @@event_scheduler");
if ($event_scheduler && $event_scheduler != "ON") {
echo "<p class='error'><code class='jush-sqlset'>event_scheduler</code>: " . h($event_scheduler) . "\n";
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$TABLE = $_GET["download"];
$fields = fields($TABLE);
header("Content-Type: application/octet-stream");

View File

@@ -1,226 +1,26 @@
<?php
namespace Adminer;
$drivers["mongo"] = "MongoDB (alpha)";
if (isset($_GET["mongo"])) {
define("DRIVER", "mongo");
define('Adminer\DRIVER', "mongo");
if (class_exists('MongoDB')) {
class Min_DB {
var $extension = "Mongo", $server_info = MongoClient::VERSION, $error, $last_id, $_link, $_db;
function connect($uri, $options) {
try {
$this->_link = new MongoClient($uri, $options);
if ($options["password"] != "") {
$options["password"] = "";
try {
new MongoClient($uri, $options);
$this->error = lang('Database does not support password.');
} catch (Exception $e) {
// this is what we want
}
}
} catch (Exception $e) {
$this->error = $e->getMessage();
}
}
function query($query) {
return false;
}
function select_db($database) {
try {
$this->_db = $this->_link->selectDB($database);
return true;
} catch (Exception $ex) {
$this->error = $ex->getMessage();
return false;
}
}
function quote($string) {
return $string;
}
}
class Min_Result {
var $num_rows, $_rows = array(), $_offset = 0, $_charset = array();
function __construct($result) {
foreach ($result as $item) {
$row = array();
foreach ($item as $key => $val) {
if (is_a($val, 'MongoBinData')) {
$this->_charset[$key] = 63;
}
$row[$key] =
(is_a($val, 'MongoId') ? "ObjectId(\"$val\")" :
(is_a($val, 'MongoDate') ? gmdate("Y-m-d H:i:s", $val->sec) . " GMT" :
(is_a($val, 'MongoBinData') ? $val->bin : //! allow downloading
(is_a($val, 'MongoRegex') ? "$val" :
(is_object($val) ? get_class($val) : // MongoMinKey, MongoMaxKey
$val
)))));
}
$this->_rows[] = $row;
foreach ($row as $key => $val) {
if (!isset($this->_rows[0][$key])) {
$this->_rows[0][$key] = null;
}
}
}
$this->num_rows = count($this->_rows);
}
function fetch_assoc() {
$row = current($this->_rows);
if (!$row) {
return $row;
}
$return = array();
foreach ($this->_rows[0] as $key => $val) {
$return[$key] = $row[$key];
}
next($this->_rows);
return $return;
}
function fetch_row() {
$return = $this->fetch_assoc();
if (!$return) {
return $return;
}
return array_values($return);
}
function fetch_field() {
$keys = array_keys($this->_rows[0]);
$name = $keys[$this->_offset++];
return (object) array(
'name' => $name,
'charsetnr' => $this->_charset[$name],
);
}
}
class Min_Driver extends Min_SQL {
public $primary = "_id";
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
$select = ($select == array("*")
? array()
: array_fill_keys($select, true)
);
$sort = array();
foreach ($order as $val) {
$val = preg_replace('~ DESC$~', '', $val, 1, $count);
$sort[$val] = ($count ? -1 : 1);
}
return new Min_Result($this->_conn->_db->selectCollection($table)
->find(array(), $select)
->sort($sort)
->limit($limit != "" ? +$limit : 0)
->skip($page * $limit)
);
}
function insert($table, $set) {
try {
$return = $this->_conn->_db->selectCollection($table)->insert($set);
$this->_conn->errno = $return['code'];
$this->_conn->error = $return['err'];
$this->_conn->last_id = $set['_id'];
return !$return['err'];
} catch (Exception $ex) {
$this->_conn->error = $ex->getMessage();
return false;
}
}
}
function get_databases($flush) {
global $connection;
$return = array();
$dbs = $connection->_link->listDBs();
foreach ($dbs['databases'] as $db) {
$return[] = $db['name'];
}
return $return;
}
function count_tables($databases) {
global $connection;
$return = array();
foreach ($databases as $db) {
$return[$db] = count($connection->_link->selectDB($db)->getCollectionNames(true));
}
return $return;
}
function tables_list() {
global $connection;
return array_fill_keys($connection->_db->getCollectionNames(true), 'table');
}
function drop_databases($databases) {
global $connection;
foreach ($databases as $db) {
$response = $connection->_link->selectDB($db)->drop();
if (!$response['ok']) {
return false;
}
}
return true;
}
function indexes($table, $connection2 = null) {
global $connection;
$return = array();
foreach ($connection->_db->selectCollection($table)->getIndexInfo() as $index) {
$descs = array();
foreach ($index["key"] as $column => $type) {
$descs[] = ($type == -1 ? '1' : null);
}
$return[$index["name"]] = array(
"type" => ($index["name"] == "_id_" ? "PRIMARY" : ($index["unique"] ? "UNIQUE" : "INDEX")),
"columns" => array_keys($index["key"]),
"lengths" => array(),
"descs" => $descs,
);
}
return $return;
}
function fields($table) {
return fields_from_edit();
}
function found_rows($table_status, $where) {
global $connection;
//! don't call count_rows()
return $connection->_db->selectCollection($_GET["select"])->count($where);
}
} elseif (class_exists('MongoDB\Driver\Manager')) {
class Min_DB {
if (class_exists('MongoDB\Driver\Manager')) {
class Db {
var $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id;
/** @var MongoDB\Driver\Manager */
var $_link;
var $_db, $_db_name;
function connect($uri, $options) {
$this->_link = new MongoDB\Driver\Manager($uri, $options);
$this->executeCommand('admin', array('ping' => 1));
$this->_link = new \MongoDB\Driver\Manager($uri, $options);
$this->executeCommand($options["db"], array('ping' => 1));
}
function executeCommand($db, $command) {
try {
return $this->_link->executeCommand($db, new MongoDB\Driver\Command($command));
return $this->_link->executeCommand($db, new \MongoDB\Driver\Command($command));
} catch (Exception $e) {
$this->error = $e->getMessage();
return array();
@@ -252,7 +52,7 @@ if (isset($_GET["mongo"])) {
}
}
class Min_Result {
class Result {
var $num_rows, $_rows = array(), $_offset = 0, $_charset = array();
function __construct($result) {
@@ -310,89 +110,14 @@ if (isset($_GET["mongo"])) {
'charsetnr' => $this->_charset[$name],
);
}
}
class Min_Driver extends Min_SQL {
public $primary = "_id";
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
global $connection;
$select = ($select == array("*")
? array()
: array_fill_keys($select, 1)
);
if (count($select) && !isset($select['_id'])) {
$select['_id'] = 0;
}
$where = where_to_query($where);
$sort = array();
foreach ($order as $val) {
$val = preg_replace('~ DESC$~', '', $val, 1, $count);
$sort[$val] = ($count ? -1 : 1);
}
if (isset($_GET['limit']) && is_numeric($_GET['limit']) && $_GET['limit'] > 0) {
$limit = $_GET['limit'];
}
$limit = min(200, max(1, (int) $limit));
$skip = $page * $limit;
try {
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) {
$connection->error = $e->getMessage();
return false;
}
}
function update($table, $set, $queryWhere, $limit = 0, $separator = "\n") {
global $connection;
$db = $connection->_db_name;
$where = sql_query_where_parser($queryWhere);
$bulk = new MongoDB\Driver\BulkWrite(array());
if (isset($set['_id'])) {
unset($set['_id']);
}
$removeFields = array();
foreach ($set as $key => $value) {
if ($value == 'NULL') {
$removeFields[$key] = 1;
unset($set[$key]);
}
}
$update = array('$set' => $set);
if (count($removeFields)) {
$update['$unset'] = $removeFields;
}
$bulk->update($where, $update, array('upsert' => false));
return $connection->executeBulkWrite("$db.$table", $bulk, 'getModifiedCount');
}
function delete($table, $queryWhere, $limit = 0) {
global $connection;
$db = $connection->_db_name;
$where = sql_query_where_parser($queryWhere);
$bulk = new MongoDB\Driver\BulkWrite(array());
$bulk->delete($where, array('limit' => $limit));
return $connection->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
}
function insert($table, $set) {
global $connection;
$db = $connection->_db_name;
$bulk = new MongoDB\Driver\BulkWrite(array());
if ($set['_id'] == '') {
unset($set['_id']);
}
$bulk->insert($set);
return $connection->executeBulkWrite("$db.$table", $bulk, 'getInsertedCount');
}
}
function get_databases($flush) {
global $connection;
$return = array();
foreach ($connection->executeCommand('admin', array('listDatabases' => 1)) as $dbs) {
foreach ($connection->executeCommand($connection->_db_name, array('listDatabases' => 1)) as $dbs) {
foreach ($dbs->databases as $db) {
$return[] = $db->name;
}
@@ -512,8 +237,8 @@ if (isset($_GET["mongo"])) {
$val = (float) $val;
$op = $match[1];
} elseif (preg_match('~^\(date\)(.+)~', $op, $match)) {
$dateTime = new DateTime($val);
$val = new MongoDB\BSON\UTCDatetime($dateTime->getTimestamp() * 1000);
$dateTime = new \DateTime($val);
$val = new \MongoDB\BSON\UTCDatetime($dateTime->getTimestamp() * 1000);
$op = $match[1];
}
switch ($op) {
@@ -553,6 +278,108 @@ if (isset($_GET["mongo"])) {
}
}
class Driver extends SqlDriver {
static $possibleDrivers = array("mongodb");
static $jush = "mongo";
var $editFunctions = array(array("json"));
var $operators = array(
"=",
"!=",
">",
"<",
">=",
"<=",
"regex",
"(f)=",
"(f)!=",
"(f)>",
"(f)<",
"(f)>=",
"(f)<=",
"(date)=",
"(date)!=",
"(date)>",
"(date)<",
"(date)>=",
"(date)<=",
);
public $primary = "_id";
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
$select = ($select == array("*")
? array()
: array_fill_keys($select, 1)
);
if (count($select) && !isset($select['_id'])) {
$select['_id'] = 0;
}
$where = where_to_query($where);
$sort = array();
foreach ($order as $val) {
$val = preg_replace('~ DESC$~', '', $val, 1, $count);
$sort[$val] = ($count ? -1 : 1);
}
if (isset($_GET['limit']) && is_numeric($_GET['limit']) && $_GET['limit'] > 0) {
$limit = $_GET['limit'];
}
$limit = min(200, max(1, (int) $limit));
$skip = $page * $limit;
try {
return new Result($this->_conn->_link->executeQuery($this->_conn->_db_name . ".$table", new \MongoDB\Driver\Query($where, array('projection' => $select, 'limit' => $limit, 'skip' => $skip, 'sort' => $sort))));
} catch (Exception $e) {
$this->_conn->error = $e->getMessage();
return false;
}
}
function update($table, $set, $queryWhere, $limit = 0, $separator = "\n") {
$db = $this->_conn->_db_name;
$where = sql_query_where_parser($queryWhere);
$bulk = new \MongoDB\Driver\BulkWrite(array());
if (isset($set['_id'])) {
unset($set['_id']);
}
$removeFields = array();
foreach ($set as $key => $value) {
if ($value == 'NULL') {
$removeFields[$key] = 1;
unset($set[$key]);
}
}
$update = array('$set' => $set);
if (count($removeFields)) {
$update['$unset'] = $removeFields;
}
$bulk->update($where, $update, array('upsert' => false));
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getModifiedCount');
}
function delete($table, $queryWhere, $limit = 0) {
$db = $this->_conn->_db_name;
$where = sql_query_where_parser($queryWhere);
$bulk = new \MongoDB\Driver\BulkWrite(array());
$bulk->delete($where, array('limit' => $limit));
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getDeletedCount');
}
function insert($table, $set) {
$db = $this->_conn->_db_name;
$bulk = new \MongoDB\Driver\BulkWrite(array());
if ($set['_id'] == '') {
unset($set['_id']);
}
$bulk->insert($set);
return $this->_conn->executeBulkWrite("$db.$table", $bulk, 'getInsertedCount');
}
}
function table($idf) {
return $idf;
}
@@ -596,10 +423,10 @@ if (isset($_GET["mongo"])) {
return $credentials[1];
}
function connect() {
function connect($credentials) {
global $adminer;
$connection = new Min_DB;
list($server, $username, $password) = $adminer->credentials();
$connection = new Db;
list($server, $username, $password) = $credentials;
if ($server == "") {
$server = "localhost:27017";
@@ -710,49 +537,4 @@ if (isset($_GET["mongo"])) {
}
return true;
}
function driver_config() {
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(
'possible_drivers' => array("mongo", "mongodb"),
'jush' => "mongo",
'operators' => $operators,
'operator_like' => "LIKE %%", // TODO: LIKE operator is not listed in operators.
'operator_regexp' => $operator_regexp,
'functions' => array(),
'grouping' => array(),
'edit_functions' => array(array("json")),
);
}
}

View File

@@ -5,12 +5,14 @@
* @author Jakub Vrana
*/
$drivers["mssql"] = "MS SQL (beta)";
namespace Adminer;
$drivers["mssql"] = "MS SQL";
if (isset($_GET["mssql"])) {
define("DRIVER", "mssql");
define('Adminer\DRIVER', "mssql");
if (extension_loaded("sqlsrv")) {
class Min_DB {
class Db {
var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $errno, $error;
function _get_error() {
@@ -24,13 +26,7 @@ if (isset($_GET["mssql"])) {
function connect($server, $username, $password) {
global $adminer;
$connection_info = [
"UID" => $username,
"PWD" => $password,
"CharacterSet" => "UTF-8",
];
$connection_info = array("UID" => $username, "PWD" => $password, "CharacterSet" => "UTF-8");
$ssl = $adminer->connectSsl();
if (isset($ssl["Encrypt"])) {
$connection_info["Encrypt"] = $ssl["Encrypt"];
@@ -38,12 +34,10 @@ if (isset($_GET["mssql"])) {
if (isset($ssl["TrustServerCertificate"])) {
$connection_info["TrustServerCertificate"] = $ssl["TrustServerCertificate"];
}
$db = $adminer->database();
if ($db != "") {
$connection_info["Database"] = $db;
}
$this->_link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info);
if ($this->_link) {
$info = sqlsrv_server_info($this->_link);
@@ -51,7 +45,6 @@ if (isset($_GET["mssql"])) {
} else {
$this->_get_error();
}
return (bool) $this->_link;
}
@@ -61,7 +54,7 @@ if (isset($_GET["mssql"])) {
}
function select_db($database) {
return $this->query("USE " . idf_escape($database));
return $this->query(use_sql($database));
}
function query($query, $unbuffered = false) {
@@ -92,7 +85,7 @@ if (isset($_GET["mssql"])) {
return false;
}
if (sqlsrv_field_metadata($result)) {
return new Min_Result($result);
return new Result($result);
}
$this->affected_rows = sqlsrv_rows_affected($result);
return true;
@@ -112,7 +105,7 @@ if (isset($_GET["mssql"])) {
}
}
class Min_Result {
class Result {
var $_result, $_offset = 0, $_fields, $num_rows;
function __construct($result) {
@@ -143,7 +136,7 @@ if (isset($_GET["mssql"])) {
$this->_fields = sqlsrv_field_metadata($this->_result);
}
$field = $this->_fields[$this->_offset++];
$return = new stdClass;
$return = new \stdClass;
$return->name = $field["Name"];
$return->orgname = $field["Name"];
$return->type = ($field["Type"] == 1 ? 254 : 0);
@@ -161,106 +154,23 @@ if (isset($_GET["mssql"])) {
}
}
} elseif (extension_loaded("mssql")) {
class Min_DB {
var $extension = "MSSQL", $_link, $_result, $server_info, $affected_rows, $error;
} elseif (extension_loaded("pdo_sqlsrv")) {
class Db extends PdoDb {
var $extension = "PDO_SQLSRV";
function connect($server, $username, $password) {
$this->_link = @mssql_connect($server, $username, $password);
if ($this->_link) {
$result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
if ($result) {
$row = $result->fetch_row();
$this->server_info = $this->result("sp_server_info 2", 2) . " [$row[0]] $row[1]";
}
} else {
$this->error = mssql_get_last_message();
}
return (bool) $this->_link;
}
function quote($string) {
$unicode = strlen($string) != strlen(utf8_decode($string));
return ($unicode ? "N" : "") . "'" . str_replace("'", "''", $string) . "'";
$this->dsn("sqlsrv:Server=" . str_replace(":", ",", $server), $username, $password);
return true;
}
function select_db($database) {
return mssql_select_db($database);
}
function query($query, $unbuffered = false) {
$result = @mssql_query($query, $this->_link); //! $unbuffered
$this->error = "";
if (!$result) {
$this->error = mssql_get_last_message();
return false;
}
if ($result === true) {
$this->affected_rows = mssql_rows_affected($this->_link);
return true;
}
return new Min_Result($result);
}
function multi_query($query) {
return $this->_result = $this->query($query);
}
function store_result() {
return $this->_result;
}
function next_result() {
return mssql_next_result($this->_result->_result);
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!is_object($result)) {
return false;
}
return mssql_result($result->_result, 0, $field);
}
}
class Min_Result {
var $_result, $_offset = 0, $_fields, $num_rows;
function __construct($result) {
$this->_result = $result;
$this->num_rows = mssql_num_rows($result);
}
function fetch_assoc() {
return mssql_fetch_assoc($this->_result);
}
function fetch_row() {
return mssql_fetch_row($this->_result);
}
function num_rows() {
return mssql_num_rows($this->_result);
}
function fetch_field() {
$return = mssql_fetch_field($this->_result);
$return->orgtable = $return->table;
$return->orgname = $return->name;
return $return;
}
function seek($offset) {
mssql_data_seek($this->_result, $offset);
}
function __destruct() {
mssql_free_result($this->_result);
// database selection is separated from the connection so dbname in DSN can't be used
return $this->query(use_sql($database));
}
}
} elseif (extension_loaded("pdo_dblib")) {
class Min_DB extends Min_PDO {
class Db extends PdoDb {
var $extension = "PDO_DBLIB";
function connect($server, $username, $password) {
@@ -269,40 +179,95 @@ if (isset($_GET["mssql"])) {
}
function select_db($database) {
// database selection is separated from the connection so dbname in DSN can't be used
return $this->query("USE " . idf_escape($database));
return $this->query(use_sql($database));
}
}
}
class Min_Driver extends Min_SQL {
class Driver extends SqlDriver {
static $possibleDrivers = array("SQLSRV", "PDO_SQLSRV", "PDO_DBLIB");
static $jush = "mssql";
var $editFunctions = array(
array(
"date|time" => "getdate",
), array(
"int|decimal|real|float|money|datetime" => "+/-",
"char|text" => "+",
)
);
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
var $functions = array("len", "lower", "round", "upper");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
var $onActions = "NO ACTION|CASCADE|SET NULL|SET DEFAULT";
var $generated = array("PERSISTED", "VIRTUAL");
function __construct($connection) {
parent::__construct($connection);
$this->types = array( //! use sys.types
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
);
}
function insertUpdate($table, $rows, $primary) {
foreach ($rows as $set) {
$fields = fields($table);
$update = array();
$where = array();
$set = reset($rows);
$columns = "c" . implode(", c", range(1, count($set)));
$c = 0;
$insert = array();
foreach ($set as $key => $val) {
$update[] = "$key = $val";
if (isset($primary[idf_unescape($key)])) {
$where[] = "$key = $val";
$c++;
$name = idf_unescape($key);
if (!$fields[$name]["auto_increment"]) {
$insert[$key] = "c$c";
}
if (isset($primary[$name])) {
$where[] = "$key = c$c";
} else {
$update[] = "$key = c$c";
}
}
//! can use only one query for all rows
if (!queries("MERGE " . table($table) . " USING (VALUES(" . implode(", ", $set) . ")) AS source (c" . implode(", c", range(1, count($set))) . ") ON " . implode(" AND ", $where) //! source, c1 - possible conflict
. " WHEN MATCHED THEN UPDATE SET " . implode(", ", $update)
. " WHEN NOT MATCHED THEN INSERT (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ");" // ; is mandatory
)) {
return false;
$values = array();
foreach ($rows as $set) {
$values[] = "(" . implode(", ", $set) . ")";
}
if ($where) {
$identity = queries("SET IDENTITY_INSERT " . table($table) . " ON");
$return = queries(
"MERGE " . table($table) . " USING (VALUES\n\t" . implode(",\n\t", $values) . "\n) AS source ($columns) ON " . implode(" AND ", $where) //! source, c1 - possible conflict
. ($update ? "\nWHEN MATCHED THEN UPDATE SET " . implode(", ", $update) : "")
. "\nWHEN NOT MATCHED THEN INSERT (" . implode(", ", array_keys($identity ? $set : $insert)) . ") VALUES (" . ($identity ? $columns : implode(", ", $insert)) . ");" // ; is mandatory
);
if ($identity) {
queries("SET IDENTITY_INSERT " . table($table) . " OFF");
}
return true;
} else {
$return = queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES\n" . implode(",\n", $values));
}
return $return;
}
function begin() {
return queries("BEGIN TRANSACTION");
}
function tableHelp($name, $is_view = false) {
$links = array(
"sys" => "catalog-views/sys-",
"INFORMATION_SCHEMA" => "information-schema-views/",
);
$link = $links[get_schema()];
if ($link) {
return "relational-databases/system-$link" . preg_replace('~_~', '-', strtolower($name)) . "-transact-sql";
}
}
}
@@ -315,15 +280,11 @@ if (isset($_GET["mssql"])) {
return ($_GET["ns"] != "" ? idf_escape($_GET["ns"]) . "." : "") . idf_escape($idf);
}
function connect() {
global $adminer;
$connection = new Min_DB;
$credentials = $adminer->credentials();
function connect($credentials) {
$connection = new Db;
if ($credentials[0] == "") {
$credentials[0] = "localhost:1433";
}
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection;
}
@@ -343,8 +304,7 @@ if (isset($_GET["mssql"])) {
}
function db_collation($db, $collations) {
global $connection;
return $connection->result("SELECT collation_name FROM sys.databases WHERE name = " . q($db));
return get_val("SELECT collation_name FROM sys.databases WHERE name = " . q($db));
}
function engines() {
@@ -352,8 +312,7 @@ if (isset($_GET["mssql"])) {
}
function logged_user() {
global $connection;
return $connection->result("SELECT SUSER_NAME()");
return get_val("SELECT SUSER_NAME()");
}
function tables_list() {
@@ -365,14 +324,18 @@ if (isset($_GET["mssql"])) {
$return = array();
foreach ($databases as $db) {
$connection->select_db($db);
$return[$db] = $connection->result("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES");
$return[$db] = get_val("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES");
}
return $return;
}
function table_status($name = "") {
$return = array();
foreach (get_rows("SELECT ao.name AS Name, ao.type_desc AS Engine, (SELECT value FROM fn_listextendedproperty(default, 'SCHEMA', schema_name(schema_id), 'TABLE', ao.name, null, null)) AS Comment FROM sys.all_objects AS ao WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') " . ($name != "" ? "AND name = " . q($name) : "ORDER BY name")) as $row) {
foreach (
get_rows("SELECT ao.name AS Name, ao.type_desc AS Engine, (SELECT value FROM fn_listextendedproperty(default, 'SCHEMA', schema_name(schema_id), 'TABLE', ao.name, null, null)) AS Comment
FROM sys.all_objects AS ao
WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') " . ($name != "" ? "AND name = " . q($name) : "ORDER BY name")) as $row
) {
if ($name != "") {
return $row;
}
@@ -392,41 +355,53 @@ if (isset($_GET["mssql"])) {
function fields($table) {
$comments = get_key_vals("SELECT objname, cast(value as varchar(max)) FROM fn_listextendedproperty('MS_DESCRIPTION', 'schema', " . q(get_schema()) . ", 'table', " . q($table) . ", 'column', NULL)");
$return = array();
foreach (get_rows("SELECT c.max_length, c.precision, c.scale, c.name, c.is_nullable, c.is_identity, c.collation_name, t.name type, CAST(d.definition as text) [default]
$table_id = get_val("SELECT object_id FROM sys.all_objects WHERE schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND type IN ('S', 'U', 'V') AND name = " . q($table));
foreach (
get_rows("SELECT c.max_length, c.precision, c.scale, c.name, c.is_nullable, c.is_identity, c.collation_name, t.name type, CAST(d.definition as text) [default], d.name default_constraint, i.is_primary_key
FROM sys.all_columns c
JOIN sys.all_objects o ON c.object_id = o.object_id
JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT JOIN sys.default_constraints d ON c.default_object_id = d.parent_column_id
WHERE o.schema_id = SCHEMA_ID(" . q(get_schema()) . ") AND o.type IN ('S', 'U', 'V') AND o.name = " . q($table)
) as $row) {
LEFT JOIN sys.default_constraints d ON c.default_object_id = d.object_id
LEFT JOIN sys.index_columns ic ON c.object_id = ic.object_id AND c.column_id = ic.column_id
LEFT JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
WHERE c.object_id = " . q($table_id)) as $row
) {
$type = $row["type"];
$length = (preg_match("~char|binary~", $type) ? $row["max_length"] : ($type == "decimal" ? "$row[precision],$row[scale]" : ""));
$length = (preg_match("~char|binary~", $type)
? $row["max_length"] / ($type[0] == 'n' ? 2 : 1)
: ($type == "decimal" ? "$row[precision],$row[scale]" : "")
);
$return[$row["name"]] = array(
"field" => $row["name"],
"full_type" => $type . ($length ? "($length)" : ""),
"type" => $type,
"length" => $length,
"default" => $row["default"],
"default" => (preg_match("~^\('(.*)'\)$~", $row["default"], $match) ? str_replace("''", "'", $match[1]) : $row["default"]),
"default_constraint" => $row["default_constraint"],
"null" => $row["is_nullable"],
"auto_increment" => $row["is_identity"],
"collation" => $row["collation_name"],
"privileges" => array("insert" => 1, "select" => 1, "update" => 1, "where" => 1, "order" => 1),
"primary" => $row["is_identity"], //! or indexes.is_primary_key
"primary" => $row["is_primary_key"],
"comment" => $comments[$row["name"]],
);
}
foreach (get_rows("SELECT * FROM sys.computed_columns WHERE object_id = " . q($table_id)) as $row) {
$return[$row["name"]]["generated"] = ($row["is_persisted"] ? "PERSISTED" : "VIRTUAL");
$return[$row["name"]]["default"] = $row["definition"];
}
return $return;
}
function indexes($table, $connection2 = null) {
$return = array();
// sp_statistics doesn't return information about primary key
foreach (get_rows("SELECT i.name, key_ordinal, is_unique, is_primary_key, c.name AS column_name, is_descending_key
foreach (
get_rows("SELECT i.name, key_ordinal, is_unique, is_primary_key, c.name AS column_name, is_descending_key
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE OBJECT_NAME(i.object_id) = " . q($table)
, $connection2) as $row) {
WHERE OBJECT_NAME(i.object_id) = " . q($table), $connection2) as $row
) {
$name = $row["name"];
$return[$name]["type"] = ($row["is_primary_key"] ? "PRIMARY" : ($row["is_unique"] ? "UNIQUE" : "INDEX"));
$return[$name]["lengths"] = array();
@@ -437,8 +412,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
}
function view($name) {
global $connection;
return array("select" => preg_replace('~^(?:[^[]|\[[^]]*])*\s+AS\s+~isU', '', $connection->result("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q($name))));
return array("select" => preg_replace('~^(?:[^[]|\[[^]]*])*\s+AS\s+~isU', '', get_val("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q($name))));
}
function collations() {
@@ -450,12 +424,12 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
}
function information_schema($db) {
return false;
return get_schema() == "INFORMATION_SCHEMA";
}
function error() {
global $connection;
return nl2br(h(preg_replace('~^(\[[^]]*])+~m', '', $connection->error)));
return nl_br(h(preg_replace('~^(\[[^]]*])+~m', '', $connection->error)));
}
function create_database($db, $collation) {
@@ -463,7 +437,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
}
function drop_databases($databases) {
return queries("DROP DATABASE " . implode(", ", array_map('idf_escape', $databases)));
return queries("DROP DATABASE " . implode(", ", array_map('Adminer\idf_escape', $databases)));
}
function rename_database($name, $collation) {
@@ -481,6 +455,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
$alter = array();
$comments = array();
$orig_fields = fields($table);
foreach ($fields as $field) {
$column = idf_escape($field[0]);
$val = $field[1];
@@ -490,14 +465,28 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
$val[1] = preg_replace("~( COLLATE )'(\\w+)'~", '\1\2', $val[1]);
$comments[$field[0]] = $val[5];
unset($val[5]);
if (preg_match('~ AS ~', $val[3])) {
unset($val[1], $val[2]);
}
if ($field[0] == "") {
$alter["ADD"][] = "\n " . implode("", $val) . ($table == "" ? substr($foreign[$val[0]], 16 + strlen($val[0])) : ""); // 16 - strlen(" FOREIGN KEY ()")
} else {
$default = $val[3];
unset($val[3]); // default values are set separately
unset($val[6]); //! identity can't be removed
if ($column != $val[0]) {
queries("EXEC sp_rename " . q(table($table) . ".$column") . ", " . q(idf_unescape($val[0])) . ", 'COLUMN'");
}
$alter["ALTER COLUMN " . implode("", $val)][] = "";
$orig_field = $orig_fields[$field[0]];
if (default_value($orig_field) != $default) {
if ($orig_field["default"] !== null) {
$alter["DROP"][] = " " . idf_escape($orig_field["default_constraint"]);
}
if ($default) {
$alter["ADD"][] = "\n $default FOR $column";
}
}
}
}
}
@@ -511,7 +500,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
$alter[""] = $foreign;
}
foreach ($alter as $key => $val) {
if (!queries("ALTER TABLE " . idf_escape($name) . " $key" . implode(",", $val))) {
if (!queries("ALTER TABLE " . table($name) . " $key" . implode(",", $val))) {
return false;
}
}
@@ -533,10 +522,12 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
} else {
$index[] = idf_escape($val[1]) . " ON " . table($table);
}
} elseif (!queries(($val[0] != "PRIMARY"
} elseif (
!queries(($val[0] != "PRIMARY"
? "CREATE $val[0] " . ($val[0] != "INDEX" ? "INDEX " : "") . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_")) . " ON " . table($table)
: "ALTER TABLE " . table($table) . " ADD PRIMARY KEY"
) . " (" . implode(", ", $val[2]) . ")")) {
) . " (" . implode(", ", $val[2]) . ")")
) {
return false;
}
}
@@ -546,8 +537,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
}
function last_id() {
global $connection;
return $connection->result("SELECT SCOPE_IDENTITY()"); // @@IDENTITY can return trigger INSERT
return get_val("SELECT SCOPE_IDENTITY()"); // @@IDENTITY can return trigger INSERT
}
function explain($connection, $query) {
@@ -562,10 +552,14 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
function foreign_keys($table) {
$return = array();
foreach (get_rows("EXEC sp_fkeys @fktable_name = " . q($table)) as $row) {
$on_actions = array("CASCADE", "NO ACTION", "SET NULL", "SET DEFAULT");
foreach (get_rows("EXEC sp_fkeys @fktable_name = " . q($table) . ", @fktable_owner = " . q(get_schema())) as $row) {
$foreign_key = &$return[$row["FK_NAME"]];
$foreign_key["db"] = $row["PKTABLE_QUALIFIER"];
$foreign_key["ns"] = $row["PKTABLE_OWNER"];
$foreign_key["table"] = $row["PKTABLE_NAME"];
$foreign_key["on_update"] = $on_actions[$row["UPDATE_RULE"]];
$foreign_key["on_delete"] = $on_actions[$row["DELETE_RULE"]];
$foreign_key["source"][] = $row["FKCOLUMN_NAME"];
$foreign_key["target"][] = $row["PKCOLUMN_NAME"];
}
@@ -577,11 +571,11 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
}
function drop_views($views) {
return queries("DROP VIEW " . implode(", ", array_map('table', $views)));
return queries("DROP VIEW " . implode(", ", array_map('Adminer\table', $views)));
}
function drop_tables($tables) {
return queries("DROP TABLE " . implode(", ", array_map('table', $tables)));
return queries("DROP TABLE " . implode(", ", array_map('Adminer\table', $tables)));
}
function move_tables($tables, $views, $target) {
@@ -592,7 +586,8 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table)
if ($name == "") {
return array();
}
$rows = get_rows("SELECT s.name [Trigger],
$rows = get_rows(
"SELECT s.name [Trigger],
CASE WHEN OBJECTPROPERTY(s.id, 'ExecIsInsertTrigger') = 1 THEN 'INSERT' WHEN OBJECTPROPERTY(s.id, 'ExecIsUpdateTrigger') = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY(s.id, 'ExecIsDeleteTrigger') = 1 THEN 'DELETE' END [Event],
CASE WHEN OBJECTPROPERTY(s.id, 'ExecIsInsteadOfTrigger') = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END [Timing],
c.text
@@ -609,13 +604,14 @@ WHERE s.xtype = 'TR' AND s.name = " . q($name)
function triggers($table) {
$return = array();
foreach (get_rows("SELECT sys1.name,
foreach (
get_rows("SELECT sys1.name,
CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1 THEN 'INSERT' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1 THEN 'DELETE' END [Event],
CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END [Timing]
FROM sysobjects sys1
JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id
WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
) as $row) { // triggers are not schema-scoped
WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)) as $row
) { // triggers are not schema-scoped
$return[$row["name"]] = array($row["Timing"], $row["Event"]);
}
return $return;
@@ -634,38 +630,70 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
}
function get_schema() {
global $connection;
if ($_GET["ns"] != "") {
return $_GET["ns"];
}
return $connection->result("SELECT SCHEMA_NAME()");
return get_val("SELECT SCHEMA_NAME()");
}
function set_schema($schema) {
$_GET["ns"] = $schema;
return true; // ALTER USER is permanent
}
function create_sql($table, $auto_increment, $style) {
global $driver;
if (is_view(table_status($table))) {
$view = view($table);
return "CREATE VIEW " . table($table) . " AS $view[select]";
}
$fields = array();
$primary = false;
foreach (fields($table) as $name => $field) {
$val = process_field($field, $field);
if ($val[6]) {
$primary = true;
}
$fields[] = implode("", $val);
}
foreach (indexes($table) as $name => $index) {
if (!$primary || $index["type"] != "PRIMARY") {
$columns = array();
foreach ($index["columns"] as $key => $val) {
$columns[] = idf_escape($val) . ($index["descs"][$key] ? " DESC" : "");
}
$name = idf_escape($name);
$fields[] = ($index["type"] == "INDEX" ? "INDEX $name" : "CONSTRAINT $name " . ($index["type"] == "UNIQUE" ? "UNIQUE" : "PRIMARY KEY")) . " (" . implode(", ", $columns) . ")";
}
}
foreach ($driver->checkConstraints($table) as $name => $check) {
$fields[] = "CONSTRAINT " . idf_escape($name) . " CHECK ($check)";
}
return "CREATE TABLE " . table($table) . " (\n\t" . implode(",\n\t", $fields) . "\n)";
}
function foreign_keys_sql($table) {
$fields = array();
foreach (foreign_keys($table) as $foreign) {
$fields[] = ltrim(format_foreign_key($foreign));
}
return ($fields ? "ALTER TABLE " . table($table) . " ADD\n\t" . implode(",\n\t", $fields) . ";\n\n" : "");
}
function truncate_sql($table) {
return "TRUNCATE TABLE " . table($table);
}
function use_sql($database) {
return "USE " . idf_escape($database);
}
function show_variables() {
return array();
function trigger_sql($table) {
$return = "";
foreach (triggers($table) as $name => $trigger) {
$return .= create_trigger(" ON " . table($table), trigger($name)) . ";";
}
/**
* @return bool
*/
function is_strict_mode() {
return false;
}
function is_c_style_escapes() {
return true;
}
function show_status() {
return array();
return $return;
}
function convert_field($field) {
@@ -676,39 +704,6 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
}
function support($feature) {
return preg_match('~^(comment|columns|database|drop_col|indexes|descidx|scheme|sql|table|trigger|view|view_trigger)$~', $feature); //! routine|
}
function driver_config() {
$types = array();
$structured_types = array();
foreach (array( //! use sys.types
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
return array(
'possible_drivers' => array("SQLSRV", "MSSQL", "PDO_DBLIB"),
'jush' => "mssql",
'types' => $types,
'structured_types' => $structured_types,
'unsigned' => array(),
'operators' => array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"),
'operator_like' => "LIKE %%",
'functions' => array("len", "lower", "round", "upper"),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array(
array(
"date|time" => "getdate",
), array(
"int|decimal|real|float|money|datetime" => "+/-",
"char|text" => "+",
)
),
);
return preg_match('~^(check|comment|columns|database|drop_col|dump|indexes|descidx|scheme|sql|table|trigger|view|view_trigger)$~', $feature); //! routine|
}
}

View File

@@ -1,11 +1,13 @@
<?php
$drivers["mysql"] = "MySQL";
namespace Adminer;
if (isset($_GET["mysql"])) {
define("DRIVER", "mysql");
$drivers = array("server" => "MySQL") + $drivers;
if (!defined('Adminer\DRIVER')) {
define('Adminer\DRIVER', "server"); // server - backwards compatibility
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
if (extension_loaded("mysqli")) {
class Min_DB extends MySQLi {
class Db extends \MySQLi {
var $extension = "MySQLi";
function __construct() {
@@ -14,19 +16,12 @@ if (isset($_GET["mysql"])) {
function connect($server = "", $username = "", $password = "", $database = null, $port = null, $socket = null) {
global $adminer;
mysqli_report(MYSQLI_REPORT_OFF);
mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
$ssl = $adminer->connectSsl();
if (isset($ssl['key']) || isset($ssl['cert']) || isset($ssl['ca'])) {
$this->ssl_set(
isset($ssl['key']) ? $ssl['key'] : null,
isset($ssl['cert']) ? $ssl['cert'] : null,
isset($ssl['ca']) ? $ssl['ca'] : null,
null, null
);
if ($ssl) {
$this->ssl_set($ssl['key'], $ssl['cert'], $ssl['ca'], '', '');
}
$return = @$this->real_connect(
($server != "" ? $host : ini_get("mysqli.default_host")),
($server . $username != "" ? $username : ini_get("mysqli.default_user")),
@@ -34,7 +29,7 @@ if (isset($_GET["mysql"])) {
$database,
(is_numeric($port) ? $port : ini_get("mysqli.default_port")),
(!is_numeric($port) ? $port : $socket),
($ssl ? MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT : 0)
($ssl ? ($ssl['verify'] !== false ? 2048 : 64) : 0) // 2048 - MYSQLI_CLIENT_SSL, 64 - MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT (not available before PHP 5.6.16)
);
$this->options(MYSQLI_OPT_LOCAL_INFILE, false);
return $return;
@@ -64,7 +59,7 @@ if (isset($_GET["mysql"])) {
}
} elseif (extension_loaded("mysql") && !((ini_bool("sql.safe_mode") || ini_bool("mysql.allow_local_infile")) && extension_loaded("pdo_mysql"))) {
class Min_DB {
class Db {
var
$extension = "MySQL", ///< @var string extension name
$server_info, ///< @var string server version
@@ -134,7 +129,7 @@ if (isset($_GET["mysql"])) {
/** Send query
* @param string
* @param bool
* @return mixed bool or Min_Result
* @return mixed bool or Result
*/
function query($query, $unbuffered = false) {
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
@@ -149,7 +144,7 @@ if (isset($_GET["mysql"])) {
$this->info = mysql_info($this->_link);
return true;
}
return new Min_Result($result);
return new Result($result);
}
/** Send query with more resultsets
@@ -161,7 +156,7 @@ if (isset($_GET["mysql"])) {
}
/** Get current resultset
* @return Min_Result
* @return Result
*/
function store_result() {
return $this->_result;
@@ -189,7 +184,7 @@ if (isset($_GET["mysql"])) {
}
}
class Min_Result {
class Result {
var
$num_rows, ///< @var int number of rows in the result
$_result, $_offset = 0 ///< @access private
@@ -236,33 +231,38 @@ if (isset($_GET["mysql"])) {
}
} elseif (extension_loaded("pdo_mysql")) {
class Min_DB extends Min_PDO {
class Db extends PdoDb {
var $extension = "PDO_MySQL";
function connect($server, $username, $password) {
global $adminer;
$dsn = "mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server));
$options = [PDO::MYSQL_ATTR_LOCAL_INFILE => false];
$options = array(\PDO::MYSQL_ATTR_LOCAL_INFILE => false);
$ssl = $adminer->connectSsl();
if (isset($ssl['key'])) {
$options[PDO::MYSQL_ATTR_SSL_KEY] = $ssl['key'];
if ($ssl) {
if ($ssl['key']) {
$options[\PDO::MYSQL_ATTR_SSL_KEY] = $ssl['key'];
}
if (isset($ssl['cert'])) {
$options[PDO::MYSQL_ATTR_SSL_CERT] = $ssl['cert'];
if ($ssl['cert']) {
$options[\PDO::MYSQL_ATTR_SSL_CERT] = $ssl['cert'];
}
if (isset($ssl['ca'])) {
$options[PDO::MYSQL_ATTR_SSL_CA] = $ssl['ca'];
if ($ssl['ca']) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $ssl['ca'];
}
$this->dsn($dsn, $username, $password, $options);
if (isset($ssl['verify'])) {
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $ssl['verify'];
}
}
$this->dsn(
"mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)),
$username,
$password,
$options
);
return true;
}
function set_charset($charset) {
$this->query("SET NAMES $charset");
$this->query("SET NAMES $charset"); // charset in DSN is ignored before PHP 5.3.6
}
function select_db($database) {
@@ -271,7 +271,7 @@ if (isset($_GET["mysql"])) {
}
function query($query, $unbuffered = false) {
$this->pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, !$unbuffered);
$this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, !$unbuffered);
return parent::query($query, $unbuffered);
}
}
@@ -280,7 +280,52 @@ if (isset($_GET["mysql"])) {
class Min_Driver extends Min_SQL {
class Driver extends SqlDriver {
static $possibleDrivers = array("MySQLi", "MySQL", "PDO_MySQL");
static $jush = "sql"; ///< @var string JUSH identifier
var $unsigned = array("unsigned", "zerofill", "unsigned zerofill");
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "FIND_IN_SET", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL");
var $functions = array("char_length", "date", "from_unixtime", "lower", "round", "floor", "ceil", "sec_to_time", "time_to_sec", "upper");
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
$this->types = array(
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
lang('Lists') => array("enum" => 65535, "set" => 64),
lang('Binary') => array("bit" => 20, "binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
lang('Geometry') => array("geometry" => 0, "point" => 0, "linestring" => 0, "polygon" => 0, "multipoint" => 0, "multilinestring" => 0, "multipolygon" => 0, "geometrycollection" => 0),
);
$this->editFunctions = array(
array(
"char" => "md5/sha1/password/encrypt/uuid",
"binary" => "md5/sha1",
"date|time" => "now",
), array(
number_type() => "+/-",
"date" => "+ interval/- interval",
"time" => "addtime/subtime",
"char|text" => "concat",
)
);
if (min_version('5.7.8', 10.2, $connection)) {
$this->types[lang('Strings')]["json"] = 4294967295;
}
if (min_version('', 10.7, $connection)) {
$this->types[lang('Strings')]["uuid"] = 128;
$this->editFunctions[0]['uuid'] = 'uuid';
}
if (min_version(9, '', $connection)) {
$this->types[lang('Numbers')]["vector"] = 16383;
$this->editFunctions[0]['vector'] = 'string_to_vector';
}
if (min_version(5.7, 10.2, $connection)) {
$this->generated = array("STORED", "VIRTUAL");
}
}
function insert($table, $set) {
return ($set ? parent::insert($table, $set) : queries("INSERT INTO " . table($table) . " ()\nVALUES ()"));
@@ -321,8 +366,8 @@ if (isset($_GET["mysql"])) {
}
}
function convertSearch($idf, array $where, array $field) {
return (preg_match('~char|text|enum|set~', $field["type"]) && !preg_match("~^utf8~", $field["collation"]) && preg_match('~[\x80-\xFF]~', $where['val'])
function convertSearch($idf, $val, $field) {
return (preg_match('~char|text|enum|set~', $field["type"]) && !preg_match("~^utf8~", $field["collation"]) && preg_match('~[\x80-\xFF]~', $val['val'])
? "CONVERT($idf USING " . charset($this->_conn) . ")"
: $idf
);
@@ -337,16 +382,24 @@ if (isset($_GET["mysql"])) {
}
}
function tableHelp($name) {
function tableHelp($name, $is_view = false) {
$maria = preg_match('~MariaDB~', $this->_conn->server_info);
if (information_schema(DB)) {
return strtolower(($maria ? "information-schema-$name-table/" : str_replace("_", "-", $name) . "-table.html"));
return strtolower("information-schema-" . ($maria ? "$name-table/" : str_replace("_", "-", $name) . "-table.html"));
}
if (DB == "mysql") {
return ($maria ? "mysql$name-table/" : "system-database.html"); //! more precise link
return ($maria ? "mysql$name-table/" : "system-schema.html"); //! more precise link
}
}
function hasCStyleEscapes() {
static $c_style;
if ($c_style === null) {
$sql_mode = $this->_conn->result("SHOW VARIABLES LIKE 'sql_mode'", 1);
$c_style = (strpos($sql_mode, 'NO_BACKSLASH_ESCAPES') === false);
}
return $c_style;
}
}
@@ -368,31 +421,14 @@ if (isset($_GET["mysql"])) {
}
/** Connect to the database
* @return mixed Min_DB or string for error
* @param array [$server, $username, $password]
* @return mixed Db or string for error
*/
function connect() {
global $adminer, $types, $structured_types, $edit_functions;
$connection = new Min_DB;
$credentials = $adminer->credentials();
function connect($credentials) {
$connection = new Db;
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
$connection->set_charset(charset($connection));
$connection->set_charset(charset($connection)); // available in MySQLi since PHP 5.0.5
$connection->query("SET sql_quote_show_create = 1, autocommit = 1");
if (min_version('5.7.8', '10.2', $connection)) {
$structured_types[lang('Strings')][] = "json";
$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->error;
@@ -410,10 +446,7 @@ if (isset($_GET["mysql"])) {
// SHOW DATABASES can take a very long time so it is cached
$return = get_session("dbs");
if ($return === null) {
$query = (min_version(5)
? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"
: "SHOW DATABASES"
); // SHOW DATABASES can be disabled by skip_show_database
$query = "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"; // SHOW DATABASES can be disabled by skip_show_database
$return = ($flush ? slow_query($query) : get_vals($query));
restart_session();
set_session("dbs", $return);
@@ -451,9 +484,8 @@ if (isset($_GET["mysql"])) {
* @return string
*/
function db_collation($db, $collations) {
global $connection;
$return = null;
$create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1);
$create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1);
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
$return = $match[1];
} elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
@@ -480,23 +512,19 @@ if (isset($_GET["mysql"])) {
* @return string
*/
function logged_user() {
global $connection;
return $connection->result("SELECT USER()");
return get_val("SELECT USER()");
}
/** Get tables list
* @return array array($name => $type)
* @return array [$name => $type]
*/
function tables_list() {
return get_key_vals(min_version(5)
? "SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME"
: "SHOW TABLES"
);
return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME");
}
/** Count tables in all databases
* @param array
* @return array array($db => $tables)
* @return array [$db => $tables]
*/
function count_tables($databases) {
$return = array();
@@ -509,17 +537,17 @@ if (isset($_GET["mysql"])) {
/** Get table status
* @param string
* @param bool return only "Name", "Engine" and "Comment" fields
* @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 [$name => ["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) {
if ($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");
} else {
$query = "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "");
}
$tables = [];
foreach (get_rows($query) as $row) {
$return = array();
foreach (
get_rows(
$fast
? "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")
: "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "")
) as $row
) {
if ($row["Engine"] == "InnoDB") {
// ignore internal comment, unnecessary since MySQL 5.1.21
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\1', $row["Comment"]);
@@ -532,11 +560,9 @@ if (isset($_GET["mysql"])) {
$row["Name"] = $name;
return $row;
}
$tables[$row["Name"]] = $row;
$return[$row["Name"]] = $row;
}
return $tables;
return $return;
}
/** Find out whether the identifier is view
@@ -558,28 +584,39 @@ if (isset($_GET["mysql"])) {
/** Get information about fields
* @param string
* @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
* @return array [$name => ["field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => , "generated" => ]]
*/
function fields($table) {
$return = array();
foreach (get_rows("SHOW FULL COLUMNS FROM " . table($table)) as $row) {
preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
$return[$row["Field"]] = array(
"field" => $row["Field"],
"full_type" => $row["Type"],
foreach (get_rows("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . q($table) . " ORDER BY ORDINAL_POSITION") as $row) {
$field = $row["COLUMN_NAME"];
$default = $row["COLUMN_DEFAULT"];
$type = $row["COLUMN_TYPE"];
$extra = $row["EXTRA"];
// https://mariadb.com/kb/en/library/show-columns/, https://github.com/vrana/adminer/pull/359#pullrequestreview-276677186
preg_match('~^(VIRTUAL|PERSISTENT|STORED)~', $extra, $generated);
preg_match('~^([^( ]+)(?:\((.+)\))?( unsigned)?( zerofill)?$~', $type, $match);
$return[$field] = array(
"field" => $field,
"full_type" => $type,
"type" => $match[1],
"length" => $match[2],
"unsigned" => ltrim($match[3] . $match[4]),
"default" => ($row["Default"] != "" || preg_match("~char|set~", $match[1]) ? (preg_match('~text~', $match[1]) ? stripslashes(preg_replace("~^'(.*)'\$~", '\1', $row["Default"])) : $row["Default"]) : null),
"null" => ($row["Null"] == "YES"),
"auto_increment" => ($row["Extra"] == "auto_increment"),
"on_update" => (preg_match('~^on update (.+)~i', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
"collation" => $row["Collation"],
"privileges" => array_flip(preg_split('~, *~', $row["Privileges"])) + ["where" => 1, "order" => 1],
"comment" => $row["Comment"],
"primary" => ($row["Key"] == "PRI"),
// https://mariadb.com/kb/en/library/show-columns/, https://github.com/vrana/adminer/pull/359#pullrequestreview-276677186
"generated" => preg_match('~^(VIRTUAL|PERSISTENT|STORED)~', $row["Extra"]),
"default" => ($generated
? $row["GENERATION_EXPRESSION"]
: ($default != "" || preg_match("~char|set~", $match[1])
? (preg_match('~text~', $match[1]) ? stripslashes(preg_replace("~^'(.*)'\$~", '\1', $default)) : $default)
: null
)
),
"null" => ($row["IS_NULLABLE"] == "YES"),
"auto_increment" => ($extra == "auto_increment"),
"on_update" => (preg_match('~\bon update (\w+)~i', $extra, $match) ? $match[1] : ""), //! available since MySQL 5.1.23
"collation" => $row["COLLATION_NAME"],
"privileges" => array_flip(explode(",", "$row[PRIVILEGES],where,order")),
"comment" => $row["COLUMN_COMMENT"],
"primary" => ($row["COLUMN_KEY"] == "PRI"),
"generated" => ($generated[1] == "PERSISTENT" ? "STORED" : $generated[1]),
);
}
return $return;
@@ -587,8 +624,8 @@ if (isset($_GET["mysql"])) {
/** Get table indexes
* @param string
* @param string Min_DB to use
* @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array(), "descs" => array()))
* @param string Db to use
* @return array [$key_name => ["type" => , "columns" => [], "lengths" => [], "descs" => []]]
*/
function indexes($table, $connection2 = null) {
$return = array();
@@ -604,25 +641,25 @@ if (isset($_GET["mysql"])) {
/** Get foreign keys in table
* @param string
* @return array array($name => array("db" => , "ns" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
* @return array [$name => ["db" => , "ns" => , "table" => , "source" => [], "target" => [], "on_delete" => , "on_update" => ]]
*/
function foreign_keys($table) {
global $connection, $on_actions;
global $driver;
static $pattern = '(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")';
$return = array();
$create_table = $connection->result("SHOW CREATE TABLE " . table($table), 1);
$create_table = get_val("SHOW CREATE TABLE " . table($table), 1);
if ($create_table) {
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($on_actions))?(?: ON UPDATE ($on_actions))?~", $create_table, $matches, PREG_SET_ORDER);
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($driver->onActions))?(?: ON UPDATE ($driver->onActions))?~", $create_table, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
preg_match_all("~$pattern~", $match[2], $source);
preg_match_all("~$pattern~", $match[5], $target);
$return[idf_unescape($match[1])] = array(
"db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
"table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
"source" => array_map('idf_unescape', $source[0]),
"target" => array_map('idf_unescape', $target[0]),
"on_delete" => ($match[6] ? $match[6] : "RESTRICT"),
"on_update" => ($match[7] ? $match[7] : "RESTRICT"),
"source" => array_map('Adminer\idf_unescape', $source[0]),
"target" => array_map('Adminer\idf_unescape', $target[0]),
"on_delete" => ($match[6] ?: "RESTRICT"),
"on_update" => ($match[7] ?: "RESTRICT"),
);
}
}
@@ -631,11 +668,10 @@ if (isset($_GET["mysql"])) {
/** Get view SELECT
* @param string
* @return array array("select" => )
* @return array ["select" => ]
*/
function view($name) {
global $connection;
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', $connection->result("SHOW CREATE VIEW " . table($name), 1)));
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', get_val("SHOW CREATE VIEW " . table($name), 1)));
}
/** Get sorted grouped list of collations
@@ -662,7 +698,7 @@ if (isset($_GET["mysql"])) {
* @return bool
*/
function information_schema($db) {
return (min_version(5) && $db == "information_schema")
return ($db == "information_schema")
|| (min_version(5.5) && $db == "performance_schema");
}
@@ -688,7 +724,7 @@ if (isset($_GET["mysql"])) {
* @return bool
*/
function drop_databases($databases) {
$return = apply_queries("DROP DATABASE", $databases, 'idf_escape');
$return = apply_queries("DROP DATABASE", $databases, 'Adminer\idf_escape');
restart_session();
set_session("dbs", null);
return $return;
@@ -740,7 +776,7 @@ if (isset($_GET["mysql"])) {
/** Run commands to create or alter table
* @param string "" to create
* @param string new name
* @param array of array($orig, $process_field, $after)
* @param array of [$orig, $process_field, $after]
* @param array of strings
* @param string
* @param string
@@ -752,10 +788,16 @@ if (isset($_GET["mysql"])) {
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
$alter = array();
foreach ($fields as $field) {
$alter[] = ($field[1]
? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "")
: "DROP " . idf_escape($field[0])
);
if ($field[1]) {
$default = $field[1][3];
if (preg_match('~ GENERATED~', $default)) {
$field[1][3] = $field[1][2];
$field[1][2] = $default;
}
$alter[] = ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "");
} else {
$alter[] = "DROP " . idf_escape($field[0]);
}
}
$alter = array_merge($alter, $foreign);
$status = ($comment !== null ? " COMMENT=" . q($comment) : "")
@@ -777,7 +819,7 @@ if (isset($_GET["mysql"])) {
/** Run commands to alter indexes
* @param string escaped table name
* @param array of array("index type", "name", array("column definition", ...)) or array("index type", "name", "DROP")
* @param array of ["index type", "name", ["column definition", ...]] or ["index type", "name", "DROP"]
* @return bool
*/
function alter_indexes($table, $alter) {
@@ -803,7 +845,7 @@ if (isset($_GET["mysql"])) {
* @return bool
*/
function drop_views($views) {
return queries("DROP VIEW " . implode(", ", array_map('table', $views)));
return queries("DROP VIEW " . implode(", ", array_map('Adminer\table', $views)));
}
/** Drop tables
@@ -811,7 +853,7 @@ if (isset($_GET["mysql"])) {
* @return bool
*/
function drop_tables($tables) {
return queries("DROP TABLE " . implode(", ", array_map('table', $tables)));
return queries("DROP TABLE " . implode(", ", array_map('Adminer\table', $tables)));
}
/** Move tables to other schema
@@ -854,7 +896,8 @@ if (isset($_GET["mysql"])) {
queries("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'");
foreach ($tables as $table) {
$name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
if (($_POST["overwrite"] && !queries("\nDROP TABLE IF EXISTS $name"))
if (
($_POST["overwrite"] && !queries("\nDROP TABLE IF EXISTS $name"))
|| !queries("CREATE TABLE $name LIKE " . table($table))
|| !queries("INSERT INTO $name SELECT * FROM " . table($table))
) {
@@ -870,8 +913,10 @@ if (isset($_GET["mysql"])) {
foreach ($views as $table) {
$name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
$view = view($table);
if (($_POST["overwrite"] && !queries("DROP VIEW IF EXISTS $name"))
|| !queries("CREATE VIEW $name AS $view[select]")) { //! USE to avoid db.table
if (
($_POST["overwrite"] && !queries("DROP VIEW IF EXISTS $name"))
|| !queries("CREATE VIEW $name AS $view[select]") //! USE to avoid db.table
) {
return false;
}
}
@@ -880,7 +925,7 @@ if (isset($_GET["mysql"])) {
/** Get information about trigger
* @param string trigger name
* @return array array("Trigger" => , "Timing" => , "Event" => , "Of" => , "Type" => , "Statement" => )
* @return array ["Trigger" => , "Timing" => , "Event" => , "Of" => , "Type" => , "Statement" => ]
*/
function trigger($name) {
if ($name == "") {
@@ -892,7 +937,7 @@ if (isset($_GET["mysql"])) {
/** Get defined triggers
* @param string
* @return array array($name => array($timing, $event))
* @return array [$name => [$timing, $event]]
*/
function triggers($table) {
$return = array();
@@ -903,7 +948,7 @@ if (isset($_GET["mysql"])) {
}
/** Get trigger options
* @return array ("Timing" => array(), "Event" => array(), "Type" => array())
* @return array ["Timing" => [], "Event" => [], "Type" => []]
*/
function trigger_options() {
return array(
@@ -913,61 +958,48 @@ if (isset($_GET["mysql"])) {
);
}
/**
* Gets information about stored routine.
*
* @param string $name
* @param string $type "FUNCTION" or "PROCEDURE"
*
* @return array ("fields" => array("field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ), "returns" => , "definition" => , "language" => )
/** Get information about stored routine
* @param string
* @param string "FUNCTION" or "PROCEDURE"
* @return array ["fields" => ["field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ], "returns" => , "definition" => , "language" => ]
*/
function routine($name, $type) {
global $connection, $enum_length, $inout, $types;
$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"];
global $driver;
$aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar");
$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,]+)['\"]?)?";
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : $inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
$create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
$type_pattern = "((" . implode("|", array_merge(array_keys($driver->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$driver->enumLength)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?";
$pattern = "$space*(" . ($type == "FUNCTION" ? "" : $driver->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
$create = get_val("SHOW CREATE $type " . idf_escape($name), 2);
preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match);
$fields = [];
$fields = array();
preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER);
foreach ($matches as $param) {
$fields[] = [
$fields[] = array(
"field" => str_replace("``", "`", $param[2]) . $param[3],
"type" => strtolower($param[5]),
"length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]),
"length" => preg_replace_callback("~$driver->enumLength~s", 'Adminer\normalize_enum', $param[6]),
"unsigned" => strtolower(preg_replace('~\s+~', ' ', trim("$param[8] $param[7]"))),
"null" => 1,
"full_type" => $param[4],
"inout" => strtoupper($param[1]),
"collation" => strtolower($param[9]),
];
);
}
return $type == "FUNCTION" ? [
return array(
"fields" => $fields,
"returns" => ["type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]],
"comment" => get_val("SELECT ROUTINE_COMMENT FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE() AND ROUTINE_NAME = " . q($name)),
) + ($type != "FUNCTION" ? array("definition" => $match[11]) : array(
"returns" => array("type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]),
"definition" => $match[17],
"language" => $info["ROUTINE_BODY"],
"comment" => $info["ROUTINE_COMMENT"],
] : [
"fields" => $fields,
"returns" => null,
"definition" => $match[11],
"language" => $info["ROUTINE_BODY"],
"comment" => $info["ROUTINE_COMMENT"],
];
"language" => "SQL", // available in information_schema.ROUTINES.BODY_STYLE
));
}
/** 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() {
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));
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
}
/** Get list of available routine languages
@@ -990,14 +1022,13 @@ if (isset($_GET["mysql"])) {
* @return string
*/
function last_id() {
global $connection;
return $connection->result("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint
return get_val("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint
}
/** Explain select
* @param Min_DB
* @param Db
* @param string
* @return Min_Result
* @return Result
*/
function explain($connection, $query) {
return $connection->query("EXPLAIN " . (min_version(5.1) && !min_version(5.7) ? "PARTITIONS " : "") . $query);
@@ -1012,35 +1043,40 @@ if (isset($_GET["mysql"])) {
return ($where || $table_status["Engine"] != "InnoDB" ? null : $table_status["Rows"]);
}
/* Not used is MySQL but checked in compile.php:
/** Get user defined types
* @return array
*/
* @return array [$id => $name]
function types() {
return array();
}
/** Get values of user defined type
* @param int
* @return string
function type_values($id) {
return "";
}
/** Get existing schemas
* @return array
*/
function schemas() {
return array();
}
/** Get current schema
* @return string
*/
function get_schema() {
return "";
}
/** Set current schema
* @param string
* @param Min_DB
* @param Db
* @return bool
*/
function set_schema($schema, $connection2 = null) {
return true;
}
*/
/** Get SQL command to create table
* @param string
@@ -1049,8 +1085,7 @@ if (isset($_GET["mysql"])) {
* @return string
*/
function create_sql($table, $auto_increment, $style) {
global $connection;
$return = $connection->result("SHOW CREATE TABLE " . table($table), 1);
$return = get_val("SHOW CREATE TABLE " . table($table), 1);
if (!$auto_increment) {
$return = preg_replace('~ AUTO_INCREMENT=\d+~', '', $return); //! skip comments
}
@@ -1086,44 +1121,21 @@ if (isset($_GET["mysql"])) {
}
/** Get server variables
* @return array ($name => $value)
* @return array [$name => $value]
*/
function show_variables() {
return get_key_vals("SHOW VARIABLES");
}
/**
* @return bool
*/
function is_strict_mode() {
static $strictMode = null;
if ($strictMode === null) {
$strictMode = (bool)preg_match('~STRICT_(TRANS|ALL)_TABLES~', get_key_vals("SHOW VARIABLES LIKE 'sql_mode'")["sql_mode"]);
}
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
* @return array ($row)
* @return array [$row]
*/
function process_list() {
return get_rows("SHOW FULL PROCESSLIST");
}
/** Get status variables
* @return array ($name => $value)
* @return array [$name => $value]
*/
function show_status() {
return get_key_vals("SHOW STATUS");
@@ -1147,7 +1159,7 @@ if (isset($_GET["mysql"])) {
/** Convert value in edit after applying functions back
* @param array one element from fields()
* @param string
* @param string SQL expression
* @return string
*/
function unconvert_field($field, $return) {
@@ -1155,7 +1167,7 @@ if (isset($_GET["mysql"])) {
$return = "UNHEX($return)";
}
if ($field["type"] == "bit") {
$return = "CONV($return, 2, 10) + 0";
$return = "CONVERT(b$return, UNSIGNED)";
}
if (preg_match("~geometry|point|linestring|polygon~", $field["type"])) {
$prefix = (min_version(8) ? "ST_" : "");
@@ -1165,11 +1177,11 @@ if (isset($_GET["mysql"])) {
}
/** Check whether a feature is supported
* @param string "comment", "copy", "database", "descidx", "drop_col", "dump", "event", "indexes", "kill", "materializedview", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "table", "trigger", "type", "variables", "view", "view_trigger"
* @param string "check", "comment", "copy", "database", "descidx", "drop_col", "dump", "event", "indexes", "kill", "materializedview", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "table", "trigger", "type", "variables", "view", "view_trigger"
* @return bool
*/
function support($feature) {
return !preg_match("~scheme|sequence|type|view_trigger|materializedview" . (min_version(8) ? "" : "|descidx" . (min_version(5.1) ? "" : "|event|partitioning" . (min_version(5) ? "" : "|routine|trigger|view"))) . "~", $feature);
return !preg_match("~scheme|sequence|type|view_trigger|materializedview" . (min_version(8) ? "" : "|descidx" . (min_version(5.1) ? "" : "|event|partitioning")) . (min_version('8.0.16', '10.2.1') ? "" : "|check") . "~", $feature);
}
/** Kill a process
@@ -1191,50 +1203,6 @@ if (isset($_GET["mysql"])) {
* @return int
*/
function max_connections() {
global $connection;
return $connection->result("SELECT @@max_connections");
}
/** Get driver config
* @return array array('possible_drivers' => , 'jush' => , 'types' => , 'structured_types' => , 'unsigned' => , 'operators' => , 'functions' => , 'grouping' => , 'edit_functions' => )
*/
function driver_config() {
$types = array(); ///< @var array ($type => $maximum_unsigned_length, ...)
$structured_types = array(); ///< @var array ($description => array($type, ...), ...)
foreach (array(
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
lang('Lists') => array("enum" => 65535, "set" => 64),
lang('Binary') => array("bit" => 20, "binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
lang('Geometry') => array("geometry" => 0, "point" => 0, "linestring" => 0, "polygon" => 0, "multipoint" => 0, "multilinestring" => 0, "multipolygon" => 0, "geometrycollection" => 0),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
return array(
'possible_drivers' => array("MySQLi", "MySQL", "PDO_MySQL"),
'jush' => "sql", ///< @var string JUSH identifier
'types' => $types,
'structured_types' => $structured_types,
'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
'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
'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"), ///< @var array grouping functions used in select
'edit_functions' => array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
array(
"char" => "md5/sha1/password/encrypt/uuid",
"binary" => "md5/sha1",
"date|time" => "now",
), array(
number_type() => "+/-",
"date" => "+ interval/- interval",
"time" => "addtime/subtime",
"char|text" => "concat",
)
),
);
return get_val("SELECT @@max_connections");
}
}

View File

@@ -1,10 +1,12 @@
<?php
namespace Adminer;
$drivers["oracle"] = "Oracle (beta)";
if (isset($_GET["oracle"])) {
define("DRIVER", "oracle");
define('Adminer\DRIVER', "oracle");
if (extension_loaded("oci8")) {
class Min_DB {
class Db {
var $extension = "oci8", $_link, $_result, $server_info, $affected_rows, $errno, $error;
var $_current_db;
@@ -50,7 +52,7 @@ if (isset($_GET["oracle"])) {
restore_error_handler();
if ($return) {
if (oci_num_fields($result)) {
return new Min_Result($result);
return new Result($result);
}
$this->affected_rows = oci_num_rows($result);
oci_free_statement($result);
@@ -70,16 +72,16 @@ if (isset($_GET["oracle"])) {
return false;
}
function result($query, $field = 1) {
function result($query, $field = 0) {
$result = $this->query($query);
if (!is_object($result) || !oci_fetch($result->_result)) {
return false;
}
return oci_result($result->_result, $field);
return oci_result($result->_result, $field + 1);
}
}
class Min_Result {
class Result {
var $_result, $_offset = 1, $num_rows;
function __construct($result) {
@@ -105,7 +107,7 @@ if (isset($_GET["oracle"])) {
function fetch_field() {
$column = $this->_offset++;
$return = new stdClass;
$return = new \stdClass;
$return->name = oci_field_name($this->_result, $column);
$return->orgname = $return->name;
$return->type = oci_field_type($this->_result, $column);
@@ -119,7 +121,7 @@ if (isset($_GET["oracle"])) {
}
} elseif (extension_loaded("pdo_oci")) {
class Min_DB extends Min_PDO {
class Db extends PdoDb {
var $extension = "PDO_OCI";
var $_current_db;
@@ -138,7 +140,34 @@ if (isset($_GET["oracle"])) {
class Min_Driver extends Min_SQL {
class Driver extends SqlDriver {
static $possibleDrivers = array("OCI8", "PDO_OCI");
static $jush = "oracle";
var $editFunctions = array(
array( //! no parentheses
"date" => "current_date",
"timestamp" => "current_timestamp",
), array(
"number|float|double" => "+/-",
"date|timestamp" => "+ interval/- interval",
"char|clob" => "||",
)
);
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL");
var $functions = array("length", "lower", "round", "upper");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
$this->types = array(
lang('Numbers') => array("number" => 38, "binary_float" => 12, "binary_double" => 21),
lang('Date and time') => array("date" => 10, "timestamp" => 29, "interval year" => 12, "interval day" => 28), //! year(), day() to second()
lang('Strings') => array("char" => 2000, "varchar2" => 4000, "nchar" => 2000, "nvarchar2" => 4000, "clob" => 4294967295, "nclob" => 4294967295),
lang('Binary') => array("raw" => 2000, "long raw" => 2147483648, "blob" => 4294967295, "bfile" => 4294967296),
);
}
//! support empty $set in insert()
@@ -157,24 +186,22 @@ if (isset($_GET["oracle"])) {
$where[] = "$key = $val";
}
}
if (!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")")
)) {
if (
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"))
) {
return false;
}
}
return true;
}
function hasCStyleEscapes() {
return true;
}
}
/**
* @param string $hostPath
* @return bool
*/
function is_server_host_valid($hostPath) {
// EasyConnect host+path format: host[/[service_name][:server_type][/instance_name]]
return (bool)preg_match('~^[^/]+(/([^/:]+)?(:[^/:]+)?(/[^/:]+)?)?$~', $hostPath);
}
function idf_escape($idf) {
return '"' . str_replace('"', '""', $idf) . '"';
@@ -184,10 +211,8 @@ if (isset($_GET["oracle"])) {
return idf_escape($idf);
}
function connect() {
global $adminer;
$connection = new Min_DB;
$credentials = $adminer->credentials();
function connect($credentials) {
$connection = new Db;
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection;
}
@@ -195,7 +220,13 @@ if (isset($_GET["oracle"])) {
}
function get_databases() {
return get_vals("SELECT tablespace_name FROM user_tablespaces ORDER BY 1");
return get_vals(
"SELECT DISTINCT tablespace_name FROM (
SELECT tablespace_name FROM user_tablespaces
UNION SELECT tablespace_name FROM all_tables WHERE tablespace_name IS NOT NULL
)
ORDER BY 1"
);
}
function limit($query, $where, $limit, $offset = 0, $separator = " ") {
@@ -210,8 +241,7 @@ if (isset($_GET["oracle"])) {
}
function db_collation($db, $collations) {
global $connection;
return $connection->result("SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'"); //! respect $db
return get_val("SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'"); //! respect $db
}
function engines() {
@@ -219,13 +249,12 @@ if (isset($_GET["oracle"])) {
}
function logged_user() {
global $connection;
return $connection->result("SELECT USER FROM DUAL");
return get_val("SELECT USER FROM DUAL");
}
function get_current_db() {
global $connection;
$db = $connection->_current_db ? $connection->_current_db : DB;
$db = $connection->_current_db ?: DB;
unset($connection->_current_db);
return $db;
}
@@ -239,23 +268,23 @@ if (isset($_GET["oracle"])) {
function views_table($columns) {
$owner = where_owner('');
return "(SELECT $columns FROM all_views WHERE " . ($owner ? $owner : "rownum < 0") . ")";
return "(SELECT $columns FROM all_views WHERE " . ($owner ?: "rownum < 0") . ")";
}
function tables_list() {
$view = views_table("view_name");
$owner = where_owner(" AND ");
return get_key_vals("SELECT table_name, 'table' FROM all_tables WHERE tablespace_name = " . q(DB) . "$owner
return get_key_vals(
"SELECT table_name, 'table' FROM all_tables WHERE tablespace_name = " . q(DB) . "$owner
UNION SELECT view_name, 'view' FROM $view
ORDER BY 1"
); //! views don't have schema
}
function count_tables($databases) {
global $connection;
$return = array();
foreach ($databases as $db) {
$return[$db] = $connection->result("SELECT COUNT(*) FROM all_tables WHERE tablespace_name = " . q($db));
$return[$db] = get_val("SELECT COUNT(*) FROM all_tables WHERE tablespace_name = " . q($db));
}
return $return;
}
@@ -266,10 +295,11 @@ ORDER BY 1"
$db = get_current_db();
$view = views_table("view_name");
$owner = where_owner(" AND ");
foreach (get_rows('SELECT table_name "Name", \'table\' "Engine", avg_row_len * num_rows "Data_length", num_rows "Rows" FROM all_tables WHERE tablespace_name = ' . q($db) . $owner . ($name != "" ? " AND table_name = $search" : "") . "
foreach (
get_rows('SELECT table_name "Name", \'table\' "Engine", avg_row_len * num_rows "Data_length", num_rows "Rows" FROM all_tables WHERE tablespace_name = ' . q($db) . $owner . ($name != "" ? " AND table_name = $search" : "") . "
UNION SELECT view_name, 'view', 0, 0 FROM $view" . ($name != "" ? " WHERE view_name = $search" : "") . "
ORDER BY 1"
) as $row) {
ORDER BY 1") as $row
) {
if ($name != "") {
return $row;
}
@@ -315,12 +345,14 @@ ORDER BY 1"
function indexes($table, $connection2 = null) {
$return = array();
$owner = where_owner(" AND ", "aic.table_owner");
foreach (get_rows("SELECT aic.*, ac.constraint_type, atc.data_default
foreach (
get_rows("SELECT aic.*, ac.constraint_type, atc.data_default
FROM all_ind_columns aic
LEFT JOIN all_constraints ac ON aic.index_name = ac.constraint_name AND aic.table_name = ac.table_name AND aic.index_owner = ac.owner
LEFT JOIN all_tab_cols atc ON aic.column_name = atc.column_name AND aic.table_name = atc.table_name AND aic.index_owner = atc.owner
WHERE aic.table_name = " . q($table) . "$owner
ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row) {
ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row
) {
$index_name = $row["INDEX_NAME"];
$column_name = $row["DATA_DEFAULT"];
$column_name = ($column_name ? trim($column_name, '"') : $row["COLUMN_NAME"]); // trim - possibly wrapped in quotes but never contains quotes inside
@@ -343,7 +375,7 @@ ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row) {
}
function information_schema($db) {
return false;
return get_schema() == "INFORMATION_SCHEMA";
}
function error() {
@@ -466,12 +498,11 @@ AND c_src.TABLE_NAME = " . q($table);
function schemas() {
$return = get_vals("SELECT DISTINCT owner FROM dba_segments WHERE owner IN (SELECT username FROM dba_users WHERE default_tablespace NOT IN ('SYSTEM','SYSAUX')) ORDER BY 1");
return ($return ? $return : get_vals("SELECT DISTINCT owner FROM all_tables WHERE tablespace_name = " . q(DB) . " ORDER BY 1"));
return ($return ?: get_vals("SELECT DISTINCT owner FROM all_tables WHERE tablespace_name = " . q(DB) . " ORDER BY 1"));
}
function get_schema() {
global $connection;
return $connection->result("SELECT sys_context('USERENV', 'SESSION_USER') FROM dual");
return get_val("SELECT sys_context('USERENV', 'SESSION_USER') FROM dual");
}
function set_schema($scheme, $connection2 = null) {
@@ -486,17 +517,6 @@ AND c_src.TABLE_NAME = " . q($table);
return get_key_vals('SELECT name, display_value FROM v$parameter');
}
/**
* @return bool
*/
function is_strict_mode() {
return false;
}
function is_c_style_escapes() {
return true;
}
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"
FROM v$session sess LEFT OUTER JOIN v$sql sql
@@ -521,39 +541,4 @@ ORDER BY PROCESS
function support($feature) {
return preg_match('~^(columns|database|drop_col|indexes|descidx|processlist|scheme|sql|status|table|variables|view)$~', $feature); //!
}
function driver_config() {
$types = array();
$structured_types = array();
foreach (array(
lang('Numbers') => array("number" => 38, "binary_float" => 12, "binary_double" => 21),
lang('Date and time') => array("date" => 10, "timestamp" => 29, "interval year" => 12, "interval day" => 28), //! year(), day() to second()
lang('Strings') => array("char" => 2000, "varchar2" => 4000, "nchar" => 2000, "nvarchar2" => 4000, "clob" => 4294967295, "nclob" => 4294967295),
lang('Binary') => array("raw" => 2000, "long raw" => 2147483648, "blob" => 4294967295, "bfile" => 4294967296),
) as $key => $val) {
$types += $val;
$structured_types[$key] = array_keys($val);
}
return array(
'possible_drivers' => array("OCI8", "PDO_OCI"),
'jush' => "oracle",
'types' => $types,
'structured_types' => $structured_types,
'unsigned' => array(),
'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"),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array(
array( //! no parentheses
"date" => "current_date",
"timestamp" => "current_timestamp",
), array(
"number|float|double" => "+/-",
"date|timestamp" => "+ interval/- interval",
"char|clob" => "||",
)
),
);
}
}

View File

@@ -1,10 +1,12 @@
<?php
namespace Adminer;
$drivers["pgsql"] = "PostgreSQL";
if (isset($_GET["pgsql"])) {
define("DRIVER", "pgsql");
define('Adminer\DRIVER', "pgsql");
if (extension_loaded("pgsql")) {
class Min_DB {
class Db {
var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error, $timeout;
function _error($errno, $error) {
@@ -19,14 +21,11 @@ if (isset($_GET["pgsql"])) {
global $adminer;
$db = $adminer->database();
set_error_handler(array($this, '_error'));
$this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
$ssl = $adminer->connectSsl();
if (isset($ssl["mode"])) {
$this->_string .= " sslmode='" . $ssl["mode"] . "'";
}
$this->_link = @pg_connect("$this->_string dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'", PGSQL_CONNECT_FORCE_NEW);
if (!$this->_link && $db != "") {
// try to connect directly with database for performance
@@ -80,7 +79,7 @@ if (isset($_GET["pgsql"])) {
$this->affected_rows = pg_affected_rows($result);
$return = true;
} else {
$return = new Min_Result($result);
$return = new Result($result);
}
if ($this->timeout) {
$this->timeout = 0;
@@ -115,7 +114,7 @@ if (isset($_GET["pgsql"])) {
}
}
class Min_Result {
class Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
@@ -133,7 +132,7 @@ if (isset($_GET["pgsql"])) {
function fetch_field() {
$column = $this->_offset++;
$return = new stdClass;
$return = new \stdClass;
if (function_exists('pg_field_table')) {
$return->orgtable = pg_field_table($this->_result, $column);
}
@@ -150,24 +149,19 @@ if (isset($_GET["pgsql"])) {
}
} elseif (extension_loaded("pdo_pgsql")) {
class Min_DB extends Min_PDO {
class Db extends PdoDb {
var $extension = "PDO_PgSQL", $timeout;
function connect($server, $username, $password) {
global $adminer;
$db = $adminer->database();
//! client_encoding is supported since 9.1, but we can't yet use min_version here
$dsn = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'";
$ssl = $adminer->connectSsl();
if (isset($ssl["mode"])) {
$dsn .= " sslmode='" . $ssl["mode"] . "'";
}
$this->dsn($dsn, $username, $password);
return true;
}
@@ -201,7 +195,53 @@ if (isset($_GET["pgsql"])) {
class Min_Driver extends Min_SQL {
class Driver extends SqlDriver {
static $possibleDrivers = array("PgSQL", "PDO_PgSQL");
static $jush = "pgsql";
var $operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE", "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // no "SQL" to avoid CSRF
var $functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
var $grouping = array("avg", "count", "count distinct", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
$this->types = array( //! arrays
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "timestamptz" => 21, "interval" => 0),
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "macaddr8" => 23, "txid_snapshot" => 0),
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
);
if (min_version(9.2, 0, $connection)) {
$this->types[lang('Strings')]["json"] = 4294967295;
if (min_version(9.4, 0, $connection)) {
$this->types[lang('Strings')]["jsonb"] = 4294967295;
}
}
$this->editFunctions = array(
array(
"char" => "md5",
"date|time" => "now",
), array(
number_type() => "+/-",
"date|time" => "+ interval/- interval", //! escape
"char|text" => "||",
)
);
if (min_version(12, 0, $connection)) {
$this->generated = array("STORED");
}
}
function enumLength($field) {
$enum = $this->types[lang('User types')][$field["type"]];
return ($enum ? type_values($enum) : "");
}
function setUserTypes($types) {
$this->types[lang('User types')] = array_flip($types);
}
function insertUpdate($table, $rows, $primary) {
global $connection;
@@ -214,9 +254,10 @@ if (isset($_GET["pgsql"])) {
$where[] = "$key = $val";
}
}
if (!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")")
)) {
if (
!(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows)
|| queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"))
) {
return false;
}
}
@@ -229,9 +270,9 @@ if (isset($_GET["pgsql"])) {
return $query;
}
function convertSearch($idf, array $where, array $field) {
function convertSearch($idf, $val, $field) {
$textTypes = "char|text";
if (strpos($where["op"], "LIKE") === false) {
if (strpos($val["op"], "LIKE") === false) {
$textTypes .= "|date|time(stamp)?|boolean|uuid|inet|cidr|macaddr|" . number_type();
}
@@ -246,10 +287,10 @@ if (isset($_GET["pgsql"])) {
return $this->_conn->warnings();
}
function tableHelp($name) {
function tableHelp($name, $is_view = false) {
$links = array(
"information_schema" => "infoschema",
"pg_catalog" => "catalog",
"pg_catalog" => ($is_view ? "view" : "catalog"),
);
$link = $links[$_GET["ns"]];
if ($link) {
@@ -257,6 +298,17 @@ if (isset($_GET["pgsql"])) {
}
}
function supportsIndex($table_status) {
return $table_status["Engine"] != "view";
}
function hasCStyleEscapes() {
static $c_style;
if ($c_style === null) {
$c_style = ($this->_conn->result("SHOW standard_conforming_strings") == "off");
}
return $c_style;
}
}
@@ -269,21 +321,11 @@ if (isset($_GET["pgsql"])) {
return idf_escape($idf);
}
function connect() {
global $adminer, $types, $structured_types;
$connection = new Min_DB;
$credentials = $adminer->credentials();
function connect($credentials) {
$connection = new Db;
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
if (min_version(9, 0, $connection)) {
$connection->query("SET application_name = 'Adminer'");
if (min_version(9.2, 0, $connection)) {
$structured_types[lang('Strings')][] = "json";
$types["json"] = 4294967295;
if (min_version(9.4, 0, $connection)) {
$structured_types[lang('Strings')][] = "jsonb";
$types["jsonb"] = 4294967295;
}
}
}
return $connection;
}
@@ -291,9 +333,9 @@ if (isset($_GET["pgsql"])) {
}
function get_databases() {
return get_vals("SELECT d.datname FROM pg_database d JOIN pg_roles r ON d.datdba = r.oid
WHERE d.datallowconn = TRUE AND has_database_privilege(d.datname, 'CONNECT') AND pg_has_role(r.rolname, 'USAGE')
ORDER BY d.datname");
return get_vals("SELECT datname FROM pg_database
WHERE datallowconn = TRUE AND has_database_privilege(datname, 'CONNECT')
ORDER BY datname");
}
function limit($query, $where, $limit, $offset = 0, $separator = " ") {
@@ -308,8 +350,7 @@ if (isset($_GET["pgsql"])) {
}
function db_collation($db, $collations) {
global $connection;
return $connection->result("SELECT datcollate FROM pg_database WHERE datname = " . q($db));
return get_val("SELECT datcollate FROM pg_database WHERE datname = " . q($db));
}
function engines() {
@@ -317,13 +358,12 @@ if (isset($_GET["pgsql"])) {
}
function logged_user() {
global $connection;
return $connection->result("SELECT user");
return get_val("SELECT user");
}
function tables_list() {
$query = "SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = current_schema()";
if (support('materializedview')) { // ' - support("materializedview") could be removed by compile.php
if (support("materializedview")) {
$query .= "
UNION ALL
SELECT matviewname, 'MATERIALIZED VIEW'
@@ -336,17 +376,38 @@ ORDER BY 1";
}
function count_tables($databases) {
return array(); // would require reconnect
global $connection;
$return = array();
foreach ($databases as $db) {
if ($connection->select_db($db)) {
$return[$db] = count(tables_list());
}
}
return $return;
}
function table_status($name = "") {
static $has_size;
if ($has_size === null) {
// https://github.com/cockroachdb/cockroach/issues/40391
$has_size = get_val("SELECT 'pg_table_size'::regproc");
}
$return = array();
foreach (get_rows("SELECT c.relname AS \"Name\", CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\", pg_table_size(c.oid) AS \"Data_length\", pg_indexes_size(c.oid) AS \"Index_length\", obj_description(c.oid, 'pg_class') AS \"Comment\", " . (min_version(12) ? "''" : "CASE WHEN c.relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\", c.reltuples as \"Rows\", n.nspname
foreach (
get_rows("SELECT
c.relname AS \"Name\",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'm' THEN 'materialized view' ELSE 'view' END AS \"Engine\"" . ($has_size ? ",
pg_table_size(c.oid) AS \"Data_length\",
pg_indexes_size(c.oid) AS \"Index_length\"" : "") . ",
obj_description(c.oid, 'pg_class') AS \"Comment\",
" . (min_version(12) ? "''" : "CASE WHEN c.relhasoids THEN 'oid' ELSE '' END") . " AS \"Oid\",
c.reltuples as \"Rows\",
n.nspname
FROM pg_class c
JOIN pg_namespace n ON(n.nspname = current_schema() AND n.oid = c.relnamespace)
WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
" . ($name != "" ? "AND relname = " . q($name) : "ORDER BY relname")
) as $row) { //! Index_length, Auto_increment
" . ($name != "" ? "AND relname = " . q($name) : "ORDER BY relname")) as $row //! Index_length, Auto_increment
) {
$return[$row["Name"]] = $row;
}
return ($name != "" ? $return[$name] : $return);
@@ -366,8 +427,8 @@ WHERE relkind IN ('r', 'm', 'v', 'f', 'p')
'timestamp without time zone' => 'timestamp',
'timestamp with time zone' => 'timestamptz',
);
foreach (get_rows("SELECT a.attname AS field, format_type(a.atttypid, a.atttypmod) AS full_type, pg_get_expr(d.adbin, d.adrelid) AS default, a.attnotnull::int, col_description(c.oid, a.attnum) AS comment" . (min_version(10) ? ", a.attidentity" : "") . "
foreach (
get_rows("SELECT a.attname AS field, format_type(a.atttypid, a.atttypmod) AS full_type, pg_get_expr(d.adbin, d.adrelid) AS default, a.attnotnull::int, col_description(c.oid, a.attnum) AS comment" . (min_version(10) ? ", a.attidentity" . (min_version(12) ? ", a.attgenerated" : "") : "") . "
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
JOIN pg_attribute a ON c.oid = a.attrelid
@@ -376,8 +437,8 @@ WHERE c.relname = " . q($table) . "
AND n.nspname = current_schema()
AND NOT a.attisdropped
AND a.attnum > 0
ORDER BY a.attnum"
) as $row) {
ORDER BY a.attnum") as $row
) {
//! collation, primary
preg_match('~([^([]+)(\((.*)\))?([a-z ]+)?((\[[0-9]*])*)$~', $row["full_type"], $match);
list(, $type, $length, $row["length"], $addon, $array) = $match;
@@ -393,9 +454,10 @@ ORDER BY a.attnum"
if (in_array($row['attidentity'], array('a', 'd'))) {
$row['default'] = 'GENERATED ' . ($row['attidentity'] == 'd' ? 'BY DEFAULT' : 'ALWAYS') . ' AS IDENTITY';
}
$row["generated"] = ($row["attgenerated"] == "s" ? "STORED" : "");
$row["null"] = !$row["attnotnull"];
$row["auto_increment"] = $row['attidentity'] || preg_match('~^nextval\(~i', $row["default"]);
$row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1, "where" => 1, "order" => 1);
$row["privileges"] = array("insert" => 1, "select" => 1, "update" => 1);
if (preg_match('~(.+)::[^,)]+(.*)~', $row["default"], $match)) {
$row["default"] = ($match[1] == "NULL" ? null : idf_unescape($match[1]) . $match[2]);
}
@@ -412,65 +474,51 @@ ORDER BY a.attnum"
$return = array();
$table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($table));
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
foreach (get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid", $connection2) as $row) {
foreach (get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row) {
$relname = $row["relname"];
$return[$relname]["type"] = ($row["indispartial"] ? "INDEX" : ($row["indisprimary"] ? "PRIMARY" : ($row["indisunique"] ? "UNIQUE" : "INDEX")));
$return[$relname]["columns"] = array();
$return[$relname]["descs"] = array();
if ($row["indkey"]) {
foreach (explode(" ", $row["indkey"]) as $indkey) {
$return[$relname]["columns"][] = $columns[$indkey];
}
$return[$relname]["descs"] = array();
foreach (explode(" ", $row["indoption"]) as $indoption) {
$return[$relname]["descs"][] = ($indoption & 1 ? '1' : null); // 1 - INDOPTION_DESC
}
}
$return[$relname]["lengths"] = array();
}
return $return;
}
function foreign_keys($table) {
global $on_actions;
global $driver;
$return = array();
foreach (get_rows("SELECT conname, condeferrable::int AS deferrable, pg_get_constraintdef(oid) AS definition
foreach (
get_rows("SELECT conname, condeferrable::int AS deferrable, pg_get_constraintdef(oid) AS definition
FROM pg_constraint
WHERE conrelid = (SELECT pc.oid FROM pg_class AS pc INNER JOIN pg_namespace AS pn ON (pn.oid = pc.relnamespace) WHERE pc.relname = " . q($table) . " AND pn.nspname = current_schema())
AND contype = 'f'::char
ORDER BY conkey, conname") as $row) {
ORDER BY conkey, conname") as $row
) {
if (preg_match('~FOREIGN KEY\s*\((.+)\)\s*REFERENCES (.+)\((.+)\)(.*)$~iA', $row['definition'], $match)) {
$row['source'] = array_map('idf_unescape', array_map('trim', explode(',', $match[1])));
$row['source'] = array_map('Adminer\idf_unescape', array_map('trim', explode(',', $match[1])));
if (preg_match('~^(("([^"]|"")+"|[^"]+)\.)?"?("([^"]|"")+"|[^"]+)$~', $match[2], $match2)) {
$row['ns'] = idf_unescape($match2[2]);
$row['table'] = idf_unescape($match2[4]);
}
$row['target'] = array_map('idf_unescape', array_map('trim', explode(',', $match[3])));
$row['on_delete'] = (preg_match("~ON DELETE ($on_actions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
$row['on_update'] = (preg_match("~ON UPDATE ($on_actions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
$row['target'] = array_map('Adminer\idf_unescape', array_map('trim', explode(',', $match[3])));
$row['on_delete'] = (preg_match("~ON DELETE ($driver->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
$row['on_update'] = (preg_match("~ON UPDATE ($driver->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION');
$return[$row['conname']] = $row;
}
}
return $return;
}
function constraints($table) {
global $on_actions;
$return = array();
foreach (get_rows("SELECT conname, consrc
FROM pg_catalog.pg_constraint
INNER JOIN pg_catalog.pg_namespace ON pg_constraint.connamespace = pg_namespace.oid
INNER JOIN pg_catalog.pg_class ON pg_constraint.conrelid = pg_class.oid AND pg_constraint.connamespace = pg_class.relnamespace
WHERE pg_constraint.contype = 'c'
AND conrelid != 0 -- handle only CONSTRAINTs here, not TYPES
AND nspname = current_schema()
AND relname = " . q($table) . "
ORDER BY connamespace, conname") as $row) {
$return[$row['conname']] = $row['consrc'];
}
return $return;
}
function view($name) {
global $connection;
return array("select" => trim($connection->result("SELECT pg_get_viewdef(" . $connection->result("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($name)) . ")")));
return array("select" => trim(get_val("SELECT pg_get_viewdef(" . get_val("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($name)) . ")")));
}
function collations() {
@@ -479,7 +527,7 @@ ORDER BY connamespace, conname") as $row) {
}
function information_schema($db) {
return ($db == "information_schema");
return get_schema() == "information_schema";
}
function error() {
@@ -488,7 +536,7 @@ ORDER BY connamespace, conname") as $row) {
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 nl2br($return);
return nl_br($return);
}
function create_database($db, $collation) {
@@ -498,11 +546,12 @@ ORDER BY connamespace, conname") as $row) {
function drop_databases($databases) {
global $connection;
$connection->close();
return apply_queries("DROP DATABASE", $databases, 'idf_escape');
return apply_queries("DROP DATABASE", $databases, 'Adminer\idf_escape');
}
function rename_database($name, $collation) {
//! current database cannot be renamed
global $connection;
$connection->close();
return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name));
}
@@ -516,6 +565,7 @@ ORDER BY connamespace, conname") as $row) {
if ($table != "" && $table != $name) {
$queries[] = "ALTER TABLE " . table($table) . " RENAME TO " . table($name);
}
$sequence = "";
foreach ($fields as $field) {
$column = idf_escape($field[0]);
$val = $field[1];
@@ -537,10 +587,15 @@ ORDER BY connamespace, conname") as $row) {
$queries[] = "ALTER TABLE " . table($name) . " RENAME $column TO $val[0]";
}
$alter[] = "ALTER $column TYPE$val[1]";
if (!$val[6]) {
$alter[] = "ALTER $column " . ($val[3] ? "SET$val[3]" : "DROP DEFAULT");
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
$sequence_name = $table . "_" . idf_unescape($val[0]) . "_seq";
$alter[] = "ALTER $column " . ($val[3] ? "SET" . preg_replace('~GENERATED ALWAYS(.*) STORED~', 'EXPRESSION\1', $val[3])
: (isset($val[6]) ? "SET DEFAULT nextval(" . q($sequence_name) . ")"
: "DROP DEFAULT" //! change to DROP EXPRESSION with generated columns
));
if (isset($val[6])) {
$sequence = "CREATE SEQUENCE IF NOT EXISTS " . idf_escape($sequence_name) . " OWNED BY " . idf_escape($table) . ".$val[0]";
}
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
}
if ($field[0] != "" || $val5 != "") {
$queries[] = "COMMENT ON COLUMN " . table($name) . ".$val[0] IS " . ($val5 != "" ? substr($val5, 9) : "''");
@@ -553,12 +608,15 @@ ORDER BY connamespace, conname") as $row) {
} elseif ($alter) {
array_unshift($queries, "ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter));
}
if ($sequence) {
array_unshift($queries, $sequence);
}
if ($comment !== null) {
$queries[] = "COMMENT ON TABLE " . table($name) . " IS " . q($comment);
}
if ($auto_increment != "") {
// if ($auto_increment != "") {
//! $queries[] = "SELECT setval(pg_get_serial_sequence(" . q($name) . ", ), $auto_increment)";
}
// }
foreach ($queries as $query) {
if (!queries($query)) {
return false;
@@ -599,7 +657,7 @@ ORDER BY connamespace, conname") as $row) {
}
function truncate_tables($tables) {
return queries("TRUNCATE " . implode(", ", array_map('table', $tables)));
return queries("TRUNCATE " . implode(", ", array_map('Adminer\table', $tables)));
return true;
}
@@ -668,26 +726,20 @@ ORDER BY connamespace, conname") as $row) {
}
function routine($name, $type) {
$info = get_rows('SELECT routine_definition, external_language, type_udt_name
$rows = get_rows('SELECT routine_definition AS definition, LOWER(external_language) AS language, *
FROM information_schema.routines
WHERE routine_schema = current_schema() AND specific_name = ' . q($name))[0];
$fields = get_rows('SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout
WHERE routine_schema = current_schema() AND specific_name = ' . q($name));
$return = $rows[0];
$return["returns"] = array("type" => $return["type_udt_name"]);
$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
WHERE specific_schema = current_schema() AND specific_name = ' . q($name) . '
ORDER BY ordinal_position');
return [
"fields" => $fields,
"returns" => ["type" => $info["type_udt_name"]],
"definition" => $info["routine_definition"],
"language" => strtolower($info["external_language"]),
"comment" => null, // Comments are not supported.
];
return $return;
}
function routines() {
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
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"
FROM information_schema.routines
WHERE routine_schema = current_schema()
ORDER BY SPECIFIC_NAME');
@@ -714,19 +766,15 @@ ORDER BY connamespace, conname") as $row) {
}
function found_rows($table_status, $where) {
global $connection;
if (preg_match(
"~ rows=([0-9]+)~",
$connection->result("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")),
$regs
)) {
if (preg_match("~ rows=([0-9]+)~", get_val("EXPLAIN SELECT * FROM " . idf_escape($table_status["Name"]) . ($where ? " WHERE " . implode(" AND ", $where) : "")), $regs)) {
return $regs[1];
}
return false;
}
function types() {
return get_vals("SELECT typname
return get_key_vals(
"SELECT oid, typname
FROM pg_type
WHERE typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema())
AND typtype IN ('b','d','e')
@@ -734,27 +782,27 @@ AND typelem = 0"
);
}
function type_values($id) {
// to get values from type string: unnest(enum_range(NULL::"$type"))
$enums = get_vals("SELECT enumlabel FROM pg_enum WHERE enumtypid = $id ORDER BY enumsortorder");
return ($enums ? "'" . implode("', '", array_map('addslashes', $enums)) . "'" : "");
}
function schemas() {
return get_vals("SELECT nspname FROM pg_namespace ORDER BY nspname");
}
function get_schema() {
global $connection;
return $connection->result("SELECT current_schema()");
return get_val("SELECT current_schema()");
}
function set_schema($schema, $connection2 = null) {
global $connection, $types, $structured_types;
global $connection, $driver;
if (!$connection2) {
$connection2 = $connection;
}
$return = $connection2->query("SET search_path TO " . idf_escape($schema));
foreach (types() as $type) { //! get types from current_schemas('t')
if (!isset($types[$type])) {
$types[$type] = 0;
$structured_types[lang('User types')][] = $type;
}
}
$driver->setUserTypes(types()); //! get types from current_schemas('t')
return $return;
}
@@ -776,8 +824,7 @@ AND typelem = 0"
}
function create_sql($table, $auto_increment, $style) {
global $connection;
$return = '';
global $driver;
$return_parts = array();
$sequences = array();
@@ -787,9 +834,6 @@ AND typelem = 0"
return rtrim("CREATE VIEW " . idf_escape($table) . " AS $view[select]", ";");
}
$fields = fields($table);
$indexes = indexes($table);
ksort($indexes);
$constraints = constraints($table);
if (!$status || empty($fields)) {
return false;
@@ -807,13 +851,15 @@ AND typelem = 0"
// sequences for fields
if (preg_match('~nextval\(\'([^\']+)\'\)~', $field['default'], $matches)) {
$sequence_name = $matches[1];
$rows = get_rows(min_version(10)
$sq = reset(get_rows((min_version(10)
? "SELECT *, cache_size AS cache_value FROM pg_sequences WHERE schemaname = current_schema() AND sequencename = " . q(idf_unescape($sequence_name))
: "SELECT * FROM $sequence_name"
);
$sq = reset($rows);
), null, "-- "));
$sequences[] = ($style == "DROP+CREATE" ? "DROP SEQUENCE IF EXISTS $sequence_name;\n" : "")
. "CREATE SEQUENCE $sequence_name INCREMENT $sq[increment_by] MINVALUE $sq[min_value] MAXVALUE $sq[max_value]" . ($auto_increment && $sq['last_value'] ? " START $sq[last_value]" : "") . " CACHE $sq[cache_value];";
. "CREATE SEQUENCE $sequence_name INCREMENT $sq[increment_by] MINVALUE $sq[min_value] MAXVALUE $sq[max_value]"
. ($auto_increment && $sq['last_value'] ? " START " . ($sq["last_value"] + 1) : "")
. " CACHE $sq[cache_value];"
;
}
}
@@ -822,32 +868,21 @@ AND typelem = 0"
$return = implode("\n\n", $sequences) . "\n\n$return";
}
// primary + unique keys
foreach ($indexes as $index_name => $index) {
switch($index['type']) {
case 'UNIQUE': $return_parts[] = "CONSTRAINT " . idf_escape($index_name) . " UNIQUE (" . implode(', ', array_map('idf_escape', $index['columns'])) . ")"; break;
case 'PRIMARY': $return_parts[] = "CONSTRAINT " . idf_escape($index_name) . " PRIMARY KEY (" . implode(', ', array_map('idf_escape', $index['columns'])) . ")"; break;
$primary = "";
foreach (indexes($table) as $index_name => $index) {
if ($index['type'] == 'PRIMARY') {
$primary = $index_name;
$return_parts[] = "CONSTRAINT " . idf_escape($index_name) . " PRIMARY KEY (" . implode(', ', array_map('Adminer\idf_escape', $index['columns'])) . ")";
}
}
foreach ($constraints as $conname => $consrc) {
foreach ($driver->checkConstraints($table) as $conname => $consrc) {
$return_parts[] = "CONSTRAINT " . idf_escape($conname) . " CHECK $consrc";
}
$return .= implode(",\n ", $return_parts) . "\n) WITH (oids = " . ($status['Oid'] ? 'true' : 'false') . ");";
// "basic" indexes after table definition
foreach ($indexes as $index_name => $index) {
if ($index['type'] == 'INDEX') {
$columns = array();
foreach ($index['columns'] as $key => $val) {
$columns[] = idf_escape($val) . ($index['descs'][$key] ? " DESC" : "");
}
$return .= "\n\nCREATE INDEX " . idf_escape($index_name) . " ON " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " USING btree (" . implode(', ', $columns) . ");";
}
}
// coments for table & fields
// comments for table & fields
if ($status['Comment']) {
$return .= "\n\nCOMMENT ON TABLE " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " IS " . q($status['Comment']) . ";";
}
@@ -858,6 +893,10 @@ AND typelem = 0"
}
}
foreach (get_rows("SELECT indexdef FROM pg_catalog.pg_indexes WHERE schemaname = current_schema() AND tablename = " . q($table) . ($primary ? " AND indexname != " . q($primary) : ""), null, "-- ") as $row) {
$return .= "\n\n$row[indexdef];";
}
return rtrim($return, ';');
}
@@ -884,30 +923,10 @@ AND typelem = 0"
return get_key_vals("SHOW ALL");
}
/**
* @return bool
*/
function is_strict_mode() {
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() {
return get_rows("SELECT * FROM pg_stat_activity ORDER BY " . (min_version(9.2) ? "pid" : "procpid"));
}
function show_status() {
}
function convert_field($field) {
}
@@ -916,7 +935,7 @@ AND typelem = 0"
}
function support($feature) {
return preg_match('~^(database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature);
return preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature);
}
function kill_process($val) {
@@ -928,46 +947,6 @@ AND typelem = 0"
}
function max_connections() {
global $connection;
return $connection->result("SHOW max_connections");
}
function driver_config() {
$types = array();
$structured_types = array();
foreach (array( //! arrays
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "timestamptz" => 21, "interval" => 0),
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "macaddr8" => 23, "txid_snapshot" => 0),
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
) as $key => $val) { //! can be retrieved from pg_type
$types += $val;
$structured_types[$key] = array_keys($val);
}
return array(
'possible_drivers' => array("PgSQL", "PDO_PgSQL"),
'jush' => "pgsql",
'types' => $types,
'structured_types' => $structured_types,
'unsigned' => array(),
'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"),
'grouping' => array("avg", "count", "count distinct", "max", "min", "sum"),
'edit_functions' => array(
array(
"char" => "md5",
"date|time" => "now",
), array(
number_type() => "+/-",
"date|time" => "+ interval/- interval", //! escape
"char|text" => "||",
)
),
'c_style_escapes' => true,
);
return get_val("SHOW max_connections");
}
}

View File

@@ -1,17 +1,17 @@
<?php
$drivers["sqlite"] = "SQLite 3";
$drivers["sqlite2"] = "SQLite 2";
namespace Adminer;
$drivers["sqlite"] = "SQLite";
if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
define("DRIVER", (isset($_GET["sqlite"]) ? "sqlite" : "sqlite2"));
if (class_exists(isset($_GET["sqlite"]) ? "SQLite3" : "SQLiteDatabase")) {
if (isset($_GET["sqlite"])) {
define('Adminer\DRIVER', "sqlite");
if (class_exists("SQLite3")) {
class Min_SQLite {
class SqliteDb {
var $extension = "SQLite3", $server_info, $affected_rows, $errno, $error, $_link;
function __construct($filename) {
$this->_link = new SQLite3($filename);
$this->_link = new \SQLite3($filename);
$version = $this->_link->version();
$this->server_info = $version["versionString"];
}
@@ -24,7 +24,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$this->error = $this->_link->lastErrorMsg();
return false;
} elseif ($result->numColumns()) {
return new Min_Result($result);
return new Result($result);
}
$this->affected_rows = $this->_link->changes();
return true;
@@ -47,11 +47,11 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return false;
}
$row = $result->_result->fetchArray();
return $row[$field];
return $row ? $row[$field] : false;
}
}
class Min_Result {
class Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
@@ -81,105 +81,23 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
}
} else {
class Min_SQLite {
var $extension = "SQLite", $server_info, $affected_rows, $error, $_link;
function __construct($filename) {
$this->server_info = sqlite_libversion();
$this->_link = new SQLiteDatabase($filename);
}
function query($query, $unbuffered = false) {
$method = ($unbuffered ? "unbufferedQuery" : "query");
$result = @$this->_link->$method($query, SQLITE_BOTH, $error);
$this->error = "";
if (!$result) {
$this->error = $error;
return false;
} elseif ($result === true) {
$this->affected_rows = $this->changes();
return true;
}
return new Min_Result($result);
}
function quote($string) {
return "'" . sqlite_escape_string($string) . "'";
}
function store_result() {
return $this->_result;
}
function result($query, $field = 0) {
$result = $this->query($query);
if (!is_object($result)) {
return false;
}
$row = $result->_result->fetch();
return $row[$field];
}
}
class Min_Result {
var $_result, $_offset = 0, $num_rows;
function __construct($result) {
$this->_result = $result;
if (method_exists($result, 'numRows')) { // not available in unbuffered query
$this->num_rows = $result->numRows();
}
}
function fetch_assoc() {
$row = $this->_result->fetch(SQLITE_ASSOC);
if (!$row) {
return false;
}
$return = array();
foreach ($row as $key => $val) {
$return[idf_unescape($key)] = $val;
}
return $return;
}
function fetch_row() {
return $this->_result->fetch(SQLITE_NUM);
}
function fetch_field() {
$name = $this->_result->fieldName($this->_offset++);
$pattern = '(\[.*]|"(?:[^"]|"")*"|(.+))';
if (preg_match("~^($pattern\\.)?$pattern\$~", $name, $match)) {
$table = ($match[3] != "" ? $match[3] : idf_unescape($match[2]));
$name = ($match[5] != "" ? $match[5] : idf_unescape($match[4]));
}
return (object) array(
"name" => $name,
"orgname" => $name,
"orgtable" => $table,
);
}
}
}
} elseif (extension_loaded("pdo_sqlite")) {
class Min_SQLite extends Min_PDO {
class SqliteDb extends PdoDb {
var $extension = "PDO_SQLite";
function __construct($filename) {
$this->dsn(DRIVER . ":$filename", "", "");
}
function select_db($db) {
return false;
}
}
}
if (class_exists("Min_SQLite")) {
class Min_DB extends Min_SQLite {
if (class_exists('Adminer\SqliteDb')) {
class Db extends SqliteDb {
function __construct() {
parent::__construct(":memory:");
@@ -208,7 +126,36 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
class Min_Driver extends Min_SQL {
class Driver extends SqlDriver {
static $possibleDrivers = array("SQLite3", "PDO_SQLite");
static $jush = "sqlite";
protected $types = array(array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0));
var $editFunctions = array(
array(
// "text" => "date('now')/time('now')/datetime('now')",
), array(
"integer|real|numeric" => "+/-",
// "text" => "date/time/datetime",
"text" => "||",
)
);
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL", "SQL"); // REGEXP can be user defined function
var $functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
function __construct($connection) {
parent::__construct($connection);
if (min_version(3.31, 0, $connection)) {
$this->generated = array("STORED", "VIRTUAL");
}
}
function structuredTypes() {
return array_keys($this->types[0]);
}
function insertUpdate($table, $rows, $primary) {
$values = array();
@@ -218,7 +165,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return queries("REPLACE INTO " . table($table) . " (" . implode(", ", array_keys(reset($rows))) . ") VALUES\n" . implode(",\n", $values));
}
function tableHelp($name) {
function tableHelp($name, $is_view = false) {
if ($name == "sqlite_sequence") {
return "fileformat2.html#seqtab";
}
@@ -227,6 +174,10 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
}
function checkConstraints($table) {
preg_match_all('~ CHECK *(\( *(((?>[^()]*[^() ])|(?1))*) *\))~', $this->_conn->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table)), $matches); //! could be inside a comment
return array_combine($matches[2], $matches[2]);
}
}
@@ -239,13 +190,12 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return idf_escape($idf);
}
function connect() {
global $adminer;
list(, , $password) = $adminer->credentials();
function connect($credentials) {
list(, , $password) = $credentials;
if ($password != "") {
return lang('Database does not support password.');
}
return new Min_DB;
return new Db;
}
function get_databases() {
@@ -257,16 +207,14 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function limit1($table, $query, $where, $separator = "\n") {
global $connection;
return (preg_match('~^INTO~', $query) || $connection->result("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')")
return (preg_match('~^INTO~', $query) || get_val("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')")
? limit($query, $where, 1, 0, $separator)
: " $query WHERE rowid = (SELECT rowid FROM " . table($table) . $where . $separator . "LIMIT 1)" //! use primary key in tables with WITHOUT rowid
);
}
function db_collation($db, $collations) {
global $connection;
return $connection->result("PRAGMA encoding"); // there is no database list so $db == DB
return get_val("PRAGMA encoding"); // there is no database list so $db == DB
}
function engines() {
@@ -286,10 +234,9 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function table_status($name = "") {
global $connection;
$return = array();
foreach (get_rows("SELECT name AS Name, type AS Engine, 'rowid' AS Oid, '' AS Auto_increment FROM sqlite_master WHERE type IN ('table', 'view') " . ($name != "" ? "AND name = " . q($name) : "ORDER BY name")) as $row) {
$row["Rows"] = $connection->result("SELECT COUNT(*) FROM " . idf_escape($row["Name"]));
$row["Rows"] = get_val("SELECT COUNT(*) FROM " . idf_escape($row["Name"]));
$return[$row["Name"]] = $row;
}
foreach (get_rows("SELECT * FROM sqlite_sequence", null, "") as $row) {
@@ -303,15 +250,13 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function fk_support($table_status) {
global $connection;
return !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
return !get_val("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
}
function fields($table) {
global $connection;
$return = array();
$primary = "";
foreach (get_rows("PRAGMA table_info(" . table($table) . ")") as $row) {
foreach (get_rows("PRAGMA table_" . (min_version(3.31) ? "x" : "") . "info(" . table($table) . ")") as $row) {
$name = $row["name"];
$type = strtolower($row["type"]);
$default = $row["dflt_value"];
@@ -319,7 +264,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
"field" => $name,
"type" => (preg_match('~int~i', $type) ? "integer" : (preg_match('~char|clob|text~i', $type) ? "text" : (preg_match('~blob~i', $type) ? "blob" : (preg_match('~real|floa|doub~i', $type) ? "real" : "numeric")))),
"full_type" => $type,
"default" => (preg_match("~'(.*)'~", $default, $match) ? str_replace("''", "'", $match[1]) : ($default == "NULL" ? null : $default)),
"default" => (preg_match("~^'(.*)'$~", $default, $match) ? str_replace("''", "'", $match[1]) : ($default == "NULL" ? null : $default)),
"null" => !$row["notnull"],
"privileges" => array("select" => 1, "insert" => 1, "update" => 1, "where" => 1, "order" => 1),
"primary" => $row["pk"],
@@ -333,14 +278,21 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$primary = $name;
}
}
$sql = $connection->result("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table));
preg_match_all('~(("[^"]*+")+|[a-z0-9_]+)\s+text\s+COLLATE\s+(\'[^\']+\'|\S+)~i', $sql, $matches, PREG_SET_ORDER);
$sql = get_val("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table));
$idf = '(("[^"]*+")+|[a-z0-9_]+)';
preg_match_all('~' . $idf . '\s+text\s+COLLATE\s+(\'[^\']+\'|\S+)~i', $sql, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$name = str_replace('""', '"', preg_replace('~^"|"$~', '', $match[1]));
if ($return[$name]) {
$return[$name]["collation"] = trim($match[3], "'");
}
}
preg_match_all('~' . $idf . '\s.*GENERATED ALWAYS AS \((.+)\) (STORED|VIRTUAL)~i', $sql, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$name = str_replace('""', '"', preg_replace('~^"|"$~', '', $match[1]));
$return[$name]["default"] = $match[3];
$return[$name]["generated"] = strtoupper($match[4]);
}
return $return;
}
@@ -395,7 +347,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$return = array();
foreach (get_rows("PRAGMA foreign_key_list(" . table($table) . ")") as $row) {
$foreign_key = &$return[$row["id"]];
//! idf_unescape in SQLite2
if (!$foreign_key) {
$foreign_key = $row;
}
@@ -406,8 +357,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function view($name) {
global $connection;
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . q($name)))); //! identifiers may be inside []
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\s+~iU', '', get_val("SELECT sql FROM sqlite_master WHERE type = 'view' AND name = " . q($name)))); //! identifiers may be inside []
}
function collations() {
@@ -444,7 +394,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return false;
}
try {
$link = new Min_SQLite($db);
$link = new SqliteDb($db);
} catch (Exception $ex) {
$connection->error = $ex->getMessage();
return false;
@@ -478,7 +428,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function auto_increment() {
return " PRIMARY KEY" . (DRIVER == "sqlite" ? " AUTOINCREMENT" : "");
return " PRIMARY KEY AUTOINCREMENT";
}
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
@@ -523,8 +473,20 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return true;
}
function recreate_table($table, $name, $fields, $originals, $foreign, $auto_increment, $indexes = array()) {
global $connection;
/** Recreate table
* @param string original name
* @param string new name
* @param array [process_field()], empty to preserve
* @param array [$original => idf_escape($new_column)], empty to preserve
* @param string [format_foreign_key()], empty to preserve
* @param int set auto_increment to this value, 0 to preserve
* @param array [[$type, $name, $columns]], empty to preserve
* @param string CHECK constraint to drop
* @param string CHECK constraint to add
* @return bool
*/
function recreate_table($table, $name, $fields, $originals, $foreign, $auto_increment = 0, $indexes = array(), $drop_check = "", $add_check = "") {
global $driver;
if ($table != "") {
if (!$fields) {
foreach (fields($table) as $key => $field) {
@@ -582,16 +544,27 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
queries("BEGIN");
}
foreach ($fields as $key => $field) {
if (preg_match('~GENERATED~', $field[3])) {
unset($originals[array_search($field[0], $originals)]);
}
$fields[$key] = " " . implode($field);
}
$fields = array_merge($fields, array_filter($foreign));
foreach ($driver->checkConstraints($table) as $check) {
if ($check != $drop_check) {
$fields[] = " CHECK ($check)";
}
}
if ($add_check) {
$fields[] = " CHECK ($add_check)";
}
$temp_name = ($table == $name ? "adminer_$name" : $name);
if (!queries("CREATE TABLE " . table($temp_name) . " (\n" . implode(",\n", $fields) . "\n)")) {
// implicit ROLLBACK to not overwrite $connection->error
return false;
}
if ($table != "") {
if ($originals && !queries("INSERT INTO " . table($temp_name) . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('idf_escape', array_keys($originals))) . " FROM " . table($table))) {
if ($originals && !queries("INSERT INTO " . table($temp_name) . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('Adminer\idf_escape', array_keys($originals))) . " FROM " . table($table))) {
return false;
}
$triggers = array();
@@ -599,8 +572,9 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$trigger = trigger($trigger_name);
$triggers[] = "CREATE TRIGGER " . idf_escape($trigger_name) . " " . implode(" ", $timing_event) . " ON " . table($name) . "\n$trigger[Statement]";
}
$auto_increment = $auto_increment ? 0 : $connection->result("SELECT seq FROM sqlite_sequence WHERE name = " . q($table)); // if $auto_increment is set then it will be updated later
if (!queries("DROP TABLE " . table($table)) // drop before creating indexes and triggers to allow using old names
$auto_increment = $auto_increment ? 0 : get_val("SELECT seq FROM sqlite_sequence WHERE name = " . q($table)); // if $auto_increment is set then it will be updated later
if (
!queries("DROP TABLE " . table($table)) // drop before creating indexes and triggers to allow using old names
|| ($table == $name && !queries("ALTER TABLE " . table($temp_name) . " RENAME TO " . table($name)))
|| !alter_indexes($name, $indexes)
) {
@@ -634,10 +608,11 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
}
foreach (array_reverse($alter) as $val) {
if (!queries($val[2] == "DROP"
if (
!queries($val[2] == "DROP"
? "DROP INDEX " . idf_escape($val[1])
: index_sql($table, $val[0], $val[1], "(" . implode(", ", $val[2]) . ")")
)) {
: index_sql($table, $val[0], $val[1], "(" . implode(", ", $val[2]) . ")"))
) {
return false;
}
}
@@ -661,7 +636,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function trigger($name) {
global $connection;
if ($name == "") {
return array("Statement" => "BEGIN\n\t;\nEND");
}
@@ -669,7 +643,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$trigger_options = trigger_options();
preg_match(
"~^CREATE\\s+TRIGGER\\s*$idf\\s*(" . implode("|", $trigger_options["Timing"]) . ")\\s+([a-z]+)(?:\\s+OF\\s+($idf))?\\s+ON\\s*$idf\\s*(?:FOR\\s+EACH\\s+ROW\\s)?(.*)~is",
$connection->result("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = " . q($name)),
get_val("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = " . q($name)),
$match
);
$of = $match[3];
@@ -705,8 +679,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function last_id() {
global $connection;
return $connection->result("SELECT LAST_INSERT_ROWID()");
return get_val("SELECT LAST_INSERT_ROWID()");
}
function explain($connection, $query) {
@@ -720,26 +693,13 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
return array();
}
function schemas() {
return array();
}
function get_schema() {
return "";
}
function set_schema($scheme) {
return true;
}
function create_sql($table, $auto_increment, $style) {
global $connection;
$return = $connection->result("SELECT sql FROM sqlite_master WHERE type IN ('table', 'view') AND name = " . q($table));
$return = get_val("SELECT sql FROM sqlite_master WHERE type IN ('table', 'view') AND name = " . q($table));
foreach (indexes($table) as $name => $index) {
if ($name == '') {
continue;
}
$return .= ";\n\n" . index_sql($table, $index['type'], $name, "(" . implode(", ", array_map('idf_escape', $index['columns'])) . ")");
$return .= ";\n\n" . index_sql($table, $index['type'], $name, "(" . implode(", ", array_map('Adminer\idf_escape', $index['columns'])) . ")");
}
return $return;
}
@@ -756,25 +716,18 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function show_variables() {
global $connection;
$return = array();
foreach (array("auto_vacuum", "cache_size", "count_changes", "default_cache_size", "empty_result_callbacks", "encoding", "foreign_keys", "full_column_names", "fullfsync", "journal_mode", "journal_size_limit", "legacy_file_format", "locking_mode", "page_size", "max_page_count", "read_uncommitted", "recursive_triggers", "reverse_unordered_selects", "secure_delete", "short_column_names", "synchronous", "temp_store", "temp_store_directory", "schema_version", "integrity_check", "quick_check") as $key) {
$return[$key] = $connection->result("PRAGMA $key");
foreach (get_rows("PRAGMA pragma_list") as $row) {
$name = $row["name"];
if ($name != "pragma_list" && $name != "compile_options") {
foreach (get_rows("PRAGMA $name") as $row) {
$return[$name] .= implode(", ", $row) . "\n";
}
}
}
return $return;
}
/**
* @return bool
*/
function is_strict_mode() {
return false;
}
function is_c_style_escapes() {
return true;
}
function show_status() {
$return = array();
foreach (get_vals("PRAGMA compile_options") as $option) {
@@ -792,30 +745,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function support($feature) {
return preg_match('~^(columns|database|drop_col|dump|indexes|descidx|move_col|sql|status|table|trigger|variables|view|view_trigger)$~', $feature);
}
function driver_config() {
$types = array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0);
return array(
'possible_drivers' => array((isset($_GET["sqlite"]) ? "SQLite3" : "SQLite"), "PDO_SQLite"),
'jush' => "sqlite",
'types' => $types,
'structured_types' => array_keys($types),
'unsigned' => array(),
'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"),
'grouping' => array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"),
'edit_functions' => array(
array(
// "text" => "date('now')/time('now')/datetime('now')",
), array(
"integer|real|numeric" => "+/-",
// "text" => "date/time/datetime",
"text" => "||",
)
),
);
return preg_match('~^(check|columns|database|drop_col|dump|indexes|descidx|move_col|sql|status|table|trigger|variables|view|view_trigger)$~', $feature);
}
}

View File

@@ -1,21 +1,24 @@
<?php
namespace Adminer;
$TABLE = $_GET["dump"];
if ($_POST && !$error) {
$cookie = "";
foreach (array("output", "format", "db_style", "routines", "events", "table_style", "auto_increment", "triggers", "data_style") as $key) {
foreach (array("output", "format", "db_style", "types", "routines", "events", "table_style", "auto_increment", "triggers", "data_style") as $key) {
$cookie .= "&$key=" . urlencode($_POST[$key]);
}
cookie("adminer_export", substr($cookie, 1));
$tables = array_flip((array) $_POST["tables"]) + array_flip((array) $_POST["data"]);
$ext = dump_headers(
(count($tables) == 1 ? key($tables) : DB),
(DB == "" || count($tables) > 1));
(DB == "" || count($tables) > 1)
);
$is_sql = preg_match('~sql~', $_POST["format"]);
if ($is_sql) {
echo "-- Adminer $VERSION " . $drivers[DRIVER] . " " . str_replace("\n", " ", $connection->server_info) . " dump\n\n";
if ($jush == "sql") {
if (JUSH == "sql") {
echo "SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
@@ -39,7 +42,7 @@ SET foreign_key_checks = 0;
foreach ((array) $databases as $db) {
$adminer->dumpDatabase($db);
if ($connection->select_db($db)) {
if ($is_sql && preg_match('~CREATE~', $style) && ($create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1))) {
if ($is_sql && preg_match('~CREATE~', $style) && ($create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1))) {
set_utf8mb4($create);
if ($style == "DROP+CREATE") {
echo "DROP DATABASE IF EXISTS " . idf_escape($db) . ";\n";
@@ -52,27 +55,37 @@ SET foreign_key_checks = 0;
}
$out = "";
if ($_POST["routines"]) {
foreach (array("FUNCTION", "PROCEDURE") as $routine) {
foreach (get_rows("SHOW $routine STATUS WHERE Db = " . q($db), null, "-- ") as $row) {
$create = remove_definer($connection->result("SHOW CREATE $routine " . idf_escape($row["Name"]), 2));
set_utf8mb4($create);
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") . "$create;;\n\n";
if ($_POST["types"]) {
foreach (types() as $id => $type) {
$enums = type_values($id);
if ($enums) {
$out .= ($style != 'DROP+CREATE' ? "DROP TYPE IF EXISTS " . idf_escape($type) . ";;\n" : "") . "CREATE TYPE " . idf_escape($type) . " AS ENUM ($enums);\n\n";
} else {
//! https://github.com/postgres/postgres/blob/REL_17_4/src/bin/pg_dump/pg_dump.c#L10846
$out .= "-- Could not export type $type\n\n";
}
}
}
if ($_POST["routines"]) {
foreach (routines() as $row) {
$name = $row["ROUTINE_NAME"];
$routine = $row["ROUTINE_TYPE"];
$create = create_routine($routine, array("name" => $name) + routine($row["SPECIFIC_NAME"], $routine));
set_utf8mb4($create);
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($name) . ";;\n" : "") . "$create;\n\n";
}
}
if ($_POST["events"]) {
foreach (get_rows("SHOW EVENTS", null, "-- ") as $row) {
$create = remove_definer($connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3));
$create = remove_definer(get_val("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3));
set_utf8mb4($create);
$out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") . "$create;;\n\n";
}
}
if ($out) {
echo "DELIMITER ;;\n\n$out" . "DELIMITER ;\n\n";
}
echo ($out && JUSH == 'sql' ? "DELIMITER ;;\n\n$out" . "DELIMITER ;\n\n" : $out);
}
if ($_POST["table_style"] || $_POST["data_style"]) {
@@ -107,7 +120,7 @@ SET foreign_key_checks = 0;
}
// add FKs after creating tables (except in MySQL which uses SET FOREIGN_KEY_CHECKS=0)
if (function_exists('foreign_keys_sql')) {
if (function_exists('Adminer\foreign_keys_sql')) {
foreach (table_status('', true) as $name => $table_status) {
$table = (DB == "" || in_array($name, (array) $_POST["tables"]));
if ($table && !is_view($table_status)) {
@@ -128,7 +141,7 @@ SET foreign_key_checks = 0;
}
if ($is_sql) {
echo "-- " . $connection->result("SELECT NOW()") . "\n";
echo "-- " . gmdate("Y-m-d H:i:s e") . "\n";
}
exit;
}
@@ -137,26 +150,29 @@ page_header(lang('Export'), $error, ($_GET["export"] != "" ? array("table" => $_
?>
<form action="" method="post">
<table cellspacing="0" class="layout">
<table class="layout">
<?php
$db_style = array('', 'USE', 'DROP+CREATE', 'CREATE');
$table_style = array('', 'DROP+CREATE', 'CREATE');
$data_style = array('', 'TRUNCATE+INSERT', 'INSERT');
if ($jush == "sql") { //! use insertUpdate() in all drivers
if (JUSH == "sql") { //! use insertUpdate() in all drivers
$data_style[] = 'INSERT+UPDATE';
}
parse_str($_COOKIE["adminer_export"], $row);
if (!$row) {
$row = array("output" => "file", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT");
$row = array("output" => "text", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT");
}
if (!isset($row["events"])) { // backwards compatibility
$row["routines"] = $row["events"] = ($_GET["dump"] == "");
$row["triggers"] = $row["table_style"];
}
echo "<tr><th>" . lang('Format') . "<td>" . html_select("format", $adminer->dumpFormat(), $row["format"], false) . "\n"; // false = radio
echo "<tr><th>" . lang('Output') . "<td>" . html_select("output", $adminer->dumpOutput(), $row["output"], 0) . "\n"; // 0 - radio
echo ($jush == "sqlite" ? "" : "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"])
echo "<tr><th>" . lang('Format') . "<td>" . html_select("format", $adminer->dumpFormat(), $row["format"], 0) . "\n"; // 0 - radio
echo (JUSH == "sqlite" ? "" : "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"])
. (support("type") ? checkbox("types", 1, $row["types"], lang('User types')) : "")
. (support("routine") ? checkbox("routines", 1, $row["routines"], lang('Routines')) : "")
. (support("event") ? checkbox("events", 1, $row["events"], lang('Events')) : "")
);
@@ -167,23 +183,20 @@ echo "<tr><th>" . lang('Tables') . "<td>" . html_select('table_style', $table_st
;
echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style, $row["data_style"]);
echo "<tr><th>" . lang('Output') . "<td>" . html_select("output", $adminer->dumpOutput(), $row["output"], false) . "\n"; // false = radio
?>
</table>
<p><input type="submit" value="<?php echo lang('Export'); ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<table cellspacing="0">
<table>
<?php
echo script("qsl('table').onclick = dumpClick;");
$prefixes = array();
if (DB != "") {
$checked = ($TABLE != "" ? "" : " checked");
echo "<thead><tr>";
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("gid('check-data').onclick = partial(formCheck, /^data\\[/);", "");
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: right;'><label class='block'>" . lang('Data') . "<input type='checkbox' id='check-data'$checked></label>" . script("qs('#check-data').onclick = partial(formCheck, /^data\\[/);", "");
echo "</thead>\n";
$views = "";
@@ -208,7 +221,7 @@ if (DB != "") {
} else {
echo "<thead><tr><th style='text-align: left;'>";
echo "<label class='block'><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . ">" . lang('Database') . "</label>";
echo script("gid('check-databases').onclick = partial(formCheck, /^databases\\[/);", "");
echo script("qs('#check-databases').onclick = partial(formCheck, /^databases\\[/);", "");
echo "</thead>\n";
$databases = $adminer->databases();
if ($databases) {

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$TABLE = $_GET["edit"];
$fields = fields($TABLE);
$where = (isset($_GET["select"]) ? ($_POST["check"] && count($_POST["check"]) == 1 ? where_check($_POST["check"][0], $fields) : "") : where($_GET, $fields));
@@ -70,7 +72,7 @@ if ($_POST["save"]) {
if ($_POST["clone"] && $field["auto_increment"]) {
$as = "''";
}
if ($jush == "sql" && preg_match("~enum|set~", $field["type"])) {
if (JUSH == "sql" && preg_match("~enum|set~", $field["type"])) {
$as = "1*" . idf_escape($name);
}
$select[] = ($as ? "$as AS " : "") . idf_escape($name);

View File

@@ -1,13 +1,9 @@
<?php
// To create Adminer just for Elasticsearch, run `../compile.php elastic`.
function adminer_object() {
include_once "../plugins/plugin.php";
include_once "../plugins/login-password-less.php";
include_once "../plugins/drivers/elastic.php";
include_once "../plugins/drivers/elastic5.php";
return new AdminerPlugin([
// 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)),
]);
return new Adminer\Adminer;
}
include "./index.php";

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$EVENT = $_GET["event"];
$intervals = array("YEAR", "QUARTER", "MONTH", "DAY", "HOUR", "MINUTE", "WEEK", "SECOND", "YEAR_MONTH", "DAY_HOUR", "DAY_MINUTE", "DAY_SECOND", "HOUR_MINUTE", "HOUR_SECOND", "MINUTE_SECOND");
$statuses = array("ENABLED" => "ENABLE", "DISABLED" => "DISABLE", "SLAVESIDE_DISABLED" => "DISABLE ON SLAVE");
@@ -16,13 +18,17 @@ if ($_POST && !$error) {
) . " ON COMPLETION" . ($row["ON_COMPLETION"] ? "" : " NOT") . " PRESERVE"
;
queries_redirect(substr(ME, 0, -1), ($EVENT != "" ? lang('Event has been altered.') : lang('Event has been created.')), queries(($EVENT != ""
? "ALTER EVENT " . idf_escape($EVENT) . $schedule
. ($EVENT != $row["EVENT_NAME"] ? "\nRENAME TO " . idf_escape($row["EVENT_NAME"]) : "")
queries_redirect(
substr(ME, 0, -1),
($EVENT != "" ? lang('Event has been altered.') : lang('Event has been created.')),
queries(
($EVENT != ""
? "ALTER EVENT " . idf_escape($EVENT) . $schedule . ($EVENT != $row["EVENT_NAME"] ? "\nRENAME TO " . idf_escape($row["EVENT_NAME"]) : "")
: "CREATE EVENT " . idf_escape($row["EVENT_NAME"]) . $schedule
) . "\n" . $statuses[$row["STATUS"]] . " COMMENT " . q($row["EVENT_COMMENT"])
. rtrim(" DO\n$row[EVENT_DEFINITION]", ";") . ";"
));
)
);
}
}
@@ -35,7 +41,7 @@ if (!$row && $EVENT != "") {
?>
<form action="" method="post">
<table cellspacing="0" class="layout">
<table class="layout">
<tr><th><?php echo lang('Name'); ?><td><input name="EVENT_NAME" value="<?php echo h($row["EVENT_NAME"]); ?>" data-maxlength="64" autocapitalize="off">
<tr><th title="datetime"><?php echo lang('Start'); ?><td><input name="STARTS" value="<?php echo h("$row[EXECUTE_AT]$row[STARTS]"); ?>">
<tr><th title="datetime"><?php echo lang('End'); ?><td><input name="ENDS" value="<?php echo h($row["ENDS"]); ?>">
@@ -47,6 +53,8 @@ if (!$row && $EVENT != "") {
<p><?php textarea("EVENT_DEFINITION", $row["EVENT_DEFINITION"]); ?>
<p>
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($EVENT != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $EVENT)); ?><?php } ?>
<?php if ($EVENT != "") { ?>
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $EVENT)); ?>
<?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
// caching headers added in compile.php
if ($_GET["file"] == "favicon.ico") {
@@ -6,21 +8,40 @@ if ($_GET["file"] == "favicon.ico") {
echo lzw_decompress(compile_file('../adminer/static/favicon.ico', 'lzw_compress'));
} elseif ($_GET["file"] == "default.css") {
header("Content-Type: text/css; charset=utf-8");
echo lzw_decompress(compile_file('../adminer/static/default.css;../vendor/vrana/jush/jush.css', 'minify_css'));
echo lzw_decompress(compile_file('../adminer/static/default.css;../externals/jush/jush.css', 'minify_css'));
} elseif ($_GET["file"] == "functions.js") {
header("Content-Type: text/javascript; charset=utf-8");
echo lzw_decompress(compile_file('../adminer/static/functions.js;static/editing.js', 'minify_js'));
} elseif ($_GET["file"] == "jush.js") {
header("Content-Type: text/javascript; charset=utf-8");
echo lzw_decompress(compile_file('../vendor/vrana/jush/modules/jush.js;../vendor/vrana/jush/modules/jush-textarea.js;../vendor/vrana/jush/modules/jush-txt.js;../vendor/vrana/jush/modules/jush-js.js;../vendor/vrana/jush/modules/jush-sql.js;../vendor/vrana/jush/modules/jush-pgsql.js;../vendor/vrana/jush/modules/jush-sqlite.js;../vendor/vrana/jush/modules/jush-mssql.js;../vendor/vrana/jush/modules/jush-oracle.js;../vendor/vrana/jush/modules/jush-simpledb.js', 'minify_js'));
echo lzw_decompress(compile_file('../externals/jush/modules/jush.js;
../externals/jush/modules/jush-textarea.js;
../externals/jush/modules/jush-txt.js;
../externals/jush/modules/jush-js.js;
../externals/jush/modules/jush-sql.js;
../externals/jush/modules/jush-pgsql.js;
../externals/jush/modules/jush-sqlite.js;
../externals/jush/modules/jush-mssql.js;
../externals/jush/modules/jush-oracle.js;
../externals/jush/modules/jush-simpledb.js', 'minify_js'));
} else {
header("Content-Type: image/gif");
switch ($_GET["file"]) {
case "plus.gif": echo compile_file('../adminer/static/plus.gif'); break;
case "cross.gif": echo compile_file('../adminer/static/cross.gif'); break;
case "up.gif": echo compile_file('../adminer/static/up.gif'); break;
case "down.gif": echo compile_file('../adminer/static/down.gif'); break;
case "arrow.gif": echo compile_file('../adminer/static/arrow.gif'); break;
case "plus.gif":
echo compile_file('../adminer/static/plus.gif');
break;
case "cross.gif":
echo compile_file('../adminer/static/cross.gif');
break;
case "up.gif":
echo compile_file('../adminer/static/up.gif');
break;
case "down.gif":
echo compile_file('../adminer/static/down.gif');
break;
case "arrow.gif":
echo compile_file('../adminer/static/arrow.gif');
break;
}
}
exit;

View File

@@ -1,12 +1,11 @@
<?php
namespace Adminer;
$TABLE = $_GET["foreign"];
$name = $_GET["name"];
$row = $_POST;
if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
$message = ($_POST["drop"] ? lang('Foreign key has been dropped.') : ($name != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.')));
$location = ME . "table=" . urlencode($TABLE);
if (!$_POST["drop"]) {
$row["source"] = array_filter($row["source"], 'strlen');
ksort($row["source"]); // enforce input order
@@ -17,18 +16,23 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-
$row["target"] = $target;
}
if ($jush == "sqlite") {
queries_redirect($location, $message, recreate_table($TABLE, $TABLE, array(), array(), array(" $name" => ($_POST["drop"] ? "" : " " . format_foreign_key($row)))));
if (JUSH == "sqlite") {
$result = recreate_table($TABLE, $TABLE, array(), array(), array(" $name" => ($row["drop"] ? "" : " " . format_foreign_key($row))));
} else {
$alter = "ALTER TABLE " . table($TABLE);
$drop = "\nDROP " . ($jush == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name);
if ($_POST["drop"]) {
query_redirect($alter . $drop, $location, $message);
} else {
query_redirect($alter . ($name != "" ? "$drop," : "") . "\nADD" . format_foreign_key($row), $location, $message);
$error = lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.') . "<br>$error"; //! no partitioning
$result = ($name == "" || queries("$alter DROP " . (JUSH == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($name)));
if (!$row["drop"]) {
$result = queries("$alter ADD" . format_foreign_key($row));
}
}
queries_redirect(
ME . "table=" . urlencode($TABLE),
($row["drop"] ? lang('Foreign key has been dropped.') : ($name != "" ? lang('Foreign key has been altered.') : lang('Foreign key has been created.'))),
$result
);
if (!$row["drop"]) {
$error = "$error<br>" . lang('Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.'); //! no partitioning
}
}
page_header(lang('Foreign key'), $error, array("table" => $TABLE), h($TABLE));
@@ -57,15 +61,22 @@ if ($row["db"] != "") {
$connection->select_db($row["db"]);
}
if ($row["ns"] != "") {
$orig_schema = get_schema();
set_schema($row["ns"]);
}
$referencable = array_keys(array_filter(table_status('', true), 'fk_support'));
$referencable = array_keys(array_filter(table_status('', true), 'Adminer\fk_support'));
$target = array_keys(fields(in_array($row["table"], $referencable) ? $row["table"] : reset($referencable)));
$onchange = "this.form['change-js'].value = '1'; this.form.submit();";
echo "<p>" . lang('Target table') . ": " . html_select("table", $referencable, $row["table"], $onchange) . "\n";
if ($jush == "pgsql") {
echo lang('Schema') . ": " . html_select("ns", $adminer->schemas(), $row["ns"] != "" ? $row["ns"] : $_GET["ns"], $onchange);
} elseif ($jush != "sqlite") {
if (support("scheme")) {
$schemas = array_filter($adminer->schemas(), function ($schema) {
return !preg_match('~^information_schema$~i', $schema);
});
echo lang('Schema') . ": " . html_select("ns", $schemas, $row["ns"] != "" ? $row["ns"] : $_GET["ns"], $onchange);
if ($row["ns"] != "") {
set_schema($orig_schema);
}
} elseif (JUSH != "sqlite") {
$dbs = array();
foreach ($adminer->databases() as $db) {
if (!information_schema($db)) {
@@ -77,7 +88,7 @@ if ($jush == "pgsql") {
?>
<input type="hidden" name="change-js" value="">
<noscript><p><input type="submit" name="change" value="<?php echo lang('Change'); ?>"></noscript>
<table cellspacing="0">
<table>
<thead><tr><th id="label-source"><?php echo lang('Source'); ?><th id="label-target"><?php echo lang('Target'); ?></thead>
<?php
$j = 0;
@@ -90,18 +101,20 @@ foreach ($row["source"] as $key => $val) {
?>
</table>
<p>
<?php echo lang('ON DELETE'); ?>: <?php echo html_select("on_delete", array(-1 => "") + explode("|", $on_actions), $row["on_delete"]); ?>
<?php echo lang('ON UPDATE'); ?>: <?php echo html_select("on_update", array(-1 => "") + explode("|", $on_actions), $row["on_update"]); ?>
<?php echo lang('ON DELETE'); ?>: <?php echo html_select("on_delete", array(-1 => "") + explode("|", $driver->onActions), $row["on_delete"]); ?>
<?php echo lang('ON UPDATE'); ?>: <?php echo html_select("on_update", array(-1 => "") + explode("|", $driver->onActions), $row["on_update"]); ?>
<?php echo doc_link(array(
'sql' => "innodb-foreign-key-constraints.html",
'mariadb' => "foreign-keys/",
'pgsql' => "sql-createtable.html#SQL-CREATETABLE-REFERENCES",
'mssql' => "ms174979.aspx",
'oracle' => "https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm#sthref2903",
'mssql' => "t-sql/statements/create-table-transact-sql",
'oracle' => "SQLRF01111",
)); ?>
<p>
<input type="submit" value="<?php echo lang('Save'); ?>">
<noscript><p><input type="submit" name="add" value="<?php echo lang('Add column'); ?>"></noscript>
<?php if ($name != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?><?php } ?>
<?php if ($name != "") { ?>
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $name)); ?>
<?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>

View File

@@ -1,44 +1,38 @@
<?php
namespace Adminer;
// any method change in this file should be transferred to editor/include/adminer.inc.php and plugins/plugin.php
class Adminer {
/** @var array operators used in select, null for all 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;
var $operators;
/** Name in title and navigation
* @return string HTML code
*/
function name() {
return "<a id='h1' href='" . h(HOME_URL) . "'>Adminer</a>";
return "<a href='https://www.adminer.org/'" . target_blank() . " id='h1'>Adminer</a>";
}
/** Connection parameters
* @return array ($server, $username, $password)
* @return array [$server, $username, $password]
*/
function credentials() {
return array(SERVER, $_GET["username"], get_password());
}
/** Get SSL connection options
* @return array array("key" => filename, "cert" => filename, "ca" => filename) or null
* @return array ["key" => filename, "cert" => filename, "ca" => filename] or null
*/
function connectSsl() {
}
/**
* Gets a private key used for permanent login.
*
* @param bool $create
*
* @return string|false Cryptic string which gets combined with password or false in case of an error.
* @throws \Random\RandomException
/** Get key used for permanent login
* @param bool
* @return string cryptic string which gets combined with password or false in case of an error
*/
function permanentLogin($create = false) {
return get_private_key($create);
return password_file($create);
}
/** Return key used to group brute force attacks; behind a reverse proxy, you want to return the last part of X-Forwarded-For
@@ -104,7 +98,7 @@ class Adminer {
*/
function head() {
?>
<link rel="stylesheet" type="text/css" href="../vendor/vrana/jush/jush.css">
<link rel="stylesheet" type="text/css" href="../externals/jush/jush.css">
<?php
return true;
}
@@ -126,12 +120,12 @@ class Adminer {
*/
function loginForm() {
global $drivers;
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('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(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('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">' . "\n");
echo "<table class='layout'>\n";
echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>', html_select("auth[driver]", $drivers, DRIVER, "loginDriver(this);"));
echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td>', '<input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">');
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input name="auth[username]" id="username" autofocus value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("qs('#username').form['auth[driver]'].onchange();"));
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">');
echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td>', '<input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">');
echo "</table>\n";
echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
@@ -144,7 +138,7 @@ class Adminer {
* @return string
*/
function loginFormField($name, $heading, $value) {
return $heading . $value;
return $heading . $value . "\n";
}
/** Authorize the user
@@ -182,14 +176,16 @@ class Adminer {
* @return null
*/
function selectLinks($tableStatus, $set = "") {
global $jush, $driver;
global $driver;
echo '<p class="links">';
$links = array("select" => lang('Select data'));
if (support("table") || support("indexes")) {
$links["table"] = lang('Show structure');
}
$is_view = false;
if (support("table")) {
if (is_view($tableStatus)) {
$is_view = is_view($tableStatus);
if ($is_view) {
$links["view"] = lang('Alter view');
} else {
$links["create"] = lang('Alter table');
@@ -202,7 +198,7 @@ class Adminer {
foreach ($links as $key => $val) {
echo " <a href='" . h(ME) . "$key=" . urlencode($name) . ($key == "edit" ? $set : "") . "'" . bold(isset($_GET[$key])) . ">$val</a>";
}
echo doc_link(array($jush => $driver->tableHelp($name)), "?");
echo doc_link(array(JUSH => $driver->tableHelp($name, $is_view)), "?");
echo "\n";
}
@@ -238,34 +234,25 @@ class Adminer {
* @return string
*/
function selectQuery($query, $start, $failed = false) {
global $jush, $driver;
$supportSql = support("sql");
$result = "<p>"
. "<code class='jush-$jush'>" . h(str_replace("\n", " ", $query)) . "</code> "
. "<span class='time'>(" . format_time($start) . ")</span>"
. ($supportSql ? " <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>" : "");
global $driver;
$return = "</p>\n"; // required for IE9 inline edit
if (!$failed && ($warnings = $driver->warnings())) {
$id = "warnings";
$result .= ($supportSql ? "," : "")
. " <a href='#$id'>" . lang('Warnings') . "</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "")
. "</p>\n"
. "<div id='$id' class='hidden'>\n$warnings</div>\n";
} else {
$result .= "</p>\n";
$return = ", <a href='#$id'>" . lang('Warnings') . "</a>" . script("qsl('a').onclick = partial(toggle, '$id');", "")
. "$return<div id='$id' class='hidden'>\n$warnings</div>\n"
;
}
return $result;
return "<p><code class='jush-" . JUSH . "'>" . h(str_replace("\n", " ", $query)) . "</code> <span class='time'>(" . format_time($start) . ")</span>"
. (support("sql") ? " <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>" : "")
. $return
;
}
/** Query printed in SQL command before execution
* @param string query to be executed
* @return string escaped query to be printed
*/
function sqlCommandQuery($query)
{
function sqlCommandQuery($query) {
return shorten_utf8(trim($query), 1000);
}
@@ -309,7 +296,7 @@ class Adminer {
if (preg_match('~json~', $field["type"])) {
$return = "<code class='jush-js'>$return</code>";
}
return ($link ? "<a href='" . h($link) . "'" . (is_web_url($link) ? target_blank() : "") . ">$return</a>" : $return);
return ($link ? "<a href='" . h($link) . "'" . (is_url($link) ? target_blank() : "") . ">$return</a>" : $return);
}
/** Value conversion used in select and edit
@@ -318,11 +305,6 @@ class Adminer {
* @return string
*/
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;
}
@@ -331,15 +313,22 @@ class Adminer {
* @return null
*/
function tableStructurePrint($fields) {
global $driver;
echo "<div class='scrollable'>\n";
echo "<table cellspacing='0' class='nowrap'>\n";
echo "<table class='nowrap odds'>\n";
echo "<thead><tr><th>" . lang('Column') . "<td>" . lang('Type') . (support("comment") ? "<td>" . lang('Comment') : "") . "</thead>\n";
$structured_types = $driver->structuredTypes();
foreach ($fields as $field) {
echo "<tr" . odd() . "><th>" . h($field["field"]);
echo "<td><span title='" . h($field["collation"]) . "'>" . h($field["full_type"]) . "</span>";
echo "<tr><th>" . h($field["field"]);
$type = h($field["full_type"]);
echo "<td><span title='" . h($field["collation"]) . "'>"
. (in_array($type, (array) $structured_types[lang('User types')]) ? "<a href='" . h(ME . 'type=' . urlencode($type)) . "'>$type</a>" : $type)
. "</span>"
;
echo ($field["null"] ? " <i>NULL</i>" : "");
echo ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : "");
echo (isset($field["default"]) ? " <span title='" . lang('Default value') . "'>[<b>" . h($field["default"]) . "</b>]</span>" : "");
$default = h($field["default"]);
echo (isset($field["default"]) ? " <span title='" . lang('Default value') . "'>[<b>" . ($field["generated"] ? "<code class='jush-" . JUSH . "'>$default</code>" : $default) . "</b>]</span>" : "");
echo (support("comment") ? "<td>" . h($field["comment"]) : "");
echo "\n";
}
@@ -347,40 +336,15 @@ class Adminer {
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
* @param array data about all indexes on a table
* @return null
*/
function tableIndexesPrint($indexes) {
echo "<table>\n";
echo "<thead><tr><th>" . lang('Type') . "</th><td>" . lang('Column (length)') . "</td></tr></thead>\n";
foreach ($indexes as $name => $index) {
ksort($index["columns"]); // enforce correct columns order
$print = [];
$print = array();
foreach ($index["columns"] as $key => $val) {
$print[] = "<i>" . h($val) . "</i>"
. ($index["lengths"][$key] ? "(" . $index["lengths"][$key] . ")" : "")
@@ -389,127 +353,91 @@ class Adminer {
}
echo "<tr title='" . h($name) . "'><th>$index[type]<td>" . implode(", ", $print) . "\n";
}
echo "</table>\n";
}
/**
* Prints columns box in select filter.
*
* @param array $select result of selectColumnsProcess()[0]
* @param array $columns selectable columns
/** Print columns box in select
* @param array result of selectColumnsProcess()[0]
* @param array selectable columns
* @return null
*/
function selectColumnsPrint($select, $columns) {
global $functions, $grouping;
print_fieldset("select", lang('Select'), $select, true);
$_GET["columns"][""] = [];
global $driver;
print_fieldset("select", lang('Select'), $select);
$i = 0;
foreach ($_GET["columns"] as $key => $val) {
if ($key != "" && $val["col"] == "") continue;
$select[""] = array();
foreach ($select as $key => $val) {
$val = $_GET["columns"][$key];
$column = select_input(
" name='columns[$i][col]'",
$columns,
$val["col"],
$key !== "" ? "selectFieldChange" : "selectAddRow"
($key !== "" ? "selectFieldChange" : "selectAddRow")
);
echo "<div ", ($key != "" ? "" : "class='no-sort'"), ">",
"<span class='jsonly handle'></span>";
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";
echo "<div>" . ($driver->functions || $driver->grouping ? html_select("columns[$i][fun]", array(-1 => "") + array_filter(array(lang('Functions') => $driver->functions, lang('Aggregation') => $driver->grouping)), $val["fun"])
. on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1)
. script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "")
. "($column)" : $column) . "</div>\n";
$i++;
}
echo "</div>", script("initSortable('#fieldset-select');"), "</fieldset>\n";
echo "</div></fieldset>\n";
}
/**
* Prints search box in select.
*
* @param array $where result of selectSearchProcess()
* @param array $columns selectable columns
/** Print search box in select
* @param array result of selectSearchProcess()
* @param array selectable columns
* @param array
* @return null
*/
function selectSearchPrint($where, $columns, $indexes) {
print_fieldset("search", lang('Search'), $where);
foreach ($indexes as $i => $index) {
if ($index["type"] == "FULLTEXT") {
echo "<div>(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST",
" <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>",
script("qsl('input').oninput = selectFieldChange;", ""),
checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL"),
"</div>\n";
echo "<div>(<i>" . implode("</i>, <i>", array_map('Adminer\h', $index["columns"])) . "</i>) AGAINST";
echo " <input type='search' name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>";
echo script("qsl('input').oninput = selectFieldChange;", "");
echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL");
echo "</div>\n";
}
}
$change_next = "this.parentNode.firstChild.onchange();";
foreach (array_merge((array) $_GET["where"], array(array())) as $i => $val) {
if (!$val || ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators))) {
echo "<div>",
select_input(
echo "<div>" . select_input(
" name='where[$i][col]'",
$columns,
$val["col"],
($val ? "selectFieldChange" : "selectAddRow"),
"(" . lang('anywhere') . ")"
),
html_select("where[$i][op]", $this->operators, $val["op"], $change_next),
"<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>",
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 html_select("where[$i][op]", $this->operators, $val["op"], $change_next);
echo "<input type='search' name='where[$i][val]' value='" . h($val["val"]) . "'>";
echo script("mixin(qsl('input'), {oninput: function () { $change_next }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch});", "");
echo "</div>\n";
}
}
echo "</div></fieldset>\n";
}
/**
* Prints order box in select filter.
*
* @param array $order result of selectOrderProcess()
* @param array $columns selectable columns
/** Print order box in select
* @param array result of selectOrderProcess()
* @param array selectable columns
* @param array
* @return null
*/
function selectOrderPrint($order, $columns, $indexes) {
print_fieldset("sort", lang('Sort'), $order, true);
$_GET["order"][""] = "";
print_fieldset("sort", lang('Sort'), $order);
$i = 0;
foreach ((array) $_GET["order"] as $key => $val) {
if ($key != "" && $val == "") continue;
echo "<div ", ($key != "" ? "" : "class='no-sort'"), ">",
"<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";
if ($val != "") {
echo "<div>" . select_input(" name='order[$i]'", $columns, $val, "selectFieldChange");
echo checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')) . "</div>\n";
$i++;
}
echo "</div>", script("initSortable('#fieldset-sort');"), "</fieldset>\n";
}
echo "<div>" . select_input(" name='order[$i]'", $columns, "", "selectAddRow");
echo checkbox("desc[$i]", 1, false, lang('descending')) . "</div>\n";
echo "</div></fieldset>\n";
}
/** Print limit box in select
@@ -557,7 +485,7 @@ class Adminer {
json_row($key);
}
echo ";\n";
echo "selectFieldChange.call(gid('form')['select']);\n";
echo "selectFieldChange.call(qs('#form')['select']);\n";
echo "</script>\n";
echo "</div></fieldset>\n";
}
@@ -587,16 +515,16 @@ class Adminer {
/** Process columns box in select
* @param array selectable columns
* @param array
* @return array (array(select_expressions), array(group_expressions))
* @return array [[select_expressions], [group_expressions]]
*/
function selectColumnsProcess($columns, $indexes) {
global $functions, $grouping;
global $driver;
$select = array(); // select expressions, empty for *
$group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
foreach ((array) $_GET["columns"] as $key => $val) {
if ($val["fun"] == "count" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
if ($val["fun"] == "count" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], $driver->functions) || in_array($val["fun"], $driver->grouping)))) {
$select[$key] = apply_sql_function($val["fun"], ($val["col"] != "" ? idf_escape($val["col"]) : "*"));
if (!in_array($val["fun"], $grouping)) {
if (!in_array($val["fun"], $driver->grouping)) {
$group[] = $select[$key];
}
}
@@ -610,62 +538,51 @@ class Adminer {
* @return array expressions to join by AND
*/
function selectSearchProcess($fields, $indexes) {
global $driver;
$return = [];
global $connection, $driver;
$return = array();
foreach ($indexes as $i => $index) {
if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") {
$return[] = "MATCH (" . implode(", ", array_map('idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")";
$return[] = "MATCH (" . implode(", ", array_map('Adminer\idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")";
}
}
foreach ((array) $_GET["where"] as $where) {
$col = $where["col"];
$op = $where["op"];
$val = $where["val"];
if ("$col$val" != "" && in_array($op, $this->operators)) {
foreach ((array) $_GET["where"] as $key => $val) {
if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
$prefix = "";
$cond = " $op";
if (preg_match('~IN$~', $op)) {
$in = process_length($val);
$cond = " $val[op]";
if (preg_match('~IN$~', $val["op"])) {
$in = process_length($val["val"]);
$cond .= " " . ($in != "" ? $in : "(NULL)");
} elseif ($op == "SQL") {
$cond = " $val"; // SQL injection
} elseif ($op == "LIKE %%") {
$cond = " LIKE " . $this->processInput($fields[$col], "%$val%");
} elseif ($op == "ILIKE %%") {
$cond = " ILIKE " . $this->processInput($fields[$col], "%$val%");
} elseif ($op == "FIND_IN_SET") {
$prefix = "$op(" . q($val) . ", ";
} elseif ($val["op"] == "SQL") {
$cond = " $val[val]"; // SQL injection
} elseif ($val["op"] == "LIKE %%") {
$cond = " LIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%");
} elseif ($val["op"] == "ILIKE %%") {
$cond = " ILIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%");
} elseif ($val["op"] == "FIND_IN_SET") {
$prefix = "$val[op](" . q($val["val"]) . ", ";
$cond = ")";
} elseif (!preg_match('~NULL$~', $op)) {
$cond .= " " . $this->processInput($fields[$col], $val);
} elseif (!preg_match('~NULL$~', $val["op"])) {
$cond .= " " . $this->processInput($fields[$val["col"]], $val["val"]);
}
if ($col != "") {
$return[] = $prefix . $driver->convertSearch(idf_escape($col), $where, $fields[$col]) . $cond;
if ($val["col"] != "") {
$return[] = $prefix . $driver->convertSearch(idf_escape($val["col"]), $val, $fields[$val["col"]]) . $cond;
} else {
// find anywhere
$cols = array();
foreach ($fields as $name => $field) {
if (isset($field["privileges"]["where"])
&& (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('~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.
if (
isset($field["privileges"]["where"])
&& (preg_match('~^[-\d.' . (preg_match('~IN$~', $val["op"]) ? ',' : '') . ']+$~', $val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
&& (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"]))
&& (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val["val"]))
) {
$cols[] = $prefix . $driver->convertSearch(idf_escape($name), $where, $field) . $cond;
$cols[] = $prefix . $driver->convertSearch(idf_escape($name), $val, $field) . $cond;
}
}
$return[] = ($cols ? "(" . implode(" OR ", $cols) . ")" : "1 = 0");
}
}
}
return $return;
}
@@ -729,7 +646,7 @@ class Adminer {
* @return string
*/
function messageQuery($query, $time, $failed = false) {
global $jush, $driver;
global $driver;
restart_session();
$history = &get_session("queries");
if (!$history[$_GET["db"]]) {
@@ -746,7 +663,7 @@ class Adminer {
$return = "<a href='#$id' class='toggle'>" . lang('Warnings') . "</a>, $return<div id='$id' class='hidden'>\n$warnings</div>\n";
}
return " <span class='time'>" . @date("H:i:s") . "</span>" // @ - time zone may be not set
. " $return<div id='$sql_id' class='hidden'><pre><code class='jush-$jush'>" . shorten_utf8($query, 1000) . "</code></pre>"
. " $return<div id='$sql_id' class='hidden'><pre><code class='jush-" . JUSH . "'>" . shorten_utf8($query, 1000) . "</code></pre>"
. ($time ? " <span class='time'>($time)</span>" : '')
. (support("sql") ? '<p><a href="' . h(str_replace("db=" . urlencode(DB), "db=" . urlencode($_GET["db"]), ME) . 'sql=&history=' . (count($history[$_GET["db"]]) - 1)) . '">' . lang('Edit') . '</a>' : '')
. '</div>'
@@ -768,10 +685,10 @@ class Adminer {
* @return array
*/
function editFunctions($field) {
global $edit_functions;
global $driver;
$return = ($field["null"] ? "NULL/" : "");
$update = isset($_GET["select"]) || where($_GET);
foreach ($edit_functions as $key => $functions) {
foreach ($driver->editFunctions as $key => $functions) {
if (!$key || (!isset($_GET["call"]) && $update)) { // relative functions
foreach ($functions as $pattern => $val) {
if (!$pattern || preg_match("~$pattern~", $field["type"])) {
@@ -796,11 +713,11 @@ class Adminer {
* @param string
* @return string custom input field or empty string for default
*/
function editInput($table, $field, $attrs, $value, $function) {
function editInput($table, $field, $attrs, $value) {
if ($field["type"] == "enum") {
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> " : "")
. enum_input("radio", $attrs, $field, $value, 0) // 0 - empty
. enum_input("radio", $attrs, $field, $value, $value === 0 ? 0 : null) // 0 - empty value
;
}
return "";
@@ -848,11 +765,10 @@ class Adminer {
* @return array
*/
function dumpOutput() {
$return = array('file' => lang('save'), 'text' => lang('open'));
$return = array('text' => lang('open'), 'file' => lang('save'));
if (function_exists('gzencode')) {
$return['gz'] = 'gzip';
}
return $return;
}
@@ -860,7 +776,7 @@ class Adminer {
* @return array empty to disable export
*/
function dumpFormat() {
return array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV');
return (support("dump") ? array('sql' => 'SQL') : array()) + array('csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV');
}
/** Export database structure
@@ -912,21 +828,32 @@ class Adminer {
* @return null prints data
*/
function dumpData($table, $style, $query) {
global $connection, $jush;
$max_packet = ($jush == "sqlite" ? 0 : 1048576); // default, minimum is 1024
global $connection;
if ($style) {
$max_packet = (JUSH == "sqlite" ? 0 : 1048576); // default, minimum is 1024
$fields = array();
$identity_insert = false;
if ($_POST["format"] == "sql") {
if ($style == "TRUNCATE+INSERT") {
echo truncate_sql($table) . ";\n";
}
$fields = fields($table);
if (JUSH == "mssql") {
foreach ($fields as $field) {
if ($field["auto_increment"]) {
echo "SET IDENTITY_INSERT " . table($table) . " ON;\n";
$identity_insert = true;
break;
}
}
}
}
$result = $connection->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers
if ($result) {
$insert = "";
$buffer = "";
$keys = array();
$generatedKeys = array();
$generated = array();
$suffix = "";
$fetch_function = ($table != '' ? 'fetch_assoc' : 'fetch_row');
while ($row = $result->$fetch_function()) {
@@ -934,8 +861,8 @@ class Adminer {
$values = array();
foreach ($row as $val) {
$field = $result->fetch_field();
if (!empty($fields[$field->name]['generated'])) {
$generatedKeys[$field->name] = true;
if ($fields[$field->name]['generated']) {
$generated[$field->name] = true;
continue;
}
$keys[] = $field->name;
@@ -952,10 +879,10 @@ class Adminer {
dump_csv($row);
} else {
if (!$insert) {
$insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('idf_escape', $keys)) . ") VALUES";
$insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('Adminer\idf_escape', $keys)) . ") VALUES";
}
foreach ($row as $key => $val) {
if (isset($generatedKeys[$key])) {
if ($generated[$key]) {
unset($row[$key]);
continue;
}
@@ -982,6 +909,9 @@ class Adminer {
} elseif ($_POST["format"] == "sql") {
echo "-- " . str_replace("\n", " ", $connection->error) . "\n";
}
if ($identity_insert) {
echo "SET IDENTITY_INSERT " . table($table) . " OFF;\n";
}
}
}
@@ -1012,10 +942,8 @@ class Adminer {
return $ext;
}
/**
* Gets the path of the file for webserver load.
*
* @return string Path of the sql import file.
/** Set the path of the file for webserver load
* @return string path of the sql dump file
*/
function importServerPath() {
return "adminer.sql";
@@ -1037,28 +965,17 @@ class Adminer {
* @return null
*/
function navigation($missing) {
global $VERSION, $jush, $drivers, $connection;
global $VERSION, $drivers, $connection;
?>
<h1>
<?php echo $this->name(); ?>
<?php if ($missing != "auth"): ?>
<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>
<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>
<?php
if (!isset($_COOKIE["adminer_version"])) {
echo script("verifyVersion('" . js_escape(ME) . "', '" . get_token() . "');");
}
?>
<?php endif; ?>
</h1>
<?php
switch_lang();
if ($missing == "auth") {
$output = "";
foreach ((array) $_SESSION["pwds"] as $vendor => $servers) {
@@ -1067,21 +984,14 @@ class Adminer {
if ($password !== null) {
$dbs = $_SESSION["db"][$vendor][$server][$username];
foreach (($dbs ? array_keys($dbs) : array("")) as $db) {
$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";
$output .= "<li><a href='" . h(auth_url($vendor, $server, $username, $db)) . "'>($drivers[$vendor]) " . h($username . ($server != "" ? "@" . $this->serverName($server) : "") . ($db != "" ? " - $db" : "")) . "</a>\n";
}
}
}
}
}
if ($output) {
echo "<ul id='logins'>\n$output</ul>\n" . script("mixin(gid('logins'), {onmouseover: menuOver, onmouseout: menuOut});");
echo "<ul id='logins'>\n$output</ul>\n" . script("mixin(qs('#logins'), {onmouseover: menuOver, onmouseout: menuOut});");
}
} else {
$tables = array();
@@ -1089,12 +999,12 @@ class Adminer {
$connection->select_db(DB);
$tables = table_status('', true);
}
echo script_src("../vendor/vrana/jush/modules/jush.js");
echo script_src("../vendor/vrana/jush/modules/jush-textarea.js");
echo script_src("../vendor/vrana/jush/modules/jush-txt.js");
echo script_src("../vendor/vrana/jush/modules/jush-js.js");
echo script_src("../externals/jush/modules/jush.js");
echo script_src("../externals/jush/modules/jush-textarea.js");
echo script_src("../externals/jush/modules/jush-txt.js");
echo script_src("../externals/jush/modules/jush-js.js");
if (support("sql")) {
echo script_src("../vendor/vrana/jush/modules/jush-$jush.js");
echo script_src("../externals/jush/modules/jush-" . JUSH . ".js");
?>
<script<?php echo nonce(); ?>>
<?php
@@ -1103,9 +1013,9 @@ class Adminer {
foreach ($tables as $table => $type) {
$links[] = preg_quote($table, '/');
}
echo "var jushLinks = { $jush: [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
echo "var jushLinks = { " . JUSH . ": [ '" . js_escape(ME) . (support("table") ? "table=" : "select=") . "\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
echo "jushLinks.$val = jushLinks.$jush;\n";
echo "jushLinks.$val = jushLinks." . JUSH . ";\n";
}
}
$server_info = $connection->server_info;
@@ -1114,29 +1024,22 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
</script>
<?php
}
$this->databasesPrint($missing);
$actions = [];
$actions = array();
if (DB == "" || !$missing) {
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")) {
$actions[] = "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Export') . "</a>";
}
$in_db = $_GET["ns"] !== "" && !$missing && DB != "";
if ($in_db) {
$actions[] = '<a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create table') . "</a>";
}
if ($_GET["ns"] !== "" && !$missing && DB != "") {
$actions[] = '<a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create table') . "</a>\n";
}
if ($actions) {
echo "<p class='links'>" . implode("\n", $actions) . "</p>";
}
if ($_GET["ns"] !== "" && !$missing && DB != "") {
echo ($actions ? "<p class='links'>\n" . implode("\n", $actions) . "\n" : "");
if ($in_db) {
if ($tables) {
$this->printTablesFilter();
$this->tablesPrint($tables);
} else {
echo "<p class='message'>" . lang('No tables.') . "</p>\n";
@@ -1145,97 +1048,65 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
}
}
/**
* Prints databases select in menu.
*
* @param $missing string
/** Prints databases list in menu
* @param string
* @return null
*/
function databasesPrint($missing) {
global $adminer, $connection;
$databases = $this->databases();
if (DB && $databases && !in_array(DB, $databases)) {
array_unshift($databases, DB);
}
echo "<form action=''><p id='dbs'>";
?>
<form action="">
<p id="dbs">
<?php
hidden_fields_get();
if ($databases) {
echo "<select id='database-select' name='db'>" . optionlist(["" => lang('Database')] + $databases, DB) . "</select>"
. script("mixin(gid('database-select'), {onmousedown: dbMouseDown, onchange: dbChange});");
} else {
echo "<input id='database-select' name='db' value='" . h(DB) . "' autocapitalize='off'>\n";
}
$db_events = script("mixin(qsl('select'), {onmousedown: dbMouseDown, onchange: dbChange});");
echo "<span title='" . lang('Database') . "'>" . lang('DB') . "</span>: " . ($databases
? html_select("db", array("" => "") + $databases, DB) . $db_events
: "<input name='db' value='" . h(DB) . "' autocapitalize='off' size='19'>\n"
);
echo "<input type='submit' value='" . lang('Use') . "'" . ($databases ? " class='hidden'" : "") . ">\n";
if (support("scheme") && $missing != "db" && DB != "" && $connection->select_db(DB)) {
echo "<br><select id='scheme-select' name='ns'>" . optionlist(["" => lang('Schema')] + $adminer->schemas(), $_GET["ns"]) . "</select>"
. script("mixin(gid('scheme-select'), {onmousedown: dbMouseDown, onchange: dbChange});");
if (support("scheme")) {
if ($missing != "db" && DB != "" && $connection->select_db(DB)) {
echo "<br>" . lang('Schema') . ": " . html_select("ns", array("" => "") + $adminer->schemas(), $_GET["ns"]) . $db_events;
if ($_GET["ns"] != "") {
set_schema($_GET["ns"]);
}
}
foreach (["import", "sql", "schema", "dump", "privileges"] as $val) {
}
foreach (array("import", "sql", "schema", "dump", "privileges") as $val) {
if (isset($_GET[$val])) {
echo "<input type='hidden' name='$val' value=''>";
break;
}
}
echo "</p></form>\n";
return null;
}
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";
}
/**
* Prints table list in menu.
*
* @param array $tables Result of table_status('', true)
/** Prints table list in menu
* @param array result of table_status('', true)
* @return null
*/
function tablesPrint($tables) {
echo "<ul id='tables'>" . script("mixin(gid('tables'), {onmouseover: menuOver, onmouseout: menuOut});");
echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $table => $status) {
$name = $this->tableName($status);
if ($name != "") {
$active = $table == $_GET["select"] || $table == $_GET["edit"];
echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"'
. bold($active, "select")
. " title='" . lang('Select data') . "'>" . lang('select') . "</a> ";
if (support("table") || support("indexes")) {
$active = in_array($table, [$_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"]]);
$class = is_view($status) ? "view" : "structure";
echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' . bold($active, $class)
. " title='" . lang('Show structure') . "' data-main='true'>$name</a>";
} else {
echo "<span data-main='true'>$name</span>";
}
echo "</li>\n";
. bold($_GET["select"] == $table || $_GET["edit"] == $table, "select")
. " title='" . lang('Select data') . "'>" . lang('select') . "</a> "
;
echo (support("table") || support("indexes")
? '<a href="' . h(ME) . 'table=' . urlencode($table) . '"'
. bold(in_array($table, array($_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"])), (is_view($status) ? "view" : "structure"))
. " title='" . lang('Show structure') . "'>$name</a>"
: "<span>$name</span>"
) . "\n";
}
}
echo "</ul>\n";
return null;
}
}

View File

@@ -1,4 +1,5 @@
<?php
namespace Adminer;
$connection = '';
@@ -16,78 +17,13 @@ if ($_COOKIE["adminer_permanent"]) {
}
}
function validate_server_input() {
if (SERVER == "") {
return;
}
$parts = parse_url(SERVER);
if (!$parts) {
auth_error(lang('Invalid server or credentials.'));
}
// Check proper URL parts.
if (isset($parts['user']) || isset($parts['pass']) || isset($parts['query']) || isset($parts['fragment'])) {
auth_error(lang('Invalid server or credentials.'));
}
// Allow only HTTP/S scheme.
if (isset($parts['scheme']) && !preg_match('~^(https?)$~i', $parts['scheme'])) {
auth_error(lang('Invalid server or credentials.'));
}
// Note that "localhost" and IP address without a scheme is parsed as a path.
$hostPath = (isset($parts['host']) ? $parts['host'] : '') . (isset($parts['path']) ? $parts['path'] : '');
// Validate host.
if (!is_server_host_valid($hostPath)) {
auth_error(lang('Invalid server or credentials.'));
}
// Check privileged ports.
if (isset($parts['port']) && ($parts['port'] < 1024 || $parts['port'] > 65535)) {
auth_error(lang('Connecting to privileged ports is not allowed.'));
}
}
if (!function_exists('is_server_host_valid')) {
/**
* @param string $hostPath
* @return bool
*/
function is_server_host_valid($hostPath)
{
return strpos($hostPath, '/') === false;
}
}
/**
* @param string $server
* @param string $username
* @param string $password
* @param string $defaultServer
* @param int|null $defaultPort
* @return string
*/
function build_http_url($server, $username, $password, $defaultServer, $defaultPort = null) {
if (!preg_match('~^(https?://)?([^:]*)(:\d+)?$~', rtrim($server, '/'), $matches)) {
auth_error(lang('Invalid server or credentials.'));
return false;
}
return ($matches[1] ?: "http://") .
($username !== "" || $password !== "" ? "$username:$password@" : "") .
($matches[2] !== "" ? $matches[2] : $defaultServer) .
(isset($matches[3]) ? $matches[3] : ($defaultPort ? ":$defaultPort" : ""));
}
function add_invalid_login() {
global $adminer;
$file = open_file_with_lock(get_temp_dir() . "/adminer.invalid");
if (!$file) {
$fp = file_open_lock(get_temp_dir() . "/adminer.invalid");
if (!$fp) {
return;
}
$invalids = unserialize(stream_get_contents($file));
$invalids = unserialize(stream_get_contents($fp));
$time = time();
if ($invalids) {
foreach ($invalids as $ip => $val) {
@@ -101,16 +37,13 @@ function add_invalid_login() {
$invalid = array($time + 30*60, 0); // active for 30 minutes
}
$invalid[1]++;
write_and_unlock_file($file, serialize($invalids));
file_write_unlock($fp, serialize($invalids));
}
function check_invalid_login() {
global $adminer;
$filename = get_temp_dir() . "/adminer.invalid";
$invalids = file_exists($filename) ? unserialize(file_get_contents($filename)) : [];
$invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : []);
$invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist
$invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : array());
$next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts
if ($next_attempt > 0) { //! do the same with permanent login
auth_error(lang('Too many unsuccessful logins, try again in %d minute(s).', ceil($next_attempt / 60)));
@@ -121,7 +54,7 @@ $auth = $_POST["auth"];
if ($auth) {
session_regenerate_id(); // defense against session fixation
$vendor = $auth["driver"];
$server = trim($auth["server"]);
$server = $auth["server"];
$username = $auth["username"];
$password = (string) $auth["password"];
$db = $auth["db"];
@@ -133,7 +66,8 @@ if ($auth) {
$permanent[$key] = "$key:" . base64_encode($private ? encrypt_string($password, $private) : "");
cookie("adminer_permanent", implode(" ", $permanent));
}
if (count($_POST) == 1 // 1 - auth
if (
count($_POST) == 1 // 1 - auth
|| DRIVER != $vendor
|| SERVER != $server
|| $_GET["username"] !== $username // "0" == "00"
@@ -147,7 +81,7 @@ if ($auth) {
set_session($key, null);
}
unset_permanent();
redirect(HOME_URL, lang('Logout successful.') . ' ' . lang('Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.'));
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>.'));
} elseif ($permanent && !$_SESSION["pwds"]) {
session_regenerate_id();
@@ -174,7 +108,6 @@ function unset_permanent() {
/** Renders an error message and a login form
* @param string plain text
* @return null exits
* @throws \Random\RandomException
*/
function auth_error($error) {
global $adminer, $has_token;
@@ -200,7 +133,7 @@ function auth_error($error) {
$error = lang('Session support must be enabled.');
}
$params = session_get_cookie_params();
cookie("adminer_key", ($_COOKIE["adminer_key"] ?: get_random_string()), $params["lifetime"]);
cookie("adminer_key", ($_COOKIE["adminer_key"] ?: rand_string()), $params["lifetime"]);
page_header(lang('Login'), $error, null);
echo "<form action='' method='post'>\n";
echo "<div>";
@@ -214,16 +147,10 @@ function auth_error($error) {
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('Adminer\Db')) {
unset($_SESSION["pwds"][DRIVER]);
unset_permanent();
page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), false);
page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", Driver::$possibleDrivers)), false);
page_footer("auth");
exit;
}
@@ -231,16 +158,23 @@ if (isset($_GET["username"]) && !class_exists("Min_DB")) {
stop_session(true);
if (isset($_GET["username"]) && is_string(get_password())) {
validate_server_input();
list($host, $port) = explode(":", SERVER, 2);
if (preg_match('~^\s*([-+]?\d+)~', $port, $match) && ($match[1] < 1024 || $match[1] > 65535)) { // is_numeric('80#') would still connect to port 80
auth_error(lang('Connecting to privileged ports is not allowed.'));
}
check_invalid_login();
$connection = connect();
$driver = new Min_Driver($connection);
$connection = connect($adminer->credentials());
if (is_object($connection)) {
$driver = new Driver($connection);
if ($adminer->operators === null) {
$adminer->operators = $driver->operators;
}
}
}
$login = null;
if (!is_object($connection) || ($login = $adminer->login($_GET["username"], get_password())) !== true) {
$error = (is_string($connection) ? h($connection) : (is_string($login) ? $login : lang('Invalid server or credentials.')));
$error = (is_string($connection) ? nl_br(h($connection)) : (is_string($login) ? $login : lang('Invalid credentials.')));
auth_error($error . (preg_match('~^ | $~', get_password()) ? '<br>' . lang('There is a space in the input password which might be the cause.') : ''));
}

View File

@@ -1,12 +1,8 @@
<?php
function adminer_errors($errno, $errstr) {
return (bool)preg_match('~^(Trying to access array offset on( value of type)? null|Undefined array key)~', $errstr);
}
namespace Adminer;
error_reporting(6135); // errors and warnings
set_error_handler('adminer_errors', E_WARNING);
include "../adminer/include/debug.inc.php";
include "../adminer/include/version.inc.php";
include "../adminer/include/errors.inc.php";
include "../adminer/include/coverage.inc.php";
// disable filter.default
@@ -32,14 +28,14 @@ if (isset($_GET["file"])) {
}
if ($_GET["script"] == "version") {
$file = open_file_with_lock(get_temp_dir() . "/adminer.version");
if ($file) {
write_and_unlock_file($file, serialize(["version" => $_POST["version"]]));
$fp = file_open_lock(get_temp_dir() . "/adminer.version");
if ($fp) {
file_write_unlock($fp, serialize(array("signature" => $_POST["signature"], "version" => $_POST["version"])));
}
exit;
}
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
global $adminer, $connection, $driver, $drivers, $error, $HTTPS, $LANG, $langs, $permanent, $has_token, $token, $translations, $VERSION; // allows including Adminer inside a function
if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
@@ -56,11 +52,7 @@ $HTTPS = ($_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")) || ini_bool
if (!defined("SID")) {
session_cache_limiter(""); // to allow restarting session
session_name("adminer_sid"); // use specific session name to get own namespace
$params = array(0, preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS);
if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
$params[] = true; // HttpOnly
}
call_user_func_array('session_set_cookie_params', $params); // ini_set() may be disabled
session_set_cookie_params(0, preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]), "", $HTTPS, true); // ini_set() may be disabled
session_start();
}
@@ -73,87 +65,33 @@ if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) {
@ini_set("zend.ze1_compatibility_mode", false); // @ - deprecated
@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/lang/$LANG.inc.php";
include "../adminer/include/pdo.inc.php";
include "../adminer/include/driver.inc.php";
include "../adminer/drivers/mysql.inc.php";
include "../adminer/drivers/pgsql.inc.php";
include "../adminer/drivers/sqlite.inc.php";
include "../adminer/drivers/pgsql.inc.php";
include "../adminer/drivers/oracle.inc.php";
include "../adminer/drivers/mssql.inc.php";
include "../adminer/drivers/mongo.inc.php";
include "./include/adminer.inc.php";
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer());
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
if (defined("DRIVER")) {
$config = driver_config();
$possible_drivers = $config['possible_drivers'];
$jush = $config['jush'];
$types = $config['types'];
$structured_types = $config['structured_types'];
$unsigned = $config['unsigned'];
$operators = $config['operators'];
$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", DRIVER ? $_GET[DRIVER] : null); // read from pgsql=localhost
define("DB", $_GET["db"]); // for the sake of speed and size
define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?'
define('Adminer\JUSH', Driver::$jush);
define('Adminer\SERVER', $_GET[DRIVER]); // read from pgsql=localhost
define('Adminer\DB', $_GET["db"]); // for the sake of speed and size
define(
'Adminer\ME',
preg_replace('~\?.*~', '', relative_uri()) . '?'
. (sid() ? SID . '&' : '')
. (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
. (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
. (DB != "" ? 'db=' . urlencode(DB) . '&' . (isset($_GET["ns"]) ? "ns=" . urlencode($_GET["ns"]) . "&" : "") : '')
);
define("HOME_URL", substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1) ?: ".");
include "../adminer/include/version.inc.php";
include "../adminer/include/design.inc.php";
include "../adminer/include/xxtea.inc.php";
include "../adminer/include/auth.inc.php";
include "./include/editing.inc.php";
include "./include/connect.inc.php";
$on_actions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()

View File

@@ -1,6 +1,18 @@
<?php
function connect_error() {
global $adminer, $connection, $token, $error, $drivers;
namespace Adminer;
if (isset($_GET["status"])) {
$_GET["variables"] = $_GET["status"];
}
if (isset($_GET["import"])) {
$_GET["sql"] = $_GET["import"];
}
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
if (DB != "" || $_GET["refresh"]) {
restart_session();
set_session("dbs", null);
}
if (DB != "") {
header("HTTP/1.1 404 Not Found");
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), true);
@@ -11,13 +23,15 @@ function connect_error() {
page_header(lang('Select database'), $error, false);
echo "<p class='links'>\n";
foreach (array(
foreach (
array(
'database' => lang('Create database'),
'privileges' => lang('Privileges'),
'processlist' => lang('Process list'),
'variables' => lang('Variables'),
'status' => lang('Status'),
) as $key => $val) {
) as $key => $val
) {
if (support($key)) {
echo "<a href='" . h(ME) . "$key='>$val</a>\n";
}
@@ -29,11 +43,11 @@ function connect_error() {
$scheme = support("scheme");
$collations = collations();
echo "<form action='' method='post'>\n";
echo "<table cellspacing='0' class='checkable'>\n";
echo "<table class='checkable odds'>\n";
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
echo "<thead><tr>"
. (support("database") ? "<td>" : "")
. "<th>" . lang('Database') . " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>"
. "<th>" . lang('Database') . (get_session("dbs") !== null ? " - <a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>" : "")
. "<td>" . lang('Collation')
. "<td>" . lang('Tables')
. "<td>" . lang('Size') . " - <a href='" . h(ME) . "dbsize=1'>" . lang('Compute') . "</a>" . script("qsl('a').onclick = partial(ajaxSetHtml, '" . js_escape(ME) . "script=connect');", "")
@@ -45,7 +59,7 @@ function connect_error() {
foreach ($databases as $db => $tables) {
$root = h(ME) . "db=" . urlencode($db);
$id = h("Db-" . $db);
echo "<tr" . odd() . ">" . (support("database") ? "<td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : "");
echo "<tr>" . (support("database") ? "<td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]), "", "", "", $id) : "");
echo "<th><a href='$root' id='$id'>" . h($db) . "</a>";
$collation = h(db_collation($db, $collations));
echo "<td>" . (support("database") ? "<a href='$root" . ($scheme ? "&amp;ns=" : "") . "&amp;database=' title='" . lang('Alter database') . "'>$collation</a>" : $collation);
@@ -71,21 +85,6 @@ function connect_error() {
}
page_footer("db");
}
if (isset($_GET["status"])) {
$_GET["variables"] = $_GET["status"];
}
if (isset($_GET["import"])) {
$_GET["sql"] = $_GET["import"];
}
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
if (DB != "" || $_GET["refresh"]) {
restart_session();
set_session("dbs", null);
}
connect_error(); // separate function to catch SQLite error
exit;
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
// coverage is used in tests and removed in compilation
if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer_coverage.ser")) {
function save_coverage() {
@@ -14,5 +16,5 @@ if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer_cov
}
}
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
register_shutdown_function('save_coverage');
register_shutdown_function('Adminer\save_coverage');
}

View File

@@ -1,27 +0,0 @@
<?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

@@ -1,13 +1,19 @@
<?php
namespace Adminer;
if (!ob_get_level()) {
ob_start(null, 4096);
}
/** Print HTML header
* @param string used in title, breadcrumb and heading, should be HTML escaped
* @param string
* @param mixed array("key" => "link", "key2" => array("link", "desc")), null for nothing, false for driver only, true for driver and server
* @param mixed ["key" => "link", "key2" => ["link", "desc"]], null for nothing, false for driver only, true for driver and server
* @param string used after colon in title and heading, should be HTML escaped
* @return null
*/
function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
global $LANG, $VERSION, $adminer, $drivers, $jush;
function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
global $LANG, $VERSION, $adminer, $drivers;
page_headers();
if (is_ajax() && $error) {
page_messages($error);
@@ -15,24 +21,16 @@ function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
}
$title_all = $title . ($title2 != "" ? ": $title2" : "");
$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>
<html lang="<?php echo $LANG; ?>" dir="<?php echo lang('ltr'); ?>">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width">
<title><?php echo $title_page; ?></title>
<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?" . filemtime("../adminer/static/functions.js")); ?>
<?php echo script_src("static/editing.js?" . filemtime("../adminer/static/editing.js")); ?>
<link rel="stylesheet" type="text/css" href="../adminer/static/default.css">
<?php echo script_src("../adminer/static/functions.js"); ?>
<?php echo script_src("static/editing.js"); ?>
<?php if ($adminer->head()) { ?>
<link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico">
<link rel="apple-touch-icon" href="../adminer/static/favicon.ico">
@@ -42,51 +40,56 @@ function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
<?php } ?>
<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(); ?>>
const body = document.body;
body.onkeydown = bodyKeydown;
body.onclick = bodyClick;
body.classList.remove("nojs");
body.classList.add("js");
mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick<?php
echo (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '$VERSION', '" . js_escape(ME) . "', '" . get_token() . "')"); // $token may be empty in auth.inc.php
?>});
document.body.className = document.body.className.replace(/ nojs/, ' js');
var offlineMessage = '<?php echo js_escape(lang('You are offline.')); ?>';
var thousandsSeparator = '<?php echo js_escape(lang(',')); ?>';
</script>
<div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div>
<?php echo script("initHelpPopup();"); ?>
<div id="help" class="jush-<?php echo JUSH; ?> jsonly hidden"></div>
<?php echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"); ?>
<div id="content">
<?php
if ($breadcrumb !== null) {
echo '<p id="breadcrumb">';
echo '<a href="' . h(HOME_URL) . '">' . lang('Home') . '</a> » ';
$server = "";
if ($breadcrumb === false) {
$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 {
$link = substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1);
echo '<p id="breadcrumb"><a href="' . h($link ?: ".") . '">' . $drivers[DRIVER] . '</a> » ';
$link = substr(preg_replace('~\b(db|ns)=[^&]*&~', '', ME), 0, -1);
$server = $adminer->serverName(SERVER);
$server = ($server != "" ? $server : lang('Server'));
if ($breadcrumb === false) {
echo "$server\n";
} else {
echo "<a href='" . h($link) . "' accesskey='1' title='Alt+Shift+1'>$server</a> » ";
if ($_GET["ns"] != "" || (DB != "" && is_array($breadcrumb))) {
echo '<a href="' . h($link . "&db=" . urlencode(DB) . (support("scheme") ? "&ns=" : "")) . '">' . h(DB) . '</a> » ';
}
if (is_array($breadcrumb)) {
if ($_GET["ns"] != "") {
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h($_GET["ns"]) . '</a> » ';
}
foreach ($breadcrumb as $key => $val) {
$desc = (is_array($val) ? $val[1] : h($val));
if ($desc != "") {
@@ -94,11 +97,9 @@ function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
}
}
}
echo "$title\n";
}
}
echo "<h2>$title_all</h2>\n";
echo "<div id='ajaxstatus' class='jsonly hidden'></div>\n";
restart_session();
@@ -108,7 +109,7 @@ function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
$databases = null;
}
stop_session();
define("PAGE_HEADER", 1);
define('Adminer\PAGE_HEADER', 1);
}
/** Send HTTP headers
@@ -132,40 +133,30 @@ function page_headers() {
$adminer->headers();
}
/**
* Gets Content Security Policy headers.
*
/** Get Content Security Policy headers
* @return array of arrays with directive name in key, allowed sources in value
* @throws \Random\RandomException
*/
function csp() {
return [
[
// 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-'
"script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'",
"connect-src" => "'self' https://api.github.com/repos/pematon/adminer/releases/latest",
"frame-src" => "'self'",
return array(
array(
"script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'", // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-'
"connect-src" => "'self'",
"frame-src" => "https://www.adminer.org",
"object-src" => "'none'",
"base-uri" => "'none'",
"form-action" => "'self'",
],
];
),
);
}
/**
* Gets a CSP nonce.
*
* @return string Base64 value.
* @throws \Random\RandomException
/** Get a CSP nonce
* @return string Base64 value
*/
function get_nonce()
{
function get_nonce() {
static $nonce;
if (!$nonce) {
$nonce = base64_encode(get_random_string(true));
$nonce = base64_encode(rand_string());
}
return $nonce;
}
@@ -185,38 +176,28 @@ function page_messages($error) {
}
}
/**
* Prints HTML footer.
*
* @param ?string $missing "auth", "db", "ns"
/** Print HTML footer
* @param string "auth", "db", "ns"
* @return null
*/
function page_footer($missing = null)
{
function page_footer($missing = "") {
global $adminer, $token;
echo "</div>"; // #content
echo "<div id='footer'>\n";
language_select();
if ($missing != "auth") {
?>
<div class="logout">
<form action="" method="post">
<?php echo h($_GET["username"]); ?>
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" id="logout">
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>
</div>
<div id="menu">
<?php $adminer->navigation($missing); ?>
</div>
<?php if ($missing != "auth") { ?>
<form action="" method="post">
<p class="logout">
<span><?php echo h($_GET["username"]) . "\n"; ?></span>
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" id="logout">
<input type="hidden" name="token" value="<?php echo $token; ?>">
</p>
</form>
<?php } ?>
<?php
}
echo "</div>\n";
echo "<div id='menu'>\n";
$adminer->navigation($missing);
echo "</div>\n";
echo script("setupSubmitHighlight(document);");
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$drivers = array();
/** Add a driver
@@ -20,16 +22,50 @@ function get_driver($id) {
return $drivers[$id];
}
/*abstract*/ class Min_SQL {
abstract class SqlDriver {
static $possibleDrivers = array();
static $jush; ///< @var string JUSH identifier
var $_conn;
protected $types = array(); ///< @var array [$description => [$type => $maximum_unsigned_length, ...], ...]
var $editFunctions = array(); ///< @var array of ["$type|$type2" => "$function/$function2"] functions used in editing, [0] - edit and insert, [1] - edit only
var $unsigned = array(); ///< @var array number variants
var $operators = array(); ///< @var array operators used in select
var $functions = array(); ///< @var array functions used in select
var $grouping = array(); ///< @var array grouping functions used in select
var $onActions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()
var $inout = "IN|OUT|INOUT";
var $enumLength = "'(?:''|[^'\\\\]|\\\\.)*'";
var $generated = array();
/** Create object for performing database operations
* @param Min_DB
* @param Db
*/
function __construct($connection) {
$this->_conn = $connection;
}
/** Get all types
* @return array [$type => $maximum_unsigned_length, ...]
*/
function types() {
return call_user_func_array('array_merge', array_values($this->types));
}
/** Get structured types
* @return array [$description => [$type, ...], ...]
*/
function structuredTypes() {
return array_map('array_keys', $this->types);
}
/** Get enum values
* @param array
* @return string or null
*/
function enumLength($field) {
}
/** Select data from table
* @param string
* @param array result of $adminer->selectColumnsProcess()[0]
@@ -39,15 +75,15 @@ function get_driver($id) {
* @param int result of $adminer->selectLimitProcess()
* @param int index of page starting at zero
* @param bool whether to print the query
* @return Min_Result
* @return Result
*/
function select($table, $select, $where, $group, $order = array(), $limit = 1, $page = 0, $print = false) {
global $adminer, $jush;
global $adminer;
$is_group = (count($group) < count($select));
$query = $adminer->selectQueryBuild($select, $where, $group, $order, $limit, $page);
if (!$query) {
$query = "SELECT" . limit(
($_GET["page"] != "last" && $limit != "" && $group && $is_group && $jush == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table),
($_GET["page"] != "last" && $limit != "" && $group && $is_group && JUSH == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . implode(", ", $select) . "\nFROM " . table($table),
($where ? "\nWHERE " . implode(" AND ", $where) : "") . ($group && $is_group ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : ""),
($limit != "" ? +$limit : null),
($page ? $limit * $page : 0),
@@ -108,7 +144,7 @@ function get_driver($id) {
* @param array of arrays with escaped columns in keys and quoted data in values
* @return bool
*/
/*abstract*/ function insertUpdate($table, $rows, $primary) {
function insertUpdate($table, $rows, $primary) {
return false;
}
@@ -143,14 +179,22 @@ function get_driver($id) {
/** Convert column to be searchable
* @param string escaped column name
* @param array array("op" => , "val" => )
* @param array ["op" => , "val" => ]
* @param array
* @return string
*/
function convertSearch($idf, array $where, array $field) {
function convertSearch($idf, $val, $field) {
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
* @param string
* @param array
@@ -180,9 +224,38 @@ function get_driver($id) {
/** Get help link for table
* @param string
* @param bool
* @return string relative URL or null
*/
function tableHelp($name) {
function tableHelp($name, $is_view = false) {
}
/** Check if C-style escapes are supported
* @return bool
*/
function hasCStyleEscapes() {
return false;
}
/** Check whether table supports indexes
* @param array result of table_status()
* @return bool
*/
function supportsIndex($table_status) {
return !is_view($table_status);
}
/** Get defined check constraints
* @param string
* @return array [$name => $clause]
*/
function checkConstraints($table) {
// MariaDB contains CHECK_CONSTRAINTS.TABLE_NAME, MySQL and PostrgreSQL not
return get_key_vals("SELECT c.CONSTRAINT_NAME, CHECK_CLAUSE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS c
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS t ON c.CONSTRAINT_SCHEMA = t.CONSTRAINT_SCHEMA AND c.CONSTRAINT_NAME = t.CONSTRAINT_NAME
WHERE c.CONSTRAINT_SCHEMA = " . q($_GET["ns"] != "" ? $_GET["ns"] : DB) . "
AND t.TABLE_NAME = " . q($table) . "
AND CHECK_CLAUSE NOT LIKE '% IS NOT NULL'"); // ignore default IS NOT NULL checks in PostrgreSQL
}
}

View File

@@ -1,32 +1,34 @@
<?php
namespace Adminer;
// This file is not used in Adminer Editor.
/** Print select result
* @param Min_Result
* @param Min_DB connection to examine indexes
* @param Result
* @param Db connection to examine indexes
* @param array
* @param int
* @return array $orgtables
*/
function select($result, $connection2 = null, $orgtables = array(), $limit = 0) {
global $jush;
$links = array(); // colno => orgtable - create links from these columns
$indexes = array(); // orgtable => array(column => colno) - primary keys
$columns = array(); // orgtable => array(column => ) - not selected columns in primary key
$blobs = array(); // colno => bool - display bytes for blobs
$types = array(); // colno => type - display char in <code>
$return = array(); // table => orgtable - mapping to use in EXPLAIN
odd(''); // reset odd for each result
for ($i=0; (!$limit || $i < $limit) && ($row = $result->fetch_row()); $i++) {
if (!$i) {
echo "<div class='scrollable'>\n";
echo "<table cellspacing='0' class='nowrap'>\n";
echo "<table class='nowrap odds'>\n";
echo "<thead><tr>";
for ($j=0; $j < count($row); $j++) {
$field = (array)$result->fetch_field();
$name = $field["name"];
$orgtable = $field["orgtable"];
$orgname = $field["orgname"];
$return[$field["table"]] = $orgtable;
if ($orgtables && $jush == "sql") { // MySQL EXPLAIN
$field = $result->fetch_field();
$name = $field->name;
$orgtable = $field->orgtable;
$orgname = $field->orgname;
$return[$field->table] = $orgtable;
if ($orgtables && JUSH == "sql") { // MySQL EXPLAIN
$links[$j] = ($name == "table" ? "table=" : ($name == "possible_keys" ? "indexes=" : null));
} elseif ($orgtable != "") {
if (!isset($indexes[$orgtable])) {
@@ -46,11 +48,11 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
$links[$j] = $orgtable;
}
}
if ($field["charsetnr"] == 63) { // 63 - binary
if ($field->charsetnr == 63) { // 63 - binary
$blobs[$j] = true;
}
$types[$j] = $field["type"];
echo "<th" . ($orgtable != "" || $field["name"] != $orgname ? " title='" . h(($orgtable != "" ? "$orgtable." : "") . $orgname) . "'" : "") . ">" . h($name)
$types[$j] = $field->type;
echo "<th" . ($orgtable != "" || $field->name != $orgname ? " title='" . h(($orgtable != "" ? "$orgtable." : "") . $orgname) . "'" : "") . ">" . h($name)
. ($orgtables ? doc_link(array(
'sql' => "explain-output.html#explain_" . strtolower($name),
'mariadb' => "explain/#the-columns-in-explain-select",
@@ -59,11 +61,11 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
}
echo "</thead>\n";
}
echo "<tr" . odd() . ">";
echo "<tr>";
foreach ($row as $key => $val) {
$link = "";
if (isset($links[$key]) && !$columns[$links[$key]]) {
if ($orgtables && $jush == "sql") { // MySQL EXPLAIN
if ($orgtables && JUSH == "sql") { // MySQL EXPLAIN
$table = $row[array_search("table=", $links)];
$link = ME . $links[$key] . urlencode($orgtables[$table] != "" ? $orgtables[$table] : $table);
} else {
@@ -72,7 +74,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
$link .= "&where" . urlencode("[" . bracket_escape($col) . "]") . "=" . urlencode($row[$j]);
}
}
} elseif (is_web_url($val)) {
} elseif (is_url($val)) {
$link = $val;
}
if ($val === null) {
@@ -86,7 +88,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
}
}
if ($link) {
$val = "<a href='" . h($link) . "'" . (is_web_url($link) ? target_blank() : '') . ">$val</a>";
$val = "<a href='" . h($link) . "'" . (is_url($link) ? target_blank() : '') . ">$val</a>";
}
echo "<td>$val";
}
@@ -97,7 +99,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
/** Get referencable tables with single column primary key except self
* @param string
* @return array ($table_name => $field)
* @return array [$table_name => $field]
*/
function referencable_primary($self) {
$return = array(); // table_name => field
@@ -150,8 +152,7 @@ function set_adminer_settings($settings) {
* @return null
*/
function textarea($name, $value, $rows = 10, $cols = 80) {
global $jush;
echo "<textarea name='" . h($name) . "' rows='$rows' cols='$cols' class='sqlarea jush-$jush' spellcheck='false' wrap='off'>";
echo "<textarea name='" . h($name) . "' rows='$rows' cols='$cols' class='sqlarea jush-" . JUSH . "' spellcheck='false' wrap='off'>";
if (is_array($value)) {
foreach ($value as $val) { // not implode() to save memory
echo h($val[0]) . "\n\n\n"; // $val == array($query, $time, $elapsed)
@@ -162,6 +163,41 @@ function textarea($name, $value, $rows = 10, $cols = 80) {
echo "</textarea>";
}
/** Generate HTML <select> or <input> if $options are empty
* @param string
* @param array
* @param string
* @param string
* @param string
* @return string
*/
function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") {
$tag = ($options ? "select" : "input");
return "<$tag$attrs" . ($options
? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
: " size='10' value='" . h($value) . "' placeholder='$placeholder'>"
) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input
}
/** Print one row in JSON object
* @param string or "" to close the object
* @param string
* @return null
*/
function json_row($key, $val = null) {
static $first = true;
if ($first) {
echo "{";
}
if ($key != "") {
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : 'null');
$first = false;
} else {
echo "\n}\n";
$first = true;
}
}
/** Print table columns for type edit
* @param string
* @param array
@@ -171,22 +207,46 @@ function textarea($name, $value, $rows = 10, $cols = 80) {
* @return null
*/
function edit_type($key, $field, $collations, $foreign_keys = array(), $extra_types = array()) {
global $structured_types, $types, $unsigned, $on_actions;
global $driver;
$type = $field["type"];
?>
<td><select name="<?php echo h($key); ?>[type]" class="type" aria-labelledby="label-type"><?php
if ($type && !isset($types[$type]) && !isset($foreign_keys[$type]) && !in_array($type, $extra_types)) {
?><td><select name="<?php echo h($key); ?>[type]" class="type" aria-labelledby="label-type"><?php
if ($type && !array_key_exists($type, $driver->types()) && !isset($foreign_keys[$type]) && !in_array($type, $extra_types)) {
$extra_types[] = $type;
}
$structured_types = $driver->structuredTypes();
if ($foreign_keys) {
$structured_types[lang('Foreign keys')] = $foreign_keys;
}
echo optionlist(array_merge($extra_types, $structured_types), $type);
?></select><td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); //! type="number" with enabled JavaScript ?> aria-labelledby="label-length"><td class="options"><?php
echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>';
echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), (preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"]) ? "CURRENT_TIMESTAMP" : $field["on_update"])) . '</select>' : '');
echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $on_actions), $field["on_delete"]) . "</select> " : " "); // space for IE
?></select><td><input
name="<?php echo h($key); ?>[length]"
value="<?php echo h($field["length"]); ?>"
size="3"
<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); //! type="number" with enabled JavaScript ?>
aria-labelledby="label-length"><td class="options"><?php
echo ($collations ? "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>' : '');
echo ($driver->unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match(number_type(), $type) ? "" : " class='hidden'") . '><option>' . optionlist($driver->unsigned, $field["unsigned"]) . '</select>' : '');
echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>'
. optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), (preg_match('~^CURRENT_TIMESTAMP~i', $field["on_update"]) ? "CURRENT_TIMESTAMP" : $field["on_update"]))
. '</select>' : ''
);
echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $driver->onActions), $field["on_delete"]) . "</select> " : " "); // space for IE
}
/** Get partition info
* @param string
* @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");
$return = array();
list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row();
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
$return["partition_names"] = array_keys($partitions);
$return["partition_values"] = array_values($partitions);
return $return;
}
/** Filter length value including enums
@@ -194,7 +254,8 @@ echo optionlist(array_merge($extra_types, $structured_types), $type);
* @return string
*/
function process_length($length) {
global $enum_length;
global $driver;
$enum_length = $driver->enumLength;
return (preg_match("~^\\s*\\(?\\s*$enum_length(?:\\s*,\\s*$enum_length)*+\\s*\\)?\\s*\$~", $length) && preg_match_all("~$enum_length~", $length, $matches)
? "(" . implode(",", $matches[0]) . ")"
: preg_replace('~^[0-9].*~', '(\0)', preg_replace('~[^-0-9,+()[\]]~', '', $length))
@@ -207,31 +268,30 @@ function process_length($length) {
* @return string
*/
function process_type($field, $collate = "COLLATE") {
global $unsigned;
global $driver;
return " $field[type]"
. process_length($field["length"])
. (preg_match(number_type(), $field["type"]) && in_array($field["unsigned"], $unsigned) ? " $field[unsigned]" : "")
. (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . q($field["collation"]) : "")
. (preg_match(number_type(), $field["type"]) && in_array($field["unsigned"], $driver->unsigned) ? " $field[unsigned]" : "")
. (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . (JUSH == "mssql" ? $field["collation"] : q($field["collation"])) : "")
;
}
/** Create SQL string from field
* @param array basic field information
* @param array information about field type
* @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT")
* @return array ["field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT"]
*/
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(
idf_escape(trim($field["field"])),
process_type($type_field),
($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp
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"]) : ""),
($field["auto_increment"] ? auto_increment() : null),
);
@@ -242,19 +302,16 @@ function process_field($field, $type_field) {
* @return string
*/
function default_value($field) {
global $driver;
$default = $field["default"];
if ($default === null) return "";
if (stripos($default, "GENERATED ") === 0) {
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);
return " DEFAULT " . ($quote ? q($default) : $default);
$generated = $field["generated"];
return ($default === null ? "" : (in_array($generated, $driver->generated)
? (JUSH == "mssql" ? " AS ($default)" . ($generated == "VIRTUAL" ? "" : " $generated") . "" : " GENERATED ALWAYS AS ($default) $generated")
: " DEFAULT " . (!preg_match('~^GENERATED ~i', $default) && (preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default))
? q($default)
: str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", (JUSH == "sqlite" ? "($default)" : $default))
)
));
}
/** Get type class to use in CSS
@@ -262,118 +319,88 @@ function default_value($field) {
* @return string class=''
*/
function type_class($type) {
foreach (array(
foreach (
array(
'char' => 'text',
'date' => 'time|year',
'binary' => 'blob',
'enum' => 'set',
) as $key => $val) {
) as $key => $val
) {
if (preg_match("~$key|$val~", $type)) {
return " class='$key'";
}
}
}
/**
* Prints table interior for fields editing.
*
* @param string $type TABLE, FUNCTION or PROCEDURE
* @param array $foreign_keys returned by referencable_primary()
/** Print table interior for fields editing
* @param array
* @param array
* @param string TABLE or PROCEDURE
* @param array returned by referencable_primary()
* @return null
*/
function edit_fields(array $fields, array $collations, $type = "TABLE", $foreign_keys = []) {
global $inout;
function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = array()) {
global $driver;
$fields = array_values($fields);
$comment_class = ($_POST ? $_POST["comments"] : adminer_setting("comments")) ? "" : "class='hidden'";
$default_class = (($_POST ? $_POST["defaults"] : adminer_setting("defaults")) ? "" : " class='hidden'");
$comment_class = (($_POST ? $_POST["comments"] : adminer_setting("comments")) ? "" : " class='hidden'");
?>
<thead><tr>
<?php
if (support("move_col")) {
echo "<td class='jsonly'></td>";
}
if ($type == "PROCEDURE") {
echo "<td></td>";
}
?>
<th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?></th>
<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>
<td id="label-length"><?php echo lang('Length'); ?></td>
<td><?php echo lang('Options'); /* no label required, options have their own label */ ?></td>
<?php echo ($type == "PROCEDURE" ? "<td>" : ""); ?>
<th id="label-name"><?php echo ($type == "TABLE" ? lang('Column name') : lang('Parameter name')); ?>
<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;"); ?>
<td id="label-length"><?php echo lang('Length'); ?>
<td><?php echo lang('Options'); /* no label required, options have their own label */ ?>
<?php if ($type == "TABLE") { ?>
<td id="label-null">NULL</td>
<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([
<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",
'mariadb' => "auto_increment/",
'sqlite' => "autoinc.html",
'pgsql' => "datatype-numeric.html#DATATYPE-SERIAL",
'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>" : ""); ?>
'mssql' => "t-sql/statements/create-table-transact-sql-identity-property",
)); ?>
<td id="label-default"<?php echo $default_class; ?>><?php echo lang('Default value'); ?>
<?php echo (support("comment") ? "<td id='label-comment'$comment_class>" . lang('Comment') : ""); ?>
<?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>
<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) . ";"); ?>
</thead>
<tbody>
<?php
echo "<tbody>\n";
echo script("mixin(qsl('tbody'), {onclick: editingClick, onkeydown: editingKeydown, oninput: editingInput});");
foreach ($fields as $i => $field) {
$i++;
$orig = $field[($_POST ? "orig" : "field")];
$display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i])) && (support("drop_col") || $orig == "");
$style = $display ? "" : "style='display: none;'";
echo "<tr $style>\n";
if (support("move_col")) {
echo "<th class='handle jsonly'></th>";
}
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";
?>
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", explode("|", $driver->inout), $field["inout"]) : "") . "<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); ?>
<?php
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";
?>
<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 echo ($field["auto_increment"] ? " checked" : ""); ?> aria-labelledby="label-ai"></label><td<?php echo $default_class; ?>><?php
echo ($driver->generated
? html_select("fields[$i][generated]", array_merge(array("", "DEFAULT"), $driver->generated), $field["generated"]) . " "
: checkbox("fields[$i][generated]", 1, $field["generated"], "", "", "", "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'>" : "");
}
}
echo "<td>";
if (support("move_col")) {
echo "<input type='image' class='icon' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'> ",
"<input type='image' class='icon hidden' name='up[$i]' src='../adminer/static/up.gif' alt='↑' title='" . lang('Move up') . "'> ",
"<input type='image' class='icon hidden' name='down[$i]' src='../adminer/static/down.gif' alt='↓' title='" . lang('Move down') . "'> ";
echo (support("move_col") ?
"<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' 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
@@ -425,44 +452,26 @@ 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))), '\\')) . "'";
}
/**
* Issue grant or revoke commands.
*
* @param bool $grant
* @param array $privileges
* @param string $columns
* @param string $on
* @param string $user
*
/** Issue grant or revoke commands
* @param string GRANT or REVOKE
* @param array
* @param string
* @param string
* @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");
function grant($grant, $privileges, $columns, $on) {
if (!$privileges) {
return true;
}
}
if ($privileges == ["GRANT OPTION", "PROXY"]) {
if ($grant) {
return (bool) queries("GRANT PROXY ON $on TO $user WITH GRANT OPTION");
} else {
return (bool) queries("REVOKE PROXY ON $on FROM $user");
}
}
return (bool) queries(
($grant ? "GRANT " : "REVOKE ") .
preg_replace('~(GRANT OPTION)\([^)]*\)~', '$1', implode("$columns, ", $privileges) . $columns) .
" ON $on " .
($grant ? "TO " : "FROM ") . $user
if ($privileges == array("ALL PRIVILEGES", "GRANT OPTION")) {
// can't be granted or revoked together
return ($grant == "GRANT"
? queries("$grant ALL PRIVILEGES$on WITH GRANT OPTION")
: queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on")
);
}
return queries("$grant " . preg_replace('~(GRANT OPTION)\([^)]*\)~', '\1', implode("$columns, ", $privileges) . $columns) . $on);
}
/** Drop old object and create a new one
* @param string drop old object query
@@ -504,11 +513,10 @@ function drop_create($drop, $create, $drop_created, $test, $drop_test, $location
* @return string
*/
function create_trigger($on, $row) {
global $jush;
$timing_event = " $row[Timing] $row[Event]" . (preg_match('~ OF~', $row["Event"]) ? " $row[Of]" : ""); // SQL injection
return "CREATE TRIGGER "
. idf_escape($row["Trigger"])
. ($jush == "mssql" ? $on . $timing_event : $timing_event . $on)
. (JUSH == "mssql" ? $on . $timing_event : $timing_event . $on)
. rtrim(" $row[Type]\n$row[Statement]", ";")
. ";"
;
@@ -520,22 +528,22 @@ function create_trigger($on, $row) {
* @return string
*/
function create_routine($routine, $row) {
global $inout, $jush;
global $driver;
$set = array();
$fields = (array) $row["fields"];
ksort($fields); // enforce fields order
foreach ($fields as $field) {
if ($field["field"] != "") {
$set[] = (preg_match("~^($inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET");
$set[] = (preg_match("~^($driver->inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET");
}
}
$definition = rtrim("\n$row[definition]", ";");
$definition = rtrim($row["definition"], ";");
return "CREATE $routine "
. idf_escape(trim($row["name"]))
. " (" . implode(", ", $set) . ")"
. (isset($_GET["function"]) ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
. ($routine == "FUNCTION" ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
. ($row["language"] ? " LANGUAGE $row[language]" : "")
. ($jush == "pgsql" ? " AS " . q($definition) : "$definition;")
. (JUSH == "pgsql" ? " AS " . q($definition) : "\n$definition;")
;
}
@@ -548,20 +556,20 @@ function remove_definer($query) {
}
/** Format foreign key to use in SQL query
* @param array ("db" => string, "ns" => string, "table" => string, "source" => array, "target" => array, "on_delete" => one of $on_actions, "on_update" => one of $on_actions)
* @param array ["db" => string, "ns" => string, "table" => string, "source" => array, "target" => array, "on_delete" => one of $on_actions, "on_update" => one of $on_actions]
* @return string
*/
function format_foreign_key($foreign_key) {
global $on_actions;
global $driver;
$db = $foreign_key["db"];
$ns = $foreign_key["ns"];
return " FOREIGN KEY (" . implode(", ", array_map('idf_escape', $foreign_key["source"])) . ") REFERENCES "
return " FOREIGN KEY (" . implode(", ", array_map('Adminer\idf_escape', $foreign_key["source"])) . ") REFERENCES "
. ($db != "" && $db != $_GET["db"] ? idf_escape($db) . "." : "")
. ($ns != "" && $ns != $_GET["ns"] ? idf_escape($ns) . "." : "")
. table($foreign_key["table"])
. " (" . implode(", ", array_map('idf_escape', $foreign_key["target"])) . ")" //! reuse $name - check in older MySQL versions
. (preg_match("~^($on_actions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "")
. (preg_match("~^($on_actions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "")
. idf_escape($foreign_key["table"])
. " (" . implode(", ", array_map('Adminer\idf_escape', $foreign_key["target"])) . ")" //! reuse $name - check in older MySQL versions
. (preg_match("~^($driver->onActions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "")
. (preg_match("~^($driver->onActions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "")
;
}
@@ -590,46 +598,37 @@ function tar_file($filename, $tmp_file) {
function ini_bytes($ini) {
$val = ini_get($ini);
switch (strtolower(substr($val, -1))) {
case 'g': $val = (int)$val * 1024; // no break
case 'm': $val = (int)$val * 1024; // no break
case 'k': $val = (int)$val * 1024;
case 'g':
$val = (int) $val * 1024; // no break
case 'm':
$val = (int) $val * 1024; // no break
case 'k':
$val = (int) $val * 1024;
}
return $val;
}
/**
* Creates link to database documentation.
*
* @param array $paths $jush => $path
* @param string $text HTML code
*
/** Create link to database documentation
* @param array JUSH => $path
* @param string HTML code
* @return string HTML code
*/
function doc_link(array $paths, $text = "<sup>?</sup>") {
global $jush, $connection;
function doc_link($paths, $text = "<sup>?</sup>") {
global $connection;
$server_info = $connection->server_info;
$version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits
$urls = [
$urls = array(
'sql' => "https://dev.mysql.com/doc/refman/$version/en/",
'sqlite' => "https://www.sqlite.org/",
'pgsql' => "https://www.postgresql.org/docs/$version/",
'mssql' => "https://msdn.microsoft.com/library/",
'mssql' => "https://learn.microsoft.com/en-us/sql/",
'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)) {
$urls['sql'] = "https://mariadb.com/kb/en/";
$paths['sql'] = (isset($paths['mariadb']) ? $paths['mariadb'] : str_replace(".html", "/", $paths['sql']));
}
if (!isset($paths[$jush]) || !$paths[$jush] ) {
return "";
}
return "<a href='" . h($urls[$jush] . $paths[$jush]) . "'" . target_blank() . ">$text</a>";
return ($paths[JUSH] ? "<a href='" . h($urls[JUSH] . $paths[JUSH] . (JUSH == 'mssql' ? "?view=sql-server-ver$version" : "")) . "'" . target_blank() . ">$text</a>" : "");
}
/** Wrap gzencode() for usage in ob_start()
@@ -637,7 +636,7 @@ function doc_link(array $paths, $text = "<sup>?</sup>") {
* @return string
*/
function ob_gzencode($string) {
// ob_start() callback recieves an optional parameter $phase but gzencode() accepts optional parameter $level
// ob_start() callback receives an optional parameter $phase but gzencode() accepts optional parameter $level
return gzencode($string);
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Adminer;
error_reporting(6135); // errors and warnings
set_error_handler(function ($errno, $errstr) {
return !!preg_match('~^(Trying to access array offset on( value of type)? null|Undefined (array key|property))~', $errstr);
}, E_WARNING);

View File

@@ -1,7 +1,10 @@
<?php
namespace Adminer;
// This file is used both in Adminer and Adminer Editor.
/** Get database connection
* @return Min_DB
* @return Db
*/
function connection() {
// can be used in customization, $connection is minified
@@ -95,7 +98,7 @@ function bracket_escape($idf, $back = false) {
/** Check if connection has at least the given version
* @param string required version
* @param string required MariaDB version
* @param Min_DB defaults to $connection
* @param Db defaults to $connection
* @return bool
*/
function min_version($version, $maria_db = "", $connection2 = null) {
@@ -108,14 +111,11 @@ function min_version($version, $maria_db = "", $connection2 = null) {
$server_info = $match[1];
$version = $maria_db;
}
if ($version == "") {
return false;
}
return (version_compare($server_info, $version) >= 0);
return $version && version_compare($server_info, $version) >= 0;
}
/** Get connection charset
* @param Min_DB
* @param Db
* @return string
*/
function charset($connection) {
@@ -161,6 +161,14 @@ function h($string) {
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
* @param string
* @param string
@@ -196,7 +204,11 @@ function optionlist($options, $selected = null, $use_keys = false) {
$opts = $v;
}
foreach ($opts as $key => $val) {
$return .= '<option' . ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '') . (($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '') . '>' . h($val);
$return .= '<option'
. ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '')
. ($selected !== null && ($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '')
. '>' . h($val)
;
}
if (is_array($v)) {
$return .= '</optgroup>';
@@ -209,7 +221,7 @@ function optionlist($options, $selected = null, $use_keys = false) {
* @param string
* @param array
* @param string
* @param string|bool true for no onchange, false for radio
* @param string true for no onchange, false for radio
* @param string
* @return string
*/
@@ -228,22 +240,6 @@ function html_select($name, $options, $value = "", $onchange = true, $labelled_b
return $return;
}
/** Generate HTML <select> or <input> if $options are empty
* @param string
* @param array
* @param string
* @param string
* @param string
* @return string
*/
function select_input($attrs, $options, $value = "", $onchange = "", $placeholder = "") {
$tag = ($options ? "select" : "input");
return "<$tag $attrs" . ($options
? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
: " size='10' value='" . h($value) . "' placeholder='$placeholder'>"
) . ($onchange ? script("qsl('$tag').onchange = $onchange;", "") : ""); //! use oninput for input
}
/** Get onclick confirmation
* @param string
* @param string
@@ -253,17 +249,18 @@ function confirm($message = "", $selector = "qsl('input')") {
return script("$selector.onclick = function () { return confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "'); };", "");
}
/**
* Prints header for hidden fieldset (close by </div></fieldset>)
* @param $id string
* @param $legend string
/** Print header for hidden fieldset (close by </div></fieldset>)
* @param string
* @param string
* @param bool
* @return null
*/
function print_fieldset($id, $legend, $visible = false, $sortable = false) {
function print_fieldset($id, $legend, $visible = false) {
echo "<fieldset><legend>";
echo "<a href='#fieldset-$id'>$legend</a>";
echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", "");
echo "</legend>";
echo "<div id='fieldset-$id' class='" . ($visible ? "" : "hidden") . ($sortable ? " sortable" : "") . "'>\n";
echo "<div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
}
/** Return class='active' if $bold is true
@@ -275,18 +272,6 @@ function bold($bold, $class = "") {
return ($bold ? " class='active $class'" : ($class ? " class='$class'" : ""));
}
/** Generate class for odd rows
* @param string return this for odd rows, empty to reset counter
* @return string
*/
function odd($return = ' class="odd"') {
static $i = 0;
if (!$return) { // reset counter
$i = -1;
}
return ($i++ % 2 ? $return : '');
}
/** Escape string for JavaScript apostrophes
* @param string
* @return string
@@ -295,25 +280,6 @@ function js_escape($string) {
return addcslashes($string, "\r\n'\\/"); // slash for <script>
}
/** Print one row in JSON object
* @param string or "" to close the object
* @param string
* @return null
*/
function json_row($key, $val = null) {
static $first = true;
if ($first) {
echo "{";
}
if ($key != "") {
echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, "\r\n\t\"\\/") . '": ' . ($val !== null ? '"' . addcslashes($val, "\r\n\"\\/") . '"' : 'null');
$first = false;
} else {
echo "\n}\n";
$first = true;
}
}
/** Get INI boolean value
* @param string
* @return bool
@@ -323,7 +289,7 @@ function ini_bool($ini) {
return (preg_match('~^(on|true|yes)$~i', $val) || (int) $val); // boolean values set by php_value are strings
}
/** Check if SID is neccessary
/** Check if SID is necessary
* @return bool
*/
function sid() {
@@ -371,6 +337,16 @@ function q($string) {
return $connection->quote($string);
}
/** Get single value from database
* @param string
* @param int
* @return string or false if error
*/
function get_val($query, $field = 0) {
global $connection;
return $connection->result($query, $field);
}
/** Get list of values from database
* @param string
* @param mixed
@@ -390,7 +366,7 @@ function get_vals($query, $column = 0) {
/** Get keys from first column and values from second
* @param string
* @param Min_DB
* @param Db
* @param bool
* @return array
*/
@@ -415,7 +391,7 @@ function get_key_vals($query, $connection2 = null, $set_keys = true) {
/** Get all rows of result
* @param string
* @param Min_DB
* @param Db
* @param string
* @return array of associative arrays
*/
@@ -428,7 +404,7 @@ function get_rows($query, $connection2 = null, $error = "<p class='error'>") {
while ($row = $result->fetch_assoc()) {
$return[] = $row;
}
} elseif (!$result && !is_object($connection2) && $error && defined("PAGE_HEADER")) {
} elseif (!$result && !is_object($connection2) && $error && (defined('Adminer\PAGE_HEADER') || $error == "-- ")) {
echo $error . error() . "\n";
}
return $return;
@@ -471,37 +447,26 @@ function escape_key($key) {
* @return string
*/
function where($where, $fields = array()) {
global $connection, $jush;
$conditions = [];
global $connection;
$return = array();
foreach ((array) $where["where"] as $key => $val) {
$key = bracket_escape($key, 1); // 1 - back
$column = escape_key($key);
if ($jush == "sql" && $fields[$key]["type"] == "json") {
$conditions[] = "$column = CAST(" . q($val) . " AS JSON)";
} elseif ($jush == "sql" && is_numeric($val) && strpos($val, ".") !== false) {
// LIKE because of floats but slow with ints.
$conditions[] = "$column LIKE " . q($val);
} elseif ($jush == "mssql") {
// 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";
$return[] = $column
. (JUSH == "sql" && $fields[$key]["type"] == "json" ? " = CAST(" . q($val) . " AS JSON)"
: (JUSH == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
: (JUSH == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text
: " = " . unconvert_field($fields[$key], q($val))
)))
; //! enum and set
if (JUSH == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
$return[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin";
}
}
foreach ((array) $where["null"] as $key) {
$conditions[] = escape_key($key) . " IS NULL";
$return[] = escape_key($key) . " IS NULL";
}
return implode(" AND ", $conditions);
return implode(" AND ", $return);
}
/** Create SQL condition from query string
@@ -549,17 +514,19 @@ function convert_fields($columns, $fields, $select = array()) {
/** Set cookie valid on current path
* @param string
* @param string
* @param int number of seconds, 0 for session cookie
* @param int number of seconds, 0 for session cookie, 2592000 - 30 days
* @return bool
*/
function cookie($name, $value, $lifetime = 2592000) { // 2592000 - 30 days
function cookie($name, $value, $lifetime = 2592000) {
global $HTTPS;
return header("Set-Cookie: $name=" . urlencode($value)
return header(
"Set-Cookie: $name=" . urlencode($value)
. ($lifetime ? "; expires=" . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT" : "")
. "; path=" . preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"])
. ($HTTPS ? "; secure" : "")
. "; HttpOnly; SameSite=lax",
false);
false
);
}
/** Restart stopped session
@@ -614,7 +581,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);
return "$match[1]?"
. (sid() ? SID . "&" : "")
. urlencode($vendor) . "=" . urlencode($server) . "&"
. ($vendor != "server" || $server != "" ? urlencode($vendor) . "=" . urlencode($server) . "&" : "")
. "username=" . urlencode($username)
. ($db != "" ? "&db=" . urlencode($db) : "")
. ($match[2] ? "&$match[2]" : "")
@@ -680,7 +647,7 @@ function query_redirect($query, $location, $message, $redirect = true, $execute
/** Execute and remember query
* @param string or null to return remembered queries, end with ';' to use DELIMITER
* @return Min_Result or array($queries, $time) if $query = null
* @return Result or [$queries, $time] if $query = null
*/
function queries($query) {
global $connection;
@@ -703,7 +670,7 @@ function queries($query) {
* @param callback
* @return bool
*/
function apply_queries($query, $tables, $escape = 'table') {
function apply_queries($query, $tables, $escape = 'Adminer\table') {
foreach ($tables as $table) {
if (!queries("$query " . $escape($table))) {
return false;
@@ -778,7 +745,8 @@ function get_file($key, $decompress = false) {
}
$name = $file["name"][$key];
$tmp_name = $file["tmp_name"][$key];
$content = file_get_contents($decompress && preg_match('~\.gz$~', $name)
$content = file_get_contents(
$decompress && preg_match('~\.gz$~', $name)
? "compress.zlib://$tmp_name"
: $tmp_name
); //! may not be reachable because of open_basedir
@@ -833,8 +801,6 @@ function is_utf8($val) {
* @return string escaped string with appended ...
*/
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
preg_match("(^(" . repeat_pattern("[\t\r\n -~]", $length) . ")($)?)", $string, $match);
}
@@ -855,7 +821,7 @@ function format_number($val) {
*/
function friendly_url($val) {
// used for blobs and export
return preg_replace('~[^a-z0-9_]~i', '-', $val);
return preg_replace('~\W~i', '-', $val);
}
/** Print hidden fields
@@ -900,7 +866,7 @@ function table_status1($table, $fast = false) {
/** Find out foreign keys for each column
* @param string
* @return array array($col => array())
* @return array [$col => []]
*/
function column_foreign_keys($table) {
global $adminer;
@@ -923,16 +889,13 @@ function column_foreign_keys($table) {
*/
function enum_input($type, $attrs, $field, $value, $empty = null) {
global $adminer;
$return = ($empty !== null && !is_strict_mode() ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === 0) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
$return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === 0) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_int($value) ? $value == $i+1 : (is_array($value) ? in_array($i+1, $value) : $value === $val));
$return .= " <label><input type='$type'$attrs value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($adminer->editVal($val, $field)) . '</label>';
$return .= " <label><input type='$type'$attrs value='" . (JUSH == "sql" ? $i+1 : h($val)) . "'" . ($checked ? ' checked' : '') . '>' . h($adminer->editVal($val, $field)) . '</label>';
}
return $return;
}
@@ -943,45 +906,45 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
* @return null
*/
function input($field, $value, $function) {
global $types, $adminer, $jush;
global $driver, $adminer;
$name = h(bracket_escape($field["field"]));
echo "<td class='function'>";
if (is_array($value) && !$function) {
$args = array($value);
if (version_compare(PHP_VERSION, 5.4) >= 0) {
$args[] = JSON_PRETTY_PRINT;
}
$value = call_user_func_array('json_encode', $args);
$value = call_user_func_array('json_encode', $args); //! requires PHP 5.2
$function = "json";
}
$reset = ($jush == "mssql" && $field["auto_increment"]);
$reset = (JUSH == "mssql" && $field["auto_increment"]);
if ($reset && !$_POST["save"]) {
$function = null;
}
$functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
$attrs = " name='fields[$name]'$disabled";
echo "<td class='function'>";
$enums = $driver->enumLength($field);
if ($enums) {
$field["type"] = "enum";
$field["length"] = $enums;
}
if ($field["type"] == "enum") {
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value, $function);
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
} else {
$has_function = (in_array($function, $functions) || isset($functions[$function]));
echo (count($functions) > 1
? "<select name='function[$name]'$disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
. help_script_command("value.replace(/^SQL\$/, '')", true)
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
. script("qsl('select').onchange = functionChange;", "")
: h(reset($functions))
) . '<td>';
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value, $function); // usage in call is without a table
$input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
if ($input != "") {
echo $input;
} elseif (preg_match('~bool~', $field["type"])) {
echo "<input type='hidden'$attrs value='0'>" .
"<input type='checkbox'" . (preg_match('~^(1|t|true|y|yes|on)$~i', $value) ? " checked='checked'" : "") . "$attrs value='1'>";
echo "<input type='hidden'$attrs value='0'>"
. "<input type='checkbox'" . (preg_match('~^(1|t|true|y|yes|on)$~i', $value) ? " checked='checked'" : "") . "$attrs value='1'>";
} elseif ($field["type"] == "set") { //! 64 bits
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) {
@@ -992,26 +955,29 @@ function input($field, $value, $function) {
} elseif (preg_match('~blob|bytea|raw|file~', $field["type"]) && ini_bool("file_uploads")) {
echo "<input type='file' name='fields-$name'>";
} elseif (($text = preg_match('~text|lob|memo~i', $field["type"])) || preg_match("~\n~", $value)) {
if ($text && $jush != "sqlite") {
if ($text && JUSH != "sqlite") {
$attrs .= " cols='50' rows='12'";
} else {
$rows = min(12, substr_count($value, "\n") + 1);
$attrs .= " cols='30' rows='$rows'";
$attrs .= " cols='30' rows='$rows'" . ($rows == 1 ? " style='height: 1.2em;'" : ""); // 1.2em - line-height
}
echo "<textarea$attrs>" . h($value) . '</textarea>';
} elseif ($function == "json" || preg_match('~^jsonb?$~', $field["type"])) {
echo "<textarea$attrs cols='50' rows='12' class='jush-js'>" . h($value) . '</textarea>';
} else {
// int(3) is only a display hint
$maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match) ? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
if ($jush == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
$types = $driver->types();
$maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match)
? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0))
: ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)
);
if (JUSH == 'sql' && min_version(5.6) && preg_match('~time~', $field["type"])) {
$maxlength += 7; // microtime
}
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
echo "<input"
. ((!$has_function || $function === "") && preg_match('~(?<!o)int(?!er)~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "")
. ($function != "now" ? " value='" . h($value) . "'" : " data-last-value='" . h($value) . "'")
. ($maxlength ? " data-maxlength='$maxlength'" : "")
. " value='" . h($value) . "'" . ($maxlength ? " data-maxlength='$maxlength'" : "")
. (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "")
. "$attrs>"
;
@@ -1025,9 +991,11 @@ function input($field, $value, $function) {
}
$first++;
}
if ($first) {
echo script("mixin(qsl('td'), {onchange: partial(skipOriginal, $first), oninput: function () { this.onchange(); }});");
}
}
}
/** Process edit input field
* @param one field from fields()
@@ -1043,13 +1011,15 @@ function process_input($field) {
$idf = bracket_escape($field["field"]);
$function = $_POST["function"][$idf];
$value = $_POST["fields"][$idf];
if ($field["type"] == "enum") {
if ($field["type"] == "enum" || $driver->enumLength($field)) {
if ($value == -1) {
return false;
}
if ($value == "") {
return "NULL";
}
}
if ($field["type"] == "enum") {
return +$value;
}
if ($field["auto_increment"] && $value == "") {
@@ -1130,27 +1100,6 @@ function search_tables() {
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
* @param string
* @param bool
@@ -1211,98 +1160,60 @@ function get_temp_dir() {
return $return;
}
/**
* Opens and exclusively lock a file.
*
* @param string $filename
* @return resource|null
/** Open and exclusively lock a file
* @param string
* @return resource or null for error
*/
function open_file_with_lock($filename)
{
$file = fopen($filename, "c+");
if (!$file) {
return null;
function file_open_lock($filename) {
$fp = @fopen($filename, "r+"); // @ - may not exist
if (!$fp) { // c+ is available since PHP 5.2.6
$fp = @fopen($filename, "w"); // @ - may not be writable
if (!$fp) {
return;
}
chmod($filename, 0660);
if (!flock($file, LOCK_EX)) {
fclose($file);
return null;
}
flock($fp, LOCK_EX);
return $fp;
}
return $file;
}
/**
* Writes and unlocks a file.
*
* @param resource $file
* @param string $data
/** Write and unlock a file
* @param resource
* @param string
*/
function write_and_unlock_file($file, $data)
{
rewind($file);
fwrite($file, $data);
ftruncate($file, strlen($data));
unlock_file($file);
function file_write_unlock($fp, $data) {
rewind($fp);
fwrite($fp, $data);
ftruncate($fp, strlen($data));
flock($fp, LOCK_UN);
fclose($fp);
}
/**
* Unlocks and closes the file.
*
* @param resource $file
/** Read password from file adminer.key in temporary directory or create one
* @param bool
* @return string or false if the file can not be created
*/
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)
{
function password_file($create) {
$filename = get_temp_dir() . "/adminer.key";
if (!$create && !file_exists($filename)) {
return false;
$return = @file_get_contents($filename); // @ - may not exist
if ($return || !$create) {
return $return;
}
$fp = @fopen($filename, "w"); // @ - can have insufficient rights //! is not atomic
if ($fp) {
chmod($filename, 0660);
$return = rand_string();
fwrite($fp, $return);
fclose($fp);
}
return $return;
}
$file = open_file_with_lock($filename);
if (!$file) {
return false;
}
$key = stream_get_contents($file);
if (!$key) {
$key = get_random_string();
write_and_unlock_file($file, $key);
} else {
unlock_file($file);
}
return $key;
}
/**
* Returns a random 32 characters long string.
*
* @param $binary bool
* @return string
* @throws \Random\RandomException
/** Get a random string
* @return string 32 hexadecimal characters
*/
function get_random_string($binary = false)
{
$bytes = function_exists('random_bytes') ? random_bytes(32) : uniqid(mt_rand(), true);
return $binary ? $bytes : md5($bytes);
function rand_string() {
return md5(uniqid(mt_rand(), true));
}
/** Format value to use in select
@@ -1331,7 +1242,7 @@ function select_value($val, $link, $field, $text_length) {
if (is_mail($val)) {
$link = "mailto:$val";
}
if (is_web_url($val)) {
if (is_url($val)) {
$link = $val; // IE 11 and all modern browsers hide referrer
}
}
@@ -1352,32 +1263,20 @@ function select_value($val, $link, $field, $text_length) {
* @param string
* @return bool
*/
function is_mail($value) {
return is_string($value) && filter_var($value, FILTER_VALIDATE_EMAIL);
function is_mail($email) {
$atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component
$pattern = "$atom+(\\.$atom+)*@($domain?\\.)+$domain";
return is_string($email) && preg_match("(^$pattern(,\\s*$pattern)*\$)i", $email);
}
/** Check whether the string is web URL address
/** Check whether the string is URL address
* @param string
* @return bool
*/
function is_web_url($value) {
if (!is_string($value) || !preg_match('~^https?://~i', $value)) {
return false;
}
$components = parse_url($value);
if (!$components) {
return false;
}
// Encode URL path. If path was encoded already, it will be encoded twice, but we are OK with that.
$encodedParts = array_map('urlencode', explode('/', $components['path']));
$url = str_replace($components['path'], implode('/', $encodedParts), $value);
parse_str($components['query'], $params);
$url = str_replace($components['query'], http_build_query($params), $url);
return (bool)filter_var($url, FILTER_VALIDATE_URL);
function is_url($string) {
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN
return preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string); //! restrict path, query and fragment characters
}
/** Check if field should be shortened
@@ -1396,9 +1295,8 @@ function is_shortable($field) {
* @return string
*/
function count_rows($table, $where, $is_group, $group) {
global $jush;
$query = " FROM " . table($table) . ($where ? " WHERE " . implode(" AND ", $where) : "");
return ($is_group && ($jush == "sql" || count($group) == 1)
return ($is_group && (JUSH == "sql" || count($group) == 1)
? "SELECT COUNT(DISTINCT " . implode(", ", $group) . ")$query"
: "SELECT COUNT(*)" . ($is_group ? " FROM (SELECT 1$query GROUP BY " . implode(", ", $group) . ") x" : $query)
);
@@ -1413,7 +1311,8 @@ function slow_query($query) {
$db = $adminer->database();
$timeout = $adminer->queryTimeout();
$slow_query = $driver->slowQuery($query, $timeout);
if (!$slow_query && support("kill") && is_object($connection2 = connect()) && ($db == "" || $connection2->select_db($db))) {
$connection2 = null;
if (!$slow_query && support("kill") && is_object($connection2 = connect($adminer->credentials())) && ($db == "" || $connection2->select_db($db))) {
$kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
?>
<script<?php echo nonce(); ?>>
@@ -1423,12 +1322,10 @@ var timeout = setTimeout(function () {
}, <?php echo 1000 * $timeout; ?>);
</script>
<?php
} else {
$connection2 = null;
}
ob_flush();
flush();
$return = @get_key_vals(($slow_query ? $slow_query : $query), $connection2, false); // @ - may be killed
$return = @get_key_vals(($slow_query ?: $query), $connection2, false); // @ - may be killed
if ($connection2) {
echo script("clearTimeout(timeout);");
ob_flush();
@@ -1491,26 +1388,13 @@ function lzw_decompress($binary) {
return $return;
}
/**
* @param string $text Help text.
* @param bool $side Side position.
*
/** Return events to display help on mouse over
* @param string JS expression
* @param bool JS expression
* @return string
*/
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);", "");
function on_help($command, $side = 0) {
return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", "");
}
/** Print edit data form
@@ -1521,7 +1405,7 @@ function help_script_command($command, $side = false)
* @return null
*/
function edit_form($table, $fields, $row, $update) {
global $adminer, $jush, $token, $error;
global $adminer, $token, $error;
$table_name = $adminer->tableName(table_status1($table, true));
page_header(
($update ? lang('Edit') : lang('Insert')),
@@ -1537,11 +1421,11 @@ function edit_form($table, $fields, $row, $update) {
?>
<form action="" method="post" enctype="multipart/form-data" id="form">
<?php
$first = 0;
if (!$fields) {
echo "<p class='error'>" . lang('You have no privileges to update this table.') . "\n";
} else {
echo "<table cellspacing='0' class='layout'>" . script("qsl('table').onkeydown = editingKeydown;");
echo "<table class='layout'>" . script("qsl('table').onkeydown = editingKeydown;");
foreach ($fields as $name => $field) {
echo "<tr><th>" . $adminer->fieldName($field);
$default = $_GET["set"][bracket_escape($name)];
@@ -1552,7 +1436,7 @@ function edit_form($table, $fields, $row, $update) {
}
}
$value = ($row !== null
? ($row[$name] != "" && $jush == "sql" && preg_match("~enum|set~", $field["type"])
? ($row[$name] != "" && JUSH == "sql" && preg_match("~enum|set~", $field["type"])
? (is_array($row[$name]) ? array_sum($row[$name]) : +$row[$name])
: (is_bool($row[$name]) ? +$row[$name] : $row[$name])
)
@@ -1582,6 +1466,9 @@ function edit_form($table, $fields, $row, $update) {
$value = "";
$function = "uuid";
}
if ($field["auto_increment"] || $function == "now" || $function == "uuid") {
$first++;
}
input($field, $value, $function);
echo "\n";
}
@@ -1608,7 +1495,7 @@ function edit_form($table, $fields, $row, $update) {
}
}
echo ($update ? "<input type='submit' name='delete' value='" . lang('Delete') . "'>" . confirm() . "\n"
: ($_POST || !$fields ? "" : script("focus(qsa('td', gid('form'))[1].firstChild);"))
: ($_POST || !$fields ? "" : script("focus(qsa('td', qs('#form'))[2*$first+1].firstChild);"))
);
if (isset($_GET["select"])) {
hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"]));

View File

@@ -1,10 +1,13 @@
<?php
namespace Adminer;
$languages = [
// not used in a single language version
$langs = array(
'en' => 'English', // Jakub Vrána - https://www.vrana.cz
'ar' => 'العربية', // Y.M Amine - Algeria - nbr7@live.fr
'bg' => 'Български', // Deyan Delchev
'bn' => 'বাংলা', // Dipak Kumar - dipak.ndc@gmail.com | Hossain Ahmed Saiman - hossain.ahmed@altscope.com
'bn' => 'বাংলা', // Dipak Kumar - dipak.ndc@gmail.com, Hossain Ahmed Saiman - hossain.ahmed@altscope.com
'bs' => 'Bosanski', // Emir Kurtovic
'ca' => 'Català', // Joan Llosas
'cs' => 'Čeština', // Jakub Vrána - https://www.vrana.cz
@@ -24,8 +27,8 @@ $languages = [
'ja' => '日本語', // Hitoshi Ozawa - http://sourceforge.jp/projects/oss-ja-jpn/releases/
'ka' => 'ქართული', // Saba Khmaladze skhmaladze@uglt.org
'ko' => '한국어', // dalli - skcha67@gmail.com
'lv' => 'Latviešu', // Kristaps Lediņš - https://krysits.com
'lt' => 'Lietuvių', // Paulius Leščinskas - http://www.lescinskas.lt
'lv' => 'Latviešu', // Kristaps Lediņš - https://krysits.com
'ms' => 'Bahasa Melayu', // Pisyek
'nl' => 'Nederlands', // Maarten Balliauw - http://blog.maartenballiauw.be
'no' => 'Norsk', // Iver Odin Kvello, mupublishing.com
@@ -45,59 +48,24 @@ $languages = [
'vi' => 'Tiếng Việt', // Giang Manh @ manhgd google mail
'zh' => '简体中文', // Mr. Lodar, vea - urn2.net - vea.urn2@gmail.com
'zh-tw' => '繁體中文', // http://tzangms.com
];
);
/**
* Returns the list of available languages.
* In compiled version, only selected languages are returned.
*
* @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.
*
/** Get current language
* @return string
*/
function get_lang()
{
function get_lang() {
global $LANG;
return $LANG;
}
/**
* Returns translated text.
*
* @param string|int $key Numeric key is used in compiled version.
* @param ?int $number
*
/** Translate string
* @param string
* @param int
* @return string
*/
function lang($key, $number = null)
{
function lang($idf, $number = null) {
global $LANG, $translations;
$key = convert_translation_key($key);
$translation = $translations[$key] ?: $key;
$translation = ($translations[$idf] ?: $idf);
if (is_array($translation)) {
$pos = ($number == 1 ? 0
: ($LANG == 'cs' || $LANG == 'sk' ? ($number && $number < 5 ? 1 : 2) // different forms for 1, 2-4, other
@@ -105,80 +73,57 @@ function lang($key, $number = null)
: ($LANG == 'pl' ? ($number % 10 > 1 && $number % 10 < 5 && $number / 10 % 10 != 1 ? 1 : 2) // different forms for 1, 2-4 except 12-14, other
: ($LANG == 'sl' ? ($number % 100 == 1 ? 0 : ($number % 100 == 2 ? 1 : ($number % 100 == 3 || $number % 100 == 4 ? 2 : 3))) // different forms for 1, 2, 3-4, other
: ($LANG == 'lt' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number % 10 > 1 && $number / 10 % 10 != 1 ? 1 : 2)) // different forms for 1, 12-19, other
: ($LANG == 'lv' ? ($number % 10 == 1 && $number % 100 != 11 ? 0 : ($number ? 1 : 2)) // different forms for 1 except 11, other, 0
: ($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
))))))); // 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];
}
$args = func_get_args();
array_shift($args);
$format = str_replace("%d", "%s", $translation);
if ($format != $translation) {
$args[0] = format_number($number);
}
return vsprintf($format, $args);
}
function language_select()
{
global $LANG, $languages;
$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();");
function switch_lang() {
global $LANG, $langs;
echo "<form action='' method='post'>\n<div id='lang'>";
echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();");
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 "</form></div>\n";
echo "</div>\n</form>\n";
}
if (isset($_POST["lang"]) && verify_token()) { // $error not yet available
cookie("adminer_lang", $_POST["lang"]);
$_SESSION["lang"] = $_POST["lang"]; // cookies may be disabled
$_SESSION["translations"] = []; // used in compiled version
$_SESSION["translations"] = array(); // used in compiled version
redirect(remove_from_uri());
}
$available_languages = get_available_languages();
$LANG = $available_languages[0];
if (isset($available_languages[$_COOKIE["adminer_lang"]])) {
$LANG = "en";
if (isset($langs[$_COOKIE["adminer_lang"]])) {
cookie("adminer_lang", $_COOKIE["adminer_lang"]);
$LANG = $_COOKIE["adminer_lang"];
} elseif (isset($available_languages[$_SESSION["lang"]])) {
} elseif (isset($langs[$_SESSION["lang"]])) {
$LANG = $_SESSION["lang"];
} else {
$accept_language = [];
$accept_language = array();
preg_match_all('~([-a-z]+)(;q=([0-9.]+))?~', str_replace("_", "-", strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"])), $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$accept_language[$match[1]] = (isset($match[3]) ? $match[3] : 1);
}
arsort($accept_language);
foreach ($accept_language as $key => $q) {
if (isset($available_languages[$key])) {
if (isset($langs[$key])) {
$LANG = $key;
break;
}
$key = preg_replace('~-.*~', '', $key);
if (!isset($accept_language[$key]) && isset($available_languages[$key])) {
if (!isset($accept_language[$key]) && isset($langs[$key])) {
$LANG = $key;
break;
}

View File

@@ -1,29 +1,23 @@
<?php
namespace Adminer;
// PDO can be used in several database drivers
if (extension_loaded('pdo')) {
/*abstract*/ class Min_PDO {
abstract class PdoDb {
var $_result, $server_info, $affected_rows, $errno, $error, $pdo;
function __construct() {
global $adminer;
$pos = array_search("SQL", $adminer->operators);
if ($pos !== false) {
unset($adminer->operators[$pos]);
}
}
function dsn($dsn, $username, $password, $options = []) {
$options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
$options[PDO::ATTR_STATEMENT_CLASS] = [Min_PDOStatement::class];
function dsn($dsn, $username, $password, $options = array()) {
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT;
$options[\PDO::ATTR_STATEMENT_CLASS] = array('Adminer\PdoDbStatement');
try {
$this->pdo = new PDO($dsn, $username, $password, $options);
$this->pdo = new \PDO($dsn, $username, $password, $options);
} catch (Exception $ex) {
auth_error(h($ex->getMessage()));
}
$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) {
return $this->pdo->quote($string);
@@ -80,15 +74,15 @@ if (extension_loaded('pdo')) {
}
}
class Min_PDOStatement extends PDOStatement {
class PdoDbStatement extends \PDOStatement {
var $_offset = 0, $num_rows;
function fetch_assoc() {
return $this->fetch(PDO::FETCH_ASSOC);
return $this->fetch(\PDO::FETCH_ASSOC);
}
function fetch_row() {
return $this->fetch(PDO::FETCH_NUM);
return $this->fetch(\PDO::FETCH_NUM);
}
function fetch_field() {
@@ -98,5 +92,11 @@ if (extension_loaded('pdo')) {
$row->charsetnr = (in_array("blob", (array) $row->flags) ? 63 : 0);
return $row;
}
function seek($offset) {
for ($i=0; $i < $offset; $i++) {
$this->fetch();
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
namespace Adminer;
class TmpFile {
var $handler;
@@ -18,5 +19,4 @@ class TmpFile {
fpassthru($this->handler);
fclose($this->handler);
}
}

View File

@@ -1,2 +1,4 @@
<?php
$VERSION = "4.12";
namespace Adminer;
$VERSION = "5.0.2";

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
/** PHP implementation of XXTEA encryption algorithm
* @author Ma Bingyao <andot@ujn.edu.cn>
* @link http://www.coolcode.cn/?action=show&id=128

View File

@@ -1,21 +1,17 @@
<?php
/**
* Adminer - Database management in a single PHP file
*
* @link https://github.com/pematon/adminer
* @author Jakub Vrana (https://www.vrana.cz/)
* @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)
/** Adminer - Compact database management
* @link https://www.adminer.org/
* @author Jakub Vrana, https://www.vrana.cz/
* @copyright 2007 Jakub Vrana
* @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)
*/
namespace Adminer;
include "./include/bootstrap.inc.php";
include "./include/tmpfile.inc.php";
$enum_length = "'(?:''|[^'\\\\]|\\\\.)*'";
$inout = "IN|OUT|INOUT";
if (isset($_GET["select"]) && ($_POST["edit"] || $_POST["clone"]) && !$_POST["save"]) {
$_GET["edit"] = $_GET["select"];
}
@@ -62,6 +58,8 @@ if (isset($_GET["download"])) {
include "./sequence.inc.php";
} elseif (isset($_GET["type"])) {
include "./type.inc.php";
} elseif (isset($_GET["check"])) {
include "./check.inc.php";
} elseif (isset($_GET["trigger"])) {
include "./trigger.inc.php";
} elseif (isset($_GET["user"])) {

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$TABLE = $_GET["indexes"];
$index_types = array("PRIMARY", "UNIQUE", "INDEX");
$table_status = table_status($TABLE, true);
@@ -10,13 +12,15 @@ if (preg_match('~MyISAM|M?aria' . (min_version(5.7, '10.2.2') ? '|InnoDB' : '')
}
$indexes = indexes($TABLE);
$primary = array();
if ($jush == "mongo") { // doesn't support primary key
if (JUSH == "mongo") { // doesn't support primary key
$primary = $indexes["_id_"];
unset($index_types[0]);
unset($indexes["_id_"]);
}
$row = $_POST;
if ($row) {
set_adminer_settings(array("index_options" => $row["options"]));
}
if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
$alter = array();
foreach ($row["indexes"] as $index) {
@@ -33,18 +37,18 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
$desc = $index["descs"][$key];
$set[] = idf_escape($column) . ($length ? "(" . (+$length) . ")" : "") . ($desc ? " DESC" : "");
$columns[] = $column;
$lengths[] = ($length ? $length : null);
$lengths[] = ($length ?: null);
$descs[] = $desc;
}
}
if ($columns) {
$existing = $indexes[$name];
if ($existing) {
ksort($existing["columns"]);
ksort($existing["lengths"]);
ksort($existing["descs"]);
if ($index["type"] == $existing["type"]
if (
$index["type"] == $existing["type"]
&& array_values($existing["columns"]) === $columns
&& (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)
&& array_values($existing["descs"]) === $descs
@@ -54,6 +58,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
continue;
}
}
if ($columns) {
$alter[] = array($index["type"], $name, $set);
}
}
@@ -91,14 +96,21 @@ if (!$row) {
$indexes[] = array("columns" => array(1 => ""));
$row["indexes"] = $indexes;
}
$lengths = (JUSH == "sql" || JUSH == "mssql");
$show_options = ($_POST ? $_POST["options"] : adminer_setting("index_options"));
?>
<form action="" method="post">
<div class="scrollable">
<table cellspacing="0" class="nowrap">
<table class="nowrap">
<thead><tr>
<th id="label-type"><?php echo lang('Index Type'); ?>
<th><input type="submit" class="wayoff"><?php echo lang('Column (length)'); ?>
<th><input type="submit" class="wayoff"><?php
echo lang('Column') . ($lengths ? "<span class='idxopts" . ($show_options ? "" : " hidden") . "'> (" . lang('length') . ")</span>" : "");
if ($lengths || support("descidx")) {
echo checkbox("options", 1, $show_options, lang('Options'), "indexOptionsShow(this.checked)", "jsonly") . "\n";
}
?>
<th id="label-name"><?php echo lang('Name'); ?>
<th><noscript><?php echo "<input type='image' class='icon' name='add[0]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>"; ?></noscript>
</thead>
@@ -124,11 +136,12 @@ foreach ($row["indexes"] as $index) {
" name='indexes[$j][columns][$i]' title='" . lang('Column') . "'",
($fields ? array_combine($fields, $fields) : $fields),
$column,
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape($jush == "sql" ? "" : $_GET["indexes"] . "_") . "')"
"partial(" . ($i == count($index["columns"]) ? "indexesAddColumn" : "indexesChangeColumn") . ", '" . js_escape(JUSH == "sql" ? "" : $_GET["indexes"] . "_") . "')"
);
echo ($jush == "sql" || $jush == "mssql" ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h($index["lengths"][$key]) . "' title='" . lang('Length') . "'>" : "");
echo "<span class='idxopts" . ($show_options ? "" : " hidden") . "'>";
echo ($lengths ? "<input type='number' name='indexes[$j][lengths][$i]' class='size' value='" . h($index["lengths"][$key]) . "' title='" . lang('Length') . "'>" : "");
echo (support("descidx") ? checkbox("indexes[$j][descs][$i]", 1, $index["descs"][$key], lang('descending')) : "");
echo " </span>";
echo "</span> </span>";
$i++;
}

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'تسجيل الدخول',
'Logout successful.' => 'تم تسجيل الخروج بنجاح.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'بيانات الدخول غير صالحة.',
'Server' => 'الخادم',
'Username' => 'اسم المستخدم',
'Password' => 'كلمة المرور',
@@ -67,6 +68,7 @@ $translations = array(
'Unable to select the table' => 'يتعذر اختيار الجدول',
'Invalid CSRF token. Send the form again.' => 'رمز CSRF غير صالح. المرجو إرسال الاستمارة مرة أخرى.',
'Comment' => 'تعليق',
'Default values' => 'القيم الافتراضية',
'%d byte(s)' => '%d بايت',
'No commands to execute.' => 'لا توجد أوامر للتنفيذ.',
'Unable to upload a file.' => 'يتعذر رفع ملف ما.',
@@ -75,7 +77,7 @@ $translations = array(
'Routine has been called, %d row(s) affected.' => 'تم استدعاء الروتين, عدد الأسطر المعدلة %d.',
'Call' => 'استدعاء',
'No extension' => 'امتداد غير موجود',
'None of the supported PHP extensions (%s) are available.' => 'إمتدادات php المدعومة غير موجودة.',
'None of the supported PHP extensions (%s) are available.' => 'إمتدادات php (%s) المدعومة غير موجودة.',
'Session support must be enabled.' => 'عليك تفعيل نظام الجلسات.',
'Session expired, please login again.' => 'إنتهت الجلسة، من فضلك أعد تسجيل الدخول.',
'Text length' => 'طول النص',
@@ -93,7 +95,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'نوع المؤشر',
'Column (length)' => 'العمود (الطول)',
'length' => 'الطول',
'View has been dropped.' => 'تم مسح العرض.',
'View has been altered.' => 'تم تعديل العرض.',
'View has been created.' => 'تم إنشاء العرض.',
@@ -169,8 +171,8 @@ $translations = array(
'Tables and views' => 'الجداول و العروض',
'Engine' => 'المحرك',
'Collation' => 'ترتيب',
'Data Length' => 'طول المعطيات.',
'Index Length' => 'طول المؤشر.',
'Data Length' => 'طول المعطيات',
'Index Length' => 'طول المؤشر',
'Data Free' => 'المساحة الحرة',
'Rows' => 'الأسطر',
',' => ',',
@@ -187,11 +189,10 @@ $translations = array(
'Clone' => 'نسخ',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'لقد تجاوزت العدد الأقصى للحقول. يرجى الرفع من %s.',
'Partition by' => 'مقسم بواسطة',
'Partition' => null,
'Partitions' => 'التقسيمات',
'Partition name' => 'اسم التقسيم',
'Values' => 'القيم',
'%d row(s) have been imported.' => 'تم استيراد %d سطرا',
'%d row(s) have been imported.' => 'تم استيراد %d سطرا.',
'anywhere' => 'في اي مكان',
'Import' => 'استيراد',
'Stop on error' => 'أوقف في حالة حدوث خطأ',
@@ -223,7 +224,6 @@ $translations = array(
'Databases have been dropped.' => 'تم حذف قواعد البيانات.',
'Database has been dropped.' => 'تم حذف قاعدة البيانات.',
'Search data in tables' => 'بحث في الجداول',
'as a regular expression' => null,
'Schema' => 'المخطط',
'Alter schema' => 'تعديل المخطط',
'Create schema' => 'إنشاء مخطط',
@@ -251,8 +251,8 @@ $translations = array(
'Network' => 'شبكة',
'Geometry' => 'هندسة',
'File exists.' => 'الملف موجود.',
'Attachments' => 'ملفات مرفقة.',
'Item%s has been inserted.' => 'تم إدراج العنصر.',
'Attachments' => 'ملفات مرفقة',
'Item%s has been inserted.' => '%sتم إدراج العنصر.',
'now' => 'الآن',
'%d query(s) executed OK.' => array('تم تنفيذ الاستعلام %d بنجاح.', 'تم تنفيذ الاستعلامات %d بنجاح.'),
'Show only errors' => 'إظهار الأخطاء فقط',
@@ -265,56 +265,4 @@ $translations = array(
'Permanent link' => 'رابط دائم',
'Edit all' => 'تعديل الكل',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Система',
'Server' => 'Сървър',
'Username' => 'Потребител',
@@ -11,14 +12,12 @@ $translations = array(
'Logout' => 'Изход',
'Logged as: %s' => 'Текущ потребител: %s',
'Logout successful.' => 'Излизането е успешно.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Невалидни потребителски данни.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Прекалено много неуспешни опити за вход, опитайте пак след %d минута.', 'Прекалено много неуспешни опити за вход, опитайте пак след %d минути.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Главната парола вече е невалидна. <a href="https://www.adminer.org/en/extension/"%s>Изберете</a> %s метод, за да я направите постоянна.',
'Language' => 'Език',
'Invalid CSRF token. Send the form again.' => 'Невалиден шифроващ ключ. Попълнете и изпратете формуляра отново.',
'If you did not send this request from Adminer then close this page.' => 'Ако не сте изпратили тази заявка през Adminer, затворете тази страница.',
'No driver' => null,
'Database driver not found.' => null,
'No extension' => 'Няма разширение',
'None of the supported PHP extensions (%s) are available.' => 'Никое от поддържаните PHP разширения (%s) не е налично.',
'Session support must be enabled.' => 'Поддръжката на сесии трябва да е разрешена.',
@@ -167,6 +166,7 @@ $translations = array(
'Options' => 'Опции',
'Comment' => 'Коментар',
'Default value' => 'Стойност по подразбиране',
'Default values' => 'Стойности по подразбиране',
'Drop' => 'Премахване',
'Are you sure?' => 'Сигурни ли сте?',
'Size' => 'Големина',
@@ -177,7 +177,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Максималния брой полета е превишен. Моля, увеличете %s.',
'Partition by' => 'Разделяне на',
'Partition' => null,
'Partitions' => 'Раздели',
'Partition name' => 'Име на раздела',
'Values' => 'Стойности',
@@ -195,7 +194,7 @@ $translations = array(
'Alter indexes' => 'Промяна на индекси',
'Add next' => 'Добавяне на следващ',
'Index Type' => 'Вид на индекса',
'Column (length)' => 'Колона (дължина)',
'length' => 'дължина',
'Foreign keys' => 'Препратки',
'Foreign key' => 'Препратка',
@@ -232,7 +231,6 @@ $translations = array(
'Search' => 'Търсене',
'anywhere' => 'навсякъде',
'Search data in tables' => 'Търсене на данни в таблиците',
'as a regular expression' => null,
'Sort' => 'Сортиране',
'descending' => 'низходящо',
'Limit' => 'Редове',
@@ -314,15 +312,12 @@ $translations = array(
'Please use one of the extensions %s.' => 'Моля, използвайте някое от разширенията %s.',
// PostgreSQL and MS SQL schema support
'Schema' => 'Схема',
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'Alter schema' => 'Промяна на схемата',
'Create schema' => 'Създаване на схема',
'Schema has been dropped.' => 'Схемата беше премахната.',
'Schema has been created.' => 'Схемата беше създадена.',
'Schema has been altered.' => 'Схемата беше променена.',
'Schema' => 'Схема',
'Invalid schema.' => 'Невалидна схема.',
// PostgreSQL sequences support
@@ -339,26 +334,4 @@ $translations = array(
'Type has been dropped.' => 'Вида беше пермахнат.',
'Type has been created.' => 'Вида беше създаден.',
'Alter type' => 'Промяна на вид',
'Drop %s?' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Да',
'No' => 'Не',
'One Time Password' => null,
'Invalid OTP code.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'লগইন',
'Logout successful.' => 'সফলভাবে লগআউট হয়েছে।',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'ভুল পাসওয়ার্ড।',
'Server' => 'সার্ভার',
'Username' => 'ইউজারের নাম',
'Password' => 'পাসওয়ার্ড',
@@ -37,7 +38,7 @@ $translations = array(
'select' => 'নির্বাচন',
'Item has been deleted.' => 'বিষয়বস্তু মুছে ফেলা হয়েছে।',
'Item has been updated.' => 'বিষয়বস্তু হালনাগাদ করা হয়েছে।',
'Item%s has been inserted.' => 'বিষয়বস্তুসমূহ সংযোজন করা হয়েছে।',
'Item%s has been inserted.' => 'বিষয়বস্তুসমূহ%s সংযোজন করা হয়েছে।',
'Edit' => 'সম্পাদনা',
'Insert' => 'সংযোজন',
'Save and insert next' => 'সংরক্ষন ও পরবর্তী সংযোজন করুন',
@@ -60,7 +61,7 @@ $translations = array(
'edit' => 'সম্পাদনা',
'Page' => 'পৃষ্ঠা',
'Query executed OK, %d row(s) affected.' => array('কোয়্যারী সম্পাদন হয়েছে, %d সারি প্রভাবিত হয়েছে।', 'কোয়্যারী সম্পাদন হয়েছে, %d সারি প্রভাবিত হয়েছে।'),
'Error in query' => 'অনুসন্ধানে ভুল আছে',
'Error in query' => 'অনুসন্ধানে ভুল আছে',
'Execute' => 'সম্পাদন করো',
'Table' => 'টেবিল',
'Foreign keys' => 'ফরেন কী',
@@ -69,6 +70,7 @@ $translations = array(
'Unable to select the table' => 'টেবিল নির্বাচন করতে অক্ষম',
'Invalid CSRF token. Send the form again.' => 'অবৈধ CSRF টোকেন। ফর্মটি আবার পাঠান।',
'Comment' => 'মন্তব্য',
'Default values' => 'ডিফল্ট মান',
'%d byte(s)' => array('%d বাইট', '%d বাইটসমূহ'),
'No commands to execute.' => 'সম্পাদন করার মত কোন নির্দেশ নেই।',
'Unable to upload a file.' => 'ফাইল আপলোড করা সম্ভব হচ্ছে না।',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'অন ডিলিট',
'ON UPDATE' => 'অন আপডেট',
'Index Type' => 'সূচী-ধরণ',
'Column (length)' => 'কলাম (দৈর্ঘ্য)',
'length' => 'দৈর্ঘ্য',
'View has been dropped.' => 'ভিউ মুছে ফেলা হয়েছে।',
'View has been altered.' => 'ভিউ পরিবর্তন করা হয়েছে।',
'View has been created.' => 'ভিউ তৈরী করা হয়েছে।',
@@ -137,7 +139,7 @@ $translations = array(
'Routine' => 'রুটিন',
'Grant' => 'অনুমতি',
'Revoke' => 'প্রত্যাহার',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'খুব বড় POST ডাটা। ডাটা সংক্ষিপ্ত করো অথবা %s কনফিগারেশন নির্দেশ বৃদ্ধি করো',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'খুব বড় POST ডাটা। ডাটা সংক্ষিপ্ত করো অথবা %s কনফিগারেশন নির্দেশ বৃদ্ধি করো',
'Logged as: %s' => '%s হিসাবে লগড',
'Move up' => 'উপরে স্থানান্তর',
'Move down' => 'নীচে স্থানান্তর',
@@ -173,7 +175,7 @@ $translations = array(
'Check' => 'পরীক্ষা',
'Repair' => 'মেরামত',
'Truncate' => 'ছাঁটাই',
'Tables have been truncated.' => 'টেবিল ছাঁটাই করা হয়েছে',
'Tables have been truncated.' => 'টেবিল ছাঁটাই করা হয়েছে',
'Rows' => 'সারিসমূহ',
',' => ',',
'0123456789' => '০১২৩৪৫৬৭৮৯',
@@ -184,12 +186,11 @@ $translations = array(
'Save and continue edit' => 'সংরক্ষণ করুন এবং সম্পাদনা চালিয়ে যান',
'original' => 'প্রকৃত',
'Tables have been dropped.' => 'টেবিলসমূহ মুছে ফেলা হয়েছে।',
'%d item(s) have been affected.' => '%d টি বিষয়বস্তু প্রভাবিত হয়েছে',
'%d item(s) have been affected.' => '%d টি বিষয়বস্তু প্রভাবিত হয়েছে',
'Whole result' => 'সম্পূর্ণ ফলাফল',
'Clone' => 'ক্লোন',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'অনুমোদিত ফিল্ড এর সর্বাধিক সংখ্যা অতিক্রম করে গেছে। অনুগ্রহপূর্বক %s বৃদ্ধি করুন।',
'Partition by' => 'পার্টিশন যার মাধ্যমে',
'Partition' => null,
'Partitions' => 'পার্টিশন',
'Partition name' => 'পার্টিশনের নাম',
'Values' => 'মানসমূহ',
@@ -206,7 +207,7 @@ $translations = array(
'Relations' => 'সম্পর্ক',
'Run file' => 'ফাইল চালাও',
'Clear' => 'সাফ করো',
'Maximum allowed file size is %sB.' => 'সর্বাধিক অনুমোদিত ফাইল সাইজ %sB.',
'Maximum allowed file size is %sB.' => 'সর্বাধিক অনুমোদিত ফাইল সাইজ %sB',
'Numbers' => 'সংখ্যা',
'Date and time' => 'তারিখ এবং সময়',
'Strings' => 'স্ট্রিং',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'স্থায়ী লগইন',
'Databases have been dropped.' => 'ডাটাবেজসমূহ মুছে ফেলা হয়েছে।',
'Search data in tables' => 'টেবিলে তথ্য খুঁজুন',
'as a regular expression' => null,
'Schema' => 'স্কিমা',
'Alter schema' => 'স্কিমা পরিবর্তন করো',
'Create schema' => 'স্কিমা তৈরী করো',
@@ -253,7 +253,7 @@ $translations = array(
'Geometry' => 'জ্যামিতি',
'File exists.' => 'ফাইল রয়েছে।',
'Attachments' => 'সংযুক্তিগুলো',
'%d query(s) executed OK.' => array('SQL-অনুসন্ধান সফলভাবে সম্পন্ন হয়েছে', '%d SQL-অনুসন্ধানসমূহ সফলভাবে সম্পন্ন হয়েছে'),
'%d query(s) executed OK.' => array('SQL-অনুসন্ধান সফলভাবে সম্পন্ন হয়েছে', '%d SQL-অনুসন্ধানসমূহ সফলভাবে সম্পন্ন হয়েছে'),
'Show only errors' => 'শুধুমাত্র ত্রুটিগুলো দেখান',
'Refresh' => 'রিফ্রেশ',
'Invalid schema.' => 'অবৈধ স্কিমা।',
@@ -265,56 +265,4 @@ $translations = array(
'Permanent link' => 'স্থায়ী লিংক',
'Edit all' => 'সবগুলো সম্পাদনা করুন',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem',
'Server' => 'Server',
'Username' => 'Korisničko ime',
@@ -11,11 +12,11 @@ $translations = array(
'Logout' => 'Odjava',
'Logged as: %s' => 'Prijavi se kao: %s',
'Logout successful.' => 'Uspešna odjava.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Nevažeće dozvole.',
'Language' => 'Jezik',
'Invalid CSRF token. Send the form again.' => 'Nevažeći CSRF kod. Proslijedite ponovo formu.',
'No extension' => 'Bez dodataka',
'None of the supported PHP extensions (%s) are available.' => 'Nijedan od podržanih PHP dodataka nije dostupan.',
'None of the supported PHP extensions (%s) are available.' => 'Nijedan od podržanih PHP dodataka (%s) nije dostupan.',
'Session support must be enabled.' => 'Morate omogućiti podršku za sesije.',
'Session expired, please login again.' => 'Vaša sesija je istekla, prijavite se ponovo.',
'%s version: %s through PHP extension %s' => '%s verzija: %s pomoću PHP dodatka je %s',
@@ -158,6 +159,7 @@ $translations = array(
'Auto Increment' => 'Auto-priraštaj',
'Options' => 'Opcije',
'Comment' => 'Komentar',
'Default values' => 'Podrazumijevane vrijednosti',
'Drop' => 'Izbriši',
'Are you sure?' => 'Da li ste sigurni?',
'Move up' => 'Pomijeri na gore',
@@ -166,7 +168,6 @@ $translations = array(
'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' => null,
'Partitions' => 'Podijele',
'Partition name' => 'Ime podijele',
'Values' => 'Vrijednosti',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Ažuriraj indekse',
'Add next' => 'Dodaj slijedeći',
'Index Type' => 'Tip indeksa',
'Column (length)' => 'kolumna (dužina)',
'length' => 'dužina',
'Foreign keys' => 'Strani ključevi',
'Foreign key' => 'Strani ključ',
@@ -221,7 +222,6 @@ $translations = array(
'Search' => 'Pretraga',
'anywhere' => 'bilo gdje',
'Search data in tables' => 'Pretraži podatke u tabelama',
'as a regular expression' => null,
'Sort' => 'Poređaj',
'descending' => 'opadajuće',
'Limit' => 'Granica',
@@ -319,47 +319,4 @@ $translations = array(
'Type has been dropped.' => 'Tip je izbrisan.',
'Type has been created.' => 'tip je spašen.',
'Alter type' => 'Ažuriraj tip',
'Drop %s?' => null,
'Materialized view' => null,
'Vacuum' => null,
'overwrite' => null,
'DB' => null,
'File must be in UTF-8 encoding.' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Da',
'No' => 'Ne',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Inicia la sessió',
'Logout successful.' => 'Desconnexió correcta.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Credencials invàlides.',
'Server' => 'Servidor',
'Username' => 'Nom d\'usuari',
'Password' => 'Contrasenya',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Comentari',
'Default values' => 'Valors per defecte',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Cap comanda per executar.',
'Unable to upload a file.' => 'Impossible adjuntar el fitxer.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipus d\'índex',
'Column (length)' => 'Columna (longitud)',
'length' => 'longitud',
'View has been dropped.' => 'S\'ha suprimit la vista.',
'View has been altered.' => 'S\'ha modificat la vista.',
'View has been created.' => 'S\'ha creat la vista.',
@@ -188,7 +190,6 @@ $translations = array(
'Tables have been dropped.' => 'S\'han suprimit les taules.',
'Clone' => 'Clona',
'Partition by' => 'Fes particions segons',
'Partition' => null,
'Partitions' => 'Particions',
'Partition name' => 'Nom de la partició',
'Values' => 'Valors',
@@ -251,7 +252,6 @@ $translations = array(
'Type has been created.' => 'S\'ha creat el tipus.',
'Alter type' => 'Modifica el tipus',
'Search data in tables' => 'Cerca dades en les taules',
'as a regular expression' => null,
'From server' => 'En el servidor',
'empty' => 'buit',
'now' => 'ara',
@@ -266,55 +266,4 @@ $translations = array(
'Permanent link' => 'Enllaç permanent',
'Edit all' => 'Edita-ho tot',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => 'Domů',
'System' => 'Systém',
'Server' => 'Server',
'Username' => 'Uživatel',
@@ -12,7 +13,7 @@ $translations = array(
'Logged as: %s' => 'Přihlášen jako: %s',
'Logout successful.' => 'Odhlášení proběhlo v pořádku.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Díky za použití Admineru, <a href="https://www.adminer.org/cs/donation/">přispějte</a> na vývoj.',
'Invalid server or credentials.' => 'Neplatný server nebo přihlašovací údaje.',
'Invalid credentials.' => 'Neplatné přihlašovací údaje.',
'There is a space in the input password which might be the cause.' => 'Problém může být, že je v zadaném hesle mezera.',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer nepodporuje přístup k databázi bez hesla, <a href="https://www.adminer.org/cs/password/"%s>více informací</a>.',
'Database does not support password.' => 'Databáze nepodporuje heslo.',
@@ -21,8 +22,6 @@ $translations = array(
'Language' => 'Jazyk',
'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.',
'No driver' => 'Žádný ovladač',
'Database driver not found.' => 'Databázový ovladač se nenašel.',
'No extension' => 'Žádné rozšíření',
'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.',
@@ -179,6 +178,7 @@ $translations = array(
'Options' => 'Volby',
'Comment' => 'Komentář',
'Default value' => 'Výchozí hodnota',
'Default values' => 'Výchozí hodnoty',
'Drop' => 'Odstranit',
'Drop %s?' => 'Odstranit %s?',
'Are you sure?' => 'Opravdu?',
@@ -190,7 +190,6 @@ $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.',
'Partition by' => 'Rozdělit podle',
'Partition' => 'Oddíl',
'Partitions' => 'Oddíly',
'Partition name' => 'Název oddílu',
'Values' => 'Hodnoty',
@@ -208,7 +207,7 @@ $translations = array(
'Alter indexes' => 'Pozměnit indexy',
'Add next' => 'Přidat další',
'Index Type' => 'Typ indexu',
'Column (length)' => 'Sloupec (délka)',
'length' => 'délka',
'Foreign keys' => 'Cizí klíče',
'Foreign key' => 'Cizí klíč',
@@ -245,7 +244,6 @@ $translations = array(
'Search' => 'Vyhledat',
'anywhere' => 'kdekoliv',
'Search data in tables' => 'Vyhledat data v tabulkách',
'as a regular expression' => 'jako regulární výraz',
'Sort' => 'Seřadit',
'descending' => 'sestupně',
'Limit' => 'Limit',
@@ -327,15 +325,12 @@ $translations = array(
'Please use one of the extensions %s.' => 'Prosím použijte jednu z koncovek %s.',
// 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',
'Create schema' => 'Vytvořit schéma',
'Schema has been dropped.' => 'Schéma bylo odstraněno.',
'Schema has been created.' => 'Schéma bylo vytvořeno.',
'Schema has been altered.' => 'Schéma bylo změněno.',
'Schema' => 'Schéma',
'Invalid schema.' => 'Nesprávné schéma.',
// PostgreSQL sequences support
@@ -353,12 +348,11 @@ $translations = array(
'Type has been created.' => 'Typ byl vytvořen.',
'Alter type' => 'Pozměnit typ',
// Plugins
'Columns' => 'Sloupce',
'Nullable' => 'Povoleno null',
'Default' => 'Výchozí',
'Yes' => 'Ano',
'No' => 'Ne',
'One Time Password' => 'Jednorázové heslo',
'Invalid OTP code.' => 'Neplatný kód OTP.',
// Table check constraints
'Checks' => 'Kontroly',
'Create check' => 'Vytvořit kontrolu',
'Alter check' => 'Změnit kontrolu',
'Check has been created.' => 'Kontrola byla vytvořena.',
'Check has been altered.' => 'Kontrola byla změněna.',
'Check has been dropped.' => 'Kontrola byla odstraněna.',
);

View File

@@ -1,6 +1,7 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'System' => 'System',
'Server' => 'Server',
'Username' => 'Brugernavn',
@@ -10,7 +11,7 @@ $translations = array(
'Logout' => 'Log ud',
'Logged as: %s' => 'Logget ind som: %s',
'Logout successful.' => 'Log af vellykket.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Ugyldige log ind oplysninger.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Master-kodeordet er udløbet. <a href="https://www.adminer.org/en/extension/"%s>Implementer</a> en metode for %s for at gøre det permanent.',
'Language' => 'Sprog',
'Invalid CSRF token. Send the form again.' => 'Ugyldigt CSRF-token - Genindsend formen.',
@@ -143,6 +144,7 @@ $translations = array(
'Auto Increment' => 'Auto Increment',
'Options' => 'Valg',
'Comment' => 'Kommentarer',
'Default values' => 'Standardværdier',
'Drop' => 'Drop',
'Are you sure?' => 'Er du sikker?',
'Move up' => 'Flyt op',
@@ -150,7 +152,6 @@ $translations = array(
'Remove' => 'Fjern',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimum antal feltnavne overskredet - øg venligst %s.',
'Partition by' => 'Partition ved',
'Partition' => null,
'Partitions' => 'Partitioner',
'Partition name' => 'Partitionsnavn',
'Values' => 'Værdier',
@@ -165,7 +166,7 @@ $translations = array(
'Alter indexes' => 'Ændre indekser',
'Add next' => 'Læg til næste',
'Index Type' => 'Indekstype',
'Column (length)' => 'Kolonne (længde)',
'length' => 'længde',
'Foreign keys' => 'Fremmednøgler',
'Foreign key' => 'Fremmednøgle',
'Foreign key has been dropped.' => 'Fremmednøglen er slettet.',
@@ -199,7 +200,6 @@ $translations = array(
'Search' => 'Søg',
'anywhere' => 'hvorsomhelst',
'Search data in tables' => 'Søg data i tabeller',
'as a regular expression' => null,
'Sort' => 'Sorter',
'descending' => 'faldende',
'Limit' => 'Limit',
@@ -280,41 +280,4 @@ $translations = array(
'Type has been created.' => 'Typen er oprettet.',
'Alter type' => 'Ændre type',
'Saving' => 'Gemmer',
'Drop %s?' => null,
'Materialized view' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Ja',
'No' => 'Nej',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,10 +1,11 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Login',
'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>',
'Invalid server or credentials.' => 'Ungültige Server oder Anmelde-Informationen.',
'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>.',
'Invalid credentials.' => 'Ungültige Anmelde-Informationen.',
'Server' => 'Server',
'Username' => 'Benutzer',
'Password' => 'Passwort',
@@ -33,7 +34,7 @@ $translations = array(
'Create database' => 'Datenbank erstellen',
'SQL command' => 'SQL-Kommando',
'Logout' => 'Abmelden',
'Use' => 'Benutzung',
'Use' => 'Auswählen',
'No tables.' => 'Keine Tabellen.',
'select' => 'zeigen',
'Item has been deleted.' => 'Datensatz wurde gelöscht.',
@@ -70,6 +71,7 @@ $translations = array(
'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.',
'Comment' => 'Kommentar',
'Default values' => 'Vorgabewerte festlegen',
'%d byte(s)' => array('%d Byte', '%d Bytes'),
'No commands to execute.' => 'Kein Kommando vorhanden.',
'Unable to upload a file.' => 'Hochladen von Datei fehlgeschlagen.',
@@ -96,7 +98,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Index-Typ',
'Column (length)' => 'Spalte (Länge)',
'length' => 'Länge',
'View has been dropped.' => 'View wurde entfernt.',
'View has been altered.' => 'View wurde geändert.',
'View has been created.' => 'View wurde erstellt.',
@@ -190,7 +192,6 @@ $translations = array(
'Clone' => 'Klonen',
'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' => 'Partition',
'Partitions' => 'Partitionen',
'Partition name' => 'Name der Partition',
'Values' => 'Werte',
@@ -225,7 +226,6 @@ $translations = array(
'Permanent login' => 'Passwort speichern',
'Databases have been dropped.' => 'Datenbanken wurden entfernt.',
'Search data in tables' => 'Suche in Tabellen',
'as a regular expression' => null,
'Schema' => 'Schema',
'Alter schema' => 'Schema ändern',
'Create schema' => 'Schema erstellen',
@@ -281,40 +281,25 @@ $translations = array(
'If you did not send this request from Adminer then close this page.' => 'Wenn Sie diese Anfrage nicht von Adminer gesendet haben, schließen Sie diese Seite.',
'You can upload a big SQL file via FTP and import it from server.' => 'Sie können eine große SQL-Datei per FTP hochladen und dann vom Server importieren.',
'You are offline.' => 'Sie sind offline.',
'You have no privileges to update this table.' => 'Sie haben keine Rechte, um diese Tabelle zu aktualisieren.',
'You have no privileges to update this table.' => 'Sie haben keine Rechte, diese Tabelle zu aktualisieren.',
'Saving' => 'Speichere',
'yes' => 'ja',
'no' => 'nein',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Das Master-Passwort ist abgelaufen. <a href="https://www.adminer.org/de/extension/"%s>Implementieren</a> Sie die %s Methode, um es permanent zu machen.',
'%d / ' => '%d / ',
'Drop %s?' => null,
'Materialized view' => null,
'Vacuum' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Full table scan' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Ja',
'No' => 'Nein',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
'Drop %s?' => '%s entfernen?',
'Materialized view' => 'Strukturierte Ansicht',
'Vacuum' => 'Vacuum',
'overwrite' => 'überschreiben',
'DB' => 'DB',
'ATTACH queries are not supported.' => 'ATTACH Abfragen werden nicht unterstützt.',
'Warnings' => 'Warnungen',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer unterstützt den Zugriff auf eine Datenbank ohne Passwort nicht, <a href="https://www.adminer.org/en/password/"%s>mehr Informationen</a>.',
'Full table scan' => 'Vollständige Überprüfung der Tabelle',
'The action will be performed after successful login with the same credentials.' => 'Die Aktion wird nach erfolgreicher Anmeldung mit denselben Anmeldedaten ausgeführt.',
'Connecting to privileged ports is not allowed.' => 'Die Verbindung zu privilegierten Ports ist nicht erlaubt.',
'There is a space in the input password which might be the cause.' => 'Es gibt ein Leerzeichen im Eingabepasswort, das die Ursache sein könnte.',
'Unknown error.' => 'Unbekannter Fehler.',
'Database does not support password.' => 'Die Datenbank unterstützt kein Passwort.',
'Disable %s or enable %s or %s extensions.' => 'Deaktivieren Sie %s oder aktivieren Sie die Erweiterungen %s oder %s.',
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Σύστημα',
'Server' => 'Διακομιστής',
'Username' => 'Όνομα Χρήστη',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Αποσύνδεση',
'Logged as: %s' => 'Συνδεθήκατε ως %s',
'Logout successful.' => 'Αποσυνδεθήκατε με επιτυχία.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Εσφαλμένα Διαπιστευτήρια.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Επανειλημμένες ανεπιτυχείς προσπάθειες σύνδεσης, δοκιμάστε ξανά σε %s λεπτό.', 'Επανειλημμένες ανεπιτυχείς προσπάθειες σύνδεσης, δοκιμάστε ξανά σε %s λεπτά.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Έληξε ο Κύριος Κωδικός. <a href="https://www.adminer.org/en/extension/"%s>Ενεργοποιήστε</a> τη μέθοδο %s για να τον κάνετε μόνιμο.',
'Language' => 'Γλώσσα',
@@ -166,6 +167,7 @@ $translations = array(
'Options' => 'Επιλογές',
'Comment' => 'Σχόλιο',
'Default value' => 'Προεπιλεγμένη τιμή',
'Default values' => 'Προεπιλεγμένες τιμές',
'Drop' => 'Διαγραφή',
'Are you sure?' => 'Είστε σίγουρος;',
'Size' => 'Μέγεθος',
@@ -176,7 +178,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Υπέρβαση μέγιστου επιτρεπόμενου αριθμού πεδίων. Παρακαλώ αυξήστε %s.',
'Partition by' => 'Τμηματοποίηση ανά',
'Partition' => null,
'Partitions' => 'Τμήματα',
'Partition name' => 'Όνομα Τμήματος',
'Values' => 'Τιμές',
@@ -194,7 +195,7 @@ $translations = array(
'Alter indexes' => 'Τροποποίηση δεικτών',
'Add next' => 'Προσθήκη επόμενου',
'Index Type' => 'Τύπος δείκτη',
'Column (length)' => 'Στήλη (μήκος)',
'length' => 'μήκος',
'Foreign keys' => 'Εξαρτημένα κλειδιά',
'Foreign key' => 'Εξαρτημένο κλειδί',
@@ -231,7 +232,6 @@ $translations = array(
'Search' => 'Αναζήτηση',
'anywhere' => 'παντού',
'Search data in tables' => 'Αναζήτηση δεδομένων στους πίνακες',
'as a regular expression' => null,
'Sort' => 'Ταξινόμηση',
'descending' => 'Φθίνουσα',
'Limit' => 'Όριο',
@@ -334,32 +334,4 @@ $translations = array(
'Type has been dropped.' => 'Ο τύπος διαγράφηκε.',
'Type has been created.' => 'Ο τύπος δημιουργήθηκε.',
'Alter type' => 'Τροποποίηση τύπου',
'Drop %s?' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$translations = array(
'Too many unsuccessful logins, try again in %d minute(s).' => array('Too many unsuccessful logins, try again in %d minute.', 'Too many unsuccessful logins, try again in %d minutes.'),
'Query executed OK, %d row(s) affected.' => array('Query executed OK, %d row affected.', 'Query executed OK, %d rows affected.'),

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Login',
'Logout successful.' => 'Sesión finalizada con éxito.',
'Invalid server or credentials.' => 'Servidor o credenciales no válidos.',
'Invalid credentials.' => 'Usuario y/o clave de acceso incorrecta.',
'Server' => 'Servidor',
'Username' => 'Usuario',
'Password' => 'Contraseña',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Comentario',
'Default values' => 'Valores predeterminados',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'No es posible ejecutar ningún comando.',
'Unable to upload a file.' => 'No es posible importar el archivo.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'AL BORRAR',
'ON UPDATE' => 'AL ACTUALIZAR',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'Columna (longitud)',
'length' => 'longitud',
'View has been dropped.' => 'Vista eliminada.',
'View has been altered.' => 'Vista modificada.',
'View has been created.' => 'Vista creada.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'Clonar',
'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' => null,
'Partitions' => 'Particiones',
'Partition name' => 'Nombre de partición',
'Values' => 'Valores',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Guardar contraseña',
'Databases have been dropped.' => 'Bases de datos eliminadas.',
'Search data in tables' => 'Buscar datos en tablas',
'as a regular expression' => 'como una expresión regular',
'Schema' => 'Esquema',
'Alter schema' => 'Modificar esquema',
'Create schema' => 'Crear esquema',
@@ -266,55 +266,4 @@ $translations = array(
'Permanent link' => 'Enlace permanente',
'Edit all' => 'Editar todos',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => '¿Eliminar %s?',
'Tables have been optimized.' => 'Tablas optimizadas.',
'Materialized view' => 'Vista materializada',
'Vacuum' => 'Vacio',
'Selected' => 'Seleccionado',
'overwrite' => 'sobreescribir',
'DB' => 'DB',
'File must be in UTF-8 encoding.' => 'El archivo debe estar codificado en UTF-8.',
'Modify' => 'Modificar',
'Load more data' => 'Cargar mas datos',
'Loading' => 'Cargando',
'ATTACH queries are not supported.' => 'ATTACH consultas no está soportado.',
'Warnings' => 'Advertencias',
'%d / ' => '%d / ',
'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>.' => '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' => 'Valor por defecto',
'Full table scan' => null,
'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,
'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.' => 'La acción se realizará tras iniciar sesión de nuevo con las mismas credenciales.',
'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.' => '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.' => '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.' => 'Puede cargar un fichero SQL grande por FTP e importarlo desde el servidor.',
'Size' => 'Tamaño',
'Compute' => 'Procesar',
'You are offline.' => 'Se encuentra desconectado.',
'You have no privileges to update this table.' => 'No tiene privilegios para actualizar esta tabla.',
'Saving' => 'Guardando',
'Unknown error.' => 'Error desconocido.',
'Database does not support password.' => 'La Base de Datos no soporta el uso de contraseña.',
'Disable %s or enable %s or %s extensions.' => 'Deshabilitar %s o habilitar %s o %s extensiones.',
'yes' => 'si',
'no' => 'no',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Logi sisse',
'Logout successful.' => 'Väljalogimine õnnestus.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Ebakorrektsed andmed.',
'Server' => 'Server',
'Username' => 'Kasutajanimi',
'Password' => 'Parool',
@@ -69,6 +70,7 @@ $translations = array(
'Unable to select the table' => 'Tabeli valimine ebaõnnestus',
'Invalid CSRF token. Send the form again.' => 'Sobimatu CSRF, palun postitage vorm uuesti.',
'Comment' => 'Kommentaar',
'Default values' => 'Vaikimisi väärtused',
'%d byte(s)' => array('%d bait', '%d baiti'),
'No commands to execute.' => 'Käsk puudub.',
'Unable to upload a file.' => 'Faili üleslaadimine pole võimalik.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Indeksi tüüp',
'Column (length)' => 'Veerg (pikkus)',
'length' => 'pikkus',
'View has been dropped.' => 'Vaade (VIEW) on edukalt kustutatud.',
'View has been altered.' => 'Vaade (VIEW) on edukalt muudetud.',
'View has been created.' => 'Vaade (VIEW) on edukalt loodud.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'Kloon',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimaalne väljade arv ületatud. Palun suurendage %s.',
'Partition by' => 'Partitsiooni',
'Partition' => null,
'Partitions' => 'Partitsioonid',
'Partition name' => 'Partitsiooni nimi',
'Values' => 'Väärtused',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Jäta mind meelde',
'Databases have been dropped.' => 'Andmebaasid on edukalt kustutatud.',
'Search data in tables' => 'Otsi kogu andmebaasist',
'as a regular expression' => null,
'Schema' => 'Struktuur',
'Alter schema' => 'Muuda struktuuri',
'Create schema' => 'Loo struktuur',
@@ -266,55 +266,4 @@ $translations = array(
'Permanent link' => 'Püsilink',
'Edit all' => 'Muuda kõiki',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'سیستم',
'Server' => 'سرور',
'Username' => 'نام کاربری',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'خروج',
'Logged as: %s' => 'ورود به عنوان: %s',
'Logout successful.' => 'با موفقیت خارج شدید.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'اعتبار سنجی نامعتبر.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('ورودهای ناموفق بیش از حد، %d دقیقه دیگر تلاش نمایید.', 'ورودهای ناموفق بیش از حد، %d دقیقه دیگر تلاش نمایید.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'رمز اصلی باطل شده است. روش %s را <a href="https://www.adminer.org/en/extension/"%s>پیاده سازی</a> کرده تا آن را دائمی سازید.',
'Language' => 'زبان',
@@ -145,7 +146,7 @@ $translations = array(
'Tables' => 'جدولها',
'Tables and views' => 'جدولها و نمایه ها',
'Table' => 'جدول',
'No tables.' => 'جدولی وجود ندارد',
'No tables.' => 'جدولی وجود ندارد.',
'Alter table' => 'ویرایش جدول',
'Create table' => 'ایجاد جدول',
'Table has been dropped.' => 'جدول حذف شد.',
@@ -164,6 +165,7 @@ $translations = array(
'Options' => 'اختیارات',
'Comment' => 'توضیح',
'Default value' => 'مقدار پیش فرض',
'Default values' => 'مقادیر پیش فرض',
'Drop' => 'حذف',
'Are you sure?' => 'مطمئن هستید؟',
'Size' => 'حجم',
@@ -174,7 +176,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'حداکثر تعداد فیلدهای مجاز اشباع شد. لطفا %s را افزایش دهید.',
'Partition by' => 'بخشبندی توسط',
'Partition' => null,
'Partitions' => 'بخشبندیها',
'Partition name' => 'نام بخش',
'Values' => 'مقادیر',
@@ -192,7 +193,7 @@ $translations = array(
'Alter indexes' => 'ویرایش ایندکسها',
'Add next' => 'افرودن بعدی',
'Index Type' => 'نوع ایندکس',
'Column (length)' => 'ستون (طول)',
'length' => 'طول',
'Foreign keys' => 'کلیدهای خارجی',
'Foreign key' => 'کلید خارجی',
@@ -229,7 +230,6 @@ $translations = array(
'Search' => 'جستجو',
'anywhere' => 'هرکجا',
'Search data in tables' => 'جستجوی داده در جدول',
'as a regular expression' => null,
'Sort' => 'مرتب کردن',
'descending' => 'نزولی',
'Limit' => 'محدودیت',
@@ -238,7 +238,7 @@ $translations = array(
'Action' => 'عملیات',
'Full table scan' => 'اسکن کامل جدول',
'Unable to select the table' => 'قادر به انتخاب جدول نیستید',
'No rows.' => 'سطری وجود ندارد',
'No rows.' => 'سطری وجود ندارد.',
'%d / ' => '%d / ',
'%d row(s)' => array('%d سطر', '%d سطر'),
'Page' => 'صفحه',
@@ -332,34 +332,4 @@ $translations = array(
'Type has been dropped.' => 'نوع حذف شد.',
'Type has been created.' => 'نوع ایجاد شد.',
'Alter type' => 'ویرایش نوع',
'Drop %s?' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Järjestelmä',
'Server' => 'Palvelin',
'Username' => 'Käyttäjänimi',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Kirjaudu ulos',
'Logged as: %s' => 'Olet kirjautunut käyttäjänä: %s',
'Logout successful.' => 'Uloskirjautuminen onnistui.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Virheelliset kirjautumistiedot.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Liian monta epäonnistunutta sisäänkirjautumisyritystä, kokeile uudestaan %d minuutin kuluttua.', 'Liian monta epäonnistunutta sisäänkirjautumisyritystä, kokeile uudestaan %d minuutin kuluttua.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Master-salasana ei ole enää voimassa. <a href="https://www.adminer.org/en/extension/"%s>Toteuta</a> %s-metodi sen tekemiseksi pysyväksi.',
'Language' => 'Kieli',
@@ -166,6 +167,7 @@ $translations = array(
'Options' => 'Asetukset',
'Comment' => 'Kommentit',
'Default value' => 'Oletusarvo',
'Default values' => 'Oletusarvot',
'Drop' => 'Poista',
'Are you sure?' => 'Oletko varma?',
'Size' => 'Koko',
@@ -176,7 +178,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Kenttien sallittu enimmäismäärä ylitetty. Kasvata arvoa %s.',
'Partition by' => 'Osioi arvolla',
'Partition' => null,
'Partitions' => 'Osiot',
'Partition name' => 'Osion nimi',
'Values' => 'Arvot',
@@ -194,7 +195,7 @@ $translations = array(
'Alter indexes' => 'Muuta indeksejä',
'Add next' => 'Lisää seuraava',
'Index Type' => 'Indeksityyppi',
'Column (length)' => 'Sarake (pituus)',
'length' => 'pituus',
'Foreign keys' => 'Vieraat avaimet',
'Foreign key' => 'Vieras avain',
@@ -231,7 +232,6 @@ $translations = array(
'Search' => 'Hae',
'anywhere' => 'kaikkialta',
'Search data in tables' => 'Hae dataa tauluista',
'as a regular expression' => null,
'Sort' => 'Lajittele',
'descending' => 'alenevasti',
'Limit' => 'Raja',
@@ -348,18 +348,4 @@ $translations = array(
'Unknown error.' => 'Tuntematon virhe.',
'Database does not support password.' => 'Tietokanta ei tue salasanaa.',
'Disable %s or enable %s or %s extensions.' => 'Poista käytöstä %s tai ota käyttöön laajennus %s tai %s.',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Kyllä',
'No' => 'Ei',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Authentification',
'Logout successful.' => 'Au revoir !',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Authentification échouée.',
'Server' => 'Serveur',
'Username' => 'Utilisateur',
'Password' => 'Mot de passe',
@@ -67,6 +68,7 @@ $translations = array(
'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.',
'Comment' => 'Commentaire',
'Default values' => 'Valeurs par défaut',
'%d byte(s)' => array('%d octet', '%d octets'),
'No commands to execute.' => 'Aucune commande à exécuter.',
'Unable to upload a file.' => 'Impossible d\'importer le fichier.',
@@ -93,7 +95,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Type d\'index',
'Column (length)' => 'Colonne (longueur)',
'length' => 'longueur',
'View has been dropped.' => 'La vue a été effacée.',
'View has been altered.' => 'La vue a été modifiée.',
'View has been created.' => 'La vue a été créée.',
@@ -187,7 +189,6 @@ $translations = array(
'Clone' => 'Cloner',
'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' => null,
'Partitions' => 'Partitions',
'Partition name' => 'Nom de la partition',
'Values' => 'Valeurs',
@@ -223,7 +224,6 @@ $translations = array(
'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.',
'Search data in tables' => 'Rechercher dans les tables',
'as a regular expression' => 'sous forme d\'expression régulière',
'Schema' => 'Schéma',
'Alter schema' => 'Modifier le schéma',
'Create schema' => 'Créer un schéma',
@@ -289,32 +289,16 @@ $translations = array(
'Default value' => 'Valeur par défaut',
'If you did not send this request from Adminer then close this page.' => 'Si vous n\'avez pas envoyé cette requête depuis Adminer, alors fermez cette page.',
'You are offline.' => 'Vous êtes hors ligne.',
'Drop %s?' => 'Supprimer %s?',
'overwrite' => 'écraser',
'DB' => 'BD',
'ATTACH queries are not supported.' => 'Requêtes ATTACH ne sont pas supportées.',
'Warnings' => 'Avertissements',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer ne supporte pas l\'accès aux bases de données sans mot de passe, <a href="https://www.adminer.org/en/password/"%s>plus d\'information</a>.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => 'Cette action sera exécutée après s\'être connecté avec les mêmes données de connexion.',
'Connecting to privileged ports is not allowed.' => 'La connexion aux ports privilégiés n\'est pas autorisée.',
'There is a space in the input password which might be the cause.' => 'Il y a un espace dans le mot de passe entré qui pourrait en être la cause.',
'Unknown error.' => 'Erreur inconnue',
'Database does not support password.' => 'La base de données ne support pas les mots de passe',
'Unknown error.' => 'Erreur inconnue.',
'Database does not support password.' => 'La base de données ne support pas les mots de passe.',
'Disable %s or enable %s or %s extensions.' => 'Désactiver %s ou activer %s or %s extensions.',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Oui',
'No' => 'Non',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Conectar',
'Logout successful.' => 'Pechouse a sesión con éxito.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Credenciais (usuario e/ou contrasinal) inválidos.',
'Server' => 'Servidor',
'Username' => 'Usuario',
'Password' => 'Contrasinal',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Comentario',
'Default values' => 'Valores predeterminados',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Non hai comandos para executar.',
'Unable to upload a file.' => 'Non é posible importar o ficheiro.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'AO BORRAR (ON DELETE)',
'ON UPDATE' => 'AO ACTUALIZAR (ON UPDATE)',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'Columna (lonxitude)',
'length' => 'lonxitude',
'View has been dropped.' => 'Eliminouse a vista.',
'View has been altered.' => 'Modificouse a vista.',
'View has been created.' => 'Creouse a vista.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'Clonar',
'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' => null,
'Partitions' => 'Particións',
'Partition name' => 'Nome da Partición',
'Values' => 'Valores',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Permanecer conectado',
'Databases have been dropped.' => 'Elimináronse as bases de datos.',
'Search data in tables' => 'Buscar datos en táboas',
'as a regular expression' => null,
'Schema' => 'Esquema',
'Alter schema' => 'Modificar esquema',
'Create schema' => 'Crear esquema',
@@ -266,11 +266,11 @@ $translations = array(
'Permanent link' => 'Ligazón permanente',
'Edit all' => 'Editar todo',
'HH:MM:SS' => 'HH:MM:SS',
'Tables have been optimized.' => 'Optimizáronse as táboas',
'Tables have been optimized.' => 'Optimizáronse as táboas.',
'Materialized view' => 'Vista materializada',
'Vacuum' => 'Baleirar',
'Selected' => 'Selección',
'File must be in UTF-8 encoding.' => 'O ficheiro ten que estar codificado con UTF-8',
'File must be in UTF-8 encoding.' => 'O ficheiro ten que estar codificado con UTF-8.',
'Modify' => 'Modificar',
'Loading' => 'Cargando',
'Load more data' => 'Cargar máis datos',
@@ -278,43 +278,15 @@ $translations = array(
'Limit rows' => 'Limitar filas',
'Default value' => 'Valor por defecto',
'Full table scan' => 'Escaneo completo da táboa',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Demasiados intentos de conexión, intentao de novo en %d minuto', 'Demasiados intentos de conexión, intentao de novo en %d minutos'),
'Too many unsuccessful logins, try again in %d minute(s).' => array('Demasiados intentos de conexión, intentao de novo en %d minuto.', 'Demasiados intentos de conexión, intentao de novo en %d minutos.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'O contrasinal principal caducou. <a href="https://www.adminer.org/en/extension/"%s>Implementa</a> o método %s para facelo permanente.',
'If you did not send this request from Adminer then close this page.' => 'Se non enviaches esta petición dende o Adminer entón pecha esta páxina',
'You can upload a big SQL file via FTP and import it from server.' => 'Podes subir un ficheiro SQL de gran tamaño vía FTP e importalo dende o servidor',
'If you did not send this request from Adminer then close this page.' => 'Se non enviaches esta petición dende o Adminer entón pecha esta páxina.',
'You can upload a big SQL file via FTP and import it from server.' => 'Podes subir un ficheiro SQL de gran tamaño vía FTP e importalo dende o servidor.',
'Size' => 'Tamaño',
'Compute' => 'Calcular',
'You are offline.' => 'Non tes conexión',
'You have no privileges to update this table.' => 'Non tes privilexios para actualizar esta táboa',
'You are offline.' => 'Non tes conexión.',
'You have no privileges to update this table.' => 'Non tes privilexios para actualizar esta táboa.',
'Saving' => 'Gardando',
'yes' => 'si',
'no' => 'non',
'Drop %s?' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Si',
'No' => 'Non',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'התחברות',
'Logout successful.' => 'ההתחברות הצליחה',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'פרטי התחברות שגויים',
'Server' => 'שרת',
'Username' => 'שם משתמש',
'Password' => 'סיסמה',
@@ -67,6 +68,7 @@ $translations = array(
'Unable to select the table' => 'בחירת הטבלה נכשלה',
'Invalid CSRF token. Send the form again.' => 'כשל באבטחת נתונים, שלח טופס שוב',
'Comment' => 'הערה',
'Default values' => 'ערכי ברירת מחדל',
'%d byte(s)' => '%d בתים',
'No commands to execute.' => 'לא נמצאו פקודות להרצה',
'Unable to upload a file.' => 'העלאת הקובץ נכשלה',
@@ -93,7 +95,7 @@ $translations = array(
'ON DELETE' => 'בעת מחיקה',
'ON UPDATE' => 'בעת עידכון',
'Index Type' => 'סוג אינדקס',
'Column (length)' => 'עמודה (אורך)',
'length' => 'אורך',
'View has been dropped.' => 'התצוגה הושלכה',
'View has been altered.' => 'התצוגה שונתה',
'View has been created.' => 'התצוגה נוצרה',
@@ -187,7 +189,6 @@ $translations = array(
'Clone' => 'שכפל',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'הגעת למספר השדות המרבי. בבקשה הגדל את %s',
'Partition by' => 'מחיצות ע"י',
'Partition' => null,
'Partitions' => 'מחיצות',
'Partition name' => 'שם מחיצה',
'Values' => 'ערכים',
@@ -223,7 +224,6 @@ $translations = array(
'Databases have been dropped.' => 'מסד הנתונים הושלך',
'Database has been dropped.' => 'מסד הנתונים הושלך',
'Search data in tables' => 'חפש מידע בטבלאות',
'as a regular expression' => null,
'Schema' => 'סכמה',
'Alter schema' => 'שנה סכמה',
'Create schema' => 'צור סכמה',
@@ -280,7 +280,7 @@ $translations = array(
'Default value' => 'ערך ברירת מחדל',
'Full table scan' => 'סריקה טבלה מלאה',
'Too many unsuccessful logins, try again in %d minute(s).' => 'יותר מידי נסיונות כניסה נכשלו, אנא נסה עוד %d דקות',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'תודה שהשתמש ב-adminer אנא שקול <a href="https://www.adminer.org/en/donation/">לתרום</a>.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'תודה שהשתמש ב-adminer אנא שקול <a href="https://www.adminer.org/en/donation/">לתרום</a>',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'סיסמת המאסטר פגה <a href="https://www.adminer.org/en/extension/"%s>התקן תוסף</a> על מנת להפוך את זה לתמידי',
'If you did not send this request from Adminer then close this page.' => 'אם לא אתה שלחת בקשה ל-Adminer הינך יכול לסגור חלון זה',
'You can upload a big SQL file via FTP and import it from server.' => 'ניתן לעלות קבצים ב-FTP ואז למשוך אותם מהשרת',
@@ -291,30 +291,4 @@ $translations = array(
'Saving' => 'שומר',
'yes' => 'כן',
'no' => 'לא',
'Drop %s?' => null,
'overwrite' => null,
'DB' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Belépés',
'Logout successful.' => 'Sikeres kilépés.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Érvénytelen adatok.',
'Server' => 'Szerver',
'Username' => 'Felhasználó',
'Password' => 'Jelszó',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Megjegyzés',
'Default values' => 'Alapértelmezett értékek',
'%d byte(s)' => array('%d bájt', '%d bájt', '%d bájt'),
'No commands to execute.' => 'Nincs végrehajtható parancs.',
'Unable to upload a file.' => 'Nem tudom feltölteni a fájlt.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'törléskor',
'ON UPDATE' => 'frissítéskor',
'Index Type' => 'Index típusa',
'Column (length)' => 'Oszop (méret)',
'length' => 'méret',
'View has been dropped.' => 'A nézet eldobva.',
'View has been altered.' => 'A nézet módosult.',
'View has been created.' => 'A nézet létrejött.',
@@ -188,7 +190,6 @@ $translations = array(
'Tables have been dropped.' => 'Táblák eldobva.',
'Clone' => 'Klónoz',
'Partition by' => 'Particionálás ezzel',
'Partition' => null,
'Partitions' => 'Particiók',
'Partition name' => 'Partició neve',
'Values' => 'Értékek',
@@ -250,7 +251,6 @@ $translations = array(
'Type has been created.' => 'Típus létrehozva.',
'Alter type' => 'Típus módosítása',
'Search data in tables' => 'Keresés a táblákban',
'as a regular expression' => null,
'From server' => 'Szerverről',
'empty' => 'üres',
'now' => 'most',
@@ -265,56 +265,4 @@ $translations = array(
'Permanent link' => 'Hivatkozás',
'Edit all' => 'Összes szerkesztése',
'HH:MM:SS' => 'óó:pp:mm',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem',
'Server' => 'Server',
'Username' => 'Pengguna',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Keluar',
'Logged as: %s' => 'Masuk sebagai: %s',
'Logout successful.' => 'Berhasil keluar.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Akses tidak sah.',
'Language' => 'Bahasa',
'Invalid CSRF token. Send the form again.' => 'Token CSRF tidak sah. Kirim ulang formulir.',
'No extension' => 'Ekstensi tidak ada',
@@ -158,6 +159,7 @@ $translations = array(
'Auto Increment' => 'Inkrementasi Otomatis',
'Options' => 'Opsi',
'Comment' => 'Komentar',
'Default values' => 'Nilai bawaan',
'Drop' => 'Hapus',
'Are you sure?' => 'Anda yakin?',
'Move up' => 'Naik',
@@ -166,7 +168,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Sudah lebih dumlah ruas maksimum yang diizinkan. Harap naikkan %s.',
'Partition by' => 'Partisi menurut',
'Partition' => null,
'Partitions' => 'Partisi',
'Partition name' => 'Nama partisi',
'Values' => 'Nilai',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Ubah indeks',
'Add next' => 'Tambah setelahnya',
'Index Type' => 'Jenis Indeks',
'Column (length)' => 'Kolom (panjang)',
'length' => 'panjang',
'Foreign keys' => 'Kunci asing',
'Foreign key' => 'Kunci asing',
@@ -220,7 +221,6 @@ $translations = array(
'Search' => 'Cari',
'anywhere' => 'di mana pun',
'Search data in tables' => 'Cari data dalam tabel',
'as a regular expression' => null,
'Sort' => 'Urutkan',
'descending' => 'menurun',
'Limit' => 'Batas',
@@ -314,52 +314,4 @@ $translations = array(
'Type has been dropped.' => 'Jenis berhasil dihapus.',
'Type has been created.' => 'Jenis berhasil dibuat.',
'Alter type' => 'Ubah jenis',
'Drop %s?' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Autenticazione',
'Logout successful.' => 'Uscita effettuata con successo.',
'Invalid server or credentials.' => 'Server o credenziali non valide.',
'Invalid credentials.' => 'Credenziali non valide.',
'Server' => 'Server',
'Username' => 'Utente',
'Password' => 'Password',
@@ -69,6 +70,7 @@ $translations = array(
'Unable to select the table' => 'Selezione della tabella non riuscita',
'Invalid CSRF token. Send the form again.' => 'Token CSRF non valido. Reinvia la richiesta.',
'Comment' => 'Commento',
'Default values' => 'Valori predefiniti',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Nessun commando da eseguire.',
'Unable to upload a file.' => 'Caricamento del file non riuscito.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipo indice',
'Column (length)' => 'Colonna (lunghezza)',
'length' => 'lunghezza',
'View has been dropped.' => 'Vista eliminata.',
'View has been altered.' => 'Vista modificata.',
'View has been created.' => 'Vista creata.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'Clona',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Troppi campi. Per favore aumentare %s.',
'Partition by' => 'Partiziona per',
'Partition' => null,
'Partitions' => 'Partizioni',
'Partition name' => 'Nome partizione',
'Values' => 'Valori',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Login permanente',
'Databases have been dropped.' => 'Database eliminati.',
'Search data in tables' => 'Cerca nelle tabelle',
'as a regular expression' => 'come espressione regolare',
'Schema' => 'Schema',
'Alter schema' => 'Modifica schema',
'Create schema' => 'Crea schema',
@@ -266,9 +266,8 @@ $translations = array(
'Permanent link' => 'Link permanente',
'Edit all' => 'Modifica tutto',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => 'Scartare %s?',
'Tables have been optimized.' => 'Le tabelle sono state ottimizzate',
'Tables have been optimized.' => 'Le tabelle sono state ottimizzate.',
'Materialized view' => 'Vista materializzata',
'Vacuum' => 'Aspira',
'Selected' => 'Selezionato',
@@ -280,13 +279,12 @@ $translations = array(
'Loading' => 'Caricamento',
'ATTACH queries are not supported.' => 'ATTACH queries non sono supportate.',
'Warnings' => 'Attenzione',
'%d / ' => array('%d / '),
'%d / ' => '%d / ',
'Limit rows' => 'Limite righe',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer non supporta accesso a databse senza password, <a href="https://www.adminer.org/it/password/"%s>piú informazioni</a>.',
'Default value' => 'Valore predefinito',
'Full table scan' => 'Analizza intera tabella',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Troppi tentativi infruttuosi di login, si prega di riprovare in %d minuto.', 'Troppi tentativi infruttuosi di login, si prega di riprovare in %d minuti.'),
'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.' => 'La password principale é scaduta. <a href="https://www.adminer.org/it/extension/"%s>Implementare</a> %s come metodo per renderla permanente.',
'The action will be performed after successful login with the same credentials.' => 'La azione verrá eseguita dopo un login valido con le stesse credenziali.',
'Connecting to privileged ports is not allowed.' => 'LA connessione a porte privilegiate non é permessa.',
@@ -298,23 +296,9 @@ $translations = array(
'You are offline.' => 'Sei disconnesso.',
'You have no privileges to update this table.' => 'Non hai i privilegi per aggiornare questa tabella.',
'Saving' => 'Salvataggio',
'Unknown error.' => 'Errore sconosciuto',
'Unknown error.' => 'Errore sconosciuto.',
'Database does not support password.' => 'Il database non supporta password.',
'Disable %s or enable %s or %s extensions.' => 'Disabilita %s o abilita %s oppure %s estensioni.',
'yes' => 'si',
'no' => 'no',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Si',
'No' => 'No',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'ログイン',
'Logout successful.' => 'ログアウト',
'Invalid server or credentials.' => null,
'Invalid credentials.' => '不正なログイン',
'Server' => 'サーバ',
'Username' => 'ユーザ名',
'Password' => 'パスワード',
@@ -68,6 +69,7 @@ $translations = array(
'Unable to select the table' => 'テーブルを選択できません',
'Invalid CSRF token. Send the form again.' => '不正なCSRFトークン。再送信してください',
'Comment' => 'コメント',
'Default values' => '規定値',
'%d byte(s)' => '%d バイト',
'No commands to execute.' => '実行するコマンドがありません',
'Unable to upload a file.' => 'ファイルをアップロードできません',
@@ -94,7 +96,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => '索引の型',
'Column (length)' => '列(長さ',
'length' => '長さ',
'View has been dropped.' => 'ビューを削除しました',
'View has been altered.' => 'ビューを変更しました',
'View has been created.' => 'ビューを作成しました',
@@ -188,7 +190,6 @@ $translations = array(
'Clone' => 'クローン',
'Maximum number of allowed fields exceeded. Please increase %s.' => '定義可能な最大フィールド数を越えました。%s を増やしてください。',
'Partition by' => 'パーティション',
'Partition' => null,
'Partitions' => 'パーティション',
'Partition name' => 'パーティション名',
'Values' => '値',
@@ -225,7 +226,6 @@ $translations = array(
'Permanent login' => '永続的にログイン',
'Databases have been dropped.' => 'データベースを削除しました',
'Search data in tables' => 'データを検索する',
'as a regular expression' => null,
'Schema' => 'スキーマ',
'Alter schema' => 'スキーマ変更',
'Create schema' => 'スキーマ追加',
@@ -275,46 +275,4 @@ $translations = array(
'yes' => 'はい',
'no' => 'いいえ',
'Default value' => '既定値',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'შესვლა',
'Logout successful.' => 'გამოხვედით სისტემიდან.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'არასწორი მომხმარებელი ან პაროლი.',
'Server' => 'სერვერი',
'Username' => 'მომხმარებელი',
'Password' => 'პაროლი',
@@ -68,6 +69,7 @@ $translations = array(
'Unable to select the table' => 'ცხრილიდან ინფორმაცია ვერ მოვიპოვე',
'Invalid CSRF token. Send the form again.' => 'უმოქმედო CSRF-ტოკენი. ფორმის კიდევ ერთხელ გაგზავნა.',
'Comment' => 'კომენტარები',
'Default values' => 'სტანდარტული მნიშვნელობა',
'%d byte(s)' => '%d ბაიტი',
'No commands to execute.' => 'შესასრულებელი ბრძანება არაა.',
'Unable to upload a file.' => 'ფაილი არ აიტვირთა სერვერზე.',
@@ -93,7 +95,7 @@ $translations = array(
'ON DELETE' => 'წაშლისას',
'ON UPDATE' => 'განახლებისას',
'Index Type' => 'ინდექსის სახეობა',
'Column (length)' => 'ველი (სიგრძე)',
'length' => 'სიგრძე',
'View has been dropped.' => 'წარმოდგენა წაიშალა.',
'View has been altered.' => 'წარმოდგენა შეიცვალა.',
'View has been created.' => 'წარმოდგენა შეიქმნა.',
@@ -186,7 +188,6 @@ $translations = array(
'Tables have been dropped.' => 'ცხრილები წაიშალა.',
'Clone' => 'კლონირება',
'Partition by' => 'დაყოფა',
'Partition' => null,
'Partitions' => 'დანაყოფები',
'Partition name' => 'დანაყოფის სახელი',
'Values' => 'პარამეტრები',
@@ -220,7 +221,6 @@ $translations = array(
'Permanent login' => 'სისტემაში დარჩენა',
'Databases have been dropped.' => 'ბაზა წაიშალა.',
'Search data in tables' => 'ცხრილებში ძებნა',
'as a regular expression' => null,
'Schema' => 'სქემა',
'Alter schema' => 'სქემის შეცვლა',
'Create schema' => 'ახალი სქემა',
@@ -301,20 +301,4 @@ $translations = array(
'Unknown error.' => 'უცნობი შეცდომა.',
'Database does not support password.' => 'ბაზაში არაა მხარდაჭერილი პაროლი.',
'Disable %s or enable %s or %s extensions.' => 'გათიშეთ %s ან ჩართეთ %s ან %s გაფართოება.',
'overwrite' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => 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
namespace Adminer;
$translations = array(
'Home' => null,
'$1-$3-$5' => '$1-$3-$5',
'%.3f s' => '%.3f 초',
'%d byte(s)' => '%d 바이트',
@@ -47,7 +48,7 @@ $translations = array(
'Clone' => '복제',
'collation' => '정렬',
'Collation' => '정렬',
'Column (length)' => '열 (길이)',
'length' => '길이',
'Column name' => '열 이름',
'Column' => '열',
'Comment' => '주석',
@@ -75,6 +76,7 @@ $translations = array(
'Database' => '데이터베이스',
'Databases have been dropped.' => '데이터베이스를 삭제했습니다.',
'Date and time' => '시간',
'Default values' => '기본값',
'Delete' => '삭제',
'descending' => '역순',
'Drop' => '삭제',
@@ -120,7 +122,7 @@ $translations = array(
'Indexes have been altered.' => '색인을 변경했습니다.',
'Indexes' => '색인',
'Insert' => '삽입',
'Invalid server or credentials.' => null,
'Invalid credentials.' => '잘못된 로그인.',
'Invalid CSRF token. Send the form again.' => '잘못된 CSRF 토큰입니다. 다시 보내주십시오.',
'Invalid database.' => '잘못된 데이터베이스입니다.',
'Invalid schema.' => '잘못된 스키마입니다.',
@@ -141,7 +143,7 @@ $translations = array(
'Logout successful.' => '로그아웃을 성공했습니다.',
'Logout' => '로그아웃',
'ltr' => 'ltr',
'Maximum allowed file size is %sB.' => '파일의 최대 크기 %sB',
'Maximum allowed file size is %sB.' => '파일의 최대 크기 %sB.',
'Maximum number of allowed fields exceeded. Please increase %s.' => '정의 가능한 최대 필드 수를 초과했습니다. %s(을)를 늘리십시오.',
'Modify' => '수정',
'Move down' => '아래로',
@@ -152,7 +154,7 @@ $translations = array(
'Network' => '네트워크 형',
'New item' => '항목 만들기',
'No commands to execute.' => '실행할 수 있는 명령이 없습니다.',
'No extension' => '확장이 없습니다.',
'No extension' => '확장이 없습니다',
'No rows.' => '행이 없습니다.',
'No tables.' => '테이블이 없습니다.',
'None of the supported PHP extensions (%s) are available.' => 'PHP 확장(%s)이 설치되어 있지 않습니다.',
@@ -171,7 +173,6 @@ $translations = array(
'Parameter name' => '매개변수 이름',
'Partition by' => '파티션',
'Partition name' => '파티션 이름',
'Partition' => null,
'Partitions' => '파티션',
'Password' => '비밀번호',
'Permanent link' => '영구적으로 링크',
@@ -204,10 +205,9 @@ $translations = array(
'Schema has been dropped.' => '스키마를 삭제했습니다.',
'Schema' => '스키마',
'Search data in tables' => '테이블 내 데이터 검색',
'as a regular expression' => null,
'Search' => '검색',
'Select data' => '데이터를 선택하십시오.',
'Select database' => '데이터베이스를 선택하십시오.',
'Select data' => '데이터를 선택하십시오',
'Select database' => '데이터베이스를 선택하십시오',
'Select' => '선택',
'select' => '선택',
'Selected' => '선택됨',
@@ -238,7 +238,7 @@ $translations = array(
'Table name' => '테이블 이름',
'Table' => '테이블',
'Tables and views' => '테이블과 뷰',
'Tables have been copied.' => '테이블을 복사했습니다',
'Tables have been copied.' => '테이블을 복사했습니다.',
'Tables have been dropped.' => '테이블을 삭제했습니다.',
'Tables have been moved.' => '테이블을 옮겼습니다.',
'Tables have been truncated.' => '테이블의 데이터 내용만 지웠습니다.',
@@ -256,7 +256,7 @@ $translations = array(
'Type has been created.' => '유형을 추가했습니다.',
'Type has been dropped.' => '유형을 삭제했습니다.',
'Type' => '형',
'Unable to select the table' => '테이블을 선택할 수 없습니다.',
'Unable to select the table' => '테이블을 선택할 수 없습니다',
'Unable to upload a file.' => '파일을 업로드 할 수 없습니다.',
'Use edit link to modify this value.' => '이 값을 수정하려면 편집 링크를 사용하십시오.',
'Use' => '사용',
@@ -278,43 +278,4 @@ $translations = array(
'You are offline.' => '오프라인입니다.',
'You can upload a big SQL file via FTP and import it from server.' => '큰 SQL 파일은 FTP를 통하여 업로드하여 서버에서 가져올 수 있습니다.',
'You have no privileges to update this table.' => '이 테이블을 업데이트할 권한이 없습니다.',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'User types' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'ATTACH queries are not supported.' => null,
'%d / ' => array(),
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistema',
'Server' => 'Serveris',
'Username' => 'Vartotojas',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Atsijungti',
'Logged as: %s' => 'Prisijungęs kaip: %s',
'Logout successful.' => 'Jūs atsijungėte nuo sistemos.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Neteisingi prisijungimo duomenys.',
'Language' => 'Kalba',
'Invalid CSRF token. Send the form again.' => 'Neteisingas CSRF tokenas. Bandykite siųsti formos duomenis dar kartą.',
'No extension' => 'Nėra plėtiio',
@@ -157,6 +158,7 @@ $translations = array(
'Auto Increment' => 'Auto Increment',
'Options' => 'Nustatymai',
'Comment' => 'Komentaras',
'Default values' => 'Reikšmės pagal nutylėjimą',
'Drop' => 'Pašalinti',
'Are you sure?' => 'Tikrai?',
'Move up' => 'Perkelti į viršų',
@@ -165,7 +167,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Viršytas maksimalus leidžiamų stulpelių kiekis. Padidinkite %s.',
'Partition by' => 'Skirstyti pagal',
'Partition' => null,
'Partitions' => 'Skirsniai',
'Partition name' => 'Skirsnio pavadinimas',
'Values' => 'Reikšmės',
@@ -182,7 +183,7 @@ $translations = array(
'Alter indexes' => 'Redaguoti indeksus',
'Add next' => 'Pridėti kitą',
'Index Type' => 'Indekso tipas',
'Column (length)' => 'Stulpelis (ilgis)',
'length' => 'ilgis',
'Foreign keys' => 'Išoriniai raktai',
'Foreign key' => 'Išorinis raktas',
@@ -219,7 +220,6 @@ $translations = array(
'Search' => 'Ieškoti',
'anywhere' => 'visur',
'Search data in tables' => 'Ieškoti duomenų lentelėse',
'as a regular expression' => null,
'Sort' => 'Rikiuoti',
'descending' => 'mažėjimo tvarka',
'Limit' => 'Limitas',
@@ -310,56 +310,4 @@ $translations = array(
'Type has been dropped.' => 'Tipas pašalintas.',
'Type has been created.' => 'Tipas sukurtas.',
'Alter type' => 'Keisti tipą',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Ieiet',
'Logout successful.' => 'Jūs veiksmīgi izgājāt no sistēmas.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Nepareizs lietotāja vārds vai parole.',
'Server' => 'Serveris',
'Username' => 'Lietotājs',
'Password' => 'Parole',
@@ -37,7 +38,7 @@ $translations = array(
'select' => 'izvēlēties',
'Item has been deleted.' => 'Ieraksts dzests.',
'Item has been updated.' => 'Ieraksts atjaunots.',
'Item%s has been inserted.' => 'Ieraksti tika ievietoti.',
'Item%s has been inserted.' => 'Ieraksti%s tika ievietoti.',
'Edit' => 'Rediģēt',
'Insert' => 'Ievietot',
'Save and insert next' => 'Saglabāt un ievietot nākamo',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Komentārs',
'Default values' => 'Noklusētā vērtība',
'%d byte(s)' => array('%d baits', '%d baiti', '%d baiti'),
'No commands to execute.' => 'Nav izpildāmu komandu.',
'Unable to upload a file.' => 'Neizdevās ielādēt failu uz servera.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'Pie dzēšanas',
'ON UPDATE' => 'Pie atjaunošanas',
'Index Type' => 'Indeksa tips',
'Column (length)' => 'Lauks (garums)',
'length' => 'garums',
'View has been dropped.' => 'Skats dzēsts.',
'View has been altered.' => 'Skats izmainīts.',
'View has been created.' => 'Skats izveidots.',
@@ -188,7 +190,6 @@ $translations = array(
'Tables have been dropped.' => 'Tabulas dzēstas.',
'Clone' => 'Klonēt',
'Partition by' => 'Sadalīt pēc',
'Partition' => null,
'Partitions' => 'Partīcijas',
'Partition name' => 'Partīcijas nosaukums',
'Values' => 'Vērtības',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Atcerēties mani',
'Databases have been dropped.' => 'Datubāzes dzēstas.',
'Search data in tables' => 'Meklēt tabulās',
'as a regular expression' => null,
'Schema' => 'Shēma',
'Alter schema' => 'Izmainīt shēmu',
'Create schema' => 'Jauna shēma',
@@ -286,10 +286,10 @@ $translations = array(
'Size' => 'Izmērs',
'Compute' => 'Izskaitļot',
'You are offline.' => 'Jūs est bezsasaistē.',
'You have no privileges to update this table.' => 'Jums nav pieejas labot šo tabulu.',
'You have no privileges to update this table.' => 'jums nav pieejas labot šo tabulu.',
'Saving' => 'Saglabāšana',
'yes' => 'jā',
'no' => 'nē',
'yes' => 'Jā',
'no' => 'Nē',
'Drop %s?' => 'Dzēst %s?',
'overwrite' => 'pārrakstīt',
'DB' => 'DB',
@@ -301,20 +301,4 @@ $translations = array(
'There is a space in the input password which might be the cause.' => 'Parole satur atstarpi, kas varētu būt lieka.',
'Unknown error.' => 'Nezināma kļūda.',
'Database does not support password.' => 'Datubāze neatbalsta paroli.',
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Jā',
'No' => 'Nē',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem',
'Server' => 'Pelayan',
'Username' => 'Nama pengguna',
@@ -12,7 +13,7 @@ $translations = array(
'Logged as: %s' => 'Log masuk sebagai: %s',
'Logout successful.' => 'Log keluar berjaya.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Terima kasih kerana menggunakan Adminer, pertimbangkan untuk <a href="https://www.adminer.org/en/donation/">menderma</a>.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Akses tidak sah.',
'Too many unsuccessful logins, try again in %d minute(s).' => 'Terlalu banyak percubaan log masuk yang gagal, sila cuba lagi dalam masa %d minit.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Kata laluan utama telah luput. <a href="https://www.adminer.org/en/extension/"%s>Gunakan</a> cara %s untuk mengekalkannya.',
'Language' => 'Bahasa',
@@ -169,6 +170,7 @@ $translations = array(
'Options' => 'Pilihan',
'Comment' => 'Komen',
'Default value' => 'Nilai lalai',
'Default values' => 'Nilai lalai',
'Drop' => 'Jatuh',
'Drop %s?' => 'Jatuhkan %s?',
'Are you sure?' => 'Anda pasti?',
@@ -180,7 +182,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Bilangan medan telah melebihi had yang dibenarkan. Sila tingkatkan %s.',
'Partition by' => 'Partition mengikut',
'Partition' => null,
'Partitions' => 'Partition',
'Partition name' => 'Nama partition',
'Values' => 'Nilai',
@@ -198,7 +199,7 @@ $translations = array(
'Alter indexes' => 'Ubah indeks',
'Add next' => 'Tambah yang seterusnya',
'Index Type' => 'Jenis Indeks',
'Column (length)' => 'Kolum (kepanjangan)',
'length' => 'kepanjangan',
'Foreign keys' => 'Kunci asing',
'Foreign key' => 'Kunci asing',
@@ -235,7 +236,6 @@ $translations = array(
'Search' => 'Cari',
'anywhere' => 'di mana-mana',
'Search data in tables' => 'Cari data dalam jadual',
'as a regular expression' => null,
'Sort' => 'Susun',
'descending' => 'menurun',
'Limit' => 'Had',
@@ -338,28 +338,4 @@ $translations = array(
'Type has been dropped.' => 'Jenis telah dijatuhkan.',
'Type has been created.' => 'Jenis telah dibuat.',
'Alter type' => 'Ubah jenis',
'overwrite' => null,
'DB' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Ya',
'No' => 'Tidak',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Aanmelden',
'Logout successful.' => 'Successvol afgemeld.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Ongeldige gebruikersgegevens.',
'Server' => 'Server',
'Username' => 'Gebruikersnaam',
'Password' => 'Wachtwoord',
@@ -70,6 +71,7 @@ $translations = array(
'Unable to select the table' => 'Onmogelijk tabel te selecteren',
'Invalid CSRF token. Send the form again.' => 'Ongeldig CSRF token. Verstuur het formulier opnieuw.',
'Comment' => 'Commentaar',
'Default values' => 'Standaard waarden',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Geen opdrachten uit te voeren.',
'Unable to upload a file.' => 'Onmogelijk bestand te uploaden.',
@@ -96,7 +98,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Index type',
'Column (length)' => 'Kolom (lengte)',
'length' => 'lengte',
'View has been dropped.' => 'View verwijderd.',
'View has been altered.' => 'View aangepast.',
'View has been created.' => 'View aangemaakt.',
@@ -190,7 +192,6 @@ $translations = array(
'Clone' => 'Dupliceer',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maximum aantal velden bereikt. Verhoog %s.',
'Partition by' => 'Partitioneren op',
'Partition' => null,
'Partitions' => 'Partities',
'Partition name' => 'Partitie naam',
'Values' => 'Waarden',
@@ -224,7 +225,6 @@ $translations = array(
'%d in total' => '%d in totaal',
'Permanent login' => 'Blijf aangemeld',
'Search data in tables' => 'Zoeken in database',
'as a regular expression' => 'als een regular expression',
'Schema' => 'Schema',
'Alter schema' => 'Schema wijzigen',
'Create schema' => 'Schema maken',
@@ -254,7 +254,7 @@ $translations = array(
'Geometry' => 'Geometrie',
'File exists.' => 'Bestand bestaat reeds.',
'Attachments' => 'Bijlagen',
'%d query(s) executed OK.' => array('%d query succesvol uitgevoerd.', '%d querys succesvol uitgevoerd'),
'%d query(s) executed OK.' => array('%d query succesvol uitgevoerd.', '%d querys succesvol uitgevoerd.'),
'Show only errors' => 'Enkel fouten tonen',
'Refresh' => 'Vernieuwen',
'Invalid schema.' => 'Ongeldig schema.',
@@ -266,7 +266,6 @@ $translations = array(
'Permanent link' => 'Permanente link',
'Edit all' => 'Alles bewerken',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => 'Verwijder %s?',
'Tables have been optimized.' => 'Tabellen zijn geoptimaliseerd.',
'Materialized view' => 'Materialized view',
@@ -278,7 +277,7 @@ $translations = array(
'Modify' => 'Aanpassen',
'Load more data' => 'Meer data inladen',
'Loading' => 'Aan het laden',
'ATTACH queries are not supported.' => 'ATTACH queries worden niet ondersteund',
'ATTACH queries are not supported.' => 'ATTACH queries worden niet ondersteund.',
'Warnings' => 'Waarschuwingen',
'%d / ' => '%d / ',
'Limit rows' => 'Rijen beperken',
@@ -286,9 +285,8 @@ $translations = array(
'Default value' => 'Standaardwaarde',
'Full table scan' => 'Full table scan',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Teveel foutieve aanmeldpogingen, probeer opnieuw binnen %d minuut.', 'Teveel foutieve aanmeldpogingen, probeer opnieuw binnen %d minuten.'),
'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.' => 'Master wachtwoord verlopen. <a href="https://www.adminer.org/en/extension/"%s>Implementeer</a> de %s methode om het permanent te maken.',
'The action will be performed after successful login with the same credentials.' => 'Deze actie zal uitgevoerd worden na het succesvol aanmelden met dezelfde gebruikersgegevens',
'The action will be performed after successful login with the same credentials.' => 'Deze actie zal uitgevoerd worden na het succesvol aanmelden met dezelfde gebruikersgegevens.',
'Connecting to privileged ports is not allowed.' => 'Verbindingen naar geprivilegieerde poorten is niet toegestaan.',
'There is a space in the input password which might be the cause.' => 'Er staat een spatie in het wachtwoord, wat misschien de oorzaak is.',
'If you did not send this request from Adminer then close this page.' => 'Als u deze actie niet via Adminer hebt gedaan, gelieve deze pagina dan te sluiten.',
@@ -298,23 +296,9 @@ $translations = array(
'You are offline.' => 'U bent offline.',
'You have no privileges to update this table.' => 'U bent niet gemachtigd om deze tabel aan te passen.',
'Saving' => 'Opslaan',
'Unknown error.' => 'Onbekende fout',
'Unknown error.' => 'Onbekende fout.',
'Database does not support password.' => 'Database ondersteunt het wachtwoord niet.',
'Disable %s or enable %s or %s extensions.' => 'Schakel %s uit or schakel extensies %s of %s in.',
'yes' => 'ja',
'no' => 'neen',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Ja',
'No' => 'Neen',
'One Time Password' => 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
namespace Adminer;
$translations = array(
'Home' => null,
'System' => 'System',
'Server' => 'Server',
'Username' => 'Brukernavn',
@@ -10,7 +11,7 @@ $translations = array(
'Logout' => 'Logg ut',
'Logged as: %s' => 'Logget inn som: %s',
'Logout successful.' => 'Utlogging vellykket.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Ugylding innloggingsinformasjon.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Master-passord er utløpt. <a href="https://www.adminer.org/en/extension/"%s>Implementer</a> en metode for %s for å gjøre det permanent.',
'Language' => 'Språk',
'Invalid CSRF token. Send the form again.' => 'Ugylding CSRF-token - Send inn skjemaet igjen.',
@@ -143,6 +144,7 @@ $translations = array(
'Auto Increment' => 'Autoinkrement',
'Options' => 'Valg',
'Comment' => 'Kommentarer',
'Default values' => 'Standardverdier',
'Drop' => 'Dropp',
'Are you sure?' => 'Er du sikker?',
'Move up' => 'Flytt opp',
@@ -150,7 +152,6 @@ $translations = array(
'Remove' => 'Fjern',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Maksimum antall feltnavn overskredet - venligst øk %s.',
'Partition by' => 'Partisjoner ved',
'Partition' => null,
'Partitions' => 'Partisjoner',
'Partition name' => 'Partisjonsnavn',
'Values' => 'Verdier',
@@ -165,7 +166,7 @@ $translations = array(
'Alter indexes' => 'Endre indekser',
'Add next' => 'Legg til neste',
'Index Type' => 'Indekstype',
'Column (length)' => 'Kolonne (lengde)',
'length' => 'lengde',
'Foreign keys' => 'Fremmednøkler',
'Foreign key' => 'Fremmednøkkel',
'Foreign key has been dropped.' => 'Fremmednøkkelen er slettet.',
@@ -199,7 +200,6 @@ $translations = array(
'Search' => 'Søk',
'anywhere' => 'hvorsomhelst',
'Search data in tables' => 'Søk data i tabeller',
'as a regular expression' => null,
'Sort' => 'Sorter',
'descending' => 'minkende',
'Limit' => 'Skranke',
@@ -280,41 +280,4 @@ $translations = array(
'Type has been created.' => 'Type er opprettet.',
'Alter type' => 'Endre type',
'Saving' => 'Lagrer',
'Drop %s?' => null,
'Materialized view' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Ja',
'No' => 'Nei',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,18 +1,22 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Rodzaj bazy',
'Server' => 'Serwer',
'Username' => 'Użytkownik',
'Password' => 'Hasło',
'Permanent login' => 'Zapamiętaj sesję',
'Login' => 'Zaloguj się',
'Logout' => 'Wyloguj',
'Logout' => 'Wyloguj się',
'Logged as: %s' => 'Zalogowany jako: %s',
'Logout successful.' => 'Wylogowano pomyślnie.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ proszę <a href="https://www.adminer.org/pl/donation/">dotację</a>.',
'Invalid server or credentials.' => 'Nieprawidłowy serwer lub dane logowania.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Dziękujemy za używanie Adminera, rozważ <a href="https://www.adminer.org/pl/donation/">dotację</a>.',
'Invalid credentials.' => 'Nieprawidłowe dane logowania.',
'There is a space in the input password which might be the cause.' => 'W haśle wejściowym znajduje się spacja, która może być przyczyną.',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer nie obsługuje dostępu do bazy danych bez hasła, <a href="https://www.adminer.org/pl/password/"%s>więcej informacji</a>.',
'Database does not support password.' => 'Baza danych nie obsługuje hasła.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Za dużo nieudanych prób logowania, spróbuj ponownie za %d minutę.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minuty.', 'Za dużo nieudanych prób logowania, spróbuj ponownie za %d minut.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ważność hasła głównego wygasła. <a href="https://www.adminer.org/pl/extension/"%s>Zaimplementuj</a> własną metodę %s, aby ustawić je na stałe.',
'Language' => 'Język',
@@ -21,8 +25,10 @@ $translations = array(
'No extension' => 'Brak rozszerzenia',
'None of the supported PHP extensions (%s) are available.' => 'Żadne z rozszerzeń PHP umożliwiających połączenie się z bazą danych (%s) nie jest dostępne.',
'Connecting to privileged ports is not allowed.' => 'Łączenie do portów uprzywilejowanych jest niedozwolone.',
'Disable %s or enable %s or %s extensions.' => 'Wyłącz %s lub włącz rozszerzenia %s lub %s.',
'Session support must be enabled.' => 'Wymagana jest obsługa sesji w PHP.',
'Session expired, please login again.' => 'Sesja wygasła, zaloguj się ponownie.',
'The action will be performed after successful login with the same credentials.' => 'Czynność zostanie wykonana po pomyślnym zalogowaniu przy użyciu tych samych danych logowania.',
'%s version: %s through PHP extension %s' => 'Wersja %s: %s za pomocą %s',
'Refresh' => 'Odśwież',
@@ -52,6 +58,8 @@ $translations = array(
'Query executed OK, %d row(s) affected.' => array('Zapytanie wykonane pomyślnie, zmieniono %d rekord.', 'Zapytanie wykonane pomyślnie, zmieniono %d rekordy.', 'Zapytanie wykonane pomyślnie, zmieniono %d rekordów.'),
'No commands to execute.' => 'Nic do wykonania.',
'Error in query' => 'Błąd w zapytaniu',
'Unknown error.' => 'Nieznany błąd.',
'Warnings' => 'Ostrzeżenia',
'ATTACH queries are not supported.' => 'Zapytania ATTACH są niewspierane.',
'Execute' => 'Wykonaj',
'Stop on error' => 'Zatrzymaj w przypadku błędu',
@@ -74,7 +82,7 @@ $translations = array(
'You can upload a big SQL file via FTP and import it from server.' => 'Większe pliki SQL możesz wgrać na serwer poprzez FTP przed zaimportowaniem.',
'You are offline.' => 'Jesteś offline.',
'Export' => 'Eksport',
'Export' => 'Eksportuj',
'Output' => 'Rezultat',
'open' => 'otwórz',
'save' => 'zapisz',
@@ -82,6 +90,7 @@ $translations = array(
'Data' => 'Dane',
'Database' => 'Baza danych',
'DB' => 'BD',
'Use' => 'Wybierz',
'Select database' => 'Wybierz bazę danych',
'Invalid database.' => 'Nie znaleziono bazy danych.',
@@ -119,6 +128,7 @@ $translations = array(
'Tables have been moved.' => 'Tabele zostały przeniesione.',
'Copy' => 'Kopiuj',
'Tables have been copied.' => 'Tabele zostały skopiowane.',
'overwrite' => 'nadpisz',
'Routines' => 'Procedury i funkcje',
'Routine has been called, %d row(s) affected.' => array('Procedura została uruchomiona, zmieniono %d rekord.', 'Procedura została uruchomiona, zmieniono %d rekordy.', 'Procedura została uruchomiona, zmieniono %d rekordów.'),
@@ -164,14 +174,15 @@ $translations = array(
'Column name' => 'Nazwa kolumny',
'Type' => 'Typ',
'Length' => 'Długość',
'Auto Increment' => 'Auto Increment',
'Auto Increment' => 'Automatyczny przyrost',
'Options' => 'Opcje',
'Comment' => 'Komentarz',
'Default value' => 'Wartość domyślna',
'Default values' => 'Wartości domyślne',
'Drop' => 'Usuń',
'Drop %s?' => 'Usunąć %s?',
'Are you sure?' => 'Czy jesteś pewien?',
'Size' => 'Wielkość',
'Are you sure?' => 'Czy na pewno?',
'Size' => 'Rozmiar',
'Compute' => 'Oblicz',
'Move up' => 'Przesuń w górę',
'Move down' => 'Przesuń w dół',
@@ -179,7 +190,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Przekroczono maksymalną liczbę pól. Zwiększ %s.',
'Partition by' => 'Partycjonowanie',
'Partition' => null,
'Partitions' => 'Partycje',
'Partition name' => 'Nazwa partycji',
'Values' => 'Wartości',
@@ -197,7 +207,7 @@ $translations = array(
'Alter indexes' => 'Zmień indeksy',
'Add next' => 'Dodaj następny',
'Index Type' => 'Typ indeksu',
'Column (length)' => 'Kolumna (długość)',
'length' => 'długość',
'Foreign keys' => 'Klucze obce',
'Foreign key' => 'Klucz obcy',
@@ -234,7 +244,6 @@ $translations = array(
'Search' => 'Szukaj',
'anywhere' => 'gdziekolwiek',
'Search data in tables' => 'Wyszukaj we wszystkich tabelach',
'as a regular expression' => null,
'Sort' => 'Sortuj',
'descending' => 'malejąco',
'Limit' => 'Limit',
@@ -253,14 +262,14 @@ $translations = array(
'Whole result' => 'Wybierz wszystkie',
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtów'),
'Import' => 'Import',
'Import' => 'Importuj',
'%d row(s) have been imported.' => array('%d rekord został zaimportowany.', '%d rekordy zostały zaimportowane.', '%d rekordów zostało zaimportowanych.'),
'File must be in UTF-8 encoding.' => 'Kodowanie pliku musi być ustawione na UTF-8.',
// in-place editing in select
'Modify' => 'Zmień',
'Ctrl+click on a value to modify it.' => 'Ctrl+kliknij wartość, aby ją edytować.',
'Use edit link to modify this value.' => 'Użyj linku edycji aby zmienić tę wartość.',
'Use edit link to modify this value.' => 'Użyj linku edycji, aby zmienić tę wartość.',
// %s can contain auto-increment value
'Item%s has been inserted.' => 'Rekord%s został dodany.',
@@ -281,7 +290,7 @@ $translations = array(
'Selected' => 'Zaznaczone',
'Clone' => 'Duplikuj',
'Delete' => 'Usuń',
'You have no privileges to update this table.' => 'Brak uprawnień do edycji tej tabeli',
'You have no privileges to update this table.' => 'Brak uprawnień do edycji tej tabeli.',
'E-mail' => 'E-mail',
'From' => 'Nadawca',
@@ -339,27 +348,11 @@ $translations = array(
'Type has been created.' => 'Typ został utworzony.',
'Alter type' => 'Zmień typ',
'overwrite' => null,
'DB' => null,
'Warnings' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Tak',
'No' => 'Nie',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
// Table check constraints
'Checks' => 'Kontrole',
'Create check' => 'Utwórz kontrolę',
'Alter check' => 'Zmień kontrolę',
'Check has been created.' => 'Kontrola została utworzona.',
'Check has been altered.' => 'Kontrola została zmieniona.',
'Check has been dropped.' => 'Kontrola została usunięta.',
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Entrar',
'Logout successful.' => 'Saída bem sucedida.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Identificação inválida.',
'Server' => 'Servidor',
'Username' => 'Usuário',
'Password' => 'Senha',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Comentário',
'Default values' => 'Valores padrões',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Nenhum comando para executar.',
'Unable to upload a file.' => 'Não é possível enviar o arquivo.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'Coluna (tamanho)',
'length' => 'tamanho',
'View has been dropped.' => 'A Visão foi apagada.',
'View has been altered.' => 'A Visão foi alterada.',
'View has been created.' => 'A Visão foi criada.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'Clonar',
'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' => null,
'Partitions' => 'Partições',
'Partition name' => 'Nome da Partição',
'Values' => 'Valores',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Login permanente',
'Databases have been dropped.' => 'A Base de dados foi apagada.',
'Search data in tables' => 'Buscar dados nas Tabelas',
'as a regular expression' => null,
'Schema' => 'Esquema',
'Alter schema' => 'Alterar esquema',
'Create schema' => 'Criar esquema',
@@ -261,60 +261,4 @@ $translations = array(
'Please use one of the extensions %s.' => 'Por favor use uma das extensões %s.',
'now' => 'agora',
'ltr' => 'ltr',
'Drop %s?' => null,
'Tables have been copied.' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'Copy' => null,
'overwrite' => null,
'DB' => null,
'Permanent link' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Edit all' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'HH:MM:SS' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Entrar',
'Logout successful.' => 'Sessão terminada com sucesso.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Identificação inválida.',
'Server' => 'Servidor',
'Username' => 'Nome de utilizador',
'Password' => 'Senha',
@@ -69,6 +70,7 @@ $translations = array(
'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.',
'Comment' => 'Comentário',
'Default values' => 'Valores predeterminados',
'%d byte(s)' => array('%d byte', '%d bytes'),
'No commands to execute.' => 'Nenhum comando para executar.',
'Unable to upload a file.' => 'Não é possível enviar o ficheiro.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'Tipo de índice',
'Column (length)' => 'coluna (tamanho)',
'length' => 'tamanho',
'View has been dropped.' => 'Vista eliminada.',
'View has been altered.' => 'Vista modificada.',
'View has been created.' => 'Vista criada.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'Clonar',
'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' => null,
'Partitions' => 'Partições',
'Partition name' => 'Nome da Partição',
'Values' => 'Valores',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Memorizar a senha',
'Databases have been dropped.' => 'Bases de dados eliminadas.',
'Search data in tables' => 'Pesquisar dados nas Tabelas',
'as a regular expression' => null,
'Schema' => 'Esquema',
'Alter schema' => 'Modificar esquema',
'Create schema' => 'Criar esquema',
@@ -261,60 +261,4 @@ $translations = array(
'Please use one of the extensions %s.' => 'Por favor use uma das extensões %s.',
'now' => 'agora',
'ltr' => 'ltr',
'Drop %s?' => null,
'Tables have been copied.' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'Copy' => null,
'overwrite' => null,
'DB' => null,
'Permanent link' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Edit all' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'HH:MM:SS' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Intră',
'Logout successful.' => 'Ați ieșit cu succes.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Numele de utilizator sau parola este greșită.',
'Server' => 'Server',
'Username' => 'Nume de utilizator',
'Password' => 'Parola',
@@ -69,6 +70,7 @@ $translations = array(
'Unable to select the table' => 'Nu am putut selecta date din tabel',
'Invalid CSRF token. Send the form again.' => 'CSRF token imposibil. Retrimite forma.',
'Comment' => 'Comentariu',
'Default values' => 'Valoarea inițială',
'%d byte(s)' => array('%d octet', '%d octeți'),
'No commands to execute.' => 'Nu sunt comenzi de executat.',
'Unable to upload a file.' => 'Nu am putut încărca fișierul pe server.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'La ștergere',
'ON UPDATE' => 'La modificare',
'Index Type' => 'Tipul indexului',
'Column (length)' => 'Coloană (lungimea)',
'length' => 'lungimea',
'View has been dropped.' => 'Reprezentarea a fost ștearsă.',
'View has been altered.' => 'Reprezentarea a fost modificată.',
'View has been created.' => 'Reprezentarea a fost creată.',
@@ -188,7 +190,6 @@ $translations = array(
'Tables have been dropped.' => 'Tabelele au fost șterse.',
'Clone' => 'Clonează',
'Partition by' => 'Împarte',
'Partition' => null,
'Partitions' => 'Secțiuni',
'Partition name' => 'Denumirea secțiunii',
'Values' => 'Parametru',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Logare permanentă',
'Databases have been dropped.' => 'Bazele de date au fost șterse.',
'Search data in tables' => 'Caută în tabele',
'as a regular expression' => null,
'Schema' => 'Schema',
'Alter schema' => 'Modifică schema',
'Create schema' => 'Crează o schemă',
@@ -261,60 +261,9 @@ $translations = array(
'Please use one of the extensions %s.' => 'Folosiți una din următoarele extensii %s.',
'now' => 'acum',
'ltr' => 'ltr',
'Tables have been copied.' => 'Tabelele au fost copiate',
'Tables have been copied.' => 'Tabelele au fost copiate.',
'Copy' => 'Copiază',
'Permanent link' => 'Adresă permanentă',
'Edit all' => 'Editează tot',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'Войти',
'Logout successful.' => 'Вы успешно покинули систему.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Неправильное имя пользователя или пароль.',
'Server' => 'Сервер',
'Username' => 'Имя пользователя',
'Password' => 'Пароль',
@@ -69,6 +70,7 @@ $translations = array(
'Unable to select the table' => 'Не удалось получить данные из таблицы',
'Invalid CSRF token. Send the form again.' => 'Недействительный CSRF-токен. Отправите форму ещё раз.',
'Comment' => 'Комментарий',
'Default values' => 'Значения по умолчанию',
'%d byte(s)' => array('%d байт', '%d байта', '%d байтов'),
'No commands to execute.' => 'Нет команд для выполнения.',
'Unable to upload a file.' => 'Не удалось загрузить файл на сервер.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'При стирании',
'ON UPDATE' => 'При обновлении',
'Index Type' => 'Тип индекса',
'Column (length)' => 'Поле (длина)',
'length' => 'длина',
'View has been dropped.' => 'Представление было удалено.',
'View has been altered.' => 'Представление было изменено.',
'View has been created.' => 'Представление было создано.',
@@ -188,7 +190,6 @@ $translations = array(
'Tables have been dropped.' => 'Таблицы были удалены.',
'Clone' => 'Клонировать',
'Partition by' => 'Разделить по',
'Partition' => null,
'Partitions' => 'Разделы',
'Partition name' => 'Название раздела',
'Values' => 'Параметры',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'Оставаться в системе',
'Databases have been dropped.' => 'Базы данных удалены.',
'Search data in tables' => 'Поиск в таблицах',
'as a regular expression' => 'как регулярное выражение',
'Schema' => 'Схема',
'Alter schema' => 'Изменить схему',
'Create schema' => 'Новая схема',
@@ -288,8 +288,8 @@ $translations = array(
'You are offline.' => 'Вы не выполнили вход.',
'You have no privileges to update this table.' => 'У вас нет прав на обновление этой таблицы.',
'Saving' => 'Сохранение',
'yes' => 'да',
'no' => 'нет',
'yes' => 'Да',
'no' => 'Нет',
'Drop %s?' => 'Удалить %s?',
'overwrite' => 'перезаписать',
'DB' => 'DB',
@@ -301,20 +301,5 @@ $translations = array(
'There is a space in the input password which might be the cause.' => 'В введеном пароле есть пробел, это может быть причиною.',
'Unknown error.' => 'Неизвестная ошибка.',
'Database does not support password.' => 'База данных не поддерживает пароль.',
'Disable %s or enable %s or %s extensions.' => 'Отключите %s или включите расширения %s или %s.',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Да',
'No' => 'Нет',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => 'Domov',
'Login' => 'Prihlásiť sa',
'Logout successful.' => 'Odhlásenie prebehlo v poriadku.',
'Invalid server or credentials.' => 'Neplatný server alebo prihlasovacie údaje.',
'Invalid credentials.' => 'Neplatné prihlasovacie údaje.',
'Server' => 'Server',
'Username' => 'Používateľ',
'Password' => 'Heslo',
@@ -70,6 +71,7 @@ $translations = array(
'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.',
'Comment' => 'Komentár',
'Default values' => 'Predvolené hodnoty',
'%d byte(s)' => array('%d bajt', '%d bajty', '%d bajtov'),
'No commands to execute.' => 'Žiadne príkazy na vykonanie.',
'Unable to upload a file.' => 'Súbor sa nepodarilo nahrať.',
@@ -77,8 +79,6 @@ $translations = array(
'File uploads are disabled.' => 'Nahrávánie súborov nie je povolené.',
'Routine has been called, %d row(s) affected.' => array('Procedúra bola zavolaná, bol zmenený %d záznam.', 'Procedúra bola zavolaná, boli zmenené %d záznamy.', 'Procedúra bola zavolaná, bolo zmenených %d záznamov.'),
'Call' => 'Zavolať',
'No driver' => 'Žiadny ovládač',
'Database driver not found.' => 'Databázový ovládač sa nenašiel.',
'No extension' => 'Žiadne rozšírenie',
'None of the supported PHP extensions (%s) are available.' => 'Nie je dostupné žiadne z podporovaných rozšírení (%s).',
'Session support must be enabled.' => 'Session premenné musia byť povolené.',
@@ -98,7 +98,7 @@ $translations = array(
'ON DELETE' => 'Pri zmazaní',
'ON UPDATE' => 'Pri aktualizácii',
'Index Type' => 'Typ indexu',
'Column (length)' => 'Stĺpec (dĺžka)',
'length' => 'dĺžka',
'View has been dropped.' => 'Pohľad bol odstránený.',
'View has been altered.' => 'Pohľad bol zmenený.',
'View has been created.' => 'Pohľad bol vytvorený.',
@@ -191,7 +191,6 @@ $translations = array(
'Whole result' => 'Celý výsledok',
'Clone' => 'Klonovať',
'Partition by' => 'Rozdeliť podľa',
'Partition' => 'Oddiel',
'Partitions' => 'Oddiely',
'Partition name' => 'Názov oddielu',
'Values' => 'Hodnoty',
@@ -226,7 +225,6 @@ $translations = array(
'Permanent login' => 'Trvalé prihlásenie',
'%d in total' => '%d celkom',
'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',
'Create schema' => 'Vytvoriť schému',
'Schema has been dropped.' => 'Schéma bola odstránená.',
@@ -259,7 +257,7 @@ $translations = array(
'%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',
'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.',
'now' => 'teraz',
'ltr' => 'ltr',
@@ -304,14 +302,4 @@ $translations = array(
'Disable %s or enable %s or %s extensions.' => 'Zakážte %s alebo povoľte rozšírenie %s alebo %s.',
'yes' => 'áno',
'no' => 'nie',
'Yes' => 'Áno',
'No' => 'Nie',
'Columns' => 'Stĺpce',
'Nullable' => 'Povolené null',
'Default' => 'Predvolené',
'One Time Password' => 'Jednorázové heslo',
'Invalid OTP code.' => 'Neplatný kód OTP.',
'Schemas' => 'Schémy',
'No schemas.' => 'Žiadne schémy.',
'Show schema' => 'Zobraziť schému',
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem',
'Server' => 'Strežnik',
'Username' => 'Uporabniško ime',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Odjavi se',
'Logged as: %s' => 'Prijavljen kot: %s',
'Logout successful.' => 'Prijava uspešna.',
'Invalid server or credentials.' => 'Neveljaven strežnik ali pravice.',
'Invalid credentials.' => 'Neveljavne pravice.',
'Language' => 'Jezik',
'Invalid CSRF token. Send the form again.' => 'Neveljaven token CSRF. Pošljite formular še enkrat.',
'No extension' => 'Brez dodatkov',
@@ -153,6 +154,7 @@ $translations = array(
'Auto Increment' => 'Samodejno povečevanje',
'Options' => 'Možnosti',
'Comment' => 'Komentar',
'Default values' => 'Privzete vrednosti',
'Drop' => 'Zavrzi',
'Are you sure?' => 'Ste prepričani?',
'Move up' => 'Premakni gor',
@@ -161,7 +163,6 @@ $translations = array(
'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' => null,
'Partitions' => 'Porazdelitve',
'Partition name' => 'Ime porazdelitve',
'Values' => 'Vrednosti',
@@ -178,7 +179,7 @@ $translations = array(
'Alter indexes' => 'Spremeni indekse',
'Add next' => 'Dodaj naslednjega',
'Index Type' => 'Tip indeksa',
'Column (length)' => 'Stolpec (dolžina)',
'length' => 'dolžina',
'Foreign keys' => 'Tuji ključi',
'Foreign key' => 'Tuj ključ',
@@ -215,7 +216,6 @@ $translations = array(
'Search' => 'Išči',
'anywhere' => 'kjerkoli',
'Search data in tables' => 'Išče podatke po tabelah',
'as a regular expression' => null,
'Sort' => 'Sortiraj',
'descending' => 'padajoče',
'Limit' => 'Limita',
@@ -305,58 +305,4 @@ $translations = array(
'Type has been dropped.' => 'Tip je zavržen.',
'Type has been created.' => 'Tip je ustvarjen.',
'Alter type' => 'Spremeni tip',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Permanent link' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Edit all' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'HH:MM:SS' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Систем',
'Server' => 'Сервер',
'Username' => 'Корисничко име',
@@ -11,11 +12,11 @@ $translations = array(
'Logout' => 'Одјава',
'Logged as: %s' => 'Пријави се као: %s',
'Logout successful.' => 'Успешна одјава.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Неважеће дозволе.',
'Language' => 'Језик',
'Invalid CSRF token. Send the form again.' => 'Неважећи CSRF код. Проследите поново форму.',
'No extension' => 'Без додатака',
'None of the supported PHP extensions (%s) are available.' => 'Ниједан од подржаних PHP додатака није доступан.',
'None of the supported PHP extensions (%s) are available.' => 'Ниједан од подржаних PHP додатака (%s) није доступан.',
'Session support must be enabled.' => 'Морате омогућити подршку за сесије.',
'Session expired, please login again.' => 'Ваша сесија је истекла, пријавите се поново.',
'%s version: %s through PHP extension %s' => '%s верзија: %s помоћу PHP додатка је %s',
@@ -158,6 +159,7 @@ $translations = array(
'Auto Increment' => 'Ауто-прираштај',
'Options' => 'Опције',
'Comment' => 'Коментар',
'Default values' => 'Подразумеване вредности',
'Drop' => 'Избриши',
'Are you sure?' => 'Да ли сте сигурни?',
'Move up' => 'Помери на горе',
@@ -166,7 +168,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Премашен је максимални број дозвољених поља. Молим увећајте %s.',
'Partition by' => 'Подели по',
'Partition' => null,
'Partitions' => 'Поделе',
'Partition name' => 'Име поделе',
'Values' => 'Вредности',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Уреди индексе',
'Add next' => 'Додај следећи',
'Index Type' => 'Тип индекса',
'Column (length)' => 'Колона (дужина)',
'length' => 'дужина',
'Foreign keys' => 'Страни кључеви',
'Foreign key' => 'Страни кључ',
@@ -220,7 +221,6 @@ $translations = array(
'Search' => 'Претрага',
'anywhere' => 'било где',
'Search data in tables' => 'Претражи податке у табелама',
'as a regular expression' => null,
'Sort' => 'Поређај',
'descending' => 'опадајуће',
'Limit' => 'Граница',
@@ -317,49 +317,4 @@ $translations = array(
'Type has been dropped.' => 'Тип је избрисан.',
'Type has been created.' => 'тип је креиран.',
'Alter type' => 'Уреди тип',
'Drop %s?' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Да',
'No' => 'Не',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'System',
'Server' => 'Server',
'Username' => 'Användarnamn',
@@ -12,7 +13,7 @@ $translations = array(
'Logged as: %s' => 'Inloggad som: %s',
'Logout successful.' => 'Du är nu utloggad.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Tack för att du använder Adminer, vänligen fundera över att <a href="https://www.adminer.org/en/donation/">donera</a>.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Ogiltiga inloggningsuppgifter.',
'There is a space in the input password which might be the cause.' => 'Det finns ett mellanslag i lösenordet, vilket kan vara anledningen.',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer tillåter inte att ansluta till en databas utan lösenord. <a href="https://www.adminer.org/en/password/"%s>Mer information</a>.',
'Database does not support password.' => 'Databasen stödjer inte lösenord.',
@@ -178,6 +179,7 @@ $translations = array(
'Options' => 'Inställningar',
'Comment' => 'Kommentar',
'Default value' => 'Standardvärde',
'Default values' => 'Standardvärden',
'Drop' => 'Ta bort',
'Drop %s?' => 'Ta bort %s?',
'Are you sure?' => 'Är du säker?',
@@ -189,7 +191,6 @@ $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.',
'Partition by' => 'Partitionera om',
'Partition' => null,
'Partitions' => 'Partitioner',
'Partition name' => 'Partition',
'Values' => 'Värden',
@@ -207,7 +208,7 @@ $translations = array(
'Alter indexes' => 'Ändra index',
'Add next' => 'Lägg till nästa',
'Index Type' => 'Indextyp',
'Column (length)' => 'Kolumn (längd)',
'length' => 'längd',
'Foreign keys' => 'Främmande nycklar',
'Foreign key' => 'Främmande nyckel',
@@ -244,7 +245,6 @@ $translations = array(
'Search' => 'Sök',
'anywhere' => 'överallt',
'Search data in tables' => 'Sök data i tabeller',
'as a regular expression' => null,
'Sort' => 'Sortera',
'descending' => 'Fallande',
'Limit' => 'Begränsning',
@@ -347,18 +347,4 @@ $translations = array(
'Type has been dropped.' => 'Typ har, typ, tagits bort.',
'Type has been created.' => 'Typ har skapats.',
'Alter type' => 'Ändra typ',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Ja',
'No' => 'Nej',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'நுழை',
'Logout successful.' => 'வெற்றிக‌ர‌மாய் வெளியேறியாயிற்று.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'ச‌ரியான‌ விப‌ர‌ங்க‌ள் இல்லை.',
'Server' => 'வ‌ழ‌ங்கி (Server)',
'Username' => 'ப‌ய‌னாள‌ர் (User)',
'Password' => 'க‌ட‌வுச்சொல்',
@@ -68,6 +69,7 @@ $translations = array(
'Unable to select the table' => 'அட்ட‌வ‌ணையை தேர்வு செய்ய‌ முடிய‌வில்லை',
'Invalid CSRF token. Send the form again.' => 'CSRF டோக்க‌ன் செல்லாது. ப‌டிவ‌த்தை மீண்டும் அனுப்ப‌வும்.',
'Comment' => 'குறிப்பு',
'Default values' => 'உள்ளிருக்கும் (Default) ம‌திப்புக‌ள் ',
'%d byte(s)' => array('%d பைட்', '%d பைட்டுக‌ள்'),
'No commands to execute.' => 'செய‌ல் ப‌டுத்த‌ எந்த‌ க‌ட்ட‌ளைக‌ளும் இல்லை.',
'Unable to upload a file.' => 'கோப்பை மேலேற்ற‌ம் (upload) செய்ய‌ இயல‌வில்லை.',
@@ -93,7 +95,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'அக‌வ‌ரிசை வ‌கை (Index Type)',
'Column (length)' => 'நெடுவ‌ரிசை (நீள‌ம்)',
'length' => 'நீள‌ம்',
'View has been dropped.' => 'தோற்ற‌ம் நீக்க‌ப்ப‌ட்ட‌து.',
'View has been altered.' => 'தோற்றம் மாற்றப்ப‌ட்ட‌து.',
'View has been created.' => 'தோற்ற‌ம் உருவாக்க‌ப்ப‌ட்ட‌து.',
@@ -186,7 +188,6 @@ $translations = array(
'Clone' => 'ந‌க‌லி (Clone)',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'அனும‌திக்க‌ப்ப‌ட்ட‌ அதிக‌ப‌ட்ச‌ கோப்புக‌ளின் எண்ணிக்கை மீற‌ப்ப‌ட்ட‌து. த‌ய‌வு செய்து %s ம‌ற்றும் %s யை அதிக‌ரிக்க‌வும்.',
'Partition by' => 'பிரித்த‌து',
'Partition' => null,
'Partitions' => 'பிரிவுக‌ள்',
'Partition name' => 'பிரிவின் பெய‌ர்',
'Values' => 'ம‌திப்புக‌ள்',
@@ -224,12 +225,11 @@ $translations = array(
'Alter schema' => 'அமைப்புமுறையை மாற்று',
'Create schema' => 'அமைப்புமுறையை உருவாக்கு',
'Search data in tables' => 'த‌க‌வ‌லை அட்ட‌வ‌ணையில் தேடு',
'as a regular expression' => null,
'Sequences' => 'வ‌ரிசைமுறை',
'Create sequence' => 'வ‌ரிசைமுறையை உருவாக்கு',
'User types' => 'ப‌ய‌னாள‌ர் வ‌கைக‌ள்',
'Create type' => 'வ‌கையை உருவாக்கு',
'Item%s has been inserted.' => 'உருப்ப‌டி (Item) சேர்க்க‌ப்ப‌ட்ட‌து.',
'Item%s has been inserted.' => 'உருப்ப‌டி (Item%s) சேர்க்க‌ப்ப‌ட்ட‌து.',
'Schema has been dropped.' => 'அமைப்புமுறை நீக்க‌ப்ப‌ட்ட‌து.',
'Schema has been created.' => 'அமைப்புமுறை உருவாக்க‌ப்ப‌ட்ட‌து.',
'Schema has been altered.' => 'அமைப்புமுறை மாற்ற‌ப்ப‌ட்ட‌து.',
@@ -265,56 +265,4 @@ $translations = array(
'Permanent link' => 'நிரந்தர இணைப்பு',
'Edit all' => 'அனைத்தையும் தொகு',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'Ctrl+click on a value to modify it.' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,9 +1,10 @@
<?php
namespace Adminer;
$translations = array(
'Home' => null,
'Login' => 'เข้าสู่ระบบ',
'Logout successful.' => 'ออกจากระบบเรียบร้อยแล้ว.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'ข้อมูลไม่ถูกต้อง.',
'Server' => 'เซอเวอร์',
'Username' => 'ชื่อผู้ใช้งาน',
'Password' => 'รหัสผ่าน',
@@ -69,6 +70,7 @@ $translations = array(
'Unable to select the table' => 'ไม่สามารถเลือกตารางได้',
'Invalid CSRF token. Send the form again.' => 'เครื่องหมาย CSRF ไม่ถูกต้อง ส่งข้อมูลใหม่อีกครั้ง.',
'Comment' => 'หมายเหตุ',
'Default values' => 'ค่าเริ่มต้น',
'%d byte(s)' => '%d ไบท์',
'No commands to execute.' => 'ไม่มีคำสั่งที่จะประมวลผล.',
'Unable to upload a file.' => 'ไม่สามารถอัปโหลดไฟล์ได้.',
@@ -95,7 +97,7 @@ $translations = array(
'ON DELETE' => 'ON DELETE',
'ON UPDATE' => 'ON UPDATE',
'Index Type' => 'ชนิดของดัชนี',
'Column (length)' => 'คอลัมน์ (ความยาว)',
'length' => 'ความยาว',
'View has been dropped.' => 'วิวถูกลบแล้ว.',
'View has been altered.' => 'วิวถูกเปลี่ยนแปลงแล้ว.',
'View has been created.' => 'วิวถูกสร้างแล้ว.',
@@ -189,7 +191,6 @@ $translations = array(
'Clone' => 'ทำซ้ำ',
'Maximum number of allowed fields exceeded. Please increase %s.' => 'จำนวนสูงสุดของฟิลด์อนุญาตให้เกิน กรุณาเพิ่มอีก %s.',
'Partition by' => 'พาร์ทิชันโดย',
'Partition' => null,
'Partitions' => 'พาร์ทิชัน',
'Partition name' => 'ชื่อของพาร์ทิชัน',
'Values' => 'ค่า',
@@ -224,7 +225,6 @@ $translations = array(
'Permanent login' => 'จดจำการเข้าสู่ระบบตลอดไป',
'Databases have been dropped.' => 'ฐานข้อมูลถูกลบแล้ว.',
'Search data in tables' => 'ค้นหาในตาราง',
'as a regular expression' => null,
'Schema' => 'Schema',
'Alter schema' => 'เปลี่ยนแปลง schema',
'Create schema' => 'สร้าง schema',
@@ -266,55 +266,4 @@ $translations = array(
'Permanent link' => 'ลิงค์ถาวร',
'Edit all' => 'แก้ไขทั้งหมด',
'HH:MM:SS' => 'HH:MM:SS',
'Drop %s?' => null,
'Tables have been optimized.' => null,
'Materialized view' => null,
'Vacuum' => null,
'Selected' => null,
'overwrite' => null,
'DB' => null,
'File must be in UTF-8 encoding.' => null,
'Modify' => null,
'Load more data' => null,
'Loading' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Full table scan' => null,
'Too many unsuccessful logins, try again in %d minute(s).' => array(),
'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,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You can upload a big SQL file via FTP and import it from server.' => null,
'Size' => null,
'Compute' => null,
'You are offline.' => null,
'You have no privileges to update this table.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'yes' => null,
'no' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Sistem',
'Server' => 'Sunucu',
'Username' => 'Kullanıcı',
@@ -12,7 +13,7 @@ $translations = array(
'Logged as: %s' => '%s olarak giriş yapıldı.',
'Logout successful.' => 'Oturum başarıyla sonlandı.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Adminer kullandığınız için teşekkür ederiz <a href="https://www.adminer.org/en/donation/">bağış yapmayı düşünün</a>.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Geçersiz kimlik bilgileri.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Çok fazla oturum açma denemesi yapıldı.', '%d Dakika sonra tekrar deneyiniz.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Ana şifrenin süresi doldu. Kalıcı olması için <a href="https://www.adminer.org/en/extension/"%s>%s medodunu</a> kullanın.',
'Language' => 'Dil',
@@ -57,7 +58,7 @@ $translations = array(
'ATTACH queries are not supported.' => 'ATTACH sorguları desteklenmiyor.',
'Execute' => 'Çalıştır',
'Stop on error' => 'Hata oluşursa dur',
'Show only errors' => 'Sadece hataları göster.',
'Show only errors' => 'Sadece hataları göster',
// sprintf() format for time of the command
'%.3f s' => '%.3f s',
'History' => 'Geçmiş',
@@ -172,6 +173,7 @@ $translations = array(
'Options' => 'Seçenekler',
'Comment' => 'Yorum',
'Default value' => 'Varsayılan değer',
'Default values' => 'Varsayılan değerler',
'Drop' => 'Sil',
'Drop %s?' => 'Sil %s?',
'Are you sure?' => 'Emin misiniz?',
@@ -183,7 +185,6 @@ $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.',
'Partition by' => 'Bununla bölümle',
'Partition' => null,
'Partitions' => 'Bölümler',
'Partition name' => 'Bölüm adı',
'Values' => 'Değerler',
@@ -201,7 +202,7 @@ $translations = array(
'Alter indexes' => 'İndeksleri değiştir',
'Add next' => 'Bundan sonra ekle',
'Index Type' => 'İndex Türü',
'Column (length)' => 'Kolon (uzunluğu)',
'length' => 'uzunluğu',
'Foreign keys' => 'Dış anahtarlar',
'Foreign key' => 'Dış anahtar',
@@ -224,7 +225,7 @@ $translations = array(
'Trigger has been dropped.' => 'Tetik silindi.',
'Trigger has been altered.' => 'Tetik değiştirildi.',
'Trigger has been created.' => 'Tetik oluşturuldu.',
'Alter trigger' => 'Tetiği değiştir.',
'Alter trigger' => 'Tetiği değiştir',
'Create trigger' => 'Tetik oluştur',
'Time' => 'Zaman',
'Event' => 'Olay',
@@ -238,7 +239,6 @@ $translations = array(
'Search' => 'Ara',
'anywhere' => 'hiçbir yerde',
'Search data in tables' => 'Tablolarda veri ara',
'as a regular expression' => null,
'Sort' => 'Sırala',
'descending' => 'Azalan',
'Limit' => 'Limit',
@@ -341,25 +341,4 @@ $translations = array(
'Type has been dropped.' => 'Tür silindi.',
'Type has been created.' => 'Tür oluşturuldu.',
'Alter type' => 'Türü değiştir',
'overwrite' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'There is a space in the input password which might be the cause.' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Evet',
'No' => 'Hayır',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Система Бази Даних',
'Server' => 'Сервер',
'Username' => 'Користувач',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Вийти',
'Logged as: %s' => 'Ви увійшли як: %s',
'Logout successful.' => 'Ви вдало вийшли з системи.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Неправильні дані входу.',
'Language' => 'Мова',
'Invalid CSRF token. Send the form again.' => 'Недійсний CSRF токен. Надішліть форму ще раз.',
'No extension' => 'Нема розширень',
@@ -158,6 +159,7 @@ $translations = array(
'Auto Increment' => 'Автоматичне збільшення',
'Options' => 'Опції',
'Comment' => 'Коментарі',
'Default values' => 'Значення за замовчуванням',
'Drop' => 'Видалити',
'Are you sure?' => 'Ви впевнені?',
'Move up' => 'Пересунути вгору',
@@ -166,7 +168,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Досягнута максимальна кількість доступних полів. Будь ласка, збільшіть %s.',
'Partition by' => 'Розділити по',
'Partition' => null,
'Partitions' => 'Розділи',
'Partition name' => 'Назва розділу',
'Values' => 'Значення',
@@ -183,7 +184,7 @@ $translations = array(
'Alter indexes' => 'Змінити індексування',
'Add next' => 'Додати ще',
'Index Type' => 'Тип індексу',
'Column (length)' => 'Стовпець (довжина)',
'length' => 'довжина',
'Foreign keys' => 'Зовнішні ключі',
'Foreign key' => 'Зовнішній ключ',
@@ -220,7 +221,6 @@ $translations = array(
'Search' => 'Пошук',
'anywhere' => 'будь-де',
'Search data in tables' => 'Шукати дані в таблицях',
'as a regular expression' => null,
'Sort' => 'Сортувати',
'descending' => 'по спаданню',
'Limit' => 'Обмеження',
@@ -344,22 +344,4 @@ $translations = array(
'Saving' => 'Збереження',
'Unknown error.' => 'Невідома помилка.',
'Database does not support password.' => 'База даних не підтримує пароль.',
'Vacuum' => null,
'%d / ' => array(),
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Так',
'No' => 'Ні',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => 'Hệ thống',
'Server' => 'Máy chủ',
'Username' => 'Tên người dùng',
@@ -11,7 +12,7 @@ $translations = array(
'Logout' => 'Thoát',
'Logged as: %s' => 'Vào dưới tên: %s',
'Logout successful.' => 'Đã thoát xong.',
'Invalid server or credentials.' => null,
'Invalid credentials.' => 'Tài khoản sai.',
'Too many unsuccessful logins, try again in %d minute(s).' => 'Bạn gõ sai tài khoản quá nhiều lần, hãy thử lại sau %d phút nữa.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Mật khẩu đã hết hạn. <a href="https://www.adminer.org/en/extension/"%s>Thử cách làm</a> để giữ cố định.',
'Language' => 'Ngôn ngữ',
@@ -60,7 +61,7 @@ $translations = array(
'File upload' => 'Tải tệp lên',
'From server' => 'Dùng tệp trên máy chủ',
'Webserver file %s' => 'Tệp trên máy chủ',
'Webserver file %s' => 'Tệp trên máy chủ %s',
'Run file' => 'Chạy tệp',
'File does not exist.' => 'Tệp không tồn tại.',
'File uploads are disabled.' => 'Chức năng tải tệp lên đã bị cấm.',
@@ -161,6 +162,7 @@ $translations = array(
'Auto Increment' => 'Tăng tự động',
'Options' => 'Tuỳ chọn',
'Comment' => 'Chú thích',
'Default values' => 'Giá trị mặc định',
'Drop' => 'Xoá',
'Are you sure?' => 'Bạn có chắc',
'Size' => 'Kích thước',
@@ -171,7 +173,6 @@ $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).',
'Partition by' => 'Phân chia bằng',
'Partition' => null,
'Partitions' => 'Phân hoạch',
'Partition name' => 'Tên phân hoạch',
'Values' => 'Giá trị',
@@ -188,7 +189,7 @@ $translations = array(
'Alter indexes' => 'Sửa chỉ mục',
'Add next' => 'Thêm tiếp',
'Index Type' => 'Loại chỉ mục',
'Column (length)' => 'Cột (độ dài)',
'length' => 'độ dài',
'Foreign keys' => 'Các khoá ngoại',
'Foreign key' => 'Khoá ngoại',
@@ -225,7 +226,6 @@ $translations = array(
'Search' => 'Tìm kiếm',
'anywhere' => 'bất cứ đâu',
'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',
'descending' => 'giảm dần',
'Limit' => 'Giới hạn',
@@ -326,39 +326,4 @@ $translations = array(
'Type has been dropped.' => 'Đã xoá kiểu.',
'Type has been created.' => 'Đã tạo kiểu.',
'Alter type' => 'Sửa kiểu dữ liệu',
'Drop %s?' => null,
'Materialized view' => null,
'overwrite' => null,
'DB' => null,
'ATTACH queries are not supported.' => null,
'Warnings' => null,
'%d / ' => array(),
'Limit rows' => null,
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => null,
'Default value' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => null,
'The action will be performed after successful login with the same credentials.' => null,
'Connecting to privileged ports is not allowed.' => null,
'There is a space in the input password which might be the cause.' => null,
'If you did not send this request from Adminer then close this page.' => null,
'You are offline.' => null,
'Saving' => null,
'Unknown error.' => null,
'Database does not support password.' => null,
'Disable %s or enable %s or %s extensions.' => null,
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => 'Có',
'No' => 'Không',
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => 'Xx',
'System' => 'Xx',
'Server' => 'Xx',
'Username' => 'Xx',
@@ -12,18 +13,17 @@ $translations = array(
'Logged as: %s' => 'Xx: %s',
'Logout successful.' => 'Xx.',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => 'Xx <a href="https://www.adminer.org/en/donation/">xx</a>.',
'Invalid server or credentials.' => 'Xx.',
'Invalid credentials.' => 'Xx.',
'There is a space in the input password which might be the cause.' => 'Xx.',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Xx, <a href="https://www.adminer.org/en/password/"%s>xx</a>.',
'Database does not support password.' => 'Xx.',
'Too many unsuccessful logins, try again in %d minute(s).' => array('Xx %d.', 'Xx %d.'),
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '<a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => 'Xx. <a href="https://www.adminer.org/en/extension/"%s>Xx</a> %s xx.',
'Language' => 'Xx',
'Invalid CSRF token. Send the form again.' => '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',
// %s contains the list of the extensions, e.g. 'mysqli, PDO_MySQL'
'None of the supported PHP extensions (%s) are available.' => 'Xx (%s).',
'Connecting to privileged ports is not allowed.' => 'Xx.',
'Disable %s or enable %s or %s extensions.' => 'Xx %s xx %s xx %s xx.',
@@ -34,7 +34,7 @@ $translations = array(
'Refresh' => 'Xx',
// text direction - 'ltr' or 'rtl'
'ltr' => 'xx',
'ltr' => 'ltr',
'Privileges' => 'Xx',
'Create user' => 'Xx',
@@ -180,6 +180,7 @@ $translations = array(
'Options' => 'Xx',
'Comment' => 'Xx',
'Default value' => 'Xx',
'Default values' => 'Xx',
'Drop' => 'Xx',
'Drop %s?' => 'Xx %s?',
'Are you sure?' => 'Xx?',
@@ -191,7 +192,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => 'Xx %s.',
'Partition by' => 'Xx',
'Partition' => 'Xx',
'Partitions' => 'Xx',
'Partition name' => 'Xx',
'Values' => 'Xx',
@@ -209,7 +209,7 @@ $translations = array(
'Alter indexes' => 'Xx',
'Add next' => 'Xx',
'Index Type' => 'Xx',
'Column (length)' => 'Xx',
'length' => 'xx',
'Foreign keys' => 'Xx',
'Foreign key' => 'Xx',
@@ -246,7 +246,6 @@ $translations = array(
'Search' => 'Xx',
'anywhere' => 'xx',
'Search data in tables' => 'Xx',
'as a regular expression' => 'xx',
'Sort' => 'Xx',
'descending' => 'xx',
'Limit' => 'Xx',
@@ -256,6 +255,7 @@ $translations = array(
'Full table scan' => 'Xx',
'Unable to select the table' => 'Xx',
'No rows.' => 'Xx.',
// used in SQL query limit and it is followed by another number, e.g. '10 / 50 rows' meaning 10 of 50 rows
'%d / ' => '%d / ',
'%d row(s)' => array('%d xx', '%d xx'),
'Page' => 'Xx',
@@ -274,7 +274,7 @@ $translations = array(
'Ctrl+click on a value to modify it.' => 'Xx.',
'Use edit link to modify this value.' => 'Xx.',
// %s can contain auto-increment value
// %s can contain auto-increment value, e.g. ' 123'
'Item%s has been inserted.' => 'Xx%s.',
'Item has been deleted.' => 'Xx.',
'Item has been updated.' => 'Xx.',
@@ -327,15 +327,12 @@ $translations = array(
'Please use one of the extensions %s.' => 'Xx %s.',
// PostgreSQL and MS SQL schema support
'Schema' => 'Xx',
'Schemas' => 'Xx',
'No schemas.' => 'Xx.',
'Show schema' => 'Xx',
'Alter schema' => 'Xx',
'Create schema' => 'Xx',
'Schema has been dropped.' => 'Xx.',
'Schema has been created.' => 'Xx.',
'Schema has been altered.' => 'Xx.',
'Schema' => 'Xx',
'Invalid schema.' => 'Xx.',
// PostgreSQL sequences support
@@ -353,12 +350,11 @@ $translations = array(
'Type has been created.' => 'Xx.',
'Alter type' => 'Xx',
// Plugins
'Columns' => 'Xx',
'Nullable' => 'Xx',
'Default' => 'Xx',
'Yes' => 'Xx',
'No' => 'Xx',
'One Time Password' => 'Xx',
'Invalid OTP code.' => 'Xx.',
// Table check constraints
'Checks' => 'Xx',
'Create check' => 'Xx',
'Alter check' => 'Xx',
'Check has been created.' => 'Xx.',
'Check has been altered.' => 'Xx.',
'Check has been dropped.' => 'Xx.',
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => '資料庫系統',
'Server' => '伺服器',
'Username' => '帳號',
@@ -11,10 +12,10 @@ $translations = array(
'Logout' => '登出',
'Logged as: %s' => '登錄為: %s',
'Logout successful.' => '成功登出。',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感謝使用Adminer請考慮為我們<a href="https://www.adminer.org/en/donation/">捐款(英文網頁)</a>.',
'Invalid server or credentials.' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感謝使用Adminer請考慮為我們<a href="https://www.adminer.org/en/donation/">捐款(英文網頁)</a>',
'Invalid credentials.' => '無效的憑證。',
'There is a space in the input password which might be the cause.' => '您輸入的密碼中有一個空格,這可能是導致問題的原因。',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer預設不支援訪問沒有密碼的資料庫<a href="https://www.adminer.org/en/password/"%s>詳情見這裡</a>.',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer預設不支援訪問沒有密碼的資料庫<a href="https://www.adminer.org/en/password/"%s>詳情見這裡</a>',
'Database does not support password.' => '資料庫不支援密碼。',
'Too many unsuccessful logins, try again in %d minute(s).' => '登錄失敗次數過多,請 %d 分鐘後重試。',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '主密碼已過期。<a href="https://www.adminer.org/en/extension/"%s>請擴展</a> %s 方法讓它永久化。',
@@ -46,7 +47,7 @@ $translations = array(
'Revoke' => '廢除',
'Process list' => '處理程序列表',
'%d process(es) have been killed.' => '%d 個 Process(es) 被終止',
'%d process(es) have been killed.' => '%d 個 Process(es) 被終止',
'Kill' => '終止',
'Variables' => '變數',
@@ -73,10 +74,10 @@ $translations = array(
'From server' => '從伺服器',
'Webserver file %s' => '網頁伺服器檔案 %s',
'Run file' => '執行檔案',
'File does not exist.' => '檔案不存在',
'File does not exist.' => '檔案不存在',
'File uploads are disabled.' => '檔案上傳已經被停用。',
'Unable to upload a file.' => '無法上傳檔案。',
'Maximum allowed file size is %sB.' => '允許的檔案上限大小為 %sB',
'Maximum allowed file size is %sB.' => '允許的檔案上限大小為 %sB',
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST 資料太大。減少資料或者增加 %s 的設定值。',
'You can upload a big SQL file via FTP and import it from server.' => '您可以通過FTP上傳大型SQL檔並從伺服器導入。',
'You are offline.' => '您離線了。',
@@ -127,11 +128,11 @@ $translations = array(
'Move' => '轉移',
'Tables have been moved.' => '已轉移資料表。',
'Copy' => '複製',
'Tables have been copied.' => '資料表已經複製',
'Tables have been copied.' => '資料表已經複製',
'overwrite' => '覆蓋',
'Routines' => '程序',
'Routine has been called, %d row(s) affected.' => '程序已被執行,%d 行被影響',
'Routine has been called, %d row(s) affected.' => '程序已被執行,%d 行被影響',
'Call' => '呼叫',
'Parameter name' => '參數名稱',
'Create procedure' => '建立預存程序',
@@ -178,6 +179,7 @@ $translations = array(
'Options' => '選項',
'Comment' => '註解',
'Default value' => '預設值',
'Default values' => '預設值',
'Drop' => '刪除',
'Drop %s?' => '刪除 %s?',
'Are you sure?' => '你確定嗎?',
@@ -189,7 +191,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => '超過允許的字段數量的最大值。請增加 %s。',
'Partition by' => '分區類型',
'Partition' => null,
'Partitions' => '分區',
'Partition name' => '分區名稱',
'Values' => '值',
@@ -207,7 +208,7 @@ $translations = array(
'Alter indexes' => '修改索引',
'Add next' => '新增下一筆',
'Index Type' => '索引類型',
'Column (length)' => '欄位(長度',
'length' => '長度',
'Foreign keys' => '外來鍵',
'Foreign key' => '外來鍵',
@@ -244,7 +245,6 @@ $translations = array(
'Search' => '搜尋',
'anywhere' => '任意位置',
'Search data in tables' => '在資料庫搜尋',
'as a regular expression' => null,
'Sort' => '排序',
'descending' => '降冪 (遞減)',
'Limit' => '限定',
@@ -274,7 +274,7 @@ $translations = array(
// %s can contain auto-increment value
'Item%s has been inserted.' => '已新增項目 %s。',
'Item has been deleted.' => '該項目已被刪除',
'Item has been deleted.' => '該項目已被刪除',
'Item has been updated.' => '已更新項目。',
'%d item(s) have been affected.' => '%d 個項目受到影響。',
'New item' => '新增項目',
@@ -347,19 +347,4 @@ $translations = array(
'Type has been dropped.' => '已刪除類型。',
'Type has been created.' => '已建立類型。',
'Alter type' => '修改類型',
// Plugins
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -1,7 +1,8 @@
<?php
namespace Adminer;
$translations = array(
// label for database system selection (MySQL, SQLite, ...)
'Home' => null,
'System' => '系统',
'Server' => '服务器',
'Username' => '用户名',
@@ -11,10 +12,10 @@ $translations = array(
'Logout' => '登出',
'Logged as: %s' => '登录用户:%s',
'Logout successful.' => '成功登出。',
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感谢使用Adminer请考虑为我们<a href="https://www.adminer.org/en/donation/">捐款(英文页面)</a>.',
'Invalid server or credentials.' => null,
'Thanks for using Adminer, consider <a href="https://www.adminer.org/en/donation/">donating</a>.' => '感谢使用Adminer请考虑为我们<a href="https://www.adminer.org/en/donation/">捐款(英文页面)</a>',
'Invalid credentials.' => '无效凭据。',
'There is a space in the input password which might be the cause.' => '您输入的密码中有一个空格,这可能是导致问题的原因。',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer默认不支持访问没有密码的数据库<a href="https://www.adminer.org/en/password/"%s>详情见这里</a>.',
'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' => 'Adminer默认不支持访问没有密码的数据库<a href="https://www.adminer.org/en/password/"%s>详情见这里</a>',
'Database does not support password.' => '数据库不支持密码。',
'Too many unsuccessful logins, try again in %d minute(s).' => '登录失败次数过多,请 %d 分钟后重试。',
'Master password expired. <a href="https://www.adminer.org/en/extension/"%s>Implement</a> %s method to make it permanent.' => '主密码已过期。<a href="https://www.adminer.org/en/extension/"%s>请扩展</a> %s 方法让它永久化。',
@@ -46,7 +47,7 @@ $translations = array(
'Revoke' => '废除',
'Process list' => '进程列表',
'%d process(es) have been killed.' => '%d 个进程被终止',
'%d process(es) have been killed.' => '%d 个进程被终止',
'Kill' => '终止',
'Variables' => '变量',
@@ -178,6 +179,7 @@ $translations = array(
'Options' => '选项',
'Comment' => '注释',
'Default value' => '默认值',
'Default values' => '默认值',
'Drop' => '删除',
'Drop %s?' => '删除 %s?',
'Are you sure?' => '您确定吗?',
@@ -189,7 +191,6 @@ $translations = array(
'Maximum number of allowed fields exceeded. Please increase %s.' => '超过最多允许的字段数量。请增加 %s。',
'Partition by' => '分区类型',
'Partition' => null,
'Partitions' => '分区',
'Partition name' => '分区名',
'Values' => '值',
@@ -207,7 +208,7 @@ $translations = array(
'Alter indexes' => '修改索引',
'Add next' => '下一行插入',
'Index Type' => '索引类型',
'Column (length)' => '列(长度)',
// 'Column (length)' => '列(长度)',
'Foreign keys' => '外键',
'Foreign key' => '外键',
@@ -244,7 +245,6 @@ $translations = array(
'Search' => '搜索',
'anywhere' => '任意位置',
'Search data in tables' => '在表中搜索数据',
'as a regular expression' => null,
'Sort' => '排序',
'descending' => '降序',
'Limit' => '范围',
@@ -347,18 +347,4 @@ $translations = array(
'Type has been dropped.' => '已删除类型。',
'Type has been created.' => '已创建类型。',
'Alter type' => '修改类型',
'Columns' => null,
'Nullable' => null,
'Default' => null,
'Yes' => null,
'No' => null,
'One Time Password' => null,
'Invalid OTP code.' => null,
'Schemas' => null,
'No schemas.' => null,
'Show schema' => null,
'No driver' => null,
'Database driver not found.' => null,
);

View File

@@ -20,17 +20,15 @@ function adminer_object() {
new AdminerDumpXml,
new AdminerDumpAlter,
//~ new AdminerSqlLog("past-" . rtrim(`git describe --tags --abbrev=0`) . ".sql"),
//~ new AdminerEditCalendar(script_src("../externals/jquery-ui/jquery-1.4.4.js") . script_src("../externals/jquery-ui/ui/jquery.ui.core.js") . script_src("../externals/jquery-ui/ui/jquery.ui.widget.js") . script_src("../externals/jquery-ui/ui/jquery.ui.datepicker.js") . script_src("../externals/jquery-ui/ui/jquery.ui.mouse.js") . script_src("../externals/jquery-ui/ui/jquery.ui.slider.js") . script_src("../externals/jquery-timepicker/jquery-ui-timepicker-addon.js") . "<link rel='stylesheet' href='../externals/jquery-ui/themes/base/jquery.ui.all.css'>\n<style>\n.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }\n.ui-timepicker-div dl { text-align: left; }\n.ui-timepicker-div dl dt { height: 25px; }\n.ui-timepicker-div dl dd { margin: -25px 0 10px 65px; }\n.ui-timepicker-div td { font-size: 90%; }\n</style>\n", "../externals/jquery-ui/ui/i18n/jquery.ui.datepicker-%s.js"),
//~ new AdminerTinymce("../externals/tinymce/jscripts/tiny_mce/tiny_mce_dev.js"),
//~ new AdminerWymeditor(array("../externals/wymeditor/src/jquery/jquery.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.explorer.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.mozilla.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.opera.js", "../externals/wymeditor/src/wymeditor/jquery.wymeditor.safari.js")),
new AdminerFileUpload(""),
new AdminerJsonColumn,
new AdminerSlugify,
new AdminerTranslation,
new AdminerForeignSystem,
new AdminerEnumOption,
new AdminerTablesFilter,
new AdminerEditForeign,
new AdminerLoginSsl(["TrustServerCertificate" => true]),
);
/* It is possible to combine customization and plugins:

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
page_header(lang('Privileges'));
echo '<p class="links"><a href="' . h(ME) . 'user=">' . lang('Create user') . "</a>";
@@ -14,15 +16,15 @@ echo "<form action=''><p>\n";
hidden_fields_get();
echo "<input type='hidden' name='db' value='" . h(DB) . "'>\n";
echo ($grant ? "" : "<input type='hidden' name='grant' value=''>\n");
echo "<table>\n";
echo "<table class='odds'>\n";
echo "<thead><tr><th>" . lang('Username') . "<th>" . lang('Server') . "<th></thead>\n";
while ($row = $result->fetch_assoc()) {
echo '<tr' . odd() . '><td>' . h($row["User"]) . "<td>" . h($row["Host"]) . '<td><a href="' . h(ME . 'user=' . urlencode($row["User"]) . '&host=' . urlencode($row["Host"])) . '">' . lang('Edit') . "</a>\n";
echo '<tr><td>' . h($row["User"]) . "<td>" . h($row["Host"]) . '<td><a href="' . h(ME . 'user=' . urlencode($row["User"]) . '&host=' . urlencode($row["Host"])) . '">' . lang('Edit') . "</a>\n";
}
if (!$grant || DB != "") {
echo "<tr" . odd() . "><td><input name='user' autocapitalize='off'><td><input name='host' value='localhost' autocapitalize='off'><td><input type='submit' value='" . lang('Edit') . "'>\n";
echo "<tr><td><input name='user' autocapitalize='off'><td><input name='host' value='localhost' autocapitalize='off'><td><input type='submit' value='" . lang('Edit') . "'>\n";
}
echo "</table>\n";

View File

@@ -1,5 +1,7 @@
<?php
$PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["procedure"]);
namespace Adminer;
$PROCEDURE = ($_GET["name"] ?: $_GET["procedure"]);
$routine = (isset($_GET["function"]) ? "FUNCTION" : "PROCEDURE");
$row = $_POST;
$row["fields"] = (array) $row["fields"];
@@ -39,17 +41,12 @@ $routine_languages = routine_languages();
<?php echo ($routine_languages ? lang('Language') . ": " . html_select("language", $routine_languages, $row["language"]) . "\n" : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>">
<div class="scrollable">
<table cellspacing="0" class="nowrap" id="edit-fields">
<table class="nowrap">
<?php
edit_fields($row["fields"], $collations, $routine);
if (isset($_GET["function"])) {
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()));
echo "<td></td></tr></tbody>\n";
echo "<tr><td>" . lang('Return type');
edit_type("returns", $row["returns"], $collations, array(), (JUSH == "pgsql" ? array("void", "trigger") : array()));
}
?>
</table>
@@ -58,6 +55,8 @@ if (isset($_GET["function"])) {
<p><?php textarea("definition", $row["definition"]); ?>
<p>
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php if ($PROCEDURE != "") { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $PROCEDURE)); ?><?php } ?>
<?php if ($PROCEDURE != "") { ?>
<input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"><?php echo confirm(lang('Drop %s?', $PROCEDURE)); ?>
<?php } ?>
<input type="hidden" name="token" value="<?php echo $token; ?>">
</form>

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
if (support("kill")) {
if ($_POST && !$error) {
$killed = 0;
@@ -16,13 +18,12 @@ page_header(lang('Process list'), $error);
<form action="" method="post">
<div class="scrollable">
<table cellspacing="0" class="nowrap checkable">
<table class="nowrap checkable odds">
<?php
echo script("mixin(qsl('table'), {onclick: tableClick, ondblclick: partialArg(tableClick, true)});");
// HTML valid because there is always at least one process
$i = -1;
foreach (process_list() as $i => $row) {
if (!$i) {
echo "<thead><tr lang='en'>" . (support("kill") ? "<th>" : "");
foreach ($row as $key => $val) {
@@ -34,13 +35,13 @@ foreach (process_list() as $i => $row) {
}
echo "</thead>\n";
}
echo "<tr" . odd() . ">" . (support("kill") ? "<td>" . checkbox("kill[]", $row[$jush == "sql" ? "Id" : "pid"], 0) : "");
echo "<tr>" . (support("kill") ? "<td>" . checkbox("kill[]", $row[JUSH == "sql" ? "Id" : "pid"], 0) : "");
foreach ($row as $key => $val) {
echo "<td>" . (
($jush == "sql" && $key == "Info" && preg_match("~Query|Killed~", $row["Command"]) && $val != "") ||
($jush == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
($jush == "oracle" && $key == "sql_text" && $val != "")
? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Clone') . '</a>'
(JUSH == "sql" && $key == "Info" && preg_match("~Query|Killed~", $row["Command"]) && $val != "") ||
(JUSH == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
(JUSH == "oracle" && $key == "sql_text" && $val != "")
? "<code class='jush-" . JUSH . "'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Clone') . '</a>'
: h($val)
);
}

View File

@@ -1,9 +1,11 @@
<?php
namespace Adminer;
page_header(lang('Database schema'), "", array(), h(DB . ($_GET["ns"] ? ".$_GET[ns]" : "")));
$table_pos = array();
$table_pos_js = array();
$SCHEMA = ($_GET["schema"] ? $_GET["schema"] : $_COOKIE["adminer_schema-" . str_replace(".", "_", DB)]); // $_COOKIE["adminer_schema"] was used before 3.2.0 //! ':' in table name
$SCHEMA = ($_GET["schema"] ?: $_COOKIE["adminer_schema-" . str_replace(".", "_", DB)]); // $_COOKIE["adminer_schema"] was used before 3.2.0 //! ':' in table name
preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~', $SCHEMA, $matches, PREG_SET_ORDER);
foreach ($matches as $i => $match) {
$table_pos[$match[1]] = array($match[2], $match[3]);
@@ -26,7 +28,7 @@ foreach (table_status('', true) as $table => $table_status) {
$field["pos"] = $pos;
$schema[$table]["fields"][$name] = $field;
}
$schema[$table]["pos"] = ($table_pos[$table] ? $table_pos[$table] : array($top, 0));
$schema[$table]["pos"] = ($table_pos[$table] ?: array($top, 0));
foreach ($adminer->foreignKeys($table) as $val) {
if (!$val["db"]) {
$left = $base_left;
@@ -50,9 +52,9 @@ foreach (table_status('', true) as $table => $table_status) {
?>
<div id="schema" style="height: <?php echo $top; ?>em;">
<script<?php echo nonce(); ?>>
gid('schema').onselectstart = function () { return false; };
qs('#schema').onselectstart = function () { return false; };
var tablePos = {<?php echo implode(",", $table_pos_js) . "\n"; ?>};
var em = gid('schema').offsetHeight / <?php echo $top; ?>;
var em = qs('#schema').offsetHeight / <?php echo $top; ?>;
document.onmousemove = schemaMousemove;
document.onmouseup = partialArg(schemaMouseup, '<?php echo js_escape(DB); ?>');
</script>
@@ -82,7 +84,10 @@ foreach ($schema as $name => $table) {
$left1 = $left - $table_pos[$name][1];
$i = 0;
foreach ($columns as $target) {
echo "\n<div class='references' title='" . h($target_name) . "' id='refd$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$target]["pos"] . "em; height: 1.25em; background: url(../adminer/static/arrow.gif) no-repeat right center;'><div style='height: .5em; border-bottom: 1px solid Gray; width: " . (-$left1) . "em;'></div></div>";
echo "\n<div class='references' title='" . h($target_name) . "' id='refd$left-" . ($i++) . "' style='left: $left1" . "em; top: " . $table["fields"][$target]["pos"] . "em; height: 1.25em; background: url(../adminer/static/arrow.gif) no-repeat right center;'>"
. "<div style='height: .5em; border-bottom: 1px solid Gray; width: " . (-$left1) . "em;'></div>"
. "</div>"
;
}
}
}

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
$row = $_POST;
if ($_POST && !$error) {
@@ -26,8 +28,7 @@ if (!$row) {
?>
<form action="" method="post">
<p><input name="name" id="name" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<?php echo script("focus(gid('name'));"); ?>
<p><input name="name" autofocus value="<?php echo h($row["name"]); ?>" autocapitalize="off">
<input type="submit" value="<?php echo lang('Save'); ?>">
<?php
if ($_GET["ns"] != "") {

View File

@@ -1,4 +1,6 @@
<?php
namespace Adminer;
header("Content-Type: text/javascript; charset=utf-8");
if ($_GET["script"] == "db") {
@@ -12,10 +14,12 @@ if ($_GET["script"] == "db") {
foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
if ($table_status[$key] != "") {
$val = format_number($table_status[$key]);
json_row("$key-$name", ($key == "Rows" && $val && $table_status["Engine"] == ($jush == "pgsql" ? "table" : "InnoDB")
if ($val >= 0) {
json_row("$key-$name", ($key == "Rows" && $val && $table_status["Engine"] == (JUSH == "pgsql" ? "table" : "InnoDB")
? "~ $val"
: $val
));
}
if (isset($sums[$key])) {
// ignore innodb_file_per_table because it is not active for tables created before it was enabled
$sums[$key] += ($table_status["Engine"] != "InnoDB" || $key != "Data_free" ? $table_status[$key] : 0);

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