2009-07-03 04:40:48 +00:00
< ? php
2025-03-05 11:28:53 +01:00
namespace Adminer ;
2025-03-29 15:17:39 +01:00
// any method change in this file should be transferred to editor/include/adminer.inc.php
2011-05-24 17:16:13 +02:00
2025-03-29 20:56:19 +01:00
/** Default Adminer plugin; it should call methods via adminer()->f() instead of $this->f() to give chance to other plugins */
2009-07-27 11:25:37 +00:00
class Adminer {
2025-03-29 20:56:19 +01:00
/** @var Adminer|Plugins */ static $instance ;
2025-03-28 09:20:10 +01:00
/** @visibility protected(set) */ public string $error = '' ; // HTML
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Name in title and navigation
2011-04-03 08:27:34 -07:00
* @ return string HTML code
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function name () : string {
2025-04-04 17:44:49 +02:00
return " <a href='https://www.adminer.org/' " . target_blank () . " id='h1'><img src='../adminer/static/logo.png' width='24' height='24' alt='' id='logo'>Adminer</a> " ;
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Connection parameters
2025-03-25 15:08:13 +01:00
* @ return array { string , string , string }
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function credentials () : array {
2013-08-10 19:06:21 -07:00
return array ( SERVER , $_GET [ " username " ], get_password ());
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2018-02-07 12:13:58 +01:00
/** Get SSL connection options
2025-03-26 15:38:04 +01:00
* @ return string [] | void
2018-02-07 12:13:58 +01:00
*/
function connectSsl () {
}
2009-12-18 17:39:48 +00:00
/** Get key used for permanent login
2025-03-29 15:21:25 +01:00
* @ return string cryptic string which gets combined with password or '' in case of an error
2009-12-18 17:39:48 +00:00
*/
2025-03-28 09:03:09 +01:00
function permanentLogin ( bool $create = false ) : string {
2013-06-11 11:02:17 +02:00
return password_file ( $create );
2009-12-18 17:39:48 +00:00
}
2013-07-24 13:00:37 -07:00
2025-03-28 09:13:36 +01:00
/** Return key used to group brute force attacks; behind a reverse proxy, you want to return the last part of X-Forwarded-For */
2025-03-28 09:03:09 +01:00
function bruteForceKey () : string {
2014-03-21 22:47:34 -07:00
return $_SERVER [ " REMOTE_ADDR " ];
}
2025-02-21 13:53:18 +01:00
2018-02-08 14:27:44 +01:00
/** Get server name displayed in breadcrumbs
* @ return string HTML code or null
*/
2025-03-28 11:46:17 +01:00
function serverName ( ? string $server ) : string {
2018-02-08 14:27:44 +01:00
return h ( $server );
}
2014-03-21 22:47:34 -07:00
2025-03-28 09:13:36 +01:00
/** Identifier of selected database */
2025-03-28 13:15:14 +01:00
function database () : ? string {
2009-08-29 13:54:25 +00:00
// should be used everywhere instead of DB
return DB ;
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2012-02-23 22:54:48 -08:00
/** Get cached list of databases
2025-03-25 13:08:03 +01:00
* @ return list < string >
2012-02-23 22:54:48 -08:00
*/
2025-03-28 09:03:09 +01:00
function databases ( bool $flush = true ) : array {
2012-02-23 22:54:48 -08:00
return get_databases ( $flush );
}
2013-07-24 13:00:37 -07:00
2025-04-07 20:54:51 +02:00
/** Print links after list of plugins */
function pluginsLinks () : void {
}
2025-03-28 14:22:42 +01:00
/** Operators used in select
* @ return list < string > operators
*/
function operators () : array {
2025-03-29 21:00:44 +01:00
return driver () -> operators ;
2025-03-28 14:22:42 +01:00
}
2013-10-24 22:16:24 -07:00
/** Get list of schemas
2025-03-25 13:08:03 +01:00
* @ return list < string >
2013-10-24 22:16:24 -07:00
*/
2025-03-28 09:03:09 +01:00
function schemas () : array {
2013-10-24 22:16:24 -07:00
return schemas ();
}
2012-08-19 17:12:19 -07:00
/** Specify limit for waiting on some slow queries like DB list
* @ return float number of seconds
*/
2025-03-28 09:03:09 +01:00
function queryTimeout () : float {
2018-03-09 18:06:52 +01:00
return 2 ;
2012-08-19 17:12:19 -07:00
}
2013-07-24 13:00:37 -07:00
2025-06-28 22:11:03 +02:00
/** Called after connecting and selecting a database */
function afterConnect () : void {
}
2025-03-28 09:13:36 +01:00
/** Headers to send before HTML output */
2025-03-28 09:03:09 +01:00
function headers () : void {
2010-10-17 22:13:32 +02:00
}
2013-07-24 13:00:37 -07:00
2018-01-09 18:53:17 +01:00
/** Get Content Security Policy headers
2025-03-31 20:20:09 +02:00
* @ param list < string [] > $csp of arrays with directive name in key , allowed sources in value
* @ return list < string [] > same as $csp
2018-01-09 18:53:17 +01:00
*/
2025-03-31 20:20:09 +02:00
function csp ( array $csp ) : array {
return $csp ;
2018-01-09 18:53:17 +01:00
}
2011-03-23 11:57:35 +01:00
/** Print HTML code inside < head >
2025-03-28 07:06:34 +01:00
* @ param bool $dark dark CSS : false to disable , true to force , null to base on user preferences
2025-03-15 01:49:42 +01:00
* @ return bool true to link favicon . ico
2011-03-23 11:57:35 +01:00
*/
2025-04-01 19:09:46 +02:00
function head ( ? bool $dark = null ) : bool {
2025-03-15 02:18:09 +01:00
// this is matched by compile.php
2025-03-15 01:49:42 +01:00
echo " <link rel='stylesheet' href='../externals/jush/jush.css'> \n " ;
echo ( $dark !== false ? " <link rel='stylesheet' " . ( $dark ? " " : " media='(prefers-color-scheme: dark)' " ) . " href='../externals/jush/jush-dark.css'> \n " : " " );
2011-03-23 11:57:35 +01:00
return true ;
}
2013-07-24 13:00:37 -07:00
2025-04-13 08:24:16 +02:00
/** Print extra classes in <body class>; must start with a space */
function bodyClass () : void {
echo " adminer " ;
}
2018-01-23 12:15:38 +01:00
/** Get URLs of the CSS files
2025-04-17 16:57:28 +02:00
* @ return string [] key is URL , value is either 'light' ( supports only light color scheme ), 'dark' or '' ( both )
2018-01-23 12:15:38 +01:00
*/
2025-03-28 09:03:09 +01:00
function css () : array {
2018-01-23 12:15:38 +01:00
$return = array ();
2025-03-15 01:49:42 +01:00
foreach ( array ( " " , " -dark " ) as $mode ) {
$filename = " adminer $mode .css " ;
if ( file_exists ( $filename )) {
2025-04-17 16:57:28 +02:00
$file = file_get_contents ( $filename );
$return [ " $filename ?v= " . crc32 ( $file )] = ( $mode
? " dark "
: ( preg_match ( '~prefers-color-scheme:\s*dark~' , $file ) ? '' : 'light' )
);
2025-03-15 01:49:42 +01:00
}
2018-01-23 12:15:38 +01:00
}
return $return ;
}
2025-03-28 09:13:36 +01:00
/** Print login form */
2025-03-28 09:03:09 +01:00
function loginForm () : void {
2025-02-23 11:42:05 +01:00
echo " <table class='layout'> \n " ;
2025-03-15 02:18:09 +01:00
// this is matched by compile.php
2025-03-29 20:56:19 +01:00
echo adminer () -> loginFormField ( 'driver' , '<tr><th>' . lang ( 'System' ) . '<td>' , html_select ( " auth[driver] " , SqlDriver :: $drivers , DRIVER , " loginDriver(this); " ));
2025-10-28 10:27:50 +01:00
echo adminer () -> loginFormField ( 'server' , '<tr><th>' . lang ( 'Server' ) . '<td>' , '<input name="auth[server]" value="' . h ( SERVER ) . '" title="' . lang ( 'hostname[:port] or :socket' ) . '" placeholder="localhost" autocapitalize="off">' );
2025-03-15 02:18:09 +01:00
// this is matched by compile.php
2025-04-01 18:27:04 +02:00
echo adminer () -> loginFormField ( 'username' , '<tr><th>' . lang ( 'Username' ) . '<td>' , '<input name="auth[username]" id="username" autofocus value="' . h ( $_GET [ " username " ]) . '" autocomplete="username" autocapitalize="off">' . script ( " const authDriver = qs('#username').form['auth[driver]']; authDriver && authDriver.onchange(); " ));
2025-03-29 20:56:19 +01:00
echo adminer () -> loginFormField ( 'password' , '<tr><th>' . lang ( 'Password' ) . '<td>' , '<input type="password" name="auth[password]" autocomplete="current-password">' );
echo adminer () -> loginFormField ( 'db' , '<tr><th>' . lang ( 'Database' ) . '<td>' , '<input name="auth[db]" value="' . h ( $_GET [ " db " ]) . '" autocapitalize="off">' );
2018-02-22 11:36:11 +01:00
echo " </table> \n " ;
2009-12-18 17:49:21 +00:00
echo " <p><input type='submit' value=' " . lang ( 'Login' ) . " '> \n " ;
2012-05-14 00:08:32 -07:00
echo checkbox ( " auth[permanent] " , 1 , $_COOKIE [ " adminer_permanent " ], lang ( 'Permanent login' )) . " \n " ;
2009-07-21 12:19:25 +00:00
}
2025-02-21 13:53:18 +01:00
2018-02-22 11:36:11 +01:00
/** Get login form field
2025-03-28 07:06:34 +01:00
* @ param string $heading HTML
* @ param string $value HTML
2018-02-22 11:36:11 +01:00
*/
2025-03-28 09:03:09 +01:00
function loginFormField ( string $name , string $heading , string $value ) : string {
2025-02-25 17:36:37 +01:00
return $heading . $value . " \n " ;
2018-02-22 11:36:11 +01:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Authorize the user
2016-06-01 09:57:17 -07:00
* @ return mixed true for success , string for error message , false for unknown error
2009-07-27 11:25:37 +00:00
*/
2025-03-28 08:23:20 +01:00
function login ( string $login , string $password ) {
2018-05-07 12:21:31 +02:00
if ( $password == " " ) {
return lang ( 'Adminer does not support accessing a database without a password, <a href="https://www.adminer.org/en/password/"%s>more information</a>.' , target_blank ());
2016-06-01 09:57:17 -07:00
}
2009-07-27 11:25:37 +00:00
return true ;
2009-07-24 10:14:36 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Table caption used in navigation and headings
2025-03-28 12:03:56 +01:00
* @ param TableStatus $tableStatus
2011-03-24 02:19:21 +01:00
* @ return string HTML code , " " to ignore table
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function tableName ( array $tableStatus ) : string {
2009-07-28 16:20:50 +00:00
return h ( $tableStatus [ " Name " ]);
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Field caption used in select and edit
2025-03-30 21:08:06 +02:00
* @ param Field | RoutineField $field
2025-03-28 07:06:34 +01:00
* @ param int $order order of column in select
2011-03-24 02:19:21 +01:00
* @ return string HTML code , " " to ignore field
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function fieldName ( array $field , int $order = 0 ) : string {
2025-03-18 09:25:08 +01:00
$type = $field [ " full_type " ];
$comment = $field [ " comment " ];
return '<span title="' . h ( $type . ( $comment != " " ? ( $type ? " : " : " " ) . $comment : '' )) . '">' . h ( $field [ " field " ]) . '</span>' ;
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2009-09-20 07:31:46 +00:00
/** Print links after select heading
2025-03-28 12:03:56 +01:00
* @ param TableStatus $tableStatus
2025-03-28 11:46:17 +01:00
* @ param ? string $set new item options , NULL for no new item
2009-07-27 11:25:37 +00:00
*/
2025-03-28 11:46:17 +01:00
function selectLinks ( array $tableStatus , ? string $set = " " ) : void {
2025-04-13 16:59:07 +02:00
$name = $tableStatus [ " Name " ];
2013-07-08 23:51:50 -07:00
echo '<p class="links">' ;
2013-07-06 10:31:21 -07:00
$links = array ( " select " => lang ( 'Select data' ));
2014-01-09 00:06:59 -08:00
if ( support ( " table " ) || support ( " indexes " )) {
2013-07-06 10:31:21 -07:00
$links [ " table " ] = lang ( 'Show structure' );
2014-01-09 00:06:59 -08:00
}
2025-02-26 19:21:13 +01:00
$is_view = false ;
2014-01-09 00:06:59 -08:00
if ( support ( " table " )) {
2025-02-26 19:21:13 +01:00
$is_view = is_view ( $tableStatus );
2025-06-11 09:27:51 +02:00
if ( ! $is_view ) {
2013-07-06 10:31:21 -07:00
$links [ " create " ] = lang ( 'Alter table' );
2025-06-11 09:27:51 +02:00
} elseif ( support ( " view " )) {
$links [ " view " ] = lang ( 'Alter view' );
2013-07-06 10:31:21 -07:00
}
2009-09-20 07:31:46 +00:00
}
2012-05-13 23:54:07 -07:00
if ( $set !== null ) {
2009-11-24 09:44:28 +00:00
$links [ " edit " ] = lang ( 'New item' );
}
foreach ( $links as $key => $val ) {
2018-02-08 11:21:33 +01:00
echo " <a href=' " . h ( ME ) . " $key = " . urlencode ( $name ) . ( $key == " edit " ? $set : " " ) . " ' " . bold ( isset ( $_GET [ $key ])) . " > $val </a> " ;
2009-09-20 07:31:46 +00:00
}
2025-03-29 21:00:44 +01:00
echo doc_link ( array ( JUSH => driver () -> tableHelp ( $name , $is_view )), " ? " );
2009-09-20 07:31:46 +00:00
echo " \n " ;
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2010-10-29 13:58:08 +02:00
/** Get foreign keys for table
2025-03-26 02:23:29 +01:00
* @ return ForeignKey [] same format as foreign_keys ()
2010-10-29 13:58:08 +02:00
*/
2025-03-28 09:03:09 +01:00
function foreignKeys ( string $table ) : array {
2010-10-29 13:58:08 +02:00
return foreign_keys ( $table );
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Find backward keys for table
2025-03-26 02:23:29 +01:00
* @ return BackwardKey []
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function backwardKeys ( string $table , string $tableName ) : array {
2009-07-27 11:25:37 +00:00
return array ();
}
2013-07-24 13:00:37 -07:00
2009-09-23 14:28:06 +00:00
/** Print backward keys for row
2025-03-28 12:03:56 +01:00
* @ param BackwardKey [] $backwardKeys
2025-03-28 07:06:34 +01:00
* @ param string [] $row
2009-09-23 14:28:06 +00:00
*/
2025-03-28 09:03:09 +01:00
function backwardKeysPrint ( array $backwardKeys , array $row ) : void {
2009-09-23 14:28:06 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Query printed in select before execution
2025-03-28 07:06:34 +01:00
* @ param string $query query to be executed
* @ param float $start start time of the query
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectQuery ( string $query , float $start , bool $failed = false ) : string {
2018-02-01 12:27:22 +01:00
$return = " </p> \n " ; // required for IE9 inline edit
2025-03-29 21:00:44 +01:00
if ( ! $failed && ( $warnings = driver () -> warnings ())) {
2018-02-01 08:55:09 +01:00
$id = " warnings " ;
2018-02-01 12:27:22 +01:00
$return = " , <a href='# $id '> " . lang ( 'Warnings' ) . " </a> " . script ( " qsl('a').onclick = partial(toggle, ' $id '); " , " " )
. " $return <div id=' $id ' class='hidden'> \n $warnings </div> \n "
2018-02-01 08:55:09 +01:00
;
}
2025-03-06 17:51:20 +01:00
return " <p><code class='jush- " . JUSH . " '> " . h ( str_replace ( " \n " , " " , $query )) . " </code> <span class='time'>( " . format_time ( $start ) . " )</span> "
2018-02-01 12:27:22 +01:00
. ( support ( " sql " ) ? " <a href=' " . h ( ME ) . " sql= " . urlencode ( $query ) . " '> " . lang ( 'Edit' ) . " </a> " : " " )
. $return
;
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2015-03-11 17:52:11 +01:00
/** Query printed in SQL command before execution
2025-03-28 07:06:34 +01:00
* @ param string $query query to be executed
2015-03-11 17:52:11 +01:00
* @ return string escaped query to be printed
*/
2025-03-28 09:03:09 +01:00
function sqlCommandQuery ( string $query ) : string {
2015-03-11 17:52:11 +01:00
return shorten_utf8 ( trim ( $query ), 1000 );
}
2025-03-28 09:13:36 +01:00
/** Print HTML code just before the Execute button in SQL command */
2025-03-28 09:03:09 +01:00
function sqlPrintAfter () : void {
2025-03-23 07:34:33 +01:00
}
2009-07-27 11:25:37 +00:00
/** Description of a row in a table
* @ return string SQL expression , empty string for no description
*/
2025-03-28 09:03:09 +01:00
function rowDescription ( string $table ) : string {
2009-07-27 11:25:37 +00:00
return " " ;
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Get descriptions of selected data
2025-03-28 07:06:34 +01:00
* @ param list < string [] > $rows all data to print
2025-03-30 21:08:06 +02:00
* @ param list < ForeignKey > [] $foreignKeys
2025-03-25 13:08:03 +01:00
* @ return list < string [] >
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function rowDescriptions ( array $rows , array $foreignKeys ) : array {
2009-07-27 11:25:37 +00:00
return $rows ;
}
2013-07-24 13:00:37 -07:00
2013-01-10 17:59:43 -08:00
/** Get a link to use in select table
2025-03-28 07:06:34 +01:00
* @ param string $val raw value of the field
2025-03-28 12:03:56 +01:00
* @ param Field $field
2025-03-26 15:38:04 +01:00
* @ return string | void null to create the default link
2013-01-10 17:59:43 -08:00
*/
2025-03-28 11:46:17 +01:00
function selectLink ( ? string $val , array $field ) {
2013-01-10 17:59:43 -08:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Value printed in select table
2025-03-28 11:46:17 +01:00
* @ param ? string $val HTML - escaped value to print
* @ param ? string $link link to foreign key
2025-03-28 12:03:56 +01:00
* @ param Field $field
2025-03-28 07:06:34 +01:00
* @ param string $original original value before applying editVal () and escaping
2009-07-27 11:25:37 +00:00
*/
2025-03-28 11:46:17 +01:00
function selectVal ( ? string $val , ? string $link , array $field , ? string $original ) : string {
2025-03-13 16:55:17 +01:00
$return = ( $val === null ? " <i>NULL</i> "
: ( preg_match ( " ~char|binary|boolean~ " , $field [ " type " ]) && ! preg_match ( " ~var~ " , $field [ " type " ]) ? " <code> $val </code> "
: ( preg_match ( '~json~' , $field [ " type " ]) ? " <code class='jush-js'> $val </code> "
: $val )
));
2025-09-07 13:44:00 +02:00
if ( is_blob ( $field ) && ! is_utf8 ( $val )) {
2017-03-10 08:19:58 +01:00
$return = " <i> " . lang ( '%d byte(s)' , strlen ( $original )) . " </i> " ;
2009-07-23 11:31:08 +00:00
}
2018-01-30 19:12:49 +01:00
return ( $link ? " <a href=' " . h ( $link ) . " ' " . ( is_url ( $link ) ? target_blank () : " " ) . " > $return </a> " : $return );
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 16:32:56 +00:00
/** Value conversion used in select and edit
2025-03-28 12:03:56 +01:00
* @ param Field $field
2009-07-27 16:32:56 +00:00
*/
2025-03-28 11:46:17 +01:00
function editVal ( ? string $val , array $field ) : ? string {
2012-09-08 22:56:34 -07:00
return $val ;
2009-07-27 16:32:56 +00:00
}
2013-07-24 13:00:37 -07:00
2025-04-06 06:24:55 +02:00
/** Get configuration options for AdminerConfig
* @ return string [] key is config description , value is HTML
*/
function config () : array {
return array ();
}
2015-12-06 01:21:37 +11:00
/** Print table structure in tabular format
2025-03-28 12:03:56 +01:00
* @ param Field [] $fields
2025-03-28 07:06:34 +01:00
* @ param TableStatus $tableStatus
2015-12-06 01:21:37 +11:00
*/
2025-04-01 19:09:46 +02:00
function tableStructurePrint ( array $fields , ? array $tableStatus = null ) : void {
2018-10-27 21:20:56 +02:00
echo " <div class='scrollable'> \n " ;
2025-02-23 11:42:05 +01:00
echo " <table class='nowrap odds'> \n " ;
2015-12-06 01:21:37 +11:00
echo " <thead><tr><th> " . lang ( 'Column' ) . " <td> " . lang ( 'Type' ) . ( support ( " comment " ) ? " <td> " . lang ( 'Comment' ) : " " ) . " </thead> \n " ;
2025-03-29 21:00:44 +01:00
$structured_types = driver () -> structuredTypes ();
2015-12-06 01:21:37 +11:00
foreach ( $fields as $field ) {
2025-02-21 21:27:41 +01:00
echo " <tr><th> " . h ( $field [ " field " ]);
2025-02-22 12:36:58 +01:00
$type = h ( $field [ " full_type " ]);
2025-03-19 22:42:02 +01:00
$collation = h ( $field [ " collation " ]);
echo " <td><span title=' $collation '> "
. ( in_array ( $type , ( array ) $structured_types [ lang ( 'User types' )])
? " <a href=' " . h ( ME . 'type=' . urlencode ( $type )) . " '> $type </a> "
: $type . ( $collation && isset ( $tableStatus [ " Collation " ]) && $collation != $tableStatus [ " Collation " ] ? " $collation " : " " ))
2025-02-22 12:36:58 +01:00
. " </span> "
;
2015-12-06 01:21:37 +11:00
echo ( $field [ " null " ] ? " <i>NULL</i> " : " " );
echo ( $field [ " auto_increment " ] ? " <i> " . lang ( 'Auto Increment' ) . " </i> " : " " );
2025-03-06 19:47:05 +01:00
$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> " : " " );
2018-02-20 16:02:25 +01:00
echo ( support ( " comment " ) ? " <td> " . h ( $field [ " comment " ]) : " " );
2015-12-06 01:21:37 +11:00
echo " \n " ;
}
echo " </table> \n " ;
2018-10-25 19:31:28 +09:00
echo " </div> \n " ;
2015-12-06 01:21:37 +11:00
}
/** Print list of indexes on table in tabular format
2025-03-28 12:03:56 +01:00
* @ param Index [] $indexes
2025-04-17 10:22:32 +02:00
* @ param TableStatus $tableStatus
2015-12-06 01:21:37 +11:00
*/
2025-04-17 10:22:32 +02:00
function tableIndexesPrint ( array $indexes , array $tableStatus ) : void {
2025-04-24 11:14:15 +02:00
$partial = false ;
foreach ( $indexes as $name => $index ) {
$partial |= !! $index [ " partial " ];
}
2025-02-23 11:42:05 +01:00
echo " <table> \n " ;
2025-04-17 10:22:32 +02:00
$default_algorithm = first ( driver () -> indexAlgorithms ( $tableStatus ));
2015-12-06 01:21:37 +11:00
foreach ( $indexes as $name => $index ) {
ksort ( $index [ " columns " ]); // enforce correct columns order
$print = array ();
foreach ( $index [ " columns " ] as $key => $val ) {
$print [] = " <i> " . h ( $val ) . " </i> "
. ( $index [ " lengths " ][ $key ] ? " ( " . $index [ " lengths " ][ $key ] . " ) " : " " )
. ( $index [ " descs " ][ $key ] ? " DESC " : " " )
;
}
2025-04-16 09:07:53 +02:00
echo " <tr title=' " . h ( $name ) . " '> " ;
2025-04-18 14:58:41 +02:00
echo " <th> $index[type] " . ( $default_algorithm && $index [ 'algorithm' ] != $default_algorithm ? " ( $index[algorithm] ) " : " " );
2025-04-16 09:07:53 +02:00
echo " <td> " . implode ( " , " , $print );
2025-04-24 11:14:15 +02:00
if ( $partial ) {
echo " <td> " . ( $index [ 'partial' ] ? " <code class='jush- " . JUSH . " '>WHERE " . h ( $index [ 'partial' ]) : " " );
}
2025-04-16 09:07:53 +02:00
echo " \n " ;
2015-12-06 01:21:37 +11:00
}
echo " </table> \n " ;
}
2009-07-27 14:40:55 +00:00
/** Print columns box in select
2025-03-28 07:06:34 +01:00
* @ param list < string > $select result of selectColumnsProcess ()[ 0 ]
* @ param string [] $columns selectable columns
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectColumnsPrint ( array $select , array $columns ) : void {
2009-09-11 19:26:27 +00:00
print_fieldset ( " select " , lang ( 'Select' ), $select );
2009-07-27 14:40:55 +00:00
$i = 0 ;
2013-07-19 10:35:31 -07:00
$select [ " " ] = array ();
2009-07-27 14:40:55 +00:00
foreach ( $select as $key => $val ) {
2025-03-27 19:56:19 +01:00
$val = idx ( $_GET [ " columns " ], $key , array ());
2018-01-12 17:52:45 +01:00
$column = select_input (
" name='columns[ $i ][col]' " ,
$columns ,
$val [ " col " ],
2018-01-22 13:51:47 +01:00
( $key !== " " ? " selectFieldChange " : " selectAddRow " )
2018-01-12 17:52:45 +01:00
);
2025-03-29 21:00:44 +01:00
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 " ])
2025-03-21 23:41:46 +01:00
. on_help ( " event.target.value && event.target.value.replace(/ | \$ /, '(') + ')' " , 1 )
2018-01-14 10:18:16 +01:00
. script ( " qsl('select').onchange = function () { helpClose(); " . ( $key !== " " ? " " : " qsl('select, input', this.parentNode).onchange(); " ) . " }; " , " " )
2013-07-19 14:10:02 -07:00
. " ( $column ) " : $column ) . " </div> \n " ;
2009-07-27 14:40:55 +00:00
$i ++ ;
}
echo " </div></fieldset> \n " ;
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Print search box in select
2025-03-28 07:06:34 +01:00
* @ param list < string > $where result of selectSearchProcess ()
* @ param string [] $columns selectable columns
* @ param Index [] $indexes
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectSearchPrint ( array $where , array $columns , array $indexes ) : void {
2009-09-11 19:26:27 +00:00
print_fieldset ( " search " , lang ( 'Search' ), $where );
2009-07-27 14:40:55 +00:00
foreach ( $indexes as $i => $index ) {
if ( $index [ " type " ] == " FULLTEXT " ) {
2025-03-05 12:28:01 +01:00
echo " <div>(<i> " . implode ( " </i>, <i> " , array_map ( 'Adminer\h' , $index [ " columns " ])) . " </i>) AGAINST " ;
2025-04-14 17:52:55 +02:00
echo " <input type='search' name='fulltext[ $i ]' value=' " . h ( idx ( $_GET [ " fulltext " ], $i )) . " '> " ;
2018-01-12 22:18:54 +01:00
echo script ( " qsl('input').oninput = selectFieldChange; " , " " );
2009-09-25 12:03:30 +00:00
echo checkbox ( " boolean[ $i ] " , 1 , isset ( $_GET [ " boolean " ][ $i ]), " BOOL " );
2018-01-21 01:25:33 +01:00
echo " </div> \n " ;
2009-07-27 14:40:55 +00:00
}
}
2018-01-12 17:52:45 +01:00
$change_next = " this.parentNode.firstChild.onchange(); " ;
2018-02-06 12:58:06 +01:00
foreach ( array_merge (( array ) $_GET [ " where " ], array ( array ())) as $i => $val ) {
2025-03-29 20:56:19 +01:00
if ( ! $val || ( " $val[col] $val[val] " != " " && in_array ( $val [ " op " ], adminer () -> operators ()))) {
2018-01-12 17:52:45 +01:00
echo " <div> " . select_input (
" name='where[ $i ][col]' " ,
$columns ,
$val [ " col " ],
( $val ? " selectFieldChange " : " selectAddRow " ),
" ( " . lang ( 'anywhere' ) . " ) "
);
2025-03-29 20:56:19 +01:00
echo html_select ( " where[ $i ][op] " , adminer () -> operators (), $val [ " op " ], $change_next );
2018-01-12 17:52:45 +01:00
echo " <input type='search' name='where[ $i ][val]' value=' " . h ( $val [ " val " ]) . " '> " ;
2018-01-12 22:18:54 +01:00
echo script ( " mixin(qsl('input'), { oninput: function () { $change_next }, onkeydown: selectSearchKeydown, onsearch: selectSearchSearch}); " , " " );
2018-01-12 17:52:45 +01:00
echo " </div> \n " ;
2009-07-27 14:40:55 +00:00
}
}
echo " </div></fieldset> \n " ;
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Print order box in select
2025-03-28 07:06:34 +01:00
* @ param list < string > $order result of selectOrderProcess ()
* @ param string [] $columns selectable columns
* @ param Index [] $indexes
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectOrderPrint ( array $order , array $columns , array $indexes ) : void {
2013-04-03 10:10:15 -07:00
print_fieldset ( " sort " , lang ( 'Sort' ), $order );
2009-07-27 14:40:55 +00:00
$i = 0 ;
foreach (( array ) $_GET [ " order " ] as $key => $val ) {
2013-07-06 10:31:21 -07:00
if ( $val != " " ) {
2018-01-12 13:08:21 +01:00
echo " <div> " . select_input ( " name='order[ $i ]' " , $columns , $val , " selectFieldChange " );
2009-09-25 12:03:30 +00:00
echo checkbox ( " desc[ $i ] " , 1 , isset ( $_GET [ " desc " ][ $key ]), lang ( 'descending' )) . " </div> \n " ;
2009-07-27 14:40:55 +00:00
$i ++ ;
}
}
2018-01-12 17:52:45 +01:00
echo " <div> " . select_input ( " name='order[ $i ]' " , $columns , " " , " selectAddRow " );
2013-06-03 08:56:18 -07:00
echo checkbox ( " desc[ $i ] " , 1 , false , lang ( 'descending' )) . " </div> \n " ;
2009-07-27 14:40:55 +00:00
echo " </div></fieldset> \n " ;
}
2013-07-24 13:00:37 -07:00
2025-03-30 21:08:06 +02:00
/** Print limit box in select */
function selectLimitPrint ( int $limit ) : void {
2009-07-27 14:40:55 +00:00
echo " <fieldset><legend> " . lang ( 'Limit' ) . " </legend><div> " ; // <div> for easy styling
2025-03-30 21:08:19 +02:00
echo " <input type='number' name='limit' class='size' value=' " . intval ( $limit ) . " '> " ;
2018-01-12 22:18:54 +01:00
echo script ( " qsl('input').oninput = selectFieldChange; " , " " );
2009-07-27 14:40:55 +00:00
echo " </div></fieldset> \n " ;
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Print text length box in select
2025-03-28 13:15:14 +01:00
* @ param numeric - string $text_length result of selectLengthProcess ()
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectLengthPrint ( string $text_length ) : void {
2012-05-13 23:54:07 -07:00
if ( $text_length !== null ) {
2009-07-27 14:40:55 +00:00
echo " <fieldset><legend> " . lang ( 'Text length' ) . " </legend><div> " ;
2012-12-05 13:11:36 -08:00
echo " <input type='number' name='text_length' class='size' value=' " . h ( $text_length ) . " '> " ;
2009-07-27 14:40:55 +00:00
echo " </div></fieldset> \n " ;
}
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Print action box in select
2025-03-28 07:06:34 +01:00
* @ param Index [] $indexes
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectActionPrint ( array $indexes ) : void {
2009-07-27 14:40:55 +00:00
echo " <fieldset><legend> " . lang ( 'Action' ) . " </legend><div> " ;
echo " <input type='submit' value=' " . lang ( 'Select' ) . " '> " ;
2012-05-16 23:54:56 -07:00
echo " <span id='noindex' title=' " . lang ( 'Full table scan' ) . " '></span> " ;
2018-01-13 22:17:00 +01:00
echo " <script " . nonce () . " > \n " ;
2025-03-20 08:58:20 +01:00
echo " const indexColumns = " ;
2012-05-16 23:54:56 -07:00
$columns = array ();
foreach ( $indexes as $index ) {
2016-08-30 13:23:14 +02:00
$current_key = reset ( $index [ " columns " ]);
if ( $index [ " type " ] != " FULLTEXT " && $current_key ) {
$columns [ $current_key ] = 1 ;
2012-05-16 23:54:56 -07:00
}
}
$columns [ " " ] = 1 ;
foreach ( $columns as $key => $val ) {
json_row ( $key );
}
echo " ; \n " ;
2018-01-12 12:50:09 +01:00
echo " selectFieldChange.call(qs('#form')['select']); \n " ;
2012-05-16 23:54:56 -07:00
echo " </script> \n " ;
2009-07-27 14:40:55 +00:00
echo " </div></fieldset> \n " ;
}
2025-02-21 13:53:18 +01:00
2011-05-24 17:16:13 +02:00
/** Print command box in select
* @ return bool whether to print default commands
*/
2025-03-28 09:03:09 +01:00
function selectCommandPrint () : bool {
2011-05-24 17:16:13 +02:00
return ! information_schema ( DB );
}
2013-07-24 13:00:37 -07:00
2011-05-24 17:16:13 +02:00
/** Print import box in select
* @ return bool whether to print default import
*/
2025-03-28 09:03:09 +01:00
function selectImportPrint () : bool {
2012-08-29 10:08:18 -07:00
return ! information_schema ( DB );
2011-05-24 17:16:13 +02:00
}
2013-07-24 13:00:37 -07:00
2009-07-28 11:18:08 +00:00
/** Print extra text in the end of a select form
2025-03-28 07:06:34 +01:00
* @ param string [] $emailFields fields holding e - mails
* @ param string [] $columns selectable columns
2009-07-28 11:18:08 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectEmailPrint ( array $emailFields , array $columns ) : void {
2009-07-28 11:18:08 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Process columns box in select
2025-03-28 07:06:34 +01:00
* @ param string [] $columns selectable columns
* @ param Index [] $indexes
2025-03-25 13:08:03 +01:00
* @ return list < list < string >> [[ select_expressions ], [ group_expressions ]]
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectColumnsProcess ( array $columns , array $indexes ) : array {
2009-07-27 14:40:55 +00:00
$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 ) {
2025-03-29 21:00:44 +01:00
if ( $val [ " fun " ] == " count " || ( $val [ " col " ] != " " && ( ! $val [ " fun " ] || in_array ( $val [ " fun " ], driver () -> functions ) || in_array ( $val [ " fun " ], driver () -> grouping )))) {
2013-07-06 10:31:21 -07:00
$select [ $key ] = apply_sql_function ( $val [ " fun " ], ( $val [ " col " ] != " " ? idf_escape ( $val [ " col " ]) : " * " ));
2025-03-29 21:00:44 +01:00
if ( ! in_array ( $val [ " fun " ], driver () -> grouping )) {
2009-07-27 14:40:55 +00:00
$group [] = $select [ $key ];
}
}
}
return array ( $select , $group );
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Process search box in select
2025-03-28 07:06:34 +01:00
* @ param Field [] $fields
* @ param Index [] $indexes
2025-03-25 13:08:03 +01:00
* @ return list < string > expressions to join by AND
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectSearchProcess ( array $fields , array $indexes ) : array {
2009-07-27 14:40:55 +00:00
$return = array ();
foreach ( $indexes as $i => $index ) {
2025-04-14 17:52:55 +02:00
if ( $index [ " type " ] == " FULLTEXT " && idx ( $_GET [ " fulltext " ], $i ) != " " ) {
2025-03-05 12:28:01 +01:00
$return [] = " MATCH ( " . implode ( " , " , array_map ( 'Adminer\idf_escape' , $index [ " columns " ])) . " ) AGAINST ( " . q ( $_GET [ " fulltext " ][ $i ]) . ( isset ( $_GET [ " boolean " ][ $i ]) ? " IN BOOLEAN MODE " : " " ) . " ) " ;
2009-07-27 14:40:55 +00:00
}
}
2018-02-06 12:56:18 +01:00
foreach (( array ) $_GET [ " where " ] as $key => $val ) {
2025-04-08 20:35:32 +02:00
$col = $val [ " col " ];
if ( " $col $val[val] " != " " && in_array ( $val [ " op " ], adminer () -> operators ())) {
$conds = array ();
foreach (( $col != " " ? array ( $col => $fields [ $col ]) : $fields ) as $name => $field ) {
$prefix = " " ;
$cond = " $val[op] " ;
if ( preg_match ( '~IN$~' , $val [ " op " ])) {
$in = process_length ( $val [ " val " ]);
$cond .= " " . ( $in != " " ? $in : " (NULL) " );
} elseif ( $val [ " op " ] == " SQL " ) {
$cond = " $val[val] " ; // SQL injection
} elseif ( preg_match ( '~^(I?LIKE) %%$~' , $val [ " op " ], $match )) {
$cond = " $match[1] " . adminer () -> processInput ( $field , " % $val[val] % " );
} elseif ( $val [ " op " ] == " FIND_IN_SET " ) {
$prefix = " $val[op] ( " . q ( $val [ " val " ]) . " , " ;
$cond = " ) " ;
} elseif ( ! preg_match ( '~NULL$~' , $val [ " op " ])) {
$cond .= " " . adminer () -> processInput ( $field , $val [ " val " ]);
}
if ( $col != " " || ( // find anywhere
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 " ]))
)) {
$conds [] = $prefix . driver () -> convertSearch ( idf_escape ( $name ), $val , $field ) . $cond ;
2009-07-27 14:40:55 +00:00
}
}
2025-04-08 20:35:32 +02:00
$return [] =
( count ( $conds ) == 1 ? $conds [ 0 ] :
( $conds ? " ( " . implode ( " OR " , $conds ) . " ) " :
" 1 = 0 "
));
2009-07-27 14:40:55 +00:00
}
}
return $return ;
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Process order box in select
2025-03-28 07:06:34 +01:00
* @ param Field [] $fields
* @ param Index [] $indexes
2025-03-25 13:08:03 +01:00
* @ return list < string > expressions to join by comma
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectOrderProcess ( array $fields , array $indexes ) : array {
2009-07-27 14:40:55 +00:00
$return = array ();
foreach (( array ) $_GET [ " order " ] as $key => $val ) {
2013-07-06 10:31:21 -07:00
if ( $val != " " ) {
2018-02-20 16:27:40 +01:00
$return [] = ( preg_match ( '~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~' , $val ) ? $val : idf_escape ( $val )) //! MS SQL uses []
2013-07-06 10:31:21 -07:00
. ( isset ( $_GET [ " desc " ][ $key ]) ? " DESC " : " " )
;
2009-07-27 14:40:55 +00:00
}
}
return $return ;
}
2013-07-24 13:00:37 -07:00
2025-03-30 21:08:06 +02:00
/** Process limit box in select */
function selectLimitProcess () : int {
return ( isset ( $_GET [ " limit " ]) ? intval ( $_GET [ " limit " ]) : 50 );
2009-07-27 14:40:55 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 14:40:55 +00:00
/** Process length box in select
2025-03-28 13:15:14 +01:00
* @ return numeric - string number of characters to shorten texts , will be escaped , empty string means unlimited
2009-07-27 14:40:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function selectLengthProcess () : string {
2025-03-28 13:15:14 +01:00
return ( isset ( $_GET [ " text_length " ]) ? " $_GET[text_length] " : " 100 " );
2009-07-27 14:40:55 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Process extras in select form
2025-03-28 07:06:34 +01:00
* @ param string [] $where AND conditions
2025-03-30 21:08:06 +02:00
* @ param list < ForeignKey > [] $foreignKeys
2009-07-27 11:25:37 +00:00
* @ return bool true if processed , false to process other parts of form
*/
2025-03-28 09:03:09 +01:00
function selectEmailProcess ( array $where , array $foreignKeys ) : bool {
2009-07-27 11:25:37 +00:00
return false ;
}
2013-07-24 13:00:37 -07:00
2012-08-23 22:17:44 -07:00
/** Build SQL query used in select
2025-03-28 07:06:34 +01:00
* @ param list < string > $select result of selectColumnsProcess ()[ 0 ]
* @ param list < string > $where result of selectSearchProcess ()
* @ param list < string > $group result of selectColumnsProcess ()[ 1 ]
* @ param list < string > $order result of selectOrderProcess ()
* @ param int $limit result of selectLimitProcess ()
* @ param int $page index of page starting at zero
2012-08-23 22:17:44 -07:00
* @ return string empty string to use default query
*/
2025-03-30 21:08:19 +02:00
function selectQueryBuild ( array $select , array $where , array $group , array $order , int $limit , ? int $page ) : string {
2012-08-23 22:17:44 -07:00
return " " ;
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Query printed after execution in the message
2025-03-28 07:06:34 +01:00
* @ param string $query executed query
* @ param string $time elapsed time
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function messageQuery ( string $query , string $time , bool $failed = false ) : string {
2009-11-03 10:55:57 +00:00
restart_session ();
2010-10-15 10:58:08 +02:00
$history = & get_session ( " queries " );
2025-03-26 04:16:17 +01:00
if ( ! idx ( $history , $_GET [ " db " ])) {
2018-01-16 16:22:24 +01:00
$history [ $_GET [ " db " ]] = array ();
}
2012-03-10 02:28:13 -08:00
if ( strlen ( $query ) > 1e6 ) {
2018-12-18 14:45:37 +01:00
$query = preg_replace ( '~[\x80-\xFF]+$~' , '' , substr ( $query , 0 , 1e6 )) . " \n … " ; // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
2011-03-22 15:12:38 +01:00
}
2014-03-07 09:33:37 -08:00
$history [ $_GET [ " db " ]][] = array ( $query , time (), $time ); // not DB - $_GET["db"] is changed in database.inc.php //! respect $_GET["ns"]
2018-02-01 13:08:28 +01:00
$sql_id = " sql- " . count ( $history [ $_GET [ " db " ]]);
2025-08-09 14:08:30 +02:00
$return = " <a href='# $sql_id ' class='toggle'> " . lang ( 'SQL command' ) . " </a> <a href='' class='jsonly copy'>🗐</a> \n " ;
2025-03-29 21:00:44 +01:00
if ( ! $failed && ( $warnings = driver () -> warnings ())) {
2018-02-01 09:21:50 +01:00
$id = " warnings- " . count ( $history [ $_GET [ " db " ]]);
2018-02-01 12:27:22 +01:00
$return = " <a href='# $id ' class='toggle'> " . lang ( 'Warnings' ) . " </a>, $return <div id=' $id ' class='hidden'> \n $warnings </div> \n " ;
2018-02-01 09:21:50 +01:00
}
2018-02-01 12:27:22 +01:00
return " <span class='time'> " . @ date ( " H:i:s " ) . " </span> " // @ - time zone may be not set
2025-10-27 15:05:38 +01:00
. " $return <div id=' $sql_id ' class='hidden'><pre><code class='jush- " . JUSH . " '> " . shorten_utf8 ( $query , 1e4 ) . " </code></pre> "
2014-03-07 09:33:37 -08:00
. ( $time ? " <span class='time'>( $time )</span> " : '' )
2013-08-02 15:11:00 -07:00
. ( 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>'
;
2009-07-27 11:25:37 +00:00
}
2013-07-24 13:00:37 -07:00
2021-02-08 09:23:57 +01:00
/** Print before edit form
2025-03-28 07:06:34 +01:00
* @ param Field [] $fields
* @ param mixed $row
2021-02-08 09:23:57 +01:00
*/
2025-03-28 11:46:17 +01:00
function editRowPrint ( string $table , array $fields , $row , ? bool $update ) : void {
2021-02-08 09:23:57 +01:00
}
2009-07-27 11:25:37 +00:00
/** Functions displayed in edit form
2025-03-30 21:08:06 +02:00
* @ param Field | array { null : bool } $field
* @ return string []
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function editFunctions ( array $field ) : array {
2010-04-22 00:33:46 +00:00
$return = ( $field [ " null " ] ? " NULL/ " : " " );
2021-02-08 17:22:53 +01:00
$update = isset ( $_GET [ " select " ]) || where ( $_GET );
2025-03-29 21:00:44 +01:00
foreach ( array ( driver () -> insertFunctions , driver () -> editFunctions ) as $key => $functions ) {
2021-02-08 17:22:53 +01:00
if ( ! $key || ( ! isset ( $_GET [ " call " ]) && $update )) { // relative functions
2010-04-21 12:01:32 +00:00
foreach ( $functions as $pattern => $val ) {
2013-07-24 16:26:41 -07:00
if ( ! $pattern || preg_match ( " ~ $pattern ~ " , $field [ " type " ])) {
2010-04-21 12:01:32 +00:00
$return .= " / $val " ;
}
}
2021-02-08 17:41:59 +01:00
}
2025-09-07 13:44:00 +02:00
if ( $key && $functions && ! preg_match ( '~set|bool~' , $field [ " type " ]) && ! is_blob ( $field )) {
2021-02-08 17:41:59 +01:00
$return .= " /SQL " ;
2009-08-28 14:09:53 +00:00
}
2009-07-23 11:31:08 +00:00
}
2021-02-08 17:22:53 +01:00
if ( $field [ " auto_increment " ] && ! $update ) {
2014-01-04 14:30:42 -08:00
$return = lang ( 'Auto Increment' );
}
2010-04-21 12:01:32 +00:00
return explode ( " / " , $return );
2009-07-23 11:31:08 +00:00
}
2013-07-24 13:00:37 -07:00
2009-07-27 11:25:37 +00:00
/** Get options to display edit field
2025-03-28 13:15:14 +01:00
* @ param ? string $table null in call . inc . php
2025-03-28 12:03:56 +01:00
* @ param Field $field
2025-03-28 07:06:34 +01:00
* @ param string $attrs attributes to use inside the tag
2025-09-07 17:57:09 +02:00
* @ param string | string [] | false | null $value false means original value
2009-07-28 10:09:05 +00:00
* @ return string custom input field or empty string for default
2009-07-27 11:25:37 +00:00
*/
2025-09-07 17:57:09 +02:00
function editInput ( ? string $table , array $field , string $attrs , $value ) : string {
2009-11-12 15:25:21 +00:00
if ( $field [ " type " ] == " enum " ) {
2025-09-07 17:57:09 +02:00
return ( isset ( $_GET [ " select " ]) ? " <label><input type='radio' $attrs value='orig' checked><i> " . lang ( 'original' ) . " </i></label> " : " " )
. enum_input ( " radio " , $attrs , $field , $value , " NULL " )
2009-11-12 15:25:21 +00:00
;
}
return " " ;
2009-07-23 11:31:08 +00:00
}
2013-07-24 13:00:37 -07:00
2017-10-01 08:45:17 -07:00
/** Get hint for edit field
2025-03-28 13:15:14 +01:00
* @ param ? string $table null in call . inc . php
2025-03-28 12:03:56 +01:00
* @ param Field $field
2017-10-01 08:45:17 -07:00
*/
2025-03-28 13:15:14 +01:00
function editHint ( ? string $table , array $field , ? string $value ) : string {
2017-10-01 08:45:17 -07:00
return " " ;
}
2009-07-27 11:25:37 +00:00
/** Process sent input
2025-03-28 12:03:56 +01:00
* @ param Field $field
2009-07-27 11:25:37 +00:00
* @ return string expression to use in a query
*/
2025-03-28 11:46:17 +01:00
function processInput ( array $field , string $value , ? string $function = " " ) : string {
2013-04-26 12:20:47 -07:00
if ( $function == " SQL " ) {
2011-03-15 17:34:25 +01:00
return $value ; // SQL injection
}
2009-07-27 16:32:56 +00:00
$name = $field [ " field " ];
2013-04-26 23:21:09 -07:00
$return = q ( $value );
2013-07-24 16:26:41 -07:00
if ( preg_match ( '~^(now|getdate|uuid)$~' , $function )) {
2009-07-27 11:25:37 +00:00
$return = " $function () " ;
2013-07-24 16:26:41 -07:00
} elseif ( preg_match ( '~^current_(date|timestamp)$~' , $function )) {
2010-05-18 00:49:37 +02:00
$return = $function ;
2018-02-20 16:27:40 +01:00
} elseif ( preg_match ( '~^([+-]|\|\|)$~' , $function )) {
2009-07-27 11:25:37 +00:00
$return = idf_escape ( $name ) . " $function $return " ;
2013-07-24 16:26:41 -07:00
} elseif ( preg_match ( '~^[+-] interval$~' , $function )) {
2025-07-29 16:47:47 +02:00
$return = idf_escape ( $name ) . " $function " . ( preg_match ( " ~^( \\ d+|'[0-9.: -]') [A-Z_]+ \$ ~i " , $value ) && JUSH != " pgsql " ? $value : $return );
2013-07-24 16:26:41 -07:00
} elseif ( preg_match ( '~^(addtime|subtime|concat)$~' , $function )) {
2009-07-27 11:25:37 +00:00
$return = " $function ( " . idf_escape ( $name ) . " , $return ) " ;
2013-07-24 16:26:41 -07:00
} elseif ( preg_match ( '~^(md5|sha1|password|encrypt)$~' , $function )) {
2009-07-27 11:25:37 +00:00
$return = " $function ( $return ) " ;
}
2012-09-08 22:56:34 -07:00
return unconvert_field ( $field , $return );
2009-07-23 16:22:50 +00:00
}
2013-07-24 13:00:37 -07:00
2025-03-22 21:04:58 +01:00
/** Return export output options
2025-03-25 13:08:03 +01:00
* @ return string []
2009-10-02 12:21:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function dumpOutput () : array {
2009-10-02 12:21:55 +00:00
$return = array ( 'text' => lang ( 'open' ), 'file' => lang ( 'save' ));
if ( function_exists ( 'gzencode' )) {
$return [ 'gz' ] = 'gzip' ;
}
2010-10-29 17:11:00 +02:00
return $return ;
2009-10-02 12:21:55 +00:00
}
2013-07-24 13:00:37 -07:00
2025-03-22 21:04:58 +01:00
/** Return export format options
2025-03-25 13:08:03 +01:00
* @ return string [] empty to disable export
2009-10-02 12:21:55 +00:00
*/
2025-03-28 09:03:09 +01:00
function dumpFormat () : array {
2025-02-25 17:07:27 +01:00
return ( support ( " dump " ) ? array ( 'sql' => 'SQL' ) : array ()) + array ( 'csv' => 'CSV,' , 'csv;' => 'CSV;' , 'tsv' => 'TSV' );
2009-10-02 12:21:55 +00:00
}
2013-07-24 13:00:37 -07:00
2013-04-03 18:49:05 -07:00
/** Export database structure
2025-03-26 13:09:49 +01:00
* @ return void prints data
2013-04-03 18:49:05 -07:00
*/
2025-03-28 09:03:09 +01:00
function dumpDatabase ( string $db ) : void {
2013-04-03 18:49:05 -07:00
}
2013-07-24 13:00:37 -07:00
2010-10-29 17:03:02 +02:00
/** Export table structure
2025-03-28 07:06:34 +01:00
* @ param int $is_view 0 table , 1 view , 2 temporary view table
2025-03-26 13:09:49 +01:00
* @ return void prints data
2010-10-29 17:03:02 +02:00
*/
2025-03-28 09:03:09 +01:00
function dumpTable ( string $table , string $style , int $is_view = 0 ) : void {
2010-10-29 17:03:02 +02:00
if ( $_POST [ " format " ] != " sql " ) {
echo " \xef \xbb \xbf " ; // UTF-8 byte order mark
if ( $style ) {
dump_csv ( array_keys ( fields ( $table )));
}
2015-03-06 09:36:20 -08:00
} else {
2013-04-29 15:42:39 -07:00
if ( $is_view == 2 ) {
$fields = array ();
foreach ( fields ( $table ) as $name => $field ) {
$fields [] = idf_escape ( $name ) . " $field[full_type] " ;
}
$create = " CREATE TABLE " . table ( $table ) . " ( " . implode ( " , " , $fields ) . " ) " ;
} else {
2018-01-22 14:33:21 +01:00
$create = create_sql ( $table , $_POST [ " auto_increment " ], $style );
2013-04-29 15:42:39 -07:00
}
2015-03-06 09:36:20 -08:00
set_utf8mb4 ( $create );
if ( $style && $create ) {
2013-04-29 15:42:39 -07:00
if ( $style == " DROP+CREATE " || $is_view == 1 ) {
echo " DROP " . ( $is_view == 2 ? " VIEW " : " TABLE " ) . " IF EXISTS " . table ( $table ) . " ; \n " ;
2010-10-29 17:03:02 +02:00
}
2013-04-29 15:42:39 -07:00
if ( $is_view == 1 ) {
2012-08-09 09:39:12 -07:00
$create = remove_definer ( $create );
2010-10-29 17:03:02 +02:00
}
2013-04-03 18:49:05 -07:00
echo " $create ; \n \n " ;
2010-10-29 17:03:02 +02:00
}
}
}
2013-07-24 13:00:37 -07:00
2010-10-29 17:03:02 +02:00
/** Export table data
2025-03-26 13:09:49 +01:00
* @ return void prints data
2010-10-29 17:03:02 +02:00
*/
2025-03-28 09:03:09 +01:00
function dumpData ( string $table , string $style , string $query ) : void {
2010-10-29 17:03:02 +02:00
if ( $style ) {
2025-03-06 17:51:20 +01:00
$max_packet = ( JUSH == " sqlite " ? 0 : 1048576 ); // default, minimum is 1024
2025-02-21 21:35:25 +01:00
$fields = array ();
2025-02-26 13:59:47 +01:00
$identity_insert = false ;
2011-02-15 17:22:50 +01:00
if ( $_POST [ " format " ] == " sql " ) {
2013-04-26 22:11:58 -07:00
if ( $style == " TRUNCATE+INSERT " ) {
echo truncate_sql ( $table ) . " ; \n " ;
}
2011-02-15 17:22:50 +01:00
$fields = fields ( $table );
2025-03-06 17:51:20 +01:00
if ( JUSH == " mssql " ) {
2025-02-26 13:59:47 +01:00
foreach ( $fields as $field ) {
if ( $field [ " auto_increment " ]) {
echo " SET IDENTITY_INSERT " . table ( $table ) . " ON; \n " ;
$identity_insert = true ;
break ;
}
}
}
2011-02-15 17:22:50 +01:00
}
2025-09-07 13:44:00 +02:00
$result = connection () -> query ( $query , 1 ); // 1 - MYSQLI_USE_RESULT
2010-10-29 17:03:02 +02:00
if ( $result ) {
$insert = " " ;
$buffer = " " ;
2012-08-09 08:57:45 -07:00
$keys = array ();
2023-12-23 23:01:26 +03:00
$generated = array ();
2012-08-11 22:59:20 -07:00
$suffix = " " ;
2013-04-26 22:57:44 -07:00
$fetch_function = ( $table != '' ? 'fetch_assoc' : 'fetch_row' );
2025-04-04 19:13:03 +02:00
$count = 0 ;
2013-04-26 22:57:44 -07:00
while ( $row = $result -> $fetch_function ()) {
2012-08-09 08:57:45 -07:00
if ( ! $keys ) {
2012-08-11 22:59:20 -07:00
$values = array ();
2012-08-09 08:57:45 -07:00
foreach ( $row as $val ) {
$field = $result -> fetch_field ();
2025-03-27 19:56:19 +01:00
if ( idx ( $fields [ $field -> name ], 'generated' )) {
2023-12-23 23:01:26 +03:00
$generated [ $field -> name ] = true ;
continue ;
}
2012-08-09 08:57:45 -07:00
$keys [] = $field -> name ;
2012-08-11 22:59:20 -07:00
$key = idf_escape ( $field -> name );
$values [] = " $key = VALUES( $key ) " ;
2012-08-09 08:57:45 -07:00
}
2012-08-11 22:59:20 -07:00
$suffix = ( $style == " INSERT+UPDATE " ? " \n ON DUPLICATE KEY UPDATE " . implode ( " , " , $values ) : " " ) . " ; \n " ;
2012-08-09 08:57:45 -07:00
}
2010-10-29 17:03:02 +02:00
if ( $_POST [ " format " ] != " sql " ) {
2011-02-15 17:22:50 +01:00
if ( $style == " table " ) {
2012-08-09 08:57:45 -07:00
dump_csv ( $keys );
2011-02-15 17:22:50 +01:00
$style = " INSERT " ;
}
2010-10-29 17:03:02 +02:00
dump_csv ( $row );
} else {
if ( ! $insert ) {
2025-03-05 12:28:01 +01:00
$insert = " INSERT INTO " . table ( $table ) . " ( " . implode ( " , " , array_map ( 'Adminer\idf_escape' , $keys )) . " ) VALUES " ;
2010-10-29 17:03:02 +02:00
}
foreach ( $row as $key => $val ) {
2023-12-23 23:01:26 +03:00
if ( $generated [ $key ]) {
unset ( $row [ $key ]);
continue ;
}
2013-04-26 22:57:44 -07:00
$field = $fields [ $key ];
2013-04-03 10:24:13 -07:00
$row [ $key ] = ( $val !== null
2019-08-20 09:47:01 +02:00
? unconvert_field ( $field , preg_match ( number_type (), $field [ " type " ]) && ! preg_match ( '~\[~' , $field [ " full_type " ]) && is_numeric ( $val ) ? $val : q (( $val === false ? 0 : $val )))
2013-04-03 10:24:13 -07:00
: " NULL "
);
2010-10-29 17:03:02 +02:00
}
2012-08-11 22:59:20 -07:00
$s = ( $max_packet ? " \n " : " " ) . " ( " . implode ( " , \t " , $row ) . " ) " ;
if ( ! $buffer ) {
$buffer = $insert . $s ;
2025-04-04 19:13:03 +02:00
} elseif ( JUSH == 'mssql'
? $count % 1000 != 0 // https://learn.microsoft.com/en-us/sql/t-sql/queries/table-value-constructor-transact-sql#limitations-and-restrictions
: strlen ( $buffer ) + 4 + strlen ( $s ) + strlen ( $suffix ) < $max_packet // 4 - length specification
) {
2012-08-11 22:59:20 -07:00
$buffer .= " , $s " ;
2010-10-29 17:03:02 +02:00
} else {
2012-08-11 22:59:20 -07:00
echo $buffer . $suffix ;
$buffer = $insert . $s ;
2010-10-29 17:03:02 +02:00
}
}
2025-04-04 19:13:03 +02:00
$count ++ ;
2010-10-29 17:03:02 +02:00
}
2012-08-11 22:59:20 -07:00
if ( $buffer ) {
echo $buffer . $suffix ;
2010-10-29 17:03:02 +02:00
}
2010-10-29 17:29:35 +02:00
} elseif ( $_POST [ " format " ] == " sql " ) {
2025-03-29 21:16:28 +01:00
echo " -- " . str_replace ( " \n " , " " , connection () -> error ) . " \n " ;
2010-10-29 17:03:02 +02:00
}
2025-02-26 13:59:47 +01:00
if ( $identity_insert ) {
echo " SET IDENTITY_INSERT " . table ( $table ) . " OFF; \n " ;
}
2010-10-29 17:03:02 +02:00
}
}
2013-07-24 13:00:37 -07:00
2012-06-29 14:41:47 -07:00
/** Set export filename
* @ return string filename without extension
*/
2025-03-28 09:03:09 +01:00
function dumpFilename ( string $identifier ) : string {
2025-09-08 08:30:13 +02:00
return friendly_url ( $identifier != " " ? $identifier : ( SERVER ? : " localhost " ));
2012-06-29 14:41:47 -07:00
}
2013-07-24 13:00:37 -07:00
2010-10-29 17:03:02 +02:00
/** Send headers for export
* @ return string extension
*/
2025-03-28 09:03:09 +01:00
function dumpHeaders ( string $identifier , bool $multi_table = false ) : string {
2010-10-29 17:03:02 +02:00
$output = $_POST [ " output " ];
2013-07-24 16:26:41 -07:00
$ext = ( preg_match ( '~sql~' , $_POST [ " format " ]) ? " sql " : ( $multi_table ? " tar " : " csv " )); // multiple CSV packed to TAR
2010-10-29 17:03:02 +02:00
header ( " Content-Type: " .
( $output == " gz " ? " application/x-gzip " :
( $ext == " tar " ? " application/x-tar " :
( $ext == " sql " || $output != " file " ? " text/plain " : " text/csv " ) . " ; charset=utf-8 "
2013-04-29 14:00:35 -07:00
)));
2011-02-17 11:43:21 +01:00
if ( $output == " gz " ) {
2025-03-10 18:51:28 +01:00
ob_start ( function ( $string ) {
// ob_start() callback receives an optional parameter $phase but gzencode() accepts optional parameter $level
return gzencode ( $string );
}, 1e6 );
2010-10-29 17:03:02 +02:00
}
return $ext ;
2009-10-02 12:21:55 +00:00
}
2013-07-24 13:00:37 -07:00
2025-03-11 08:59:38 +01:00
/** Print text after export
2025-03-26 13:09:49 +01:00
* @ return void prints data
2025-03-11 08:59:38 +01:00
*/
2025-03-28 09:03:09 +01:00
function dumpFooter () : void {
2025-03-11 08:59:38 +01:00
if ( $_POST [ " format " ] == " sql " ) {
echo " -- " . gmdate ( " Y-m-d H:i:s e " ) . " \n " ;
}
}
2017-09-27 18:09:14 +02:00
/** Set the path of the file for webserver load
* @ return string path of the sql dump file
*/
2025-03-28 09:03:09 +01:00
function importServerPath () : string {
2017-09-27 18:09:14 +02:00
return " adminer.sql " ;
}
2011-01-06 09:30:07 +01:00
/** Print homepage
* @ return bool whether to print default homepage
*/
2025-03-28 09:03:09 +01:00
function homepage () : bool {
2013-07-06 10:31:21 -07:00
echo '<p class="links">' . ( $_GET [ " ns " ] == " " && support ( " database " ) ? '<a href="' . h ( ME ) . 'database=">' . lang ( 'Alter database' ) . " </a> \n " : " " );
2011-06-03 13:49:47 +02:00
echo ( support ( " scheme " ) ? " <a href=' " . h ( ME ) . " scheme='> " . ( $_GET [ " ns " ] != " " ? lang ( 'Alter schema' ) : lang ( 'Create schema' )) . " </a> \n " : " " );
2011-07-12 15:45:55 +02:00
echo ( $_GET [ " ns " ] !== " " ? '<a href="' . h ( ME ) . 'schema=">' . lang ( 'Database schema' ) . " </a> \n " : " " );
2011-06-03 13:50:20 +02:00
echo ( support ( " privileges " ) ? " <a href=' " . h ( ME ) . " privileges='> " . lang ( 'Privileges' ) . " </a> \n " : " " );
2025-06-11 19:33:07 +02:00
if ( $_GET [ " ns " ] !== " " ) {
echo ( support ( " routine " ) ? " <a href='#routines'> " . lang ( 'Routines' ) . " </a> \n " : " " );
echo ( support ( " sequence " ) ? " <a href='#sequences'> " . lang ( 'Sequences' ) . " </a> \n " : " " );
echo ( support ( " type " ) ? " <a href='#user-types'> " . lang ( 'User types' ) . " </a> \n " : " " );
echo ( support ( " event " ) ? " <a href='#events'> " . lang ( 'Events' ) . " </a> \n " : " " );
}
2011-01-06 09:30:07 +01:00
return true ;
}
2013-07-24 13:00:37 -07:00
2025-03-22 21:04:58 +01:00
/** Print navigation after Adminer title
2025-03-28 07:06:34 +01:00
* @ param string $missing can be " auth " if there is no database connection , " db " if there is no database selected , " ns " with invalid schema
2009-07-27 11:25:37 +00:00
*/
2025-03-28 09:03:09 +01:00
function navigation ( string $missing ) : void {
2025-04-04 17:29:14 +02:00
echo " <h1> " . adminer () -> name () . " <span class='version'> " . VERSION ;
2025-03-18 16:45:15 +01:00
$new_version = $_COOKIE [ " adminer_version " ];
2025-03-28 17:52:49 +01:00
echo " <a href='https://www.adminer.org/#download' " . target_blank () . " id='version'> " . ( version_compare ( VERSION , $new_version ) < 0 ? h ( $new_version ) : " " ) . " </a> " ;
2025-03-18 16:45:15 +01:00
echo " </span></h1> \n " ;
2025-03-15 02:18:09 +01:00
// this is matched by compile.php
2025-02-23 11:18:28 +01:00
switch_lang ();
2010-05-06 14:21:22 +02:00
if ( $missing == " auth " ) {
2019-07-19 13:52:24 +02:00
$output = " " ;
2013-07-05 08:28:37 -07:00
foreach (( array ) $_SESSION [ " pwds " ] as $vendor => $servers ) {
2010-05-06 14:21:22 +02:00
foreach ( $servers as $server => $usernames ) {
2025-03-28 22:39:12 +01:00
$name = h ( get_setting ( " vendor- $vendor - $server " ) ? : get_driver ( $vendor ));
2010-05-06 14:21:22 +02:00
foreach ( $usernames as $username => $password ) {
2012-05-13 23:54:07 -07:00
if ( $password !== null ) {
2013-07-05 08:28:37 -07:00
$dbs = $_SESSION [ " db " ][ $vendor ][ $server ][ $username ];
2012-09-08 21:29:16 -07:00
foreach (( $dbs ? array_keys ( $dbs ) : array ( " " )) as $db ) {
2025-06-23 19:08:55 +02:00
$output .= " <li><a href=' " . h ( auth_url ( $vendor , $server , $username , $db )) . " '>( $name ) " . h ( " $username @ " . ( $server != " " ? adminer () -> serverName ( $server ) : " " ) . ( $db != " " ? " - $db " : " " )) . " </a> \n " ;
2012-09-08 21:29:16 -07:00
}
2010-05-06 14:21:22 +02:00
}
}
}
}
2019-07-19 13:52:24 +02:00
if ( $output ) {
echo " <ul id='logins'> \n $output </ul> \n " . script ( " mixin(qs('#logins'), { onmouseover: menuOver, onmouseout: menuOut}); " );
}
2010-05-06 14:21:22 +02:00
} else {
2021-02-12 09:53:20 +01:00
$tables = array ();
2014-01-30 09:06:58 -08:00
if ( $_GET [ " ns " ] !== " " && ! $missing && DB != " " ) {
2025-03-29 21:16:28 +01:00
connection () -> select_db ( DB );
2014-01-30 09:06:58 -08:00
$tables = table_status ( '' , true );
}
2025-03-29 20:56:19 +01:00
adminer () -> syntaxHighlighting ( $tables );
adminer () -> databasesPrint ( $missing );
2024-10-14 09:52:18 +02:00
$actions = array ();
2010-10-19 17:29:27 +02:00
if ( DB == " " || ! $missing ) {
2024-10-14 09:52:18 +02:00
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> " ;
}
2025-02-25 17:07:27 +01:00
$actions [] = " <a href=' " . h ( ME ) . " dump= " . urlencode ( isset ( $_GET [ " table " ]) ? $_GET [ " table " ] : $_GET [ " select " ]) . " ' id='dump' " . bold ( isset ( $_GET [ " dump " ])) . " > " . lang ( 'Export' ) . " </a> " ;
2010-10-19 17:29:27 +02:00
}
2024-10-14 09:52:18 +02:00
$in_db = $_GET [ " ns " ] !== " " && ! $missing && DB != " " ;
2025-03-18 12:53:40 +01:00
if ( $in_db ) {
2024-10-14 09:52:18 +02:00
$actions [] = '<a href="' . h ( ME ) . 'create="' . bold ( $_GET [ " create " ] === " " ) . " > " . lang ( 'Create table' ) . " </a> " ;
}
echo ( $actions ? " <p class='links'> \n " . implode ( " \n " , $actions ) . " \n " : " " );
if ( $in_db ) {
if ( $tables ) {
2025-03-29 20:56:19 +01:00
adminer () -> tablesPrint ( $tables );
2024-10-14 09:52:18 +02:00
} else {
echo " <p class='message'> " . lang ( 'No tables.' ) . " </p> \n " ;
2012-07-29 16:05:37 -07:00
}
}
2009-09-19 20:16:15 +00:00
}
}
2013-07-24 13:00:37 -07:00
2025-03-16 13:52:04 +01:00
/** Set up syntax highlight for code and < textarea >
2025-03-28 12:03:56 +01:00
* @ param TableStatus [] $tables
2025-03-16 13:52:04 +01:00
*/
2025-03-28 09:03:09 +01:00
function syntaxHighlighting ( array $tables ) : void {
2025-03-16 13:52:04 +01:00
// this is matched by compile.php
2025-04-07 14:12:44 +02:00
echo script_src ( " ../externals/jush/modules/jush.js " , true );
echo script_src ( " ../externals/jush/modules/jush-autocomplete-sql.js " , true );
echo script_src ( " ../externals/jush/modules/jush-textarea.js " , true );
echo script_src ( " ../externals/jush/modules/jush-txt.js " , true );
echo script_src ( " ../externals/jush/modules/jush-js.js " , true );
2025-03-16 13:52:04 +01:00
if ( support ( " sql " )) {
2025-04-07 14:12:44 +02:00
echo script_src ( " ../externals/jush/modules/jush- " . JUSH . " .js " , true );
2025-03-16 13:52:04 +01:00
echo " <script " . nonce () . " > \n " ;
if ( $tables ) {
$links = array ();
foreach ( $tables as $table => $type ) {
$links [] = preg_quote ( $table , '/' );
}
2025-07-07 15:01:46 +02:00
echo " var jushLinks = { " . JUSH . " : " ;
json_row ( js_escape ( ME ) . ( support ( " table " ) ? " table " : " select " ) . '=$&' , '/\b(' . implode ( '|' , $links ) . ')\b/g' , false );
if ( support ( 'routine' )) {
foreach ( routines () as $row ) {
json_row ( js_escape ( ME ) . 'function=' . urlencode ( $row [ " SPECIFIC_NAME " ]) . '&name=$&' , '/\b' . preg_quote ( $row [ " ROUTINE_NAME " ], '/' ) . '(?=["`]?\()/g' , false );
}
}
json_row ( '' );
echo " }; \n " ;
2025-03-16 13:52:04 +01:00
foreach ( array ( " bac " , " bra " , " sqlite_quo " , " mssql_bra " ) as $val ) {
echo " jushLinks. $val = jushLinks. " . JUSH . " ; \n " ;
}
2025-04-08 16:57:25 +02:00
if ( isset ( $_GET [ " sql " ]) || isset ( $_GET [ " trigger " ]) || isset ( $_GET [ " check " ])) {
$tablesColumns = array_fill_keys ( array_keys ( $tables ), array ());
foreach ( driver () -> allFields () as $table => $fields ) {
foreach ( $fields as $field ) {
$tablesColumns [ $table ][] = $field [ " field " ];
}
2025-04-03 15:07:27 +02:00
}
2025-04-08 16:57:25 +02:00
echo " addEventListener('DOMContentLoaded', () => { autocompleter = jush.autocompleteSql(' " . idf_escape ( " " ) . " ', " . json_encode ( $tablesColumns ) . " ); }); \n " ;
2025-04-03 15:07:27 +02:00
}
2025-03-16 13:52:04 +01:00
}
echo " </script> \n " ;
}
2025-04-07 14:12:44 +02:00
echo script ( " syntaxHighlighting(' " . preg_replace ( '~^(\d\.?\d).*~s' , '\1' , connection () -> server_info ) . " ', ' " . connection () -> flavor . " '); " );
2025-03-16 13:52:04 +01:00
}
2025-03-28 09:13:36 +01:00
/** Print databases list in menu */
2025-03-28 09:03:09 +01:00
function databasesPrint ( string $missing ) : void {
2025-03-29 20:56:19 +01:00
$databases = adminer () -> databases ();
2021-02-07 14:28:16 +01:00
if ( DB && $databases && ! in_array ( DB , $databases )) {
2018-03-01 12:09:10 +01:00
array_unshift ( $databases , DB );
}
2025-03-18 16:45:15 +01:00
echo " <form action=''> \n <p id='dbs'> \n " ;
2013-06-25 09:58:08 -07:00
hidden_fields_get ();
2018-02-01 22:22:29 +01:00
$db_events = script ( " mixin(qsl('select'), { onmousedown: dbMouseDown, onchange: dbChange}); " );
2025-04-07 11:23:34 +02:00
echo " <label title=' " . lang ( 'Database' ) . " '> " . lang ( 'DB' ) . " : " . ( $databases
2025-03-08 19:57:36 +01:00
? html_select ( " db " , array ( " " => " " ) + $databases , DB ) . $db_events
2025-02-22 08:12:04 +01:00
: " <input name='db' value=' " . h ( DB ) . " ' autocapitalize='off' size='19'> \n "
2025-04-07 11:23:34 +02:00
) . " </label> " ;
2013-06-25 09:58:08 -07:00
echo " <input type='submit' value=' " . lang ( 'Use' ) . " ' " . ( $databases ? " class='hidden' " : " " ) . " > \n " ;
2021-02-12 16:08:40 +01:00
if ( support ( " scheme " )) {
2025-03-29 21:16:28 +01:00
if ( $missing != " db " && DB != " " && connection () -> select_db ( DB )) {
2025-04-07 11:23:34 +02:00
echo " <br><label> " . lang ( 'Schema' ) . " : " . html_select ( " ns " , array ( " " => " " ) + adminer () -> schemas (), $_GET [ " ns " ]) . " $db_events </label> " ;
2012-08-20 22:03:39 -07:00
if ( $_GET [ " ns " ] != " " ) {
set_schema ( $_GET [ " ns " ]);
}
}
}
2018-03-09 18:18:45 +01:00
foreach ( array ( " import " , " sql " , " schema " , " dump " , " privileges " ) as $val ) {
if ( isset ( $_GET [ $val ])) {
2025-03-18 17:15:10 +01:00
echo input_hidden ( $val );
2018-03-09 18:18:45 +01:00
break ;
}
}
2012-08-20 22:03:39 -07:00
echo " </p></form> \n " ;
}
2013-07-24 13:00:37 -07:00
2025-03-22 21:04:58 +01:00
/** Print table list in menu
2025-03-28 12:03:56 +01:00
* @ param TableStatus [] $tables
2009-09-19 20:16:15 +00:00
*/
2025-03-28 09:03:09 +01:00
function tablesPrint ( array $tables ) : void {
2018-01-12 15:27:44 +01:00
echo " <ul id='tables'> " . script ( " mixin(qs('#tables'), { onmouseover: menuOver, onmouseout: menuOut}); " );
2013-04-26 20:04:57 -07:00
foreach ( $tables as $table => $status ) {
2025-04-09 06:27:09 +02:00
$table = " $table " ; // do not highlight "0" as active everywhere
2025-03-29 20:56:19 +01:00
$name = adminer () -> tableName ( $status );
2025-06-03 15:05:12 +02:00
if ( $name != " " && ! $status [ " partition " ]) {
2021-01-27 00:30:44 +01:00
echo '<li><a href="' . h ( ME ) . 'select=' . urlencode ( $table ) . '"'
. bold ( $_GET [ " select " ] == $table || $_GET [ " edit " ] == $table , " select " )
. " title=' " . lang ( 'Select data' ) . " '> " . lang ( 'select' ) . " </a> "
;
2018-02-08 10:35:54 +01:00
echo ( support ( " table " ) || support ( " indexes " )
? '<a href="' . h ( ME ) . 'table=' . urlencode ( $table ) . '"'
2025-04-06 07:04:49 +02:00
. bold ( in_array ( $table , array ( $_GET [ " table " ], $_GET [ " create " ], $_GET [ " indexes " ], $_GET [ " foreign " ], $_GET [ " trigger " ], $_GET [ " check " ], $_GET [ " view " ])), ( is_view ( $status ) ? " view " : " structure " ))
2018-02-08 10:35:54 +01:00
. " title=' " . lang ( 'Show structure' ) . " '> $name </a> "
: " <span> $name </span> "
) . " \n " ;
}
2009-07-03 06:26:01 +00:00
}
2014-12-08 00:01:52 +01:00
echo " </ul> \n " ;
2009-07-03 06:26:01 +00:00
}
2025-05-06 19:02:46 +02:00
2025-10-26 15:15:10 +01:00
/** Get server variables
* @ return list < string [] > [[ $name , $value ]]
*/
function showVariables () : array {
return show_variables ();
}
/** Get status variables
* @ return list < string [] > [[ $name , $value ]]
*/
function showStatus () : array {
return show_status ();
}
2025-05-06 19:02:46 +02:00
/** Get process list
* @ return list < string [] > [ $row ]
*/
function processList () : array {
return process_list ();
}
/** Kill a process
* @ param numeric - string $id
* @ return Result | bool
*/
function killProcess ( string $id ) {
return kill_process ( $id );
}
2009-07-03 04:40:48 +00:00
}