2014-07-17 3 views
0

저는 많은 문제를 일으키는이 스크립트를 만들었습니다. 나는 MySQL에 능숙하지 못하며 아마도 SQL에 대한 지식이 너무 뛰어 났을 것입니다.하지만이 작업을 정말로하고 싶습니다.PHP + MySQL 스크립트가 작동하지 않습니다.

내 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 | 등

이 스크립트가하는 일, 음, 내가 무엇을 원

  • 검사는 주어진 블록은 이미 내가 존재하는 경우,

    • 확인 사용자 이름과 암호, 그리고 운이 좋게 작동합니다 할 것입니다 존재하지 않는 경우 N "블록"
    • 는 새 것으로 이미 존재하는 블록의 값 (은/후를) 대체 존재하는 경우,
    • 는에 "블록"을 추가합니다.

    하지만 작동하지 않으며 그 이유를 알고 있습니다. 나는 그것이 SQL이기 때문에 그것이지만, 어떻게 작동하게하는지 알아낼 수 없다는 것을 압니다.

  • +2

    [안녕하세요, 제 이름은] (http://xkcd.com/327/)'Robert '; 테이블 계정을 삭제하십시오; - 그리고 내가 당신의 사이트를 방문했을 때 모든 것이 깨집니다. [SQL 주입] (http : //en.wikipedia.org/wiki/SQL_injection), 선호하면 [pdo 또는 mysqli] (http://php.net/manual/en/mysqlinfo.api.choosing.php)를 사용 하시겠습니까? – scragar

    +0

    [link] (http://beta.phpformatter.com/)에 코드를 들여 놓아야하고 실제로 그렇게하고 싶은지 확인하십시오. – simeg

    답변

    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 
    

    당신은 당신이 X, Y, Z를 얻기 위해 그것을 구문 분석 할 수 있습니다, 당신은 데이터를 쿼리 할 때 제공 한 데이터 레이아웃을 재 작성하고 누군가가 x20y30z40/12345과 같은 무언가를 추가하려고 할 때 수, 및 데이터 부분.

    +0

    사용자가 변경할 수있는 블록이 1000x1000 = 1 MIL이므로 60 메일과 60 마일이 같아서 atleast 100 세계를 위해 곱 해져서 변경 될 수있는 6 억 개의 블록을 가지고 있기 때문에 내가 말했던 방식으로 데이터베이스를 구조 할 수 없다. 정말로 6 억 줄을 가진 데이터베이스를 원한다. 훨씬 더 단순한 100 개의 큰 행이 필요하다 :) 메신저 그것을 목적 행렬에 모두 저장하는 방법으로, 그리고 그것은 문제가 아닌 것으로 생각된다. 블록이 이미있는 경우 출력이 정확하지 않거나 1 : / –

    관련 문제