DerRaphael's httpQuery (
http://www.autohotkey.com/forum/topic33506.html) has been a godsend and I've used it for a couple of applications. Now I've got a use which I think maybe stretching the envelope. I've got an application which uses Amazon's S3 on-line storage facility. Amazon has provided the capability for folks to upload via a posted web form. With my application a browser isn't used but instead an ahk script which processes files (videos) and then uploads them to S3. By using the Amazon post capability I do not have to share my Amazon secret keys with my users. The problem is I can't get it to work. And truthfully I'm messing with stuff I don't totally understand fully. (But having said that I've made some progress and at least have it to the point where perhaps I can reasonably and hopefully get some help.) I really think a lot of folks could use this capability if it can be made to work.
This effort is based on the amazon service as described here. (
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1434)
What happens is a page generates a properly constructed "policy document" and an encoded "signature value" which is used to authorize an upload to an S3 account within a certain time period. (The signature value is generated based on the policy document and the account owners private 'secret key') These two items populate hidden fields in the form. Then, in the browser usage the users selects a file and then clicks submit and the post is pointed to amazon which then validates the documents and accepts the file and stores it in the specified account 'bucket'. On success amazon returns with a redirected landing page. (In the example it is set to the same page.)
So this is how far that I've got. I built the test php page which works fine with a browser. That page has two entry points. One is the typical, first use, page where one is invited to pick a file to upload to my account. The second is when it is redirected to on success. In the later case I simply share the url with the last uploaded file so that it can be verified that it got there and that it can be retrieved. So far so good. Now for ahk (non browser application) I added a third entry point. That is when httpQuery hits the page with a POSTdata variable of 'policy' set. Then the page simply returns the policy document and signature value as a result. Then (the idea anyway) is that my ahk program uses those values to populate POSTdata to the query to be sent to the amazon url. Something at this point breaks. I don't know if its because I needed to do something different for the https use for the amazon page or something else. I'm assume that the redirect is not an issue as that would just come back as an html string that I would ignore (other than using it to verify success.)
As I mentioned I really think something like this could be really useful for storing data on S3 without the necessity of sharing private secret keys. If anyone is interested my page is available to play with. It is located here. (
http://wakewatcher.redirect.hm/sandbox/SendVidS3.php)
You can upload test files up to 50k.
The web page code is:
Code:
<?PHP
// Example of how to send a file to the Amazon S3 service with PHP
// Inspired by: http://developer.amazonwebservices.com/connect/entry!default.jspa?categoryID=139&externalID=1434&fromSearchPage=true
//
// Puts up a page which allows the user to select a file and sendit directly to S3, and calls this same page with the results whencompleted
// Change the following to correspond to your system:
$AWS_ACCESS_KEY = 'my public key';
$AWS_SECRET_KEY = 'its a secret thats the point';
$S3_BUCKET = 'autohotkey';
$S3_FOLDER = 'folder/'; // folder within bucket
$MAX_FILE_SIZE = 50 * 1024; // KB size limit
$SUCCESS_REDIRECT = ' http://wakewatcher.redirect.hm/sandbox/SendVidS3.php';
// setup transfer form
$expTime = time() + (1 * 60 * 60); // now plus one hour (1 hour; 60 mins; 60secs)
$expTimeStr = gmdate('Y-m-d\TH:i:s\Z', $expTime);
// create policy document
$policyDoc = '
{"expiration": "' . $expTimeStr . '",
"conditions": [
{"bucket": "' . $S3_BUCKET . '"},
["starts-with", "$key", "' . $S3_FOLDER . '"],
{"acl": "public-read"},
{"success_action_redirect": "' . $SUCCESS_REDIRECT . '"},
["starts-with", "$Content-Type", ""],
["starts-with", "$Content-Disposition", ""],
["content-length-range", 0, ' . $MAX_FILE_SIZE . ']
]
}
';
//echo "policyDoc: " . $policyDoc . '<BR/>';
// remove CRLFs from policy document
$policyDoc = implode(explode('\r', $policyDoc));
$policyDoc = implode(explode('\n', $policyDoc));
$policyDoc64 = base64_encode($policyDoc); // encode to base 64
// create policy document signature
$sigPolicyDoc = base64_encode(hash_hmac("sha1", $policyDoc64, $AWS_SECRET_KEY, TRUE/*raw_output*/));
if(isset($_POST['policy']))
die($policyDoc64 . " " . $sigPolicyDoc);
// create document header
echo '
<html>
<head>
<title>S3 POST Form</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
';
if(isset($_GET['bucket'])) {
$Bucket = $_GET['bucket'];
$Key = $_GET['key'];
echo 'URL (public read) : http://s3.amazonaws.com/' . $Bucket . '/' . $Key . ' or Click <a href="http://s3.amazonaws.com/' . $Bucket . '/' . $Key . '">HERE</a> <br>';
}
Echo "<br>policyDoc64:<br>$policyDoc64<br><br>sigPolicyDoc:<br>$sigPolicyDoc<br><br>";
// create file transfer form
echo '
<form action=" https://' . $S3_BUCKET . '.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
<input type="hidden" name="key" value="' . $S3_FOLDER . '${filename}">
<input type="hidden" name="AWSAccessKeyId" value="' . $AWS_ACCESS_KEY . '">
<input type="hidden" name="acl" value="public-read">
<input type="hidden" name="success_action_redirect" value="' . $SUCCESS_REDIRECT . '">
<input type="hidden" name="policy" value="' . $policyDoc64 . '">
<input type="hidden" name="signature" value="' . $sigPolicyDoc . '">
<input type="hidden" name="Content-Disposition" value="attachment; filename=${filename}">
<input type="hidden" name="Content-Type" id="Content-Type" value="video/mp4">
File to upload to S3 (size limit 50kb):
<input name="file" id="file" type="file">
<br/><br/>
<input type="submit" value="Upload File to S3">
</form>
';
// create document footer
echo '
</body>
</html>
';
?>
The ahk prototype script is:
Code:
loop:
FileSelectFile,filename,,Pick a File which is less than 50K
POSTdata := "policy=Y"
URL = http://www.wakewatcher.redirect.hm/sandbox/SendVidS3.php
length := httpQuery(result:="",URL,POSTdata)
varSetCapacity(result,-1)
stringgetpos,pos,result,%A_Space%
stringtrimright,policyDoc64,result,% length - pos
stringtrimleft,sigPolicyDoc,result,% Pos + 1
;msgbox policyDoc64:`n%policyDoc64%`n`nsigPolicyDoc:`n%sigPolicyDoc%
POSTdataString = key=folder/${filename}
POSTdataString = %POSTdataString%&AWSAccessKeyId=19SPCQ42SZ55Y0GM3JG2
POSTdataString = %POSTdataString%&success_action_redirect=http://www.wakewatcher.redirect.hm/sandbox/SendVidS3.php
POSTdataString = %POSTdataString%&policy=%policyDoc64%
POSTdataString = %POSTdataString%&signature=%sigPolicyDoc%
POSTdataString = %POSTdataString%&Content-Disposition=attachment`; filename=${filename}
POSTdataString = %POSTdataString%&Content-Type=Y
POSTdataString = %POSTdataString%&file=%filename%
URL = https://autohotkey.s3.amazonaws.com
length := httpQuery(result:="",URL,POSTdata)
varSetCapacity(result,-1)
msgbox Returned Result: %result%
goto loop
One thing the original php script did was use some java script to determine the mime type. Of course this wouldn't work in the ahk implementation since there isn't a browser involved. I expected that I would have to determine it using ahk but as a test I just set it static to a character and it doesn't complain.
Anyway I'm hoping that I can use this somehow to auto-magically upload files to S3 using this post form method.