├── .gitignore
├── README.md
├── changelog.md
├── phpminiadmin.php
└── samples
├── phpminiconfig.magento.php
├── phpminiconfig.php
├── phpminiconfig.sugarcrm.php
├── phpminiconfig.typo3.php
├── phpminiconfig.vtiger.php
└── phpminiconfig.wordpress.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /phpminiconfig.php
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [other screenshots](https://sourceforge.net/projects/phpminiadmin/#screenshots)
4 |
5 | ## How to Install
6 | - Download [phpminiadmin.php](https://raw.github.com/osalabs/phpminiadmin/master/phpminiadmin.php) file
7 | - example: `wget https://raw.github.com/osalabs/phpminiadmin/master/phpminiadmin.php`
8 | - Copy/Upload it to your webserver public directory (www or public_html or whatever...)
9 | - Open in your browser `http://yoursite.com/phpminiadmin.php`
10 |
11 | **Recommended:** For additional security you may edit phpminiadmin.php file and set some password (see `$ACCESS_PWD` variable)
12 |
13 | ### Dependencies
14 | The only required php extension is `mysqli`. Therefore if you got a white screen install it:
15 |
16 | `sudo apt-get install php-mysql` on Debian
17 | or enable `extension=php_mysqli.dll` in php.ini on Windows
18 |
19 | ## Config file (optional)
20 |
21 | You can also create phpminiconfig.php in the same directory as phpminiadmin.php with database credentials or password.
22 | This way you can easily install future releases of phpminiadmin.php
23 |
24 | In the directory samples you'll find phpminiconfig.php for known OpenSource packages
25 |
26 | - See phpminiconfig.php for an empty example
27 | - See phpminiconfig.magento.php to read Magento its app/etc/local.xml ($ACCESS_PWD is required)
28 | - See phpminiconfig.sugarcrm.php to read SugarCRM its config.php ($ACCESS_PWD is required)
29 | - See phpminiconfig.wordpress.php to read Wordpress its wp-config.php ($ACCESS_PWD is required)
30 | - See phpminiconfig.vtiger.php to read Vtiger its config.inc.php ($ACCESS_PWD is required)
31 |
32 | ## Links
33 | - [Screenshots](http://sourceforge.net/project/screenshots.php?group_id=181023)
34 | - [Live demo](http://phpminiadmin.sourceforge.net/phpminiadmin.php) (pwd: pmaiscool)
35 | - [Download latest version](https://raw.githubusercontent.com/osalabs/phpminiadmin/master/phpminiadmin.php)
36 | - [SourceForge page of the phpMiniAdmin](http://phpminiadmin.sourceforge.net/)
37 | - [My X/Twitter](https://x.com/osalabs)
38 | - [My website](http://osalabs.com)
39 |
40 | ## Change Log
41 |
42 | ### changes in phpMiniAdmin 1.9.240801 (latest)
43 | - fixed one php short open tag
44 |
45 | ### changes in phpMiniAdmin 1.9.240727
46 | - support for PHP 8.3 (cleaned up some PHP Warnings, deprecations)
47 | - enhancements:
48 | - multiple db servers support - define server's configs via `$DBSERVERS` and quickly switch between servers via top navbar dropdown
49 | - "ps" menu item in top navbar - shortcut for "show processlist"
50 | - "SHOW TABLE STATUS" now works quicker because emulated via select from `information_schema.TABLES`
51 | - "WITH" (Common Table Expressions (CTEs)) support
52 | - moved include for phpminiconfig a bit further, so it allows override more things
53 | - security improvements:
54 | - `$ACCESS_PWD` now is enforced except for local usage
55 | - added by default "SET GLOBAL local_infile=0" to prevent unwanted use of `LOAD DATA LOCAL INFILE`. Controlled by `$IS_LOCAL_INFILE` on the beginning of the script.
56 |
57 | ### changes in phpMiniAdmin 1.9.210705
58 | - removed use of function `get_magic_quotes_gpc` deprecated since PHP 7.4.0
59 | - utf8mb4 is now default charset
60 | - tested in PHP 8, cleaned up several PHP Warnings
61 |
62 | [see older changes in changelog](changelog.md)
63 |
64 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | ### changes in phpMiniAdmin 1.9.240727 (latest)
2 | - support for PHP 8.3 (cleaned up some PHP Warnings, deprecations)
3 | - enhancements:
4 | - multiple db servers support - define server's configs via `$DBSERVERS` and quickly switch between servers via top navbar dropdown
5 | - "ps" menu item in top navbar - shortcut for "show processlist"
6 | - "SHOW TABLE STATUS" now works quicker because emulated via select from `information_schema.TABLES`
7 | - "WITH" (Common Table Expressions (CTEs)) support
8 | - moved include for phpminiconfig a bit further, so it allows override more things
9 | - security improvements:
10 | - `$ACCESS_PWD` now is enforced except for local usage
11 | - added by default "SET GLOBAL local_infile=0" to prevent unwanted use of `LOAD DATA LOCAL INFILE`. Controlled by `$IS_LOCAL_INFILE` on the beginning of the script.
12 |
13 | ### changes in phpMiniAdmin 1.9.210705 (latest)
14 | - removed use of function `get_magic_quotes_gpc` deprecated since PHP 7.4.0
15 | - utf8mb4 is now default charset
16 | - tested in PHP 8, cleaned up several PHP Warnings
17 |
18 | ### changes in phpMiniAdmin 1.9.210129
19 | - limited max packet size during export to aviod PHP memory exhausted errors on huge tables
20 |
21 | ### changes in phpMiniAdmin 1.9.200928
22 | - added ability to setup SSL connection (define at least "ssl_ca" in `$DBDEF`)
23 |
24 | ### changes in phpMiniAdmin 1.9.190822
25 | - added ability to set socket for db connection
26 |
27 | ### changes in phpMiniAdmin 1.9.170203
28 | - added "compact view" option. If checked - width/height of grid cells limited, so you can see more rows/columns in case your data is large. And in this mode you can double-click on cells to "expand" just that particular cell.
29 |
30 | ### changes in phpMiniAdmin 1.9.170117
31 | - greatly optimized memory usage for large result sets (especially in export)
32 |
33 | ### changes in phpMiniAdmin 1.9.161116
34 | - added ability to dump exports right on server, without need to download
35 | - added ability to import from .sql or .gz file right on server, without need to upload one
36 | - fixed export, now it won't dump data for VIEWs
37 |
38 | ### changes in phpMiniAdmin 1.9.160705
39 | - screen appearance changes/fixes
40 | - added buttons which inserts standard "template" queries for Select, Insert, Update, Delete
41 | - disabled counting total number of records for pagination as it slows down response, especially on large datasets. Set `$IS_COUNT=true` to enable this feature back.
42 |
43 | ### changes in phpMiniAdmin 1.9.160630
44 |
45 | - all queries now base64 encoded to bypass applications firewalls. Note, **IE10 browser or later required from now**
46 | - SHOW TABLE STATUS fixed to display views, also Comments column added
47 | - fixed Settings/Login/Logoff
48 |
49 | ### changes in phpMiniAdmin 1.9.150729
50 |
51 | - switched to MySQLi because MySQL extension deprecated in PHP7
52 |
53 | ### changes in phpMiniAdmin 1.9.150108
54 |
55 | - httponly cookies so your plain password cannot be stolen by javascript
56 | - export disables foreign key checks
57 | - ask for super privilege(otherwise you get a error on import)
58 | - added support for a config file with credentials
59 |
60 | ### changes in phpMiniAdmin 1.9.141219
61 |
62 | - added: total count of records displayed for selects with pagination (example: 50 out of 104)
63 | - fixed: labels on forms, so inputs can be correctly narrated for blind users
64 |
65 | ### changes in phpMiniAdmin 1.9.140405
66 |
67 | - fixed: couple low risk XSS vulnerabilities
68 | - fixed: CSV export in UTF-8
69 | - added: ability to quickly create new database without SQL knowledge
70 | - added: autofocus to login pwd field
71 | - added: some minor compatibility changes for PHP 4.x
72 | - changed: yellow row highlight removed if clicked again
73 | - changed: if field contains binary data (char codes < 32), only first 16 hex will be displayed (if you want to dump full content - select just one this field)
74 |
75 | ### changes in phpMiniAdmin 1.8.120510
76 |
77 | - fixed: Undefined offset in get_rand_str
78 | - fixed: automatic relogin on XSS error
79 | - added: page navigator at the bottom
80 | - added: row counts, table sizes on the table list
81 | - added: MIT license
82 | - added: query history via browser's localStorage
83 | - added: if database empty - show databases
84 | - added: after import - show tables
85 | - changed: moved from html 4.01 to html 5
86 | - changed: simplified settings form
87 |
88 | ### changes in phpMiniAdmin 1.7.111025
89 |
90 | - fixed: unable to relogin on XSS error
91 | - fixed: truncate button doesn't work
92 | - minor changes in text labels and css styles
93 |
94 |
--------------------------------------------------------------------------------
/phpminiadmin.php:
--------------------------------------------------------------------------------
1 | http://osalabs.com
5 |
6 | Light standalone PHP script for quick and easy access MySQL databases.
7 | http://phpminiadmin.sourceforge.net
8 |
9 | Dual licensed: GPL v2 and MIT, see texts at http://opensource.org/licenses/
10 | */
11 |
12 | $ACCESS_PWD=''; #!!!IMPORTANT!!! this is script access password, SET IT if you want to protect you DB from public access
13 |
14 | #DEFAULT db connection settings
15 | # --- WARNING! --- if you set defaults - it's recommended to set $ACCESS_PWD to protect your db!
16 | $DBSERVERS=[]; #array of arrays ['iname'=>'srv name', 'config'=>[see $DBDEF]] - define if you need manage multiple db servers
17 | $DBDEF=array(
18 | 'user'=>"",#required
19 | 'pwd'=>"", #required
20 | #optional:
21 | 'db'=>"", #default DB
22 | 'host'=>"",
23 | 'port'=>"",
24 | 'socket'=>"",
25 | 'chset'=>"utf8mb4",#optional, default charset
26 | #optional paths for ssl
27 | 'ssl_key'=>NULL,
28 | 'ssl_cert'=>NULL,
29 | 'ssl_ca'=>'',#minimum this is required for ssl connections, if set - ssl connection will try to be established. Example: /path/to/cacert.pem
30 | );
31 | $IS_LOCAL_INFILE=false; #by default disable LOAD DATA LOCAL INFILE
32 | $IS_COUNT=false; #set to true if you want to see Total records when pagination occurs (SLOWS down all select queries!)
33 | $DUMP_FILE=dirname(__FILE__).'/pmadump'; #path to file without extension used for server-side exports (timestamp, .sql/.csv/.gz extension added) or imports(.sql)
34 | if (function_exists('date_default_timezone_set')) date_default_timezone_set('UTC');#required by PHP 5.1+
35 |
36 | //constants
37 | $VERSION='1.9.240801';
38 | $MAX_ROWS_PER_PAGE=50; #max number of rows in select per one page
39 | $D="\r\n"; #default delimiter for export
40 | $BOM=chr(239).chr(187).chr(191);
41 | $SHOW_D="SHOW DATABASES";
42 | $SHOW_T="SHOW TABLE STATUS";
43 | $DB=[]; #working copy for DB settings
44 | $SRV='';#selected server iname
45 | $self=$_SERVER['PHP_SELF'];
46 |
47 | $secure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
48 | @session_set_cookie_params(0, null, null, $secure, true);
49 | ini_set('session.use_only_cookies', 1);
50 | @session_start();
51 |
52 | if (!isset($_SESSION['XSS'])) $_SESSION['XSS']=get_rand_str(16);
53 | $xurl='XSS='.$_SESSION['XSS'];
54 |
55 | ini_set('display_errors',0); #turn on to debug db or script issues
56 | error_reporting(E_ALL ^ E_NOTICE);
57 |
58 | file_exists($f=dirname(__FILE__) . '/phpminiconfig.php')&&require($f); // Read from config (easier to update/override)
59 |
60 | if(isset($_REQUEST['login'])){
61 | if ($_REQUEST['pwd']!=$ACCESS_PWD){
62 | $err_msg="Invalid password. Try again";
63 | }else{
64 | $_SESSION['is_logged']=true;
65 | loadcfg();
66 | }
67 | }
68 |
69 | if(isset($_REQUEST['logoff'])){
70 | check_xss();
71 | $_SESSION=[];
72 | savecfg();
73 | session_destroy();
74 | $url=$self;
75 | if (!$ACCESS_PWD) $url='/';
76 | header("location: $url");
77 | exit;
78 | }
79 |
80 | if (!isset($_SESSION['is_logged'])){
81 | if (empty($ACCESS_PWD)){
82 | if (isTrusted()){
83 | $_SESSION['is_logged']=true;
84 | loadcfg();
85 | }else{
86 | die("Set ACCESS_PWD to protect your database.");
87 | }
88 | }else{
89 | print_login();
90 | exit;
91 | }
92 | }
93 | if (isset($_REQUEST['savecfg'])){
94 | check_xss();
95 | savecfg();
96 | }
97 |
98 | loadsess();
99 |
100 | if (isset($_REQUEST['showcfg'])){
101 | print_cfg();
102 | exit;
103 | }
104 |
105 | //get initial values
106 | $SQLq=trim(b64d($_REQUEST['q']??''));
107 | $page=intval($_REQUEST['p']??0);
108 | $isRefresh=intval($_REQUEST['refresh']??0);
109 | if ($isRefresh && $DB['db'] && preg_match('/^show/',$SQLq) ) $SQLq=$SHOW_T;
110 |
111 | if (db_connect('nodie')){
112 | $time_start=microtime_float();
113 |
114 | if ($_REQUEST['pi']??0){
115 | ob_start();phpinfo();$html=ob_get_clean();preg_match("/
]*>(.*?)<\/body>/is",$html,$m);
116 | $sqldr='
'.$m[1].'
';
117 | }else{
118 | if ($DB['db']){
119 | if ($_REQUEST['shex']??0){
120 | print_export();
121 | }elseif ($_REQUEST['doex']??0){
122 | check_xss();do_export();
123 | }elseif ($_REQUEST['shim']??0){
124 | print_import();
125 | }elseif ($_REQUEST['doim']??0){
126 | check_xss();do_import();
127 | }elseif ($_REQUEST['dosht']??0){
128 | check_xss();do_sht();
129 | }elseif (!$isRefresh || preg_match('/^select|with|show|explain|desc/i',$SQLq) ){
130 | if ($SQLq)check_xss();
131 | do_sql($SQLq);#perform non-select SQL only if not refresh (to avoid dangerous delete/drop)
132 | }
133 | }else{
134 | if ( $isRefresh ){
135 | check_xss();do_sql($SHOW_D);
136 | }elseif ($_REQUEST['crdb']??0){
137 | check_xss();do_sql('CREATE DATABASE '.dbqid($_REQUEST['new_db']));do_sql($SHOW_D);
138 | }elseif ( preg_match('/^(?:show\s+(?:databases|status|variables|process)|create\s+database|grant\s+)/i',$SQLq) ){
139 | check_xss();do_sql($SQLq);
140 | }else{
141 | $err_msg="Select Database first";
142 | if (!$SQLq) do_sql($SHOW_D);
143 | }
144 | }
145 | }
146 | $time_all=ceil((microtime_float()-$time_start)*10000)/10000;
147 |
148 | print_screen();
149 | }else{
150 | print_cfg();
151 | }
152 |
153 | function do_sql($q){
154 | global $dbh,$last_sth,$last_sql,$reccount,$out_message,$SQLq,$SHOW_T,$DB;
155 | $SQLq=$q;
156 |
157 | $is_shts=0;
158 | if ($q==$SHOW_T){
159 | #emulate show table status faster
160 | $is_shts=1;
161 | $q="select TABLE_NAME as Name,Engine,Version,Row_format,TABLE_ROWS as `Rows`,Avg_row_length,Data_length,Max_data_length,Index_length,TABLE_COMMENT as Comment
162 | from information_schema.TABLES where TABLE_TYPE IN ('BASE TABLE','VIEW')
163 | and TABLE_SCHEMA=".dbq($DB['db']);
164 | }
165 |
166 | if (!do_multi_sql($q)){
167 | $out_message="Error: ".mysqli_error($dbh);
168 | }else{
169 | if ($last_sth && $last_sql){
170 | if($is_shts)$last_sql=$SHOW_T;
171 | $SQLq=$last_sql;
172 | if (preg_match("/^select|with|show|explain|desc/i",$last_sql)) {
173 | if ($q!=$last_sql) $out_message="Results of the last select displayed:";
174 | display_select($last_sth,$last_sql);
175 | } else {
176 | $reccount=mysqli_affected_rows($dbh);
177 | $out_message="Done.";
178 | if (preg_match("/^insert|replace/i",$last_sql)) $out_message.=" Last inserted id=".get_identity();
179 | if (preg_match("/^drop|truncate/i",$last_sql)) do_sql($SHOW_T);
180 | }
181 | }
182 | }
183 | }
184 |
185 | function display_select($sth,$q){
186 | global $dbh,$SRV,$DB,$sqldr,$reccount,$is_sht,$xurl,$is_sm;
187 | $rc=["o","e"];
188 | $srvn=ue($SRV);
189 | $dbn=ue($DB['db']);
190 | $sqldr='';
191 |
192 | $is_shd=(preg_match('/^show\s+databases/i',$q));
193 | $is_sht=(preg_match('/^show\s+tables|^SHOW\s+TABLE\s+STATUS/',$q));
194 | $is_show_crt=(preg_match('/^show\s+create\s+table/i',$q));
195 |
196 | if ($sth===FALSE or $sth===TRUE) return;#check if $sth is not a mysql resource
197 |
198 | $reccount=mysqli_num_rows($sth);
199 | $fields_num=mysqli_field_count($dbh);
200 |
201 | $w='';
202 | if ($is_sm) $w='sm ';
203 | if ($is_sht || $is_shd) {$w='wa';
204 | $url='?'.$xurl."&db=$dbn&srv=$srvn";
205 | $sqldr.="