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

HTTP POST Array Serialization: textutils to PHP

Started by Blitzninja, 12 April 2014 - 03:42 PM
Blitzninja #1
Posted 12 April 2014 - 05:42 PM
Dear all,

I currently am playing FTB Monster and I run a massive powerplant for the people in the area and couple of times the system went down without me knowing. Meanwhile at school our final project for web development is basically something that combines HTML, CSS, JS, PHP and databases.

So I decided to make a website to remotely administrate and monitor the powerplant, including history (with charts, etc) and otherwise.

The data I will be sending every interval (approx 15s, will finalize later based on server load) to the database for storage is stored in a large array which will have new data/vars added as the powerplant grows and thus manually serializing the array is not really viable.

Question: What I was looking for was if the textutils.serialize(arg) function uses the same encoding format as the PHP serialize($arg) function so that I can just serialize the array with textutils and deserialize it with PHP's unserialize($arg) serverside orcan textutils encode it properly for automatic reception as $_POST by PHP.

This would be very helpful to know. I've searched the forums and google to no sucess.

Note: On my phone, will post code later.

Edit: Code examples:


_POST = {}
cmd_interval = 15 -- time in seconds between each update
function initPOST()
	-- First time initialization
	_POST.steam_buffer	  = {0, 0}	-- FOR ALL: (current, max)
	_POST.energy_rf_main	= {0, 0}
	_POST.energy_rf_emer	= {0, 0}
	_POST.energy_eu_main	= {0, 0}
	_POST.energy_eu_emer	= {0, 0}
	_POST.action			= "update"
	_POST.init			  = true
end
function updateDB()
	if (_POST.init ~= nil) then
		-- Potential use of textutils.serialize()
		_POST.action = "update"
		return http.post("http://mywebserver.com/ftbinterface.php", textutils.serialize(_POST))
	else
		initPost()
		return "error"
	end
end
function reqCMDs()
	if (_POST.init ~= nil) then
		_POST.action = "getcmds"
		return http.post("http://mywebserver.com/ftbinterface.php", textutils.serialize(_POST))
	end
end

I know the code above is semi-functional but it's hard for me to get a feel for it when you don't know if it works.

P.S. PHP Code is protected against SQL Injections so no worries.


Sincerely,

Blitzninja.
Edited on 13 April 2014 - 01:29 AM
Lyqyd #2
Posted 13 April 2014 - 07:01 AM
I find it highly unlikely that PHP's serialize function would generate a valid Lua table declaration, or that its unserialize would be able to make heads or tails of Lua table syntax.
Lignum #3
Posted 13 April 2014 - 12:50 PM
PHP's serialize and unserialize are not the same ones as in textutils.
You've got three ways to approach this problem:
  1. Make your own serializer and implement it in both, PHP and Lua. It may take up some time to write but it wouldn't be too hard.
  2. Write a PHP function that reads Lua's serialized data.
  3. Or if you're lazy: Use a Lua interpreter (like this one) to read the data. This is a very dirty solution and I don't recommend it but it works.
Blitzninja #4
Posted 13 April 2014 - 04:34 PM
PHP's serialize and unserialize are not the same ones as in textutils.
You've got three ways to approach this problem:
  1. Make your own serializer and implement it in both, PHP and Lua. It may take up some time to write but it wouldn't be too hard.
  2. Write a PHP function that reads Lua's serialized data.
  3. Or if you're lazy: Use a Lua interpreter (like this one) to read the data. This is a very dirty solution and I don't recommend it but it works.


I'm probably gonna write my own out of OCD
Shazz #5
Posted 13 April 2014 - 05:07 PM
Or you can just use this JSON API for Lua.
And on the other end, use PHP's JSON functions.
Blitzninja #6
Posted 14 April 2014 - 02:15 PM
Or you can just use this JSON API for Lua.
And on the other end, use PHP's JSON functions.

Looks good I think I'll give it a shot.

Ok so in the Lua JSON API, the guy uses a member from the object to get the decoded data called "thisVariableWasInTheJSONAndThisIsCoolerThanUsingStringGmatchToFindEverything".

Is he kidding or do I have to use that too?


Edit, nvm. That was just a somewhat confusing way to say "decoded_obj.member"

UPDATE:

Ok so here is the current communication code, look good?
Lua:

_POST = {}
cmd_interval = 15 -- time in seconds between each update
function initPOST()
    -- First time initialization
    os.loadAPI("json")
    _POST.steam_buffer		  = 0
    _POST.energy_rf_main	    = 0
    _POST.energy_rf_emer	    = 0
    _POST.energy_eu_main	    = 0
    _POST.energy_eu_emer	    = 0
    _POST.steam_buffer_max	  = 0
    _POST.energy_rf_main_max    = 0
    _POST.energy_rf_emer_max    = 0
    _POST.energy_eu_main_max    = 0
    _POST.energy_eu_emer_max    = 0
    _POST.action		    = "update"
    _POST.init			  = true
end
function updateDB()
    if (_POST.init ~= nil) then
	    _POST.action = "update"
	    return http.post("http://mywebserver.com/ftbinterface.php", 'json_enc='..json.encode(_POST))
    else
	    initPost()
	    return "error"
    end
end
function reqCMDs()
	    return http.post("http://mywebserver.com/ftbinterface.php", 'action=\'getcmds\'&init=\'true\'')
end

PHP: ftbinterface.php

<?php
require_once 'databasefunc.inc.php';
//For easy changing and neatness
$sql_host	   = 'localhost';
$sql_user	   = 'root';
$sql_pass	   = '*****';
$sql_db		 = 'ftb';
$sql_charset    = 'utf8';
$sql = createDBSession($sql_host, $sql_user, $sql_pass, $sql_db, $sql_charset);
if (isset($_POST['json_enc'])&amp;&amp;!empty($_POST['json_enc']))
{
    $decoded_post = json_decode($_POST);
}
else
{
    $decoded_post = $_POST;
}
if (isset($decoded_post['init'])&amp;&amp;!empty($decoded_post['init']))
{
    if ($decoded_post['action']=='update')
    {
	    foreach ($decoded_post as $k=>$v)
	    {
		    if ($k!='action' || $k!='init')
		    {
			    echo query(
				    "INSERT INTO monster_world1 (Var, Data) VALUES ($k, $v) ON DUPLICATE KEY UPDATE Data=?",
				    array($v), $sql);
		    }
	    }
    }
    elseif ($decoded_post['action']=='getcmds')
    {
	    $r = query("SELECT Var, Data2 FROM monster_world1 WHERE Var=?", array('cmd_buffer'), $sql);
	    if (!empty($r))
	    {
		    echo $r;
	    }
	    else
	    {
		    query("INSERT INTO monster_world1 (Var, Data) VALUES ('cmd_buffer',?)", array(''), $sql);
		    echo '';
	    }
    }
}

PHP: databasefunc.inc.php:

<?php

function createDBSession($mysql_host, $mysql_user, $mysql_pass, $mysql_db, $mysql_charset)
{
    $dsn = "mysql:host=".$mysql_host.";dbname=".$mysql_db.";charset=".$mysql_charset;
    $opt = array(
	    PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
	    PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC
    );
    return new PDO($dsn, $mysql_user, $mysql_pass, $opt);
}
function createDBSessionOpt($mysql_host, $mysql_user, $mysql_pass, $mysql_db, $mysql_charset, array $opt)
{
    $dsn = "mysql:host=".$mysql_host.";dbname=".$mysql_db.";charset=".$mysql_charset;
    return new PDO($dsn, $mysql_user, $mysql_pass, $opt);
}
function query(string $querybase, array $queryreplace, PDO $pdo)
{
    try
    {
	    $pdo->beginTransaction();
	    $sql_p = $pdo->prepare($querybase);
	    $sql_p->execute($queryreplace);
	    $result = $sql_p->fetchAll();
	    $pdo->commit();
	    return $result;
    }
    catch(Exception $e)
    {
	    $pdo->rollBack();
	    return 'Error: '.$e->getMessage();
    }
}
?>

What do you guys think?
Edited on 14 April 2014 - 03:06 PM