<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>tlrobinson.net blog &#187; S3</title>
	<atom:link href="http://tlrobinson.net/blog/category/s3/feed/" rel="self" type="application/rss+xml" />
	<link>http://tlrobinson.net/blog</link>
	<description></description>
	<lastBuildDate>Mon, 06 Apr 2009 08:37:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Amazon S3 PHP helpers</title>
		<link>http://tlrobinson.net/blog/2008/04/amazon-s3-php-helpers/</link>
		<comments>http://tlrobinson.net/blog/2008/04/amazon-s3-php-helpers/#comments</comments>
		<pubDate>Fri, 18 Apr 2008 12:27:12 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[S3]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=38</guid>
		<description><![CDATA[The Amazon documentation for using S3 with PHP refers to an elusive function called &#8220;setAuthorizationHeader&#8221;. It&#8217;s apparently supposed to magically set the correct value for the Authorization header on a Pear HTTP_Request object. As far as I could tell, it &#8230; <a href="http://tlrobinson.net/blog/2008/04/amazon-s3-php-helpers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Amazon documentation for using S3 with PHP refers to an elusive function called &#8220;setAuthorizationHeader&#8221;. It&#8217;s apparently supposed to magically set the correct value for the Authorization header on a Pear HTTP_Request object. As far as I could tell, it didn&#8217;t actually exist &#8212; but I wanted it, so I wrote it:</p>
<p><a href="http://tlrobinson.net/misc/s3.php.txt">Source</a></p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#dd0000;">&lt;?php</span></p>
<p><span style="color:#881350;">require_once</span> <span style="color:#eb7300;">&#8216;Crypt/HMAC.php&#8217;</span>;<br />
<span style="color:#881350;">require_once</span> <span style="color:#eb7300;">&#8216;HTTP/Request.php&#8217;</span>;</p>
<p><span style="color:#661aa9;">define</span>(<span style="color:#eb7300;">&quot;S3URL&quot;</span>, <span style="color:#eb7300;">&#8216;http://s3.amazonaws.com&#8217;</span>);<br />
<span style="color:#661aa9;">define</span>(<span style="color:#eb7300;">&quot;AWSACCESSKEYID&quot;</span>, <span style="color:#eb7300;">&#8216;XXXXXXXXXXXXXXXXXXXX&#8217;</span>);<br />
<span style="color:#661aa9;">define</span>(<span style="color:#eb7300;">&quot;AWSSECRETKEYID&quot;</span>, <span style="color:#eb7300;">&#8216;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&#8217;</span>);</p>
<p><span style="color:#825900;">$s3_hasher</span> =&amp; <span style="color:#881350;">new</span> <span style="color:#003369;">Crypt_HMAC</span>(AWSSECRETKEYID, <span style="color:#eb7300;">&quot;sha1&quot;</span>);</p>
<p><span style="color:#881350;">function</span> <span style="color:#003369;">s3_sign</span>(<span style="color:#825900;">$StringToSign</span>)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">global</span> <span style="color:#825900;">$s3_hasher</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> <span style="color:#003369;">hex2b64</span>(<span style="color:#825900;">$s3_hasher</span>-&gt;<span style="color:#003369;">hash</span>(<span style="color:#825900;">$StringToSign</span>));<br />
}</p>
<p><span style="color:#881350;">function</span> <span style="color:#003369;">hex2b64</span>(<span style="color:#825900;">$str</span>)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$raw</span> = <span style="color:#eb7300;">&#8221;</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">for</span><span style="color:#003369;"> </span>(<span style="color:#825900;">$i</span> = <span style="color:#0000ff;">0</span>; <span style="color:#825900;">$i</span> &lt; <span style="color:#661aa9;">strlen</span>(<span style="color:#825900;">$str</span>); <span style="color:#825900;">$i</span> += <span style="color:#0000ff;">2</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$raw</span> .= <span style="color:#661aa9;">chr</span>(<span style="color:#661aa9;">hexdec</span>(<span style="color:#661aa9;">substr</span>(<span style="color:#825900;">$str</span>, <span style="color:#825900;">$i</span>, <span style="color:#0000ff;">2</span>)));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> <span style="color:#661aa9;">base64_encode</span>(<span style="color:#825900;">$raw</span>);<br />
}</p>
<p><span style="color:#881350;">function</span> <span style="color:#003369;">setAuthorizationHeader</span>(<span style="color:#825900;">$request</span>)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$headers</span> = <span style="color:#825900;">$request</span>-&gt;_requestHeaders;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$HTTP_Verb</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#825900;">$request</span>-&gt;_method;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Content_MD5</span> &nbsp;&nbsp;&nbsp;= <span style="color:#825900;">$headers</span>[<span style="color:#eb7300;">'content-md5'</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Content_Type</span> &nbsp;&nbsp;= <span style="color:#825900;">$headers</span>[<span style="color:#eb7300;">'content-type'</span>];</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Get the date, or set it if not already:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(!<span style="color:#003369;">isset</span>(<span style="color:#825900;">$headers</span>[<span style="color:#eb7300;">'date'</span>])) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Date</span> = <span style="color:#661aa9;">gmdate</span>(<span style="color:#eb7300;">&quot;D, d M Y H:i:s T&quot;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$request</span>-&gt;<span style="color:#003369;">addHeader</span>(<span style="color:#eb7300;">&quot;date&quot;</span>, <span style="color:#825900;">$Date</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Date</span> = <span style="color:#825900;">$headers</span>[<span style="color:#eb7300;">'date'</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Canonicalize the Amazon headers:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedAmzHeaders</span> = <span style="color:#eb7300;">&#8221;</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$amz_headers</span> = <span style="color:#881350;">array</span>();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">foreach</span><span style="color:#003369;"> </span>(<span style="color:#825900;">$headers</span> <span style="color:#881350;">as</span> <span style="color:#825900;">$key</span> =&gt; <span style="color:#825900;">$value</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#661aa9;">substr</span>(<span style="color:#825900;">$key</span>, <span style="color:#0000ff;">0</span>, <span style="color:#0000ff;">6</span>) == <span style="color:#eb7300;">&#8216;x-amz-&#8217;</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#003369;">isset</span>(<span style="color:#825900;">$amz_headers</span>[<span style="color:#825900;">$key</span>]))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$amz_headers</span>[<span style="color:#825900;">$key</span>] .= <span style="color:#eb7300;">&#8216;,&#8217;</span> . <span style="color:#825900;">$value</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$amz_headers</span>[<span style="color:#825900;">$key</span>] = <span style="color:#825900;">$value</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#661aa9;">ksort</span>(<span style="color:#825900;">$amz_headers</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">foreach</span><span style="color:#003369;"> </span>(<span style="color:#825900;">$amz_headers</span> <span style="color:#881350;">as</span> <span style="color:#825900;">$key</span> =&gt; <span style="color:#825900;">$value</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedAmzHeaders</span> .= <span style="color:#825900;">$key</span> . <span style="color:#eb7300;">&#8216;:&#8217;</span> . <span style="color:#825900;">$value</span> . <span style="color:#eb7300;">&quot;\n&quot;</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Canonicalize the resource string<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedResource</span> &nbsp;&nbsp;&nbsp;= <span style="color:#eb7300;">&#8221;</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$host</span> = <span style="color:#825900;">$request</span>-&gt;<span style="color:#003369;">_generateHostHeader</span>();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#825900;">$host</span> != <span style="color:#eb7300;">&#8216;s3.amazonaws.com&#8217;</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$pos</span> = <span style="color:#661aa9;">strpos</span>(<span style="color:#825900;">$host</span>, <span style="color:#eb7300;">&#8216;s3.amazonaws.com&#8217;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedResource</span> .= <span style="color:#eb7300;">&#8216;/&#8217;</span> . (<span style="color:#825900;">$pos</span> === <span style="color:#881350;">false</span>) ? <span style="color:#825900;">$host</span> : <span style="color:#661aa9;">substr</span>(<span style="color:#825900;">$host</span>, <span style="color:#0000ff;">0</span>, <span style="color:#825900;">$pos</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedResource</span> .= <span style="color:#825900;">$request</span>-&gt;_url-&gt;path;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// TODO: sub-resources &quot;?acl&quot;, &quot;?location&quot;, &quot;?logging&quot;, or &quot;?torrent&quot;<br />
</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Build the string to sign:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$StringToSign</span> = <span style="color:#825900;">$HTTP_Verb</span> . <span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Content_MD5</span> . <span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Content_Type</span> . <span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Date</span> . <span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedAmzHeaders</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$CanonicalizedResource</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Signature</span> = <span style="color:#003369;">s3_sign</span>(<span style="color:#825900;">$StringToSign</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Authorization</span> = <span style="color:#eb7300;">&quot;AWS&quot;</span> . <span style="color:#eb7300;">&quot; &quot;</span> . AWSACCESSKEYID . <span style="color:#eb7300;">&quot;:&quot;</span> . <span style="color:#825900;">$Signature</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Set the Authorization header:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$request</span>-&gt;<span style="color:#003369;">addHeader</span>(<span style="color:#eb7300;">&quot;Authorization&quot;</span>, <span style="color:#825900;">$Authorization</span>);<br />
}</p>
<p><span style="color:#881350;">function</span> <span style="color:#003369;">s3AuthURL</span>(<span style="color:#825900;">$Resource</span>, <span style="color:#825900;">$HTTP_Verb</span> = <span style="color:#eb7300;">&#8216;GET&#8217;</span>, <span style="color:#825900;">$seconds</span> = <span style="color:#0000ff;">120</span>)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Calculate expiration time:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Expires</span> = <span style="color:#661aa9;">time</span>() + <span style="color:#825900;">$seconds</span>;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Build the string to sign:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$StringToSign</span> = <span style="color:#825900;">$HTTP_Verb</span> . <span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#eb7300;">&quot;\n&quot;</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Expires</span> . <span style="color:#eb7300;">&quot;\n&quot;</span> . <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Resource</span>;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#825900;">$Signature</span> = <span style="color:#003369;">s3_sign</span>(<span style="color:#825900;">$StringToSign</span>);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// Build the authorized URL:<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> &nbsp;S3URL . <span style="color:#825900;">$Resource</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#eb7300;">&#8216;?AWSAccessKeyId=&#8217;</span> &nbsp;. AWSACCESSKEYID .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#eb7300;">&#8216;&amp;Expires=&#8217;</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <span style="color:#825900;">$Expires</span> .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#eb7300;">&#8216;&amp;Signature=&#8217;</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. <span style="color:#661aa9;">urlencode</span>(<span style="color:#825900;">$Signature</span>);<br />
}</p>
<p><span style="color:#dd0000;">?&gt;</span></div>
<p><em>Note: this hasn&#8217;t been tested extensively, so use it at your own risk. Post a comment or contact me at <script type="text/javascript">email_link();</script> if you find any bugs. Also, IANAPHPE.</em></p>
<p>Just replace the XX&#8217;s with your keys and it should work with <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/gsg/CreatingABucket.html">this sample code</a>.</p>
<p>There&#8217;s also a function for creating query string authorized URLs.</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2008/04/amazon-s3-php-helpers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

