2009-07-03 06:26:01 +00:00
< ? php
2009-07-27 11:25:37 +00:00
class Adminer {
function name () {
return lang ( 'Editor' );
}
function credentials () {
return array (); // default INI settings
}
function database () {
2009-07-30 14:12:18 +00:00
global $dbh ;
2009-07-28 11:04:49 +00:00
$dbs = get_databases ( false );
2009-07-30 14:12:18 +00:00
return ( ! $dbs
? $dbh -> result ( $dbh -> query ( " SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1) " )) // username without the database list
: $dbs [( information_schema ( $dbs [ 0 ]) ? 1 : 0 )] // first available database
);
2009-07-27 11:25:37 +00:00
}
function loginForm ( $username ) {
2009-07-21 12:19:25 +00:00
?>
2009-07-21 15:25:05 +00:00
< table cellspacing = " 0 " >
2009-09-09 20:47:42 +00:00
< tr >< th >< ? php echo lang ( 'Username' ); ?> <td><input type="hidden" name="server" value=""><input name="username" value="<?php echo h($username); ?>">
2009-07-21 15:25:05 +00:00
< tr >< th >< ? php echo lang ( 'Password' ); ?> <td><input type="password" name="password">
</ table >
2009-07-21 12:19:25 +00:00
< ? php
}
2009-07-27 11:25:37 +00:00
function login ( $login , $password ) {
return true ;
}
function tableName ( $tableStatus ) {
2009-07-28 16:20:50 +00:00
return h ( strlen ( $tableStatus [ " Comment " ]) ? $tableStatus [ " Comment " ] : $tableStatus [ " Name " ]);
2009-07-27 11:25:37 +00:00
}
2009-07-27 16:51:40 +00:00
function fieldName ( $field , $order = 0 ) {
2009-07-28 16:20:50 +00:00
return h ( strlen ( $field [ " comment " ]) ? $field [ " comment " ] : $field [ " field " ]);
2009-07-27 11:25:37 +00:00
}
function selectLinks ( $tableStatus ) {
return " " ;
}
function backwardKeys ( $table ) {
global $dbh ;
$return = array ();
$result = $dbh -> query ( " SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
2009-07-22 11:36:27 +00:00
FROM information_schema . KEY_COLUMN_USAGE
2009-07-27 11:25:37 +00:00
WHERE TABLE_SCHEMA = " . $dbh->quote ( $this->database ()) . "
AND REFERENCED_TABLE_SCHEMA = " . $dbh->quote ( $this->database ()) . "
2009-07-22 11:36:27 +00:00
AND REFERENCED_TABLE_NAME = " . $dbh->quote ( $table ) . "
2009-07-24 06:05:21 +00:00
ORDER BY ORDINAL_POSITION " ); //! requires MySQL 5
2009-07-27 11:25:37 +00:00
if ( $result ) {
while ( $row = $result -> fetch_assoc ()) {
$return [ $row [ " TABLE_NAME " ]][ $row [ " CONSTRAINT_NAME " ]][ $row [ " COLUMN_NAME " ]] = $row [ " REFERENCED_COLUMN_NAME " ];
}
2009-07-22 11:04:03 +00:00
}
2009-07-27 11:25:37 +00:00
return $return ;
2009-07-22 11:04:03 +00:00
}
2009-07-27 11:25:37 +00:00
function selectQuery ( $query ) {
return " <!-- " . str_replace ( " -- " , " --><!-- " , $query ) . " --> \n " ;
}
function rowDescription ( $table ) {
// first varchar column
foreach ( fields ( $table ) as $field ) {
if ( $field [ " type " ] == " varchar " ) {
2009-07-30 15:37:20 +00:00
return idf_escape ( $field [ " field " ]);
2009-07-27 11:25:37 +00:00
}
2009-07-23 14:42:38 +00:00
}
2009-07-30 15:37:20 +00:00
return " " ;
2009-07-23 14:42:38 +00:00
}
2009-07-27 11:25:37 +00:00
function rowDescriptions ( $rows , $foreignKeys ) {
global $dbh ;
$return = $rows ;
foreach ( $rows [ 0 ] as $key => $val ) {
foreach (( array ) $foreignKeys [ $key ] as $foreignKey ) {
if ( count ( $foreignKey [ " source " ]) == 1 ) {
$id = idf_escape ( $foreignKey [ " target " ][ 0 ]);
$name = $this -> rowDescription ( $foreignKey [ " table " ]);
if ( strlen ( $name )) {
// find all used ids
$ids = array ();
foreach ( $rows as $row ) {
$ids [ $row [ $key ]] = $dbh -> quote ( $row [ $key ]);
}
// uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow
$descriptions = array ();
$result = $dbh -> query ( " SELECT $id , $name FROM " . idf_escape ( $foreignKey [ " table " ]) . " WHERE $id IN ( " . implode ( " , " , $ids ) . " ) " );
while ( $row = $result -> fetch_row ()) {
$descriptions [ $row [ 0 ]] = $row [ 1 ];
}
// use the descriptions
foreach ( $rows as $n => $row ) {
$return [ $n ][ $key ] = $descriptions [ $row [ $key ]];
}
break ;
2009-07-23 14:42:38 +00:00
}
2009-07-20 15:34:05 +00:00
}
}
}
2009-07-27 11:25:37 +00:00
return $return ;
2009-07-20 15:34:05 +00:00
}
2009-07-27 11:25:37 +00:00
function selectVal ( $val , $link , $field ) {
$return = ( $val == " <i>NULL</i> " ? " " : $val );
if ( ereg ( 'blob|binary' , $field [ " type " ]) && ! is_utf8 ( $val )) {
$return = lang ( '%d byte(s)' , strlen ( $val ));
if ( ereg ( " ^(GIF| \xFF \xD8 \xFF | \x89 \x50 \x4E \x47 \x0D \x0A \x1A \x0A ) " , $val )) { // GIF|JPG|PNG, getimagetype() works with filename
2009-07-30 14:55:09 +00:00
$return = " <img src=' $link ' alt=' $return '> " ;
2009-07-27 11:25:37 +00:00
}
2009-07-24 10:14:36 +00:00
}
2009-07-28 10:09:05 +00:00
if ( $field [ " full_type " ] == " tinyint(1) " && $return != " " ) { // bool
2009-07-28 16:20:50 +00:00
$return = '<img src="' . ( $val ? " ../adminer/plus.gif " : " ../adminer/cross.gif " ) . '" alt="' . h ( $val ) . '">' ;
2009-07-28 10:09:05 +00:00
}
2009-07-30 14:55:09 +00:00
return ( $link ? " <a href=' $link '> $return </a> " : $return );
2009-07-24 10:14:36 +00:00
}
2009-07-27 11:25:37 +00:00
2009-07-27 16:32:56 +00:00
function editVal ( $val , $field ) {
if ( ereg ( 'date|timestamp' , $field [ " type " ])) {
return preg_replace ( '~^([0-9]{2}([0-9]+))-(0?([0-9]+))-(0?([0-9]+))~' , lang ( '$1-$3-$5' ), $val );
}
return $val ;
}
2009-07-27 14:40:55 +00:00
function selectColumnsPrint ( $select , $columns ) {
//! allow grouping functions by indexes
}
function selectSearchPrint ( $where , $columns , $indexes ) {
//! from-to, foreign keys
echo '<fieldset><legend>' . lang ( 'Search' ) . " </legend><div> \n " ;
$i = 0 ;
foreach (( array ) $_GET [ " where " ] as $val ) {
if ( strlen ( " $val[col] $val[val] " )) {
echo " <div><select name='where[ $i ][col]'><option value=''> " . lang ( '(anywhere)' ) . optionlist ( $columns , $val [ " col " ], true ) . " </select> " ;
2009-07-28 16:20:50 +00:00
echo " <input name='where[ $i ][val]' value=' " . h ( $val [ " val " ]) . " '></div> \n " ;
2009-07-27 14:40:55 +00:00
$i ++ ;
}
}
echo " <div><select name='where[ $i ][col]' onchange='select_add_row(this);'><option value=''> " . lang ( '(anywhere)' ) . optionlist ( $columns , null , true ) . " </select> " ;
echo " <input name='where[ $i ][val]'></div> \n " ;
echo " </div></fieldset> \n " ;
}
function selectOrderPrint ( $order , $columns , $indexes ) {
//! desc
$orders = array ();
2009-07-28 14:21:05 +00:00
foreach ( $indexes as $key => $index ) {
2009-07-27 14:40:55 +00:00
$order = array ();
foreach ( $index [ " columns " ] as $val ) {
$order [] = $this -> fieldName ( array ( " field " => $val , " comment " => $columns [ $val ]));
}
2009-07-28 14:21:05 +00:00
if ( count ( array_filter ( $order , 'strlen' )) > 1 && $key != " PRIMARY " ) {
$orders [ $key ] = implode ( " , " , $order );
2009-07-27 14:40:55 +00:00
}
}
if ( $orders ) {
echo '<fieldset><legend>' . lang ( 'Sort' ) . " </legend><div> " ;
2009-07-28 14:23:46 +00:00
echo " <select name='index_order'> " . optionlist ( array ( " " => " " ) + $orders , $_GET [ " index_order " ], true ) . " </select> " ;
2009-07-27 14:40:55 +00:00
echo " </div></fieldset> \n " ;
}
}
function selectLimitPrint ( $limit ) {
echo " <fieldset><legend> " . lang ( 'Limit' ) . " </legend><div> " ; // <div> for easy styling
echo " <select name='limit'> " . optionlist ( array ( " " , " 30 " , " 100 " ), $limit ) . " </select> " ;
echo " </div></fieldset> \n " ;
}
function selectLengthPrint ( $text_length ) {
}
function selectActionPrint () {
echo " <fieldset><legend> " . lang ( 'Action' ) . " </legend><div> " ;
echo " <input type='submit' value=' " . lang ( 'Select' ) . " '> " ;
echo " </div></fieldset> \n " ;
}
2009-09-09 20:47:42 +00:00
function selectEmailPrint ( $emailFields , $columns ) {
2009-07-28 11:18:08 +00:00
global $confirm ;
if ( $emailFields ) {
2009-09-09 20:47:42 +00:00
echo '<fieldset><legend><a href="#fieldset-email" onclick="return !toggle(\'fieldset-email\');">' . lang ( 'E-mail' ) . " </a></legend><div id='fieldset-email' " . ( $_POST [ " email_append " ] ? " " : " class='hidden' " ) . " > \n " ;
2009-09-09 20:49:30 +00:00
echo " <p> " . lang ( 'From' ) . " : <input name='email_from' value=' " . h ( $_POST ? $_POST [ " email_from " ] : $_COOKIE [ " adminer_email " ]) . " '> \n " ;
2009-09-09 20:47:42 +00:00
echo lang ( 'Subject' ) . " : <input name='email_subject' value=' " . h ( $_POST [ " email_subject " ]) . " '> \n " ;
echo " <p><textarea name='email_message' rows='15' cols='60'> " . h ( $_POST [ " email_message " ] . ( $_POST [ " email_append " ] ? '{$' . " $_POST[email_addition] } " : " " )) . " </textarea><br> \n " ;
echo " <select name='email_addition'> " . optionlist ( $columns , $_POST [ " email_addition " ]) . " </select> <input type='submit' name='email_append' value=' " . lang ( 'Insert' ) . " '> \n " ; //! JavaScript
2009-07-28 16:20:50 +00:00
echo " <p> " . ( count ( $emailFields ) == 1 ? '<input type="hidden" name="email_field" value="' . h ( key ( $emailFields )) . '">' : '<select name="email_field">' . optionlist ( $emailFields ) . '</select> ' );
2009-07-28 11:18:08 +00:00
echo " <input type='submit' name='email' value=' " . lang ( 'Send' ) . " ' $confirm > \n " ;
echo " </div></fieldset> \n " ;
}
}
2009-07-27 14:40:55 +00:00
function selectColumnsProcess ( $columns , $indexes ) {
return array ( array (), array ());
}
2009-07-28 14:21:05 +00:00
function selectSearchProcess ( $fields , $indexes ) {
2009-07-27 14:40:55 +00:00
$return = array ();
foreach (( array ) $_GET [ " where " ] as $val ) {
2009-09-01 14:24:08 +00:00
$col = $val [ " col " ];
if ( strlen ( " $col $val[val] " )) {
$conds = array ();
foreach (( strlen ( $col ) ? array ( $col => $fields [ $col ]) : $fields ) as $name => $field ) {
if ( strlen ( $col ) || is_numeric ( $val [ " val " ]) || ! ereg ( 'int|float|double|decimal' , $field [ " type " ])) {
$text_type = ereg ( 'char|text|enum|set' , $field [ " type " ]);
$value = $this -> processInput ( $field , ( strlen ( $val [ " val " ]) && $text_type && strpos ( $val [ " val " ], " % " ) === false ? " % $val[val] % " : $val [ " val " ]));
$conds [] = idf_escape ( $name ) . ( $value == " NULL " ? " IS " : ( $val [ " op " ] != " = " && $text_type ? " LIKE " : " = " )) . " $value " ;
2009-07-27 14:40:55 +00:00
}
}
2009-09-01 14:24:08 +00:00
$return [] = ( $conds ? " ( " . implode ( " OR " , $conds ) . " ) " : " 0 " );
2009-07-27 14:40:55 +00:00
}
}
return $return ;
}
2009-07-28 14:21:05 +00:00
function selectOrderProcess ( $fields , $indexes ) {
2009-07-28 11:04:49 +00:00
if ( $_GET [ " order " ]) {
return array ( idf_escape ( $_GET [ " order " ][ 0 ]) . ( isset ( $_GET [ " desc " ][ 0 ]) ? " DESC " : " " ));
}
2009-07-28 14:31:03 +00:00
$index_order = $_GET [ " index_order " ];
foreach (( strlen ( $index_order ) ? array ( $indexes [ $index_order ]) : $indexes ) as $index ) {
if ( strlen ( $index_order ) || $index [ " type " ] == " INDEX " ) {
$desc = false ;
foreach ( $index [ " columns " ] as $val ) {
if ( ereg ( 'date|timestamp' , $fields [ $val ][ " type " ])) {
$desc = true ;
break ;
}
2009-07-28 14:21:05 +00:00
}
2009-07-28 14:31:03 +00:00
$return = array ();
foreach ( $index [ " columns " ] as $val ) {
$return [] = idf_escape ( $val ) . ( $desc ? " DESC " : " " );
}
return $return ;
2009-07-28 14:21:05 +00:00
}
}
2009-07-28 14:31:03 +00:00
return array ();
2009-07-27 14:40:55 +00:00
}
function selectLimitProcess () {
return ( isset ( $_GET [ " limit " ]) ? $_GET [ " limit " ] : " 30 " );
}
function selectLengthProcess () {
return " 100 " ;
}
2009-09-09 20:19:27 +00:00
function selectEmailProcess ( $where , $foreignKeys ) {
2009-07-27 11:25:37 +00:00
global $dbh ;
2009-09-09 20:47:42 +00:00
if ( $_POST [ " email_append " ]) {
return true ;
}
2009-07-27 11:25:37 +00:00
if ( $_POST [ " email " ]) {
$sent = 0 ;
if ( $_POST [ " all " ] || $_POST [ " check " ]) {
$field = idf_escape ( $_POST [ " email_field " ]);
2009-09-09 15:54:02 +00:00
$subject = $_POST [ " email_subject " ];
$message = $_POST [ " email_message " ];
preg_match_all ( '~\\{\\$([a-z0-9_]+)\\}~i' , " $subject . $message " , $matches ); // allows {$name} in subject or message
$result = $dbh -> query ( " SELECT DISTINCT $field , " . implode ( " , " , array_map ( 'idf_escape' , array_unique ( $matches [ 1 ]))) . " FROM " . idf_escape ( $_GET [ " select " ])
2009-07-27 11:25:37 +00:00
. " WHERE $field IS NOT NULL AND $field != '' "
. ( $where ? " AND " . implode ( " AND " , $where ) : " " )
. ( $_POST [ " all " ] ? " " : " AND (( " . implode ( " ) OR ( " , array_map ( 'where_check' , ( array ) $_POST [ " check " ])) . " )) " )
);
2009-09-09 20:19:27 +00:00
$rows = array ();
2009-09-09 15:54:02 +00:00
while ( $row = $result -> fetch_assoc ()) {
2009-09-09 20:19:27 +00:00
$rows [] = $row ;
}
foreach ( $this -> rowDescriptions ( $rows , $foreignKeys ) as $row ) {
2009-09-09 15:54:02 +00:00
$replace = array ();
foreach ( $matches [ 1 ] as $val ) {
2009-09-09 20:49:30 +00:00
$replace [ '{$' . " $val } " ] = $row [ $val ]; //! allow literal {$name}
2009-09-09 15:54:02 +00:00
}
$email = $row [ $_POST [ " email_field " ]];
if ( is_email ( $email ) && mail ( $email , email_header ( strtr ( $subject , $replace )), strtr ( $message , $replace ),
2009-07-27 11:25:37 +00:00
" MIME-Version: 1.0 \n Content-Type: text/plain; charset=utf-8 \n Content-Transfer-Encoding: 8bit "
. ( is_email ( $_POST [ " email_from " ]) ? " \n From: $_POST[email_from] " : " " ) //! should allow address with a name but simple application of email_header() adds the default server domain
)) {
$sent ++ ;
}
2009-07-24 10:55:01 +00:00
}
2009-07-24 10:52:24 +00:00
}
2009-09-09 20:49:30 +00:00
cookie ( " adminer_email " , $_POST [ " email_from " ]);
2009-07-27 11:25:37 +00:00
redirect ( remove_from_uri (), lang ( '%d e-mail(s) have been sent.' , $sent ));
2009-07-24 10:52:24 +00:00
}
2009-07-27 11:25:37 +00:00
return false ;
2009-07-24 10:52:24 +00:00
}
2009-07-27 11:25:37 +00:00
function messageQuery ( $query ) {
return " <!-- \n " . str_replace ( " -- " , " --><!-- " , $query ) . " \n --> " ;
}
function editFunctions ( $field ) {
2009-08-28 14:16:44 +00:00
$return = array ( " " => ( $field [ " null " ] || $field [ " auto_increment " ] ? " " : " * " ));
2009-08-04 13:55:29 +00:00
if ( ereg ( 'date|time' , $field [ " type " ])) {
$return [] = " now " ;
}
return $return ;
2009-07-27 11:25:37 +00:00
}
2009-07-28 10:09:05 +00:00
function editInput ( $table , $field , $attrs , $value ) {
2009-07-27 11:25:37 +00:00
global $dbh ;
$foreign_keys = column_foreign_keys ( $table );
foreach (( array ) $foreign_keys [ $field [ " field " ]] as $foreign_key ) {
if ( count ( $foreign_key [ " source " ]) == 1 ) {
$id = idf_escape ( $foreign_key [ " target " ][ 0 ]);
$name = $this -> rowDescription ( $foreign_key [ " table " ]);
if ( strlen ( $name ) && $dbh -> result ( $dbh -> query ( " SELECT COUNT(*) FROM " . idf_escape ( $foreign_key [ " table " ]))) <= 1000 ) { // optionlist with more than 1000 options would be too big
2009-07-30 08:12:54 +00:00
$return = array ( " " => " " );
2009-07-28 10:09:05 +00:00
$result = $dbh -> query ( " SELECT $id , $name FROM " . idf_escape ( $foreign_key [ " table " ]) . " ORDER BY 2 " );
2009-07-27 11:25:37 +00:00
while ( $row = $result -> fetch_row ()) {
$return [ $row [ 0 ]] = $row [ 1 ];
}
2009-07-28 10:09:05 +00:00
return " <select $attrs > " . optionlist ( $return , $value , true ) . " </select> " ;
2009-07-23 14:42:38 +00:00
}
}
}
2009-07-28 10:09:05 +00:00
if ( $field [ " full_type " ] == " tinyint(1) " ) { // bool
2009-07-28 16:28:47 +00:00
return '<input type="checkbox" value="' . h ( $value ? $value : 1 ) . '"' . ( $value ? ' checked' : '' ) . " $attrs > " ;
2009-07-28 10:09:05 +00:00
}
2009-08-18 09:36:32 +00:00
if ( ereg ( 'date|timestamp' , $field [ " type " ])) {
return " <input value=' " . h ( $value ) . " ' $attrs > ( " . lang ( 'yyyy-mm-dd' ) . " ) " ; //! maxlength
}
2009-07-28 10:09:05 +00:00
return '' ;
2009-07-23 14:42:38 +00:00
}
2009-07-27 11:25:37 +00:00
2009-07-27 16:32:56 +00:00
function processInput ( $field , $value , $function = " " ) {
2009-07-27 11:25:37 +00:00
global $dbh ;
2009-08-04 13:55:29 +00:00
if ( $function == " now " ) {
return " $function () " ;
}
2009-08-20 15:37:39 +00:00
$return = $dbh -> quote ( ereg ( 'date|timestamp' , $field [ " type " ]) && preg_match ( '(^' . str_replace ( '\\$1' , '(?P<p1>[0-9]+)' , preg_replace ( '~(\\\\\\$([2-6]))~' , '(?P<p\\2>[0-9]{1,2})' , preg_quote ( lang ( '$1-$3-$5' )))) . '(.*))' , $value , $match )
2009-07-30 13:27:21 +00:00
? ( $match [ " p1 " ] ? $match [ " p1 " ] : ( $match [ " p2 " ] < 70 ? 20 : 19 ) . $match [ " p2 " ]) . " - $match[p3] $match[p4] - $match[p5] $match[p6] " . end ( $match )
2009-07-30 09:25:37 +00:00
: $value
);
2009-07-28 10:09:05 +00:00
if ( ! ereg ( 'varchar|text' , $field [ " type " ]) && $field [ " full_type " ] != " tinyint(1) " && ! strlen ( $value )) {
2009-07-27 11:25:37 +00:00
$return = " NULL " ;
}
return $return ;
}
function navigation ( $missing ) {
if ( $missing != " auth " ) {
?>
2009-07-03 06:26:01 +00:00
< form action = " " method = " post " >
< p >
2009-07-11 20:30:40 +00:00
< input type = " hidden " name = " token " value = " <?php echo $_SESSION["tokens"] [ $_GET["server"] ]; ?> " >
< input type = " submit " name = " logout " value = " <?php echo lang('Logout'); ?> " >
2009-07-14 11:09:39 +00:00
</ p >
2009-07-03 06:26:01 +00:00
</ form >
< ? php
2009-07-27 11:25:37 +00:00
if ( $missing != " db " ) {
$table_status = table_status ();
if ( ! $table_status ) {
echo " <p class='message'> " . lang ( 'No tables.' ) . " \n " ;
} else {
2009-08-07 08:29:50 +00:00
echo " <p id='tables'> \n " ;
2009-07-27 11:25:37 +00:00
foreach ( $table_status as $row ) {
$name = $this -> tableName ( $row );
if ( isset ( $row [ " Engine " ]) && strlen ( $name )) { // ignore views and tables without name
2009-07-30 08:12:54 +00:00
echo " <a href=' " . h ( ME ) . 'select=' . urlencode ( $row [ " Name " ]) . " '> $name </a><br> \n " ;
2009-07-27 11:25:37 +00:00
}
2009-07-03 06:26:01 +00:00
}
}
}
}
}
2009-07-27 11:25:37 +00:00
2009-07-03 06:26:01 +00:00
}
2009-09-09 11:03:03 +00:00
$adminer = ( function_exists ( 'adminer_object' ) ? adminer_object () : new Adminer );