This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Thib0704's profile picture

Need help : HTTP

Started by Thib0704, 08 July 2013 - 02:41 PM
Thib0704 #1
Posted 08 July 2013 - 04:41 PM
Hi,
I am trying to make a function that sends a script to my database.
The problem is When I am trying to send a file the PHP scripts dosn't
seem to receive the file But when I am sending the file from a web browser No Problems,
PHP inserts them in the database it works like a charm .
when I print the encoded script on the screen No problems it shows it perfectly

I would like to see if you ( forum pro's )
could fix the problem ?
here is the code :


    function upload(username ,password ,fileName ,filePath)
        if not username then
            return "Username missing"
        end
        if not password then
            return "Password missing"   
        end
        if not fileName then
            return "Please define a Filename"
        end
        if not filePath then
            return "Please define a Filepath"
        end
        if fs.exists(filePath) ~= true then
            return "file not found"
        end
            local file = fs.open(filePath,"r")
            content = file.readAll()
                file.close()
            local password = sha256(password)
            local sFile = textutils.urlEncode(fileName)
local response = http.post(CloudServer.."upload.php?username="..username.."&password="..password.."&filename="..sFile.."&filecode="..textutils.urlEncode(content))
                if response then
                    sResponse = response.readAll()
                    response.close()
                        return sResponse
                else
                    return "Cannot connect to host"
                end   
        end
theoriginalbit #2
Posted 08 July 2013 - 05:16 PM
If you're using $_POST in your PHP it should be

local response = http.post(CloudServer.."upload.php", "username="..username.."&password="..password.."&filename="..sFile.."&filecode="..textutils.urlEncode(content))
Note it is http.post( url, post_data )

If you're using $_GET in your PHP it should be

local response = http.get(CloudServer.."upload.php?username="..username.."&password="..password.."&filename="..sFile.."&filecode="..textutils.urlEncode(content))
Note it is http.get( url )
Thib0704 #3
Posted 08 July 2013 - 06:21 PM
Hi,
Thank's for your response
i'm using urldecode($_GET["filecode"'])
now as I said in my previous post
I can receive the data comming from a webbrowser but not from computercraft
what I mean by that ( sorry English isn't my primary language and i'm only 13 ) :
computercraft HTTP API -> Webserver : dosnt receive the FileCode.
Web Browser -> Webserver : no problem.

here is my php script :


<?php
$username = urldecode($_GET["username"]);
$password = urldecode($_GET["password"]);
$name = urldecode($_GET["filename"]);
$file = urldecode($_GET["filecode"]);
mysql_connect("", "", "") or die(mysql_error());
mysql_select_db("SecretUpComingProject :P/>") or die(mysql_error());

// $password = hash("sha256",$password);
$hashedpass = hash("sha512",$password);


$query = mysql_query("SELECT * FROM account WHERE Username = '".$username."'") or die(mysql_error());

if (mysql_num_rows($query) < 1 )
{
    die("Invalid Account");
}

while($row = mysql_fetch_array($query)) {

      if( $row['Password'] == $hashedpass ){

        $files = mysql_query("SELECT Name FROM files WHERE Username = '".$username."'") or die(mysql_error());
           
            if ( mysql_num_rows($files) == 15 ) {
                die("Exeeded File limit");
            }
                   
        $names = mysql_query("SELECT * FROM files WHERE Name = '".$name."'") or die(mysql_error());
           

        while ($sName = mysql_fetch_array($names)){
           
        if( $sName["Username"] == $username ){
       
            if ( mysql_num_rows($names) > 0 ){
                die("Name Already Exists");
            }
        }
        }   

        $response = mysql_query("INSERT INTO `files`(`Name`, `Username`, `Code`) VALUES ('$name', '$username', '$file')") or die(mysql_error());
        echo "Successfuly  uploaded";
        echo $file;

    }
    else {   
    echo "NotLogged";
}

}

?>
theoriginalbit #4
Posted 08 July 2013 - 06:36 PM
I stand by what I've posted. Either change http.post to http.get, and then on your webpage form use <form action="get" … > instead of the post in the action… or use post in your webpage and CC and use $_GET instead of $_POST in your PHP. You cannot swap between them at will, they both have different processes of passing the data to your php script.

Side note: please look into using prepared statements for your SQL queries so that we do not have another NDFJay incident. At the current state your code is VERY susceptible to SQL injection…
Thib0704 #5
Posted 08 July 2013 - 06:46 PM
By prepared statements you mean Having people injecting PHP code into my database
If yes i'm trying to learn how to make it so this won't happen. If you have any tips
please consider giving me some.
Thank's

and I think i will go with $_POST as I heard they where more secure then $_GET
theoriginalbit #6
Posted 09 July 2013 - 01:34 AM
Ok firstly, it really is up to you which to go with, because the difference between post and get is well, nothing really more "secure".
The way it works is with get, the data being sent to the website exists in the url, as plaintext for the user to see (and where appropriate characters are encoded to be http safe). On the PHP side all the values within the $_GET variable are already decoded for you from the http safe format.
The difference with post is that the data is not in the url, it is actually in the http header which is not visible to the average user, but more advanced users can still capture this http packet and read its header if they really wanted to. Now on the PHP side the values within the $_POST variable are not decoded, they exist in the raw format they came in, which means you have to decode them yourself (like you're doing).
Now the advantage of the data not appearing in the url is a redundant point when it comes to ComputerCraft because, well, there is no browser or url bar for the user to see, and if you chose to print that data is being sent, then you can just not show them the data with get requests anyway. So in terms of CC, go either one, in terms of web applications, you can still go either one, just depends if you wish to show the get query to the user or not… for example Google uses get, you can see all the url data when you do searches…
Here you go, here is a nice little StackOverflow question on the matter


By prepared statement I mean stopping people from being able to do SQL injection. Since I have recently done this for a boring project at uni, I actually have an example on my computer I can just show you… this is my account registration script ( I've heavily commented it for you :)/> )

Spoiler


<?php
	// make sure we can redirect (this was just a nice little function that made redirects nicer to user over and over)
	// for your case you would most likely use die("why it died") so that the browser gets the error, and computercraft gets the error message
	// so that you can tell your user why the registration failed
	// NOTE: the scripts at the other end are designed to receive a GET, which is why the redirects are formatted in the way they are (plus its easier to do GET than POST from PHP)
	require_once($_SERVER['DOCUMENT_ROOT'] . "eta/functions/redirect.php");

	if (!isset($_POST['rpass'])){ redirect('index.php?e'); }

	// The salt is just a bunch of random data to help further hide the hashed password and make it harder to do a lookup on the hashed password
	// each user has a different salt so that even two passwords if the same, have different hashed values
	$salt = hash("sha256",mcrypt_create_iv(64));

	// get the register details from the post data
	$input_username = urldecode($_POST["user"]);
	$input_email = urldecode($_POST["email"]);
	$input_password = urldecode($_POST["pass"]);
	$input_repeat_password = urldecode($_POST["rpass"]);

	// deleted variable validation... not needed for this example to you Thib0704

	// create a new mysql connection
	$connection = new mysqli($db_host, $db_user, $db_pass, $db_name);

	// make sure there is a connection
	if (mysqli_connect_error()) { redirect('register.php?d'); }

	// create a prepared statement to check if the username exists already, the ? is where values will end up going
	$query = "SELECT COUNT(username) FROM user WHERE username = ?;";

	// create the statement
	$stmt = $connection->prepare($query);

	// fill in the blanks that were in the query, i.e. place the username in the ? ... s means string, there are other letters for other data types
	$stmt->bind_param("s", $input_username);

	// check if the execution succeeded
	if (!$stmt->execute()){ redirect('register.php?d'); }

	// bind the returned data to variables, this gets the return result from the database and adds it into the $usersWithThatName variable
	$stmt->bind_result($usersWithThatName);

	// complete the process
	$stmt->fetch();

	// make sure no other users have the same username
	if($usersWithThatName != 0){ redirect('register.php?x'); }

	// close the mysql statement, don't close the connection, we have more to do still
	$stmt->close();

	// create a prepared statement to make sure the email hasn't been used before, the process is exactly the same as above
	$query = "SELECT COUNT(email) FROM user WHERE email = ?;";
	$stmt = $connection->prepare($query);
	$stmt->bind_param("s", $input_email);
	if (!$stmt->execute()){ redirect('register.php?d'); }
	$stmt->bind_result($usersWithThatEmail);
	$stmt->fetch();
	if($usersWithThatEmail != 0){ redirect('register.php?l'); }
	$stmt->close();

	// append the salt to the input password and then hash it, making sure to use the same hashing algorithm otherwise the weakest link is the lower hash algo
	$hashed_password = hash("sha256", $input_password . $salt);

	// create a prepared statement to insert many variables into the table (we have to insert the salt so we can know what the users salt is later)
	$insert_stmt = "INSERT INTO user (username, password, salt, email, securityLevel) VALUES(?, ?, ?, ?, 1);";
	$stmt = $connection->prepare($insert_stmt);

	// now notice that we have an 's' per ?, so for each ? you must have a value to put into it, again this is a bad example because all we used were varchar2 everywhere
	// as that was all we needed to use, but there are other letters for other data types
	$stmt->bind_param("ssss", $input_username, $hashed_password, $salt, $input_email);

	if (!$stmt->execute()){ redirect('register.php?d'); }

	// I left this in just so you could see that you can get the primary key of the result, in this case for us it was a number as the unique user id and we then made
	// a folder for them on the server
	$userId = $connection->insert_id;
	mkdir($_SERVER['DOCUMENT_ROOT'] . 'eta/user_data/' . $userId);

	// this line takes us back to a page, but below the closing php tag you could just have html code like "registration successful" and that is:
	// 1 what the browser will show and
	// 2 the only text computercraft will get back
	redirect('index.php?s');
?>
Edited on 08 July 2013 - 11:38 PM
Thib0704 #7
Posted 09 July 2013 - 04:16 AM
Wow Thank's for this AMAZING script !
I think i will learn a lot with :)/>

Will it change something if I change the password encryption to sha512 ? code
I think it would be easier if we PM ourself so I could Post you the code without everyone seeing the :P/>.

Thank's
theoriginalbit #8
Posted 09 July 2013 - 04:38 AM
Thanks :)/>

Changing the hashing algorithm from sha256 to sha512 would not change much, it is a little better, but if you want the best one you use m_crypt or something like that, it takes quite some time to create the hash, but that is the point. Also be aware that a hashing algorithm is not a password encryption. Encryption is very different to hashing.

You may PM if you wish, and it your request I can send you my files for that website the php was from. It is no where near usefully as commented as the above code I gave you, but it is commented.