<?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; PHP</title>
	<atom:link href="http://tlrobinson.net/blog/category/php/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>
		<item>
		<title>Stealing LAPD&#039;s crime data</title>
		<link>http://tlrobinson.net/blog/2007/03/stealing-lapds-crime-data/</link>
		<comments>http://tlrobinson.net/blog/2007/03/stealing-lapds-crime-data/#comments</comments>
		<pubDate>Sun, 18 Mar 2007 11:21:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[TOOBS]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=7</guid>
		<description><![CDATA[This post explains how to get data from LAPD&#8217;s [crime maps](http://www.lapdcrimemaps.org/) website. See my [previous post](http://tlrobinson.net/blog/?p=6) on scraping DPS&#8217;s incident logs for background of TOOBS. After completing the TOOBS project for the UPE P.24 programming contest I was checking out &#8230; <a href="http://tlrobinson.net/blog/2007/03/stealing-lapds-crime-data/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This post explains how to get data from LAPD&#8217;s [crime maps](http://www.lapdcrimemaps.org/) website. See my [previous post](http://tlrobinson.net/blog/?p=6) on scraping DPS&#8217;s incident logs for background of TOOBS.</p>
<p>After completing the TOOBS project for the UPE P.24 programming contest I was checking out LAPD&#8217;s [crime maps](http://www.lapdcrimemaps.org/) website, which is similar to TOOBS (but not as cool!), and I realized I could integrate their data with DPS&#8217;s data for the ultimate Los Angeles / USC crime map. There very little overlap between the LAPD and DPS data since the two are separate entities. Murders and some other incidents may show up in both, but hopefully these are rare&#8230;</p>
<p>The LAPD system also uses JavaScript and XMLHttpRequest to fetch the data from a server side script. Additionally, there is no security to check that the requests are coming from the LAPD web app. This means we can easily, and (as far as i know) legally, access their data.</p>
<p>Due to the same origin policy that restricts JavaScript to only making requests to the originating server, you cannot simply use their PHP script from your own JavaScript, you must use sort of a proxy. While this policy can be annoying, it is necessary to limit what malicious JavaScript could do.</p>
<p>To obtain the crime data from LAPD&#8217;s servers, we begin by forming the request URL which contains parameters such as the start date, the interval length, lat/lon coordinates, radius, and crime types. A HTTP request is made to their server, and the response is stored.</p>
<p>We notice the response is simply JavaScript that gets eval&#8217;d on the client:</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; ">searchPoints = <span style="color:#881350;">new</span> <span style="color:#003369;">Array </span>();</p>
<p>searchPoints[<span style="color:#0000ff;">0</span>] = <span style="color:#881350;">new</span> <span style="color:#003369;">searchPoint </span>(<span style="color:#760f15;">&#8217;0&#8242;</span>, <span style="color:#760f15;">&#8216;#070307306&#8242;</span>, <span style="color:#760f15;">&#8216;lightblue&#8217;</span>, <span style="color:#760f15;">&#8217;17&#8242;</span>, <span style="color:#760f15;">&#8216;-118.301638&#8242;</span>, <span style="color:#760f15;">&#8217;34.022812&#8242;</span>, <span style="color:#760f15;">&#8217;14XX W 36th St&#8217;</span>, <span style="color:#760f15;">&#8217;0.74&#8242;</span>, <span style="color:#760f15;">&#8217;6&#8242;</span>, <span style="color:#760f15;">&#8217;02-04-2007 10:45:00 PM&#8217;</span>, <span style="color:#760f15;">&#8216;Southwest Division: 213-485-6571&#8242;</span>);<br />
searchPoints[<span style="color:#0000ff;">1</span>] = <span style="color:#881350;">new</span> <span style="color:#003369;">searchPoint </span>(<span style="color:#760f15;">&#8217;1&#8242;</span>, <span style="color:#760f15;">&#8216;#070307280&#8242;</span>, <span style="color:#760f15;">&#8216;violet&#8217;</span>, <span style="color:#760f15;">&#8217;17&#8242;</span>, <span style="color:#760f15;">&#8216;-118.284008&#8242;</span>, <span style="color:#760f15;">&#8217;34.033212&#8242;</span>, <span style="color:#760f15;">&#8217;25XX S Hoover St&#8217;</span>, <span style="color:#760f15;">&#8217;0.52&#8242;</span>, <span style="color:#760f15;">&#8217;3&#8242;</span>, <span style="color:#760f15;">&#8217;02-04-2007 10:00:00 PM&#8217;</span>, <span style="color:#760f15;">&#8216;Southwest Division: 213-485-6571&#8242;</span>);<br />
searchPoints[<span style="color:#0000ff;">2</span>] = <span style="color:#881350;">new</span> <span style="color:#003369;">searchPoint </span>(<span style="color:#760f15;">&#8217;2&#8242;</span>, <span style="color:#760f15;">&#8216;#070307224&#8242;</span>, <span style="color:#760f15;">&#8216;cyan&#8217;</span>, <span style="color:#760f15;">&#8217;17&#8242;</span>, <span style="color:#760f15;">&#8216;-118.304108&#8242;</span>, <span style="color:#760f15;">&#8217;34.032481&#8242;</span>, <span style="color:#760f15;">&#8217;26XX Dalton Av&#8217;</span>, <span style="color:#760f15;">&#8217;0.83&#8242;</span>, <span style="color:#760f15;">&#8217;4&#8242;</span>, <span style="color:#760f15;">&#8217;02-04-2007 12:15:00 AM&#8217;</span>, <span style="color:#760f15;">&#8216;Southwest Division: 213-485-6571&#8242;</span>);<br />
searchPoints[<span style="color:#0000ff;">3</span>] = <span style="color:#881350;">new</span> <span style="color:#003369;">searchPoint </span>(<span style="color:#760f15;">&#8217;3&#8242;</span>, <span style="color:#760f15;">&#8216;#070307222&#8242;</span>, <span style="color:#760f15;">&#8216;blue&#8217;</span>, <span style="color:#760f15;">&#8217;17&#8242;</span>, <span style="color:#760f15;">&#8216;-118.2903&#8242;</span>, <span style="color:#760f15;">&#8217;34.0284&#8242;</span>, <span style="color:#760f15;">&#8216;Menlo Av and 29th Av&#8217;</span>, <span style="color:#760f15;">&#8217;0.02&#8242;</span>, <span style="color:#760f15;">&#8217;2&#8242;</span>, <span style="color:#760f15;">&#8217;02-03-2007 11:00:00 PM&#8217;</span>, <span style="color:#760f15;">&#8216;Southwest Division: 213-485-6571&#8242;</span>);<br />
&#8230;</div>
<p>We could simply redirect this code to our own app and do the processing on the client side with JavaScript, but we also notice that JavaScript syntax is very similar to PHP syntax. By creating a compatible PHP object called searchPoint and prepending a &#8220;$&#8221; to each variable name, we have valid PHP code that we can simply eval. The result is an array of searchPoint objects that we can easily add to our response, or insert into a database, or whatever we want!</p>
<p>Note that this is <em>extremely</em> insecure since we&#8217;re eval&#8217;ing text that we got from somewhere else. By changing the response, the provider of the data could execute any PHP they wanted on my server.</p>
<p>A more secure method would be to actually parse the data rather than letting PHP&#8217;s eval do the work.</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2007/03/stealing-lapds-crime-data/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

