PDA

View Full Version : TinyMyTester-یک برنامهء کوچک تست و مدیریت MySQL



eshpilen
چهارشنبه 02 تیر 1389, 18:25 عصر
<!--
Project by Hamidreza Mz
Email: hamidreza_mz -=(at)=- yahoo -=(dot)=- com

This is a helping program primarily for the purpose of
some common simple testings on MySQL's accounts,
MySQL SQL, etc. that I needed and used
and I found it very useful at least for me (as a web developer and learner in MySQL and other relevant tools).
It is not in any way as powerful and complete as a program such as phpmyadmin
and did not started for replacing it
but it is now being a distinct program with its special use cases;
it very smaller, faster and very easy and fast to setup, and also has some
special features that was needed but cant be found in phpmyadmin; You will see ;)
Remember it is not in any way complete; it is tentative.
I distribute it now as Free Software (Under GPL).
Hope that can be useful for some others.
-->
<?php

//modify=1

if(ini_get('register_globals'))
exit("<center><span>Error: Turn that damned register globals off!</span></center>");

error_reporting(E_ALL);
ini_set('display_errors', '1');

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//you should set a full privileged MySQL user here:
$host='localhost';
$user='root';
$pass='root_pass';
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

//Sorry! almost all of the following is pure uncommented code. :<

if(count($_POST)) {
$post=true;
if($user==$_POST['user']) {
$orig_pass=$pass;
$pass=$_POST['pass'];
}
}
else $post=false;

header('Content-Type: text/html; charset=utf-8');
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0");
header('Pragma: private');
header("Pragma: no-cache");

$log='';
$dlf='\n----------------\n';
$db_conn_err=false;
$flag=false;

//+++++++++++++++++++++++++++++++++++++++++++++++

class hm_db {

var $err_msg='';
var $link=NULL;
var $result=NULL;

//=======================================
function hm_db($host='', $user='', $pass='', $db_name='')
{

$this->link= @ mysql_connect($host, $user, $pass);
if(!$this->link) {
$this->error();
return;
}

if($db_name) $this->select($db_name);

}
//=======================================
function select($db_name)
{
$this->err_msg='';
if( @ mysql_select_db($db_name)) return true;
$this->error();
return false;
}
//=======================================
function close()
{
$this->err_msg='';
if(is_resource($this->link)) {
if( @ mysql_close($this->link)) return true;
$this->error();
return false;
}
else {
$this->error('Apparently there is no MySQL connection resource to close');
return false;
}

}
//=======================================
function free_result() {
if(is_resource($this->result))if(! @ mysql_free_result($this->result)) {
$this->error();
return false;
}
else return true;

$this->error('No query result exists');
return false;
}
//=======================================
function destruct() {
if(is_resource($this->result)) if(! @ mysql_free_result($this->result)) {
$this->error();
return false;
}

if(is_resource($this->link)) if($this->close()) return true;
else {
$this->error();
return false;
}

$this->error('Apparently there is no MySQL connection resource to close');
return false;
}
//=======================================
function error($msg='')
{
$this->err_msg=get_class($this).': '.(($msg)? $msg : mysql_error());
}
//========= query related =========

function result_num($query=null)
{
$this->err_msg='';
if(!is_null($query) and !$this->query($query)) return false;
if(is_resource($this->result)) return mysql_num_rows($this->result);
$this->error('No query result exists');
return false;
}
//=======================================
function quote_smart($value, $identifier=false)
{

if(!is_numeric($value)) {
if(get_magic_quotes_gpc()) $value = stripslashes($value);
if(!$identifier) return "'" .mysql_real_escape_string($value) . "'";
else if(strpos($value, '`')===false) return '`' .$value . '`';
else {
$this->error("Value contains invalid character (backtick - '`') for identifiers");
return false;
}
}
else return $value;

}
//=======================================
function query($query)
{
$this->err_msg='';
$this->result= @ mysql_query($query, $this->link);
if($this->result) return $this->result;
$this->error();
return false;
}
//=======================================
function fetch_row($type=MYSQL_ASSOC)
{

$this->err_msg='';
if(is_resource($this->result)) return mysql_fetch_array($this->result, $type);
$this->error('No query result exists');
return false;

}
//=======================================
function field_name($no=NULL)
{

$this->err_msg='';
if(is_resource($this->result)) {//result
$num=mysql_num_fields($this->result);
if(!is_null($no)) {//$no
if(!is_int($no)) {
$this->error("Invalid no value '$no'");
return false;
}
if($no>=0 and $no<$num) return mysql_field_name($this->result, $no);
$this->error('Field number out of range');
return false;
}//$no
else {
for($i=0; $i<$num; $i++) $arr[]=mysql_field_name($this->result, $i);
return $arr;
}
}//result
$this->error('No query result exists');
return false;

}

}

//+++++++++++++++++++++++++++++++++++++++++++

$db=new hm_db($host, $user, $pass);

if($db->err_msg) {
$db_conn_err=true;
$log.="Can not connect to MySQL at '$host' with superuser name '$user'!\\nPassword: '$pass'.\\nReason:{$db->err_msg}.$dlf";
}
else {//connected
$db->query("SET NAMES 'utf8'");
if($db->query("select user() as u, current_user() as cu")) {
$flag=true;
$arr=$db->fetch_row();
$current_account=$arr['cu'];
$arr=explode('@', $arr['u']);
$client_host=$arr[1];
$arr=explode('@', $current_account);
$current_host=$arr[1];
$current_user=$arr[0];
$log.="Connected to MySQL as '$current_account' (Should be super user).$dlf";
}
else $log.="Connected to MySQL at '$host'.{$dlf}Can not get user and current_user of MySQL.$dlf";
}//connected

?>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="0">
<meta http-equiv="generator" content="Kate" />
<title>TinyMyTester</title>
<style>
.err {
color: red;
background-color: yellow;
font-size: large;
width: 250pt;
padding: 2pt;
}
td {
padding-left: 2pt;
padding-right: 2pt;
white-space: pre;
}
.wrn {
font-size: large;
}
</style>
<script language="javascript">
function init() {
query=document.getElementById('query');
sel=document.getElementById('sel');
retain_pass=document.getElementById('retain_pass') ;
pass=document.getElementById('pass');
user=document.getElementById('user');
submit_btn=document.getElementById('submit_btn');
admin_btn=document.getElementById('admin_btn');
//-----------------------
set_submit_title();
}

function fill(text) {
query.value=text;
query.focus();
}

function set_submit_title() {
submit_btn.title="Submit query as '"+user.options[user.selectedIndex].text+"'";
}

function admin_btn_visibility(visibility) {
admin_btn.style.visibility=visibility;
}

restore_flag=false;
super_user=false;
super_ch=false;

function user_change() {

if(user.selectedIndex) {//normal user
if(restore_flag) {
if(!super_ch) pass.value=pass_val;
retain_pass.checked=true;
}
else if(!retain_pass.checked) pass.value='';
restore_flag=false;
super_ch=false;
super_user=false;
admin_btn_visibility('visible');
}//normal user
else {//superuser is selected (first list option)
if(retain_pass.checked) {
pass_val=pass.value;
restore_flag=true;
}
<?php
if($db_conn_err and isset($orig_pass)) echo "pass.value='$orig_pass';\n";
else echo "pass.value='$pass';\n";
?>
retain_pass.checked=false;
super_user=true;
admin_btn_visibility('hidden');
}//superuser
set_submit_title();

}

function retain_ch() {
if(super_user) if(retain_pass.checked) super_ch=true;
else super_ch=false;
}

function fill_log(text) {
document.getElementById('log').value=text+"< End of log >";
}
</script>
</head>
<body bgcolor="#7587b0" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000" onLoad="init();"><center>
<form method="post" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
<table cellspacing="0" cellpadding="0" style="padding: 0; margin: 0"><tr><td><nobr>
<textarea rows="4" readonly style="width: 100%; height: 100%" id="log" title="Detailed proceed log of this program's database activities">Proceed log goes here...</textarea>
</nobr></td><td><table border><tr><td><nobr>
Query:
<?php
echo '<input type="text" name="query" id="query" size="35" value="';
if($post) echo $_POST['query'];
echo '"> <input type="button" value="Clear" onClick="fill(\'\');">';
echo '</nobr></td><td><nobr>';
echo 'Default database: <select name="database"><option value=""></option>';
if(!$db_conn_err) {
if($db->query('show databases')) {
$log.="Read database names.$dlf";
while($arr=$db->fetch_row()) {
echo '<option value="'.$arr['Database'].'"';
if($post and $_POST['database']==$arr['Database']) echo " selected";
echo ">{$arr['Database']}</option>";
}
}
else $log.="Can not read MySQL database names!\\nReason:{$db->err_msg}.$dlf";
}
echo '</select></nobr></td></tr><tr><td><nobr>';

echo 'MySQL user: ';

echo '<select name="user" onChange="user_change();" id="user"><option style="color: red" value="';
if($flag) echo "$current_user\">$current_account";
else echo "$user\">$user";
echo '</option>';

if(!$db_conn_err) if($db->query(($flag)? "select user, host from mysql.user where host='$client_host' or host='%' or host='' order by host desc, user":"select user, host from mysql.user")) {//7
$log.="Got user accounts.$dlf";

$expl_anonym=false;
$perc_anonym=false;
$explicit=array();
$percent=array();

while($arr=$db->fetch_row()) {//8
$account[]=array($arr['user'], $arr['host']);

if($flag and $arr['host']==$client_host) {
if($arr['user']!='') $explicit[]=$arr['user'];
else $expl_anonym=true;
}
else if($arr['host']=='%') if($arr['user']!='') $percent[]=$arr['user'];
else $perc_anonym=true;
}//8

foreach($account as $arr) {//9
if($arr[1]=='%' and ($expl_anonym or in_array($arr[0], $explicit))) continue;
if($arr[1]=='' and ($expl_anonym or $perc_anonym or in_array($arr[0], $explicit) or in_array($arr[0], $percent))) continue;

if((($flag)?$current_user:$user)!=$arr[0]) {//5
echo "<option value=\"{$arr[0]}\"";
if($post and $_POST['user']==$arr[0]) echo ' selected ';
echo ">{$arr[0]}@{$arr[1]}</option>";
}//5
}//9

}//7
else $log.="Can not read MySQL accounts!\\nReason:{$db->err_msg}.$dlf";

echo '</select></nobr></td><td><nobr>';

echo 'Pass: ';
echo '<input type="text" size="8" id="pass" name="pass" title="MySQL user\'s password" onClick="this.value=\'\';" value="';
if($post) echo $_POST['pass'];
else echo $pass;
echo '">';

echo ' Reuse for others: <input type="checkbox" id="retain_pass" title="Retain password for use with other MySQL user accounts" onClick="retain_ch();" name="retain_pass"';
if(isset($_POST['retain_pass'])) echo ' checked ';
echo '">';
echo '</nobr></td></tr>';

?>

<tr><td><nobr>Drafts:
<select id="sel" onChange="fill(this.options[this.selectedIndex].value);">
<option value="SHOW CREATE TABLE ">SHOW CREATE TABLE</option>
<option value="SHOW VARIABLES LIKE '%'">SHOW VARIABLES LIKE '%'</option>
<option value="SHOW STATUS LIKE '%'">SHOW STATUS LIKE '%'</option>
<option value="SHOW FULL COLUMNS FROM ">SHOW FULL COLUMNS FROM </option>
<option value="DESCRIBE ">DESCRIBE</option>
<option value="EXPLAIN ">EXPLAIN </option>
<option value="SHOW CREATE DATABASE ">SHOW CREATE DATABASE </option>
<option value="SHOW TABLE STATUS LIKE ''">SHOW TABLE STATUS LIKE ''</option>
<option value="CREATE TABLE ">CREATE TABLE</option>
<option value="SHOW TABLES">SHOW TABLES</option>
<option value="SHOW DATABASES">SHOW DATABASES</option>
<option value="SELECT * FROM ">SELECT * FROM</option>
<option value="INSERT INTO ">INSERT INTO</option>
<option value="TRUNCATE ">TRUNCATE </option>
<option value="DELETE FROM ">DELETE FROM</option>
<option value="DROP TABLE ">DROP TABLE</option>
<option value="DROP DATABASE ">DROP DATABASE</option>
<option value="CREATE DATABASE ">CREATE DATABASE</option>
<option value="RENAME TABLE ">RENAME TABLE</option>
<option value="DROP INDEX ">DROP INDEX</option>
<option value="CREATE INDEX ">CREATE INDEX </option>
<option value="UPDATE ">UPDATE </option>
<option value="SHOW PROCESSLIST">SHOW PROCESSLIST</option>
<option value="DROP USER ">DROP USER</option>
<option value="GRANT ">GRANT</option>
<option value="SHOW FULL PROCESSLIST">SHOW FULL PROCESSLIST</option>
<option value="REVOKE ">REVOKE</option>
<option value="SET PASSWORD ">SET PASSWORD</option>
<option value="FLUSH PRIVILEGES">FLUSH PRIVILEGES</option>
<option value="DROP USER ">DROP USER</option>
<option value="ANALYZE TABLE ">ANALYZE TABLE</option>
<option value="CHECK TABLE ">CHECK TABLE</option>
<option value="CHECKSUM TABLE ">CHECKSUM TABLE</option>
<option value="OPTIMIZE TABLE ">OPTIMIZE TABLE</option>
<option value="REPAIR ">REPAIR</option>
<option value="RESTORE TABLE ">RESTORE TABLE</option>
<option value="SHOW GRANTS FOR ">SHOW GRANTS FOR</option>
<option value="SHOW OPEN TABLES ">SHOW OPEN TABLES</option>
<option value="SHOW PRIVILEGES">SHOW PRIVILEGES</option>
<option value="SHOW WARNINGS">SHOW WARNINGS</option>
<option value="SHOW ERRORS">SHOW ERRORS</option>
</select>
<input type="button" value="Set" onClick="fill(sel.options[sel.selectedIndex].value);">
</nobr></td><td><nobr>
<center>
<input id="submit_btn" type="submit" value="Submit" title="Submit query as user specified in 'MySQL user' field">
<input id="admin_btn" name="super" style="visibility: visible" type="submit" value="Submit as admin" title="Submit query as superuser (<?php if($flag) echo $current_account; else echo $user; ?>)">
<input type="reset" value="Reset" title="Reset form (to last used values)">
</center>
</nobr></td></tr></table></td><td valign="center" align="center"><div style="background: yellow; border: thin solid black; padding: 2pt"><a href="<?php $_SERVER['SCRIPT_NAME']; ?>" title="By Hamidreza Mz - Email: hamidreza_mz -=(at)=- yahoo -=(dot)=- com">Tiny<br />MY<br />Tester</a></div></td></tr></table></form>
<hr />
<?php

if(!$post and $db_conn_err) echo '<div class="err">Can not connect to MySQL!<br />'."<small>Reason:{$db->err_msg}.</small>".'</div>';

if($post) {//post

$query=$_POST['query'];
$pass=$_POST['pass'];
$user2=$_POST['user'];
$default_db=$_POST['database'];

if($db_conn_err or ($user2!=$user and !isset($_POST['super']))) {
$db->destruct();
$db=new hm_db($host, $user2, $pass);
if($db->err_msg) {
$db_conn_err=true;
$log.="Can not connect to MySQL at '$host' with user name '$user2'!\\nPassword: '$pass'.\\nReason:{$db->err_msg}.$dlf";
}
else {
$db->query("SET NAMES 'utf8'");
if($db->query("select current_user() as cu")) {
$arr=$db->fetch_row();
$current_account=$arr['cu'];
$log.="Connected to MySQL as '$current_account'.$dlf";
}
else $log.="Connected to MySQL at '$host'.{$dlf}Can not get user of MySQL.$dlf";
}
}

if($db_conn_err) echo '<div class="err">Can not connect to MySQL!<br />'."<small>Reason:{$db->err_msg}.</small>".'</div>';
else {//connect successful

if($default_db) if($db->select($default_db)) $log.="Selected database '$default_db'.$dlf";
else $log.="Can not select database '$default_db'!\\nReason:{$db->err_msg}.$dlf";

if($query=='') {
echo '<div class="wrn">No query to execute.</div>';
}
else if(!$db->query($query)) {
$log.="Query '".addslashes($query)."' failed!\\nReason:{$db->err_msg}.$dlf";
echo '<div class="err">Query failed!<br />'."<small>Reason:{$db->err_msg}.</small>".'</div>';
}
else if($db->result_num()) {//tuples
$log.="Query '".addslashes($query)."' executed successfully.\\nReturned tuples.$dlf";

echo '<table style="border: medium solid #000">';

$header=$db->field_name();
$bg=true;
$no=1;
$i=15;

while($arr=$db->fetch_row(MYSQL_NUM)) {//while

if($i==15) {
echo '<tr bgcolor="green" align="center"><td></td>';
foreach($header as $title) echo "<td >$title</td>";
echo '</tr>';
$i=0;
}

if($bg) {
echo '<tr bgcolor="#e1f999" valign="top">';
$bg=false;
}
else {
echo '<tr bgcolor="#f9ec78" valign="top">';
$bg=true;
}

echo '<td bgcolor="green">'.$no.'</td>';

foreach($arr as $value) echo "<td>$value</td>";
echo '</tr>';
$no++;
$i++;

}//while

echo '</table>';

}//tuples
else {
$log.="Query '".addslashes($query)."' executed successfully.\\nNo tuples returned.$dlf";
echo '<div style="padding: 2pt"><span style="border: medium solid #000; padding: 2pt"><span style="background: #e1f999">Query executed successfully (With no tuples returned).</span></span></div>';
}

}//connect successful
}//post

echo "<script language=\"javascript\">\nfill_log(\"$log\");\n";
if(!$post or $user2==$user) echo "admin_btn_visibility('hidden');";
echo "\n</script>";

?>

</center>
</body></html>

eshpilen
چهارشنبه 02 تیر 1389, 18:26 عصر
این برنامهء مختصر رو برای انجام راحتتر و عملی تست ها و کارهای متداول خودم نوشتم؛ پی اچ پی مای ادمین رو در دسترس نداشتم و فکر کردم کارهای مورد نیاز بنده محدودتر و خاص هست و نیازی به مای ادمین نداره؛ گذشته از دردسرهای احتمالی دانلود و نصب و تنظیم و تشکیلات دیگش که البته بنظرم زیاد جدی هم نباید باشن بیشتر دیدم اصلا نسخه هایی از مای ادمین که بنده دیدم تمام امکاناتی رو که بنده میخوام، حداقل به راحتی ای که خودم میتونم با یک برنامهء سفارشی بهش دست پیدا کنم نداره. خلاصه این شد قضیهء نوشتن این برنامه.
البته اولش این برنامه خیلی ساده تر و مختصر و کم امکانات بود و فقط کارهایی رو که میخواستم بصورت نیمه دستی انجام میدادم باهاش، با اینحال واقعا مفید و کارساز بود و خیلی چیزها رو برام آسون کرد که بدون اون یا بی خیالش میشدم و یا خیلی سخت بود و زمان و انرژی خیلی بیشتری صرف میشد.
وقتی به فکر افتادم اون رو دراختیار دیگران و به خصوص مبتدیهایی که ممکنه نیازهایی مشابه داشته باشن قرارش بدم فکر کردم بهتره کاملتر و مجهزترش کنم تا هم برای خودم مفیدتر باشه و هم بدرد افراد بیشتری بخوره. شب دیروز و امروز تا حالا روش کار کردم تا به این صورت درآمده. امیدوارم برای کسی مفید واقع بشه. مخصوصا یک فایلش کردم که سریع قابل درج در فروم و همچنین برداشت و استفاده از اون باشه؛ بهرحال از شلوغی و ناخوانایی کد عذر میخوام؛ جایی نبود که وقت روی مسایل مختلف دیگه بذارم و فقط مستقیما به عملکرد پرداختم و تاحد وقت و انرژی معقول تست و باگیابی کردم تا بخوبی کار کنه.
اگر باگی درش کشف کردید با Test case مربوطه در جستار درج کنید.

در قسمتی که بین علامتهای <<<< قرار گرفته، مشخصات یک اکانت ادمینی (دارای اختیارات لازم) مای اس کیو ال رو باید وارد کنید که برنامه ازش برای استخراج اطلاعاتی که بصورت خودکار در فیلدها درج میکنه استفاده میکنه.

eshpilen
چهارشنبه 02 تیر 1389, 18:27 عصر
میخواستم چند نکته رو بگم برای کسانی که میخوان این برنامه رو اجرا کنن.
- سوپر یوزری که مشخصاتش در برنامه درج شده root@localhost هست و فکر میکنم این کاربر بطور پیشفرض در نصبهای مای اس کیو ال وجود داره، با این تفاوت که پسورد نداره (پسورد خالی)؛ اون پسورد (root_pass) رو بنده برای مقاصد تست خودم و نمایش و سنجش عملکرد قسمتهای مختلف برنامه بخصوص رابط کاربری اضافه کردم. پس احتمالا یک راه راحت برای راه انداختن سریع برنامه بصورت لوکال این هست که پسورد رو خالی قرار بدید.
- برای اضافه کردن سوپر یوزر جدید هم میشه از این فرمان در کلاینت مای اس کیو ال استفاده کرد (البته با پی اچ پی یا هر برنامهء دیگه ای هم که میشه باهاش به مای اس کیو ال کوئری لازم رو فرستاد امکان پذیر هست - البته یادتون نره که این فرمان دسترسی ادمینی لازم یا سوپر یوزر میخواد):


grant all on *.* to 'tinytest'@'localhost' identified by 'root_pass'

اگر از کلاینت خود مای اس کیو ال استفاده میکنید آخرش یک سمیکالن هم اضافه کنید.
اگر بجای نام کاربری tinytest از root یا هر نام کاربری دیگه ای که اکانتش از قبل موجوده استفاده بشه، مشخصات اون اکانت اعم از پسورد و دسترسی ها مطابق دستور آپدیت میشه درصورت تفاوت.
البته بهتره مبتدیها اکانت root رو تغییر ندن، چون ممکنه بعضی برنامه های دیگه که از این اکانت استفاده میکنن از کار بیفتن (بطور مثال کلاینت خود مای اس کیو ال) و باید تنظیماتشون رو آپدیت کرد.

در پایان باید ذکر کنم که تمام تستهای این برنامه هم در این محیط انجام و نتایج و اطلاعات درج شده در این جستار ازش کسب شده:

ردهت فدورا لینوکس ۵
مای اس کیو ال ۵
پی اچ پی ۵
آپاچی ۲.۲
فایرفاکس ۱.۵