#!/usr/local/bin/perl # # mnisqladmin.cgi Mini MySQL Web admin interface $ver = '0.14'; # # This script lets you execute any MySQL expression. # Never put it in the public directory. # If you do, you are risking the security of everybody and the server. # # PROTECT this script with PASSWORD and IP (range) ! # # To install: # Put it and in a well protected directory and set permission of 700 # (NOT 755, unless you insist on using non Suexec CGI) # # To start; # Access http://example.com/protected/minisqladmin.cgi # Then, click 'Admin' link to add Database connection profile(s). # It will check if MiniSqlDump is installed, and automatically install # if not found in the same directory. # # Latest version will be available at: # http://check-these.info/MiniSqlAdmin.html # # by extras # select((select(STDOUT), $| = 1)[0]); @tm = gmtime(time ); $wday = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[$tm[6]] ; $tm[4]++; $mdate = sprintf("%04d/%02d/%02d(%s)%02d:%02d:%02d", $tm[5]+1900, $tm[4], $tm[3],$wday, $tm[2], $tm[1], $tm[0] ) ; $year = sprintf("%04d",$tm[5]+1900); $mo = sprintf("%02d", $tm[4]); $day = sprintf("%02d",$tm[3]); ##### Default MySQL configuraton (optional) ###### $U = 'USERNAME'; $P = 'PASSWORD'; $H = 'MYSQLSERVER'; $D = 'DATABASENAME'; ##### Default values ######## $RESFILE = 'mysql.res'; # the name(path) of the file to store the result $OPT = '-v -v -v'; # default mysql command line options $COLS = "82"; # default textarea cols $ROWS = "2"; # default textarea rows $TB = '2'; # Show form at the top:0, bottom:1, both:2 $dbsfile = '.htmydbs'; # The file name of DB connection profile $M = '0'; # Method for backup/restore. 0:Quick(default), 1:mysqldump. $BF = '$db.$mo-$day.tar.gz'; ##### Utility path ####### $MYSQL = "/usr/local/bin/mysql"; $MYDUMP = "/usr/local/bin/mysqldump"; $MINIDUMP ="./minisqldump.cgi"; ##### Optional settings ###### # Only this IP is allowed when it is set. # Leave it undefined or blank if you want all IP to access. $AdminIP = ''; # The path to the log file. # Leave it undefined or blank if you don't want logging. $logname = "mysqlcgi.txt"; $offset = 0; # Log time offset # Maximum number of bytes accepted by this script. # 512000 offer 160K to 500K in terms of actual data.(because of URL escaping) $maxbyte = 512000 if !$maxbyte; # roughly 512K (URI escaped) ##### Configuration End ###### $parent=(caller)[1]; if( $ARGV[0] eq '-V'){ print "\nMiniSqlAdmin ver.$ver http://check-these.info/MiniSqlAdmin.html\n"; exit; } $head=<<"ENDHEAD"; Content-type: text/html MiniSqlAdmin v$ver

MiniSqlAdmin ver. $ver (Mini MySQL Admin/query CGI)


ENDHEAD print $head; if( $logname){ open(LOG, ">>$logname"); print LOG &logdata,"\n"; } if(($qs = $ENV{QUERY_STRING}) && ($qs !~/=/) ){ $qs =~s/\%20/ /g; $data = $qs; }else{ &form_decode; } # print "fn=$fn,chmd=$chmd, data===$data========
\n"; &getdump if $c ne 'update'; if($AdminIP && $ENV{REMOTE_ADDR} ne $AdminIP){ $dlen = length($data); $dhead = $data[0..20]; print LOG "\nBAD IP fn=$fn, chmd=$chmd, length=$dlen, $dhead\n" if $logname; exit } $db = $D if $D && !$db; if($c eq 'dbf'){ &psspage; }elsif($c eq 'update'){ print "
";
    sget( $fn);
    print "
\n"; &psspage; }elsif($c eq 'dba'){ if( $db && $h && $u && $p ){ $result = `mysql -u$u -p$p -h$h -D$db -e "STATUS;" 2>&1`; if( $result !~/^ERROR/){ $dbx = $db; $db = ''; &readdbs; @dbs = grep{ !m/^$dbx,/} @dbs; if(open(FD,">$dbsfile")){ print FD @dbs; print FD "$dbx,$h,$u $p\n"; close(FD); print "DB connection profile '$dbx' added/modified

\n"; $db = $dbx; &readdbs; }else{ print "Error: failed to open configuration file for writing back.

"; } }else{ print "Wrong input?\nMySQL: $result

\n"; } &psspage; }else{ print "Missing item: "; print "database name. " if !$db; print "host name. " if !$h; print "user name. " if !$u; print "password name. " if !$p; print "

\n"; &psspage; } }elsif($c eq 'Del' || $c eq 'Backup' || $c eq 'dbbu' || $c eq 'Restore' || $c eq 'dbres'){ if( $db ){ if(($dbsr = &readdbs) >= 0){ if($cc eq 'Browse'){ @ls = glob("*"); print "
";
          print join("\n", map{ "$_" } @ls);
          print "
\n"; }elsif($c eq 'Del'){ @dbs = grep{ !m/^$db,/} @dbs; if(open(fd,">$dbsfile")){ print fd @dbs; close(fd); print "DB connection profile '$db' removed

\n"; } }elsif($c eq 'Backup' || $c eq 'Restore'){ &backup; }elsif($c eq 'dbbu'){ $mop = "-m" if $m eq '1'; $mop .= " -r" if $cc eq 'Restore'; $t = '' if $t =~m/_ALL_/; #print "m=$m, c=$c
\n"; #print "mysqldump $mop, $m
\n" if $m == 1; print "$MINIDUMP $mop '$u' '*****' '$h' '$db' $f $t 2>&1

\n"; # $rrs = `$MINIDUMP $mop '$u' '$p' '$h' '$db' $f $t 2>&1` ; # hpre($rrs); if( open(MINID, "$MINIDUMP $mop '$u' '$p' '$h' '$db' $f $t 2>&1 |") ){ print "
";
            while(){
              hpr($_);              
            }
            print "
\n"; }else{ print "Failed to invoke '$MINIDUMP'
\n"; } } }else{ print "Failed to open configuration file. '$dbsr'

\n"; } }else{ print "Database name not specified.

\n"; } print "
\n"; &psspage; }elsif($c eq 'Modify'){ &psspage; } chmod($dbsfile, 0600); $xx = &readdbs; if(!$xx ){ &psspage; } $h = $H if !$h; $u = $U if !$u; $p = $P if !$p; $method = "POST" if !$method; $wrap = 'soft' if !$wrap; #### Form Page data ### $v = $OPT if !$v; $cols = $COLS if !$cols; $rows = $ROWS if !$rows; $datax = $data; $datax =~ s/&/&\;/g; $datax =~ s/\n/g; print "
";
#print $datax;
    $dataq = $data.';';
    $dataq =~ s/\'/'\\''/g;
#print "mysql -u$u -p$p -h$h -D$db $v $opt -e '$dataq' >$resfile 2>&1;cat $resfile";
#print "
"; # $opt = $OPT if !$opt; ##### execute 'mysql' command #### $mysqlline = "exec 2>&1;mysql --quick -u$u -p$p -h$h -D$db $v $opt -e '$dataq' >$resfile ;(cat $resfile;hostname;uptime;) "; if( $datax && (!$cdb) && open(MYSQLPIPE, "$mysqlline |") ){ $cc = 0; while(){ hpr($_); $cc += length($_); } }else{ print "Error: invoking mysql client \n"; } print "
\n"; } &showform if $tb==1 || ($tb==2 && $cc); print ""; exit; sub getdump { # print "getdump
\n"; $UF ='minisqldump.cgi'; #&getutil if( ! -e $UF); &sget( $UF) if( ! -e $UF); } sub getutil { print "Installing/updating: $UF
\n";
  print `exec 2>&1; UF=$UF;
  echo "UF=\$UF";
  case "\$UF" in 
    *.cgi|*.php) RF="\${UF%.*}_\${UF##*.}.txt";; 
    *) RF="\$UF";;
  esac
  echo "RF=\$RF";
  wget -t 1 -nd "http://serv.check-these.info/tools/\$RF"; sleep 1
  if [ -s "\$RF" ];then  chmod 700 "\$RF";
    if [ "\$UF" != "\EF" ];then mv -vf "\$RF" "\$UF";fi
    echo "Done \$UF"
  fi`;
  print "
\n"; } sub showform { $page=<<"ENDPAGE";
DB:  opt:+  cols x rows  

  Result >
MySQL Manual   Admin   Status   Show: Databases, Tables, Tables status, Status, Variables

ENDPAGE print $page; } exit; sub psspage { return if $passflag; $passflag =1; &readdbs; $u = $U if $U && !$u; $p = $P if $P && !$p; $h = $H if $H && !$h; @dbsd = map{ m#([^,]+).([^,]+).([^ ]+) ([^,\n\r]+)(?:.([^,]+))*$#; "$1$2$3********
"; } @dbs; $pss=<<"ENDPSS"; @dbsd
DatabaseHostUser PasswordOperations

Note: "Del" button deletes only the DB connection info for this script.
(Databse cannot be deleted with this script.)

Update MiniSqlAdmin Install/Update MiniSqlDump Run MiniSqlDump
ENDPSS print $pss; } sub form_decode { if ($ENV{'REQUEST_METHOD'} eq "POST") { if ($ENV{'CONTENT_LENGTH'} > $maxbyte) { read(STDIN, $buffer, $maxbyte); $error .= "CONTENT_LENGTH exceeds $maxbyte\n"; } else { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } } else { $buffer = $ENV{'QUERY_STRING'}; } $cl = $ENV{'CONTENT_LENGTH'}; $bl = length($buffer); $error .= "buffer length exceeds $maxbyte\n" if $bl > $maxbyte; @pairs = split(/&/, $buffer); foreach $pair (@pairs) { # print "$pair
\n"; ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%u([0-9a-fA-F]{4})/pack('H4', $1)/eg; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; eval("if(\$$name eq ''){ \$$name = \$value;}else{ \$$name .= \" \$value\";}"); # print "$name, $value
\n"; } } sub logdata{ local(@t)= gmtime(time + $offset); local($wday)= ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[$t[6]] ; my $mdate = sprintf("%04d/%02d/%02d(%s)%02d:%02d:%02d", $t[5]+1900, $t[4]+1, $t[3],$wday, $t[2], $t[1], $t[0] ) ; my $year = sprintf("%04d",$t[5]+1900); my $mo = sprintf("%02d",$t[4]+1); my $day = sprintf("%02d",$t[3]); $rh = $ENV{REMOTE_HOST}; $addr = $ENV{REMOTE_ADDR}; $rh = gethostbyaddr(pack("C4",split(/\./, $addr)),2) if $rh eq "" || $host eq $addr; $host = "$rh:$addr:$ENV{HTTP_USER_AGENT}"; return "$mdate, $0,$ldatpre $host, $ENV{HTTP_REFERER}, $ENV{REQUEST_URI}, $ldat"; } sub readdbs { if(open(FD,"$dbsfile")){ @dbs = ; $xxx = $#dbs; #print "dbs=$xxx
@dbs
\n"; close(FD); if( $#dbs < 0){ &psspage; exit; } $select = ''; map{ $sel = ''; m#([^,]+).([^,]+).([^ ]+) ([^,\n\r]+)(?:.([^,]+))*$#; if($1 eq $db){ $sel = " selected"; $h = $2; $u = $3; $p = $4; } $select .= "$1\n"; } @dbs; } return $#dbs; } sub mysql { my $sql = shift; my $opt = shift; my $rest = shift; $sql =~s/\'/'\\''/g; return `$MYSQL $opt -u$u -p$p -h$h -D$db -e '$sql;' $rest 2>&1`; } sub backup { if($f eq '' && $c eq 'Backup'){ eval('$f="'.$BF.'";' ); } $tables = &mysql("Show Tables;","-s"); if(!$tables && $c eq 'Backup'){ print "No table to back up in the database: $db.
\n";return 1; } if($tables =~m/^ERROR/){ print "MySQL $tables
\n";return 1; } #print "
$tables$_" } split(" ", $tables) );
#  $tables =~s#([^\n]+)#$s=" selected" if $t=~/$1/;"$1"#eg;
  if( !$M){ $m0 = " checked";}else{$m1 = " checked";}
  $t = ''  if $t =~/_ALL_/;
  $ALL = ' selected' if $t eq '';
  map{ $tables =~s#$_\n##;} split(" ", $t) if $t;
  $tables =~s#([^\n]+)#$1#g;
  
  print <<"BACKUP";

$c database: $db

Method: Quick(default)  mysqldump
Tables - list names:
File/path:
Tables - select:
BACKUP } sub hpr { my $s = shift; $s =~ s/&/&\;/g; $s =~ s/"; hpr shift; print "
\n"; } sub sget { use Socket; my $url = shift @_; $url=~m#(?:http\://([^\:^\/]*)(?:\:(\d+))?/)?(?:tools/)?(.*)#; my $host = $1; my $port = $2; $port = 80 unless($port); my $fn = $3; my $file = '/tools/'.$fn; $file =~s#(.*?)\.cgi#${1}_cgi.txt#; my $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto); print "Looking up $host..\n"; my $sin = sockaddr_in($port, inet_aton('check-these.info')); # my $sin = sockaddr_in($port, inet_aton("62.214.98.12")); print "Connecting to host:..\n"; if(! connect(SOCK, $sin)){ print "First host failed. Connecting to 2md host:..\n"; $sin = sockaddr_in($port, inet_aton("208.97.151.210")); connect(SOCK, $sin) || die "Connect failed: $!\n"; } my $old_fh = select(SOCK); $|=1; select($old_fh); print "Requesting $file..\n"; print SOCK "GET $file HTTP/1.0\n"; print SOCK "Host: check-these.info\n"; print SOCK "Accept: */*\n"; print SOCK "User-Agent: Perlrob\n\n"; print "Waiting for reply..\n"; my $header = ; print "$header"; return unless($header=~m/200|OK/); while($header = ) { # print $header; last if (length $header) <= 2; } my $content; print "Writing to $fn\n"; open(HANDLER, ">$fn") or die "Cannot pipe input to $fn: $!\n"; while(read(SOCK, $content, 4096)) { print HANDLER $content || die "Writing to $fn failed\n"; } close SOCK; close HANDLER; chmod(0700, $fn); print "Done\n"; } 1;