Skip to content

Instantly share code, notes, and snippets.

@efreed
Created June 29, 2015 17:16
Show Gist options
  • Save efreed/5bcbf2f2ab85575a23f5 to your computer and use it in GitHub Desktop.
Save efreed/5bcbf2f2ab85575a23f5 to your computer and use it in GitHub Desktop.
S3 REST
class OdysysCache {
protected $_key = 'abc';
protected $_secret = 'abc123xyz';
protected $_bucket = 'odysyscache';
/**
* Write a file to the S3 Bucket
* @param String $file_name
* @param mixed $file_data
* @param String $file_type Optional MIME type, or will be auto set from the file extention
* @return boolean
*/
function put($file_name, $file_data, $file_type = null) {
$file_name = strtolower($file_name);
if(empty($file_type)) {
if (strpos($file_name, '.css'))
$file_type = 'text/css';
if (strpos($file_name, '.js'))
$file_type = 'application/javascript';
}
if(empty($file_type)) {
$file_type = 'application/octet-stream'; // the most generic so we at least have something
}
// opening HTTP connection to Amazon S3
$fp = fsockopen("$this->_bucket.s3.amazonaws.com", 80, $errno, $errstr, 30);
if (!$fp) {
die("$errstr ($errno)\n");
}
// Uploading object
$file_length = strlen($file_data); // for Content-Length HTTP field
$dt = gmdate('r'); // GMT based timestamp
// preparing String to Sign (see AWS S3 Developer Guide)
$string2sign = "PUT
$file_type
$dt
x-amz-acl:public-read
/$this->_bucket/$file_name";
// preparing HTTP PUT query
$query = "PUT /$this->_bucket/$file_name HTTP/1.1
Host: s3.amazonaws.com
x-amz-acl: public-read
Connection: keep-alive
Content-Type: $file_type
Content-Length: $file_length
Date: $dt
Authorization: AWS {$this->_key}:" . $this->amazon_hmac($string2sign)."\n\n";
$query .= $file_data;
$resp = $this->send($fp, $query);
fclose($fp);
if (strpos($resp, '<Error>') !== false) {
report_error('failed upload to S3', array('resp'=>$resp));
return false;
}
echo "Your file's URL is: http://s3.amazonaws.com/{$this->_bucket}/{$file_name}\n";
return true;
}
// Sending HTTP query and receiving, with trivial keep-alive support
private function send($fp, $q, $debug = false) {
if ($debug) echo "\nQUERY<<{$q}>>\n";
fwrite($fp, $q);
$r = '';
$check_header = true;
while (!feof($fp)) {
$tr = fgets($fp, 256);
if ($debug) echo "\nRESPONSE<<{$tr}>>";
$r .= $tr;
if (($check_header)&&(strpos($r, "\r\n\r\n") !== false))
{
// if content-length == 0, return query result
if (strpos($r, 'Content-Length: 0') !== false)
return $r;
}
// Keep-alive responses does not return EOF
// they end with \r\n0\r\n\r\n string
if (substr($r, -7) == "\r\n0\r\n\r\n")
return $r;
}
return $r;
}
// hmac-sha1 code START
// hmac-sha1 function: assuming key is global $aws_secret 40 bytes long
// read more at http://en.wikipedia.org/wiki/HMAC
// warning: key($aws_secret) is padded to 64 bytes with 0x0 after first function call
private function amazon_hmac($stringToSign) {
// helper function binsha1 for amazon_hmac (returns binary value of sha1 hash)
if (!function_exists('binsha1'))
{
if (version_compare(phpversion(), "5.0.0", ">=")) {
function binsha1($d) { return sha1($d, true); }
} else {
function binsha1($d) { return pack('H*', sha1($d)); }
}
}
if (strlen($this->_secret) == 40)
$this->_secret = $this->_secret . str_repeat(chr(0), 24);
$ipad = str_repeat(chr(0x36), 64);
$opad = str_repeat(chr(0x5c), 64);
$hmac = binsha1(($this->_secret^$opad) . binsha1(($this->_secret^$ipad).$stringToSign));
return base64_encode($hmac);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment