我制作了这个脚本给我带来了很多麻烦。我不太擅长MySQL,也许我正在尝试为我的SQL知识做过于先进的事情,但我真的非常希望能够做到这一点。
我的PHP脚本是:
<?PHP
$getusername=$_GET['user'];
$getpassword=$_GET['pass'];
$getworldname=$_GET['worldname'];
$getblock=$_GET['block'];
$getpos=$_GET['pos'];
$user_name = "asdasdasd";
$password = "asdasd";
$database = "asdasd";
$server = "localhost";
$db_handle = mysql_connect($server, $user_name, $password);
$db_found = mysql_select_db($database, $db_handle);
$SQL="SELECT * FROM accounts WHERE username='$getusername' and password='$getpassword'";
$result=mysql_query($SQL);
$count=mysql_num_rows($result);
if($count==1){
$blockstring=$getpos.'/'.$getblock.'|';
$SQL="SELECT LOCATE('$getpos', blocks) FROM worlds WHERE name='$getworldname'";
$result=mysql_query($SQL);
$count=mysql_num_rows($result);
echo $count;
//if there's already that block
if ($result!=0){
$posUnknown='|'.$getpos.'/';
$posKnown='|'.$getpos.'/'.$getblock;
$SQL="UPDATE worlds SET blocks=replace(blocks,concat('$posUnknown',substring_index(substring_index(blocks, '$posUnknown', 2), '|', 1),'|'),'$posKnown') WHERE name='$getworldname'";
$result=mysql_query($SQL);
}else{
$SQL="UPDATE worlds SET blocks=CONCAT(blocks,'$blockstring') WHERE name='$getworldname'";
$result=mysql_query($SQL);
}
print 'OK';
}else{
print 'NO';
}
?>
我确定我犯了一些错误,也是查询中的大错,但遗憾的是我无法弄清楚我做错了什么。
块的内容示例可以是:
x10y20z30 / 0 | x999y1231z30 / 1 | x3330y4444z0 / 99999 |等
这个脚本的功能,以及我希望它做的是:
但它没有用,我知道为什么。我知道这是因为SQL,但我无法弄清楚如何使它工作。
答案 0 :(得分:1)
正如评论中所指出的,您的代码安全性存在严重问题。我已经做了我能做的事情,而没有真正改变你的代码在做什么:
<?PHP
$getusername=$_GET['user'];
$getpassword=$_GET['pass'];
$getworldname=$_GET['worldname'];
$getblock=$_GET['block'];
$getpos=$_GET['pos'];
$user_name = "asdasdasd";
$password = "asdasd";
$database = "asdasd";
$server = "localhost";
你应该使用mysqli,而不是mysql:
$db = new mysqli($server, $user_name, $password, $database);
在使用real_escape_string:
的查询中使用之前,所有输入都需要进行转义 $SQL="SELECT * FROM accounts WHERE username='" . $db->real_escape_string($getusername) . "' and password='" . $db->real_escape_string($getpassword) . "'";
$result=$db->query($SQL);
$count=$result->num_rows;
if($count==1) {
$blockstring=$getpos.'/'.$getblock.'|';
$SQL="SELECT LOCATE('" . $db->real_escape_string($getpos) . "', blocks) FROM worlds WHERE name='" . $db->real_escape_string($getworldname) . "'";
$result=$db->query($SQL);
$count=$result->num_rows;
echo $count;
//if there's already that block
if ($count!=0) {
$posUnknown='|'.$getpos.'/';
$posKnown='|'.$getpos.'/'.$getblock;
这可能是您遇到麻烦的地方,因为看起来您将所有这些信息存储在一行中:
$SQL="UPDATE worlds SET blocks=replace(blocks,concat('" . $db->real_escape_string($posUnknown) ."',substring_index(substring_index(blocks, '" . $db->real_escape_string($posUnknown). "', 2), '|', 1),'|'),'" . $db->real_escape_string($posKnown) . "') WHERE name='" . $db->real_escape_string($getworldname). "'";
$result=$db->query($SQL);
} else {
$SQL="UPDATE worlds SET blocks=CONCAT(blocks,'" . $db->real_escape_string($blockstring) ."') WHERE name='" . $db->real_escape_string($getworldname) . "'";
$result=$db->query($SQL);
}
print 'OK';
} else {
print 'NO';
}
?>
由于您的所有块信息都在一个列中被推到一起,因此您的数据库根本没有标准化,看起来像这样:
Worlds
name blocks
你的数据库的结构应该更像这样:
Worlds
id | name
---------------
1 | demoworld
Blocks
id | WorldID | x | y | z | data
-----------------------------------------
1 | 1 | 10 | 20 | 30 | 0
2 | 1 | 999 | 1231 | 30 | 1
3 | 1 | 33330 | 4444 | 0 | 99999
您可以重新创建查询数据时提供的数据布局,当有人尝试添加x20y30z40 / 12345之类的内容时,您可以解析它以获取x,y,z和数据部分。