Automatically uploading info to a website?
Posted by Areadien on Tue 07 Aug 2018 02:34 AM — 27 posts, 85,107 views.
It’s possible, but I don’t think it would be particularly easy.
The format for sending messages to a HTTP server is well-documented, but if you are not familiar with it, it could be fairly daunting. Plus, you presumably need to authenticate yourself to the site. Normally when you do that in a web browser it sends a cookie which, when returned for the next transaction, identifies you as the logged-in user.
If you tried to automate all that you would have to somehow log in, save the cookie, retrieve it when you finished a quest, and send that along with the other information.
Probably what would be easier would be to just save your quest completions to a text file (possibly with markup if your blog/site supports that) and then periodically (eg. each day) upload that to your site.
<form action ="post">
<input name = "character" type = "text" value = "" /> <input name = "questNum" type = "text" value = "" /> <input name = "time" type = "text" value = "" />
</form>In particular the graphic about the format of a HTTP message:

You could use the LuaSocket library, some description here:
https://www.gammon.com.au/forum/?id=4935
Also look here for more recent instructions:
http://www.gammon.com.au/forum/?id=8319&reply=3#reply3
Based on the graphic above, you just need to substitute the path to the processing page, omit the cookie line, change the post parameters, and then connect to the web server, send that message, and disconnect.
Microsoft Windows [Version 10.0.17134.191]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\System32>cd c:\luasocket
c:\luasocket>lua
Lua 5.0.2 Copyright (C) 1994-2004 Tecgraf, PUC-Rio
> dofile("lua.lua")
> http = require "http"
> a, b, c = http.request("http://localhost/mm/abby.php")
> print(a, b, c)
Hello World
200 table: 00A3F930
>
Me: What is your name?
You: My name is Areadien
The point is that PHP forms don't really care if you previously saw the form or not, as each interaction with the server is independent of the other. Thus you could say:
You: My name is Areadien
You can do this without even seeing the question. Thus, you can "fill in" a form, without seeing it. You just send the appropriate data fields (as in the example above: "action=save").
The page URL is: http://10.0.0.2/hms/dates.php
(You won't be able to access that, of course, as it is a private IP address).
That is in this line:
url = "http://10.0.0.2/hms/dates.php",
You can see in the code below the form being "filled in" here:
request_body = fixrequest { StartDate = '1 Jan 2018', Range = '20' }
The URL encoding should handle things like multiple lines, spaces inside a field, and so on.
http = require "socket.http"
-- converts characters that are not alphanumeric
-- into the form %xx (for use in cookies, forms etc.)
function urlencode (s)
return (string.gsub (s, "%W",
function (str)
return string.format ("%%%02X", string.byte (str))
end ))
end -- function urlencode
-- turn a table of POST values into a url-encoded string
function fixrequest (req)
local t = { }
for k, v in pairs (req) do
table.insert (t, urlencode(k) .. '=' .. urlencode(v))
end -- for
return table.concat (t, "&")
end -- fixrequest
request_body = fixrequest { StartDate = '1 Jan 2018', Range = '20' }
response_body = {}
socket.http.request {
url = "http://10.0.0.2/hms/dates.php",
method = "POST",
headers = {
["Content-Length"] = string.len(request_body),
["Content-Type"] = "application/x-www-form-urlencoded"
}, -- end of headers
source = ltn12.source.string(request_body),
sink = ltn12.sink.table(response_body)
} -- end of request table
require "tprint"
tprint (response_body)
Effectively this is "posting" the form with the given URL, with the specified fields in "request_body" filled in with the specified values, and then getting the response. If your main aim is for the form to add to a database you could ignore the response, or maybe just check that you haven't got an error message.
If you aren't sure of the field names you can "view page source" in your web browser and check out what is used in the form. For example, in the above case:
<form METHOD="post" ACTION=/hms/dates.php>
Starting date: <input type=text Name="StartDate" size=20 maxlength=20 value="" autofocus>
+/- days or end date: <input type=text Name="Range" size=20 maxlength=20 value="">
<input Type=submit Name=Submit Value="Calculate">
</form>
function questUpload (name, line, wildcards)
-- put stuff here
end -- questUpload
Leave out the last two lines (the tprint stuff), of course, because that is just for debugging. You will need to change the URL and the names of the fields that are to be populated.
<aliases>
<alias enabled="y" match="^upload$" regexp="y" send_to="12" sequence="100">
<send>testUpload()</send>
</alias>
</aliases>Here's the functions:
function urlencode (s)
return string.gsub(s, "%W", string.format("%%%02X", string.byte(str)))
end -- function urlencode
function fixrequest(req)
local t = {}
for k, v in pairs (req) do
table.insert(t, urlencode(k) .. '=' .. urlencode(v))
end -- for
return table.concat(t, "&")
end -- fixrequest
function testUpload()
http = require "socket.http"
request_body = fixrequest {character = "Aberdeen", qnum = 43, time = 1534372981}
response_body = {}
socket.http.request {
url = "http://localhost/mm/abby.php",
method = "POST",
headers = {
["Content-Length"] = string.len(request_body),
["Content-Type"] = "application/x-www-form-urlencoded"
}, -- end of headers
source = ltn12.source.string(request_body),
sink = ltn12.sink.table(response_body)
} -- end of request table
cNote("done")
end --function testUploadAnd here's my form.
<form action = "" method = "post">
<input name = "character" type = "text" value = "" /> <input name = "qnum" type = "text" value = "" /> <input name = "completed" type = "text" value = "" />
<input type = "submit" value = "Submit" />
</form><?php
print_r($_POST);
if(!empty($_POST))
{
$connect = @mysqli_connect('localhost', 'mm_i', 'password', 'mm');
if($connect === false)
{
bn('<p>');
bn('<span>Error: Unable to connect to MySQL on line 6 in mm/abby.php: ' . mysqli_connect_error() . '</span>');
bn('</p>');
bn('<p>');
exit;
}
else
{
$result = mysqli_query($connect, "INSERT INTO myquests VALUES(NULL, '{$_POST['character']}', {$_POST['qnum']}, {$_POST['completed']});")
or die("Could not execute sql query <b>" . htmlentities($query) . "</b> on line $line in mm/abby.php: " . mysqli_error($connect));
mysqli_close($connect) or die("Could not close server connection on line " . __LINE__ . " in mm/abby.php because: " . mysqli_error());
}
}?>
<form action = "" method = "post">'
<input name = "character" type = "text" value = "" /> <input name = "qnum" type = "text" value = "" /> <input name = "completed" type = "text" value = "" /><br />
<input type = "submit" value = "Submit" />
</form>And then here's the table:
CREATE TABLE IF NOT EXISTS `myquests` (
`entry` int(15) NOT NULL AUTO_INCREMENT,
`charName` varchar(12) NOT NULL,
`qnum` int(5) NOT NULL,
`completion` int(10) NOT NULL,
PRIMARY KEY (`entry`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Immediate execution
[string "Script file"]:799: bad argument #1 to 'byte' (string expected, got nil)
stack traceback:
[C]: in function 'byte'
[string "Script file"]:799: in function 'urlencode'
[string "Script file"]:805: in function 'fixrequest'
[string "Script file"]:812: in function 'testUpload'
[string "Alias: "]:1: in main chunk
Error context in script:
795 :
796 :
797 :
798 : function urlencode (s)
799*: return string.gsub(s, "%W", string.format("%%%02X", string.byte(str)))
800 : end -- function urlencode
801 :
802 : function fixrequest(req)
803 : local t = {}
It might also be helpful to "assert" the socket.http.request so you get back some error message if it fails. Both changes here:
-- converts characters that are not alphanumeric
-- into the form %xx (for use in cookies, forms etc.)
function urlencode (s)
return (string.gsub (s, "%W",
function (str)
return string.format ("%%%02X", string.byte (str))
end ))
end -- function urlencode
function fixrequest(req)
local t = {}
for k, v in pairs (req) do
table.insert(t, urlencode(k) .. '=' .. urlencode(v))
end -- for
return table.concat(t, "&")
end -- fixrequest
function testUpload()
http = require "socket.http"
request_body = fixrequest {character = "Aberdeen", qnum = 43, time = 1534372981}
response_body = {}
assert (socket.http.request {
url = "http://localhost/mm/abby.php",
method = "POST",
headers = {
["Content-Length"] = string.len(request_body),
["Content-Type"] = "application/x-www-form-urlencoded"
}, -- end of headers
source = ltn12.source.string(request_body),
sink = ltn12.sink.table(response_body)
}) -- end of request table
Note("done")
end --function testUpload
Now, with the string.gsub, do I absolutely have to have the anonymous function? In other words, can I change the code to an equivalent that doesn't have it?
Also, I'm doing this now; it seems to be the equivalent, but I'm not sure.
function urlencode (s)
return string.gsub (s, "%W", string.format ("%%%02X", string.byte ('%1')))
end -- function urlencodeIf so, it is because you rewrote my function urlencode
Yeah, I had to get rid of the anonymous function.
Actually, I know why it didn't error. I had another function named urlencode after the one you provided, so it was using that one, I guess.
Also, I'm doing this now; it seems to be the equivalent, but I'm not sure.
It doesn't seem to work for me:
function urlencode (s)
return string.gsub (s, "%W", string.format ("%%%02X", string.byte ('%1')))
end -- function urlencode
print (urlencode "jack goes to the market")
Give me:
Run-time error
World: smaug2
Immediate execution
[string "Immediate"]:2: invalid capture index
stack traceback:
[C]: in function 'gsub'
[string "Immediate"]:2: in function 'urlencode'
[string "Immediate"]:5: in main chunk
Yeah, I had to get rid of the anonymous function.
You didn't have to, you chose to, and this improved function doesn't work quite as well.
<?php
print_r($_POST);
if(!empty($_POST))
{
$connect = @mysqli_connect('localhost', 'mm_i', 'password', 'mm');
if($connect === false)
{
echo('<p>');
echo('<span>Error: Unable to connect to MySQL on line 6 in mm/abby.php: ' . mysqli_connect_error() . '</span>');
echo('</p>');
echo('<p>');
exit;
}
else
{
$query = "INSERT INTO myquests VALUES(NULL, '{$_POST['character']}', '{$_POST['qnum']}', '{$_POST['completed']}');";
$result = mysqli_query($connect, $query)
or die("Could not execute sql query <b>" . htmlentities($query) . "</b> in mm/abby.php: " . mysqli_error($connect));
mysqli_close($connect) or die("Could not close server connection on line " . __LINE__ . " in mm/abby.php because: " . mysqli_error());
}
}?>
<form action = "" method = "post">'
<input name = "character" type = "text" value = "" /> <input name = "qnum" type = "text" value = "" /> <input name = "completed" type = "text" value = "" /><br />
<input type = "submit" value = "Submit" />
</form>
Yours had various issues, for example "htmlentities($query)" where $query was not defined.
It also isn't great as HTML, you should really have <html><head><body> etc. tags in it so it looks like a proper web page. However for computer filling-in it is probably OK.
Once that was sorted, I could fill in the PHP page, press Submit, and a record was added to the database.
I also tweaked the script (for example the urlencode). You also had:
request_body = fixrequest {character = "Aberdeen", qnum = 43, time = 1534372981}
However the PHP page called the variable "completed" not "time". You have to get details like this right.
-- converts characters that are not alphanumeric
-- into the form %xx (for use in cookies, forms etc.)
function urlencode (s)
return (string.gsub (s, "%W",
function (str)
return string.format ("%%%02X", string.byte (str))
end ))
end -- function urlencode
function fixrequest(req)
local t = {}
for k, v in pairs (req) do
table.insert(t, urlencode(k) .. '=' .. urlencode(v))
end -- for
return table.concat(t, "&")
end -- fixrequest
function testUpload()
http = require "socket.http"
request_body = fixrequest {character = "Aberdeen", qnum = 43, completed = 1534372981}
response_body = {}
assert (socket.http.request {
url = "http://localhost/mm/abby.php",
method = "POST",
headers = {
["Content-Length"] = string.len(request_body),
["Content-Type"] = "application/x-www-form-urlencoded"
}, -- end of headers
source = ltn12.source.string(request_body),
sink = ltn12.sink.table(response_body)
}) -- end of request table
Note("done")
end --function testUpload
With all that done, it does indeed add records to the database.
Yeah, I had to get rid of the anonymous function.
You didn't have to, you chose to, and this improved function doesn't work quite as well.
Yeah, that was an error. I meant, "I had to if I wanted to get rid of the anonymous function." Not that I actually had to get rid of the anonymous function.
Yours had various issues, for example "htmlentities($query)" where $query was not defined.
Yeah, that's what I get for using my own functions--in this case, it's called sqlQuery($query)--and not thoroughly changing them so that I don't have to specifically provide the definitions for them.
If you look at reply #3 in this thread you will see that the GET parameters are in a different place (on the URL) so you would need to add them to the end of the URL, like:
url = "http://localhost/mm/abby.php?character=Aberdeen&qnum=43",
Then the request_body would be empty.