<?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>Geekality &#187; Tutorial</title>
	<atom:link href="http://www.geekality.net/tag/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.geekality.net</link>
	<description>With a hint of Social Ineptitude</description>
	<lastBuildDate>Sun, 05 Feb 2012 17:53:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>PHP Tutorial: PayPal Instant Payment Notification (IPN)</title>
		<link>http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/</link>
		<comments>http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/#comments</comments>
		<pubDate>Sat, 28 May 2011 21:01:47 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[IPN]]></category>
		<category><![CDATA[PayPal]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1420</guid>
		<description><![CDATA[In a previous post I tried to give an introduction on how to get started with PayPal Payment Data Transfers (PDT). PDT is very handy in several cases, but you can&#8217;t always rely on it since it requires the user &#8230; <a href="http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.rgbstock.com/photo/mswM744/got+a+letter"><img src="http://www.geekality.net/wp-content/uploads/2011/05/Got-a-letter-300x225.jpg" alt="Got a letter" title="rgbstock.com" width="300" height="225" class="alignright size-medium wp-image-1674" /></a>In <a href="/?p=1210">a previous post</a> I tried to give an introduction on how to get started with PayPal Payment Data Transfers (PDT). PDT is very handy in several cases, but you can&#8217;t always rely on it since it requires the user to return to your page after doing the payment. That will <em>often</em> happen, but it&#8217;s not guaranteed to happen. If you for example want to mark an order in your system as paid or something like that, you most likely want to use PayPal Instant Payment Notifications (IPN) in addition to PDT.</p>
<blockquote><p>Instant Payment Notification (IPN) is a message service that notifies you of events related to PayPal transactions. You can use it to automate back-office and administrative functions, such as fulfilling orders, tracking customers, and providing status and other information related to a transaction. &#8212; <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&#038;content_ID=developer/e_howto_admin_IPNIntro">PayPal</a></p></blockquote>
<p>Once again the documentation, tutorials and code samples I found on this was a bit all over the place. Sort of messy and outdated. So, once again I decided to do my own thing and just follow the steps required and implement them myself. And since the tutorial on PDT turned out to be a bit of a success, I decided to share this too. Hopefully it can make the lives of fellow developers easier <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p><span id="more-1420"></span></p>
<h2>How it works</h2>
<p>The concept is pretty simple. You first give PayPal an address to a listener, for example <code class="codecolorer text default"><span class="text">http://business.example.com/ipn/listener.php</span></code>. Then, whenever something happens, PayPal will post information about the event to that address. So for example if someone completes a payment, your listener will be notified shortly after with the transaction details and all you need to know.</p>
<p>This tutorial will focus on the listener part, as the setting up part on PayPal is very simple (Leave a comment if you disagree). Just go to the PayPal account settings, find the IPN settings and give the URL to your IPN listener. For testing we don&#8217;t even need to do that. All we need to do is to set up a PayPal Developer Account. We can then use their very handy <a href="https://developer.paypal.com/cgi-bin/devscr?cmd=_ipn-link-session">Instant Payment Notification (IPN) simulator</a> that you find among their <a href="https://developer.paypal.com/cgi-bin/devscr?cmd=_tools-session">Test Tools</a>. So let&#8217;s get started!</p>
<h2>Step 0: Sign up for a Developer Account</h2>
<p>If you haven&#8217;t, go <a href="/?p=1176">sign up for a PayPal Developer account</a>. We don&#8217;t need to set up any accounts this time, as we will simply use the mentioned simulator.</p>
<p>Using the simulator is ultra simple. You just enter the address of your listener and choose a transaction type. You can then fill out all the data that should be in this fake transaction and then just hit &#8220;Send IPN&#8221; at the bottom. Luckily PayPal actually fills out all the fields with random test data, so unless you are trying to test something specific, you can just ignore the data and hit the button right away <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>Now, to the actual listener file&#8230;</p>
<h2>Step 1: Catch the IPN</h2>
<p>First thing we need to do in our listener is of course to catch the data we get from PayPal. The data is sent as a POST request, so PHP has actually done that for us. We just need to grab it <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$ipn_post_data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_POST</span><span style="color: #339933;">;</span></div></div>
<h2>Step 2: Verification</h2>
<p>Since what we got could just be plain bogus from some stranger, we need to verify it with PayPal. This is done by taking all the POST data in its unaltered state, add one field to the beginning, and then send it back. In return we should then get one word, <code class="codecolorer text default"><span class="text">VERIFIED</span></code> or <code class="codecolorer text default"><span class="text">INVALID</span></code>. To do that, we can use our old buddy cURL.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Choose url</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'test_ipn'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ipn_post_data</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">===</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$ipn_post_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'test_ipn'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'https://www.sandbox.paypal.com/cgi-bin/webscr'</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">else</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'https://www.paypal.com/cgi-bin/webscr'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Set up request to PayPal</span><br />
<span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">curl_setopt_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><br />
<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; CURLOPT_URL <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$url</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_POST <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_POSTFIELDS <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">http_build_query</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmd'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'_notify-validate'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$ipn_post_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_RETURNTRANSFER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_HEADER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_SSL_VERIFYPEER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_CAINFO <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'cacert.pem'</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Execute request and get response and status code</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$status</span> &nbsp; <span style="color: #339933;">=</span> <span style="color: #990000;">curl_getinfo</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> CURLINFO_HTTP_CODE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Close connection</span><br />
<span style="color: #990000;">curl_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$status</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">200</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$response</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'VERIFIED'</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// All good! Proceed...</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #b1b100;">else</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Not good. Ignore, or log for investigation...</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Note that in the very beginning actually check for a field called <code class="codecolorer text default"><span class="text">test_ipn</span></code>. If that exists with a value of 1, it means it&#8217;s a request from the sandbox. In other words, we can choose the correct PayPal interface by just looking for that.</p>
<p>You can also see I set two cURL options called <code class="codecolorer text default"><span class="text">SSL_VERIFYPEER</span></code> and <code class="codecolorer text default"><span class="text">CAINFO</span></code>. The reason for that you will find in my post on <a href="http://www.geekality.net/?p=1413">cURL SSL verification</a>.</p>
<h2>Step 3: Fix character set</h2>
<p>Now that we know the data is valid, we can start to deal with it. What you get could be in a different character set than what you want though, so we should fix that first. The data should contain a key called <code class="codecolorer text default"><span class="text">charset</span></code> which specifies what character set the data is using. We just need to check for that and if needed convert from that to what we want, for example UTF-8.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'charset'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$charset</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Ignore if same as our default</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$charset</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'utf-8'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Otherwise convert all the values</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ipn_data</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mb_convert_encoding</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'utf-8'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$charset</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// And store the charset values for future reference</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'utf-8'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset_original'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$charset</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h2>Step 4: Use the data!</h2>
<p>Yup, believe it or not, that was everything that was needed to catch an IPN message from PayPal. Where you go from here completely depends on what exactly you need to do. </p>
<p>What you at least should do is the following:</p>
<ol>
<li>Confirm that the payment status is Completed.<br />
PayPal sends IPN messages for pending and denied payments as well, so don&#8217;t ship stuff or anything until the payment has cleared.</li>
<li>Use the transaction ID to verify that the transaction has not already been processed.<br />
This prevents you from processing the same transaction twice. You can for example store the transaction id in a database and check against those before you do anything with incoming IPNs. If you&#8217;re smart you could also store the time the IPN came in and the raw IPN data. This way you have a log of all incoming messages you can use if you need to reprocess something or for debugging if something weird is going on.</li>
<li>Make sure the receiver&#8217;s email address is the one you expected.</li>
<li>Make sure the price, item description, et cetera, match what it should be.</li>
</ol>
<p>And then finally you should of course make sure your customer gets what they should <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>You can read more about PayPal Instant Payment Notifications in their <a href="https://cms.paypal.com/cms_content/US/en_US/files/developer/IPNGuide.pdf">IPN Guide</a>.</p>
<h2>Working sample</h2>
<p>I have put together a working sample you can check out over at <a href="http://samples.geekality.net/ipn/">samples.geekality.net/ipn</a>. Hopefully this tutorial and that sample can help you get started with all of this <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>I also put together an IPN handler class you can use pretty much out of the box. The sample uses it, and it&#8217;s very simple. Just extend the class, override the <code class="codecolorer text default"><span class="text">process</span></code> method and do what you need. Below is a simple example.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #666666; font-style: italic;">// example listener.php</span><br />
<br />
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'ipn_handler.class.php'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> My_Ipn_Handler <span style="color: #000000; font-weight: bold;">extends</span> IPN_Handler<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> process<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$post_data</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Let the IPN_Handler do it's processing,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// which includes validating and fixing the encoding</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">process</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Check if validation failed</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP/1.0 400 Bad Request'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">400</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">exit</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Seems it all was good, so in lack of better things to do,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// let's JSON encode it and dump it to a file</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">file_put_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ipn.txt'</span><span style="color: #339933;">,</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>PHP_EOL<span style="color: #339933;">,</span> FILE_APPEND<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000088;">$handler</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Ipn_Handler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$handler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">process</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>That&#8217;s all! I&#8217;m sorry it took so long to get this tutorial written, but hopefully someone can find it useful. I have learned a lot writing it at least! Please leave a comment if it was helpful, if it wasn&#8217;t helpful, if there are mistakes, typos, or if you just want to say thank you <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1420&amp;md5=c6fc8bcc514c281c5c7d8f2173c0042b" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/feed/</wfw:commentRss>
		<slash:comments>87</slash:comments>
		</item>
		<item>
		<title>PHP: How to get all images from an HTML page</title>
		<link>http://www.geekality.net/2011/05/12/php-how-to-get-all-images-from-an-html-page/</link>
		<comments>http://www.geekality.net/2011/05/12/php-how-to-get-all-images-from-an-html-page/#comments</comments>
		<pubDate>Thu, 12 May 2011 21:59:59 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[cURL]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Parsing]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Regular Expression]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1585</guid>
		<description><![CDATA[I was curious to how I could make something similar to what Facebook does when you add a link. Somehow it loads images found on the page your link leads to, and then it presents them to you so you &#8230; <a href="http://www.geekality.net/2011/05/12/php-how-to-get-all-images-from-an-html-page/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_1598" class="wp-caption alignright" style="width: 243px"><a href="http://www.rgbstock.com/photo/mg2mFcI/Photo+Template+5"><img src="http://www.geekality.net/wp-content/uploads/2011/05/photo-template-233x300.jpg" alt="" title="Photo Template" width="233" height="300" class="size-medium wp-image-1598" /></a><p class="wp-caption-text">rgbstock.com</p></div>I was curious to how I could make something similar to what Facebook does when you add a link. Somehow it loads images found on the page your link leads to, and then it presents them to you so you can select one you want to use as a thumbnail.</p>
<p>Well, step one to solve this is of course to find all the images on a page, and that is what I will present in this post. It will be sort of like a backend service we can use later from an AJAX call. You post it a URL, and you get all the image URLs it found back. Let&#8217;s put the petal to medal!</p>
<p><span id="more-1585"></span></p>
<h2>Getting the URL</h2>
<p>We&#8217;ll use POST for this, and it shouldn&#8217;t require much explanation.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'url'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; ? <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'url'</span><span style="color: #009900;">&#93;</span> <br />
&nbsp; &nbsp; <span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span></div></div>
<h2>Loading the HTML</h2>
<p>To load the HTML we&#8217;ll use the handy <a href="http://php.net/manual/en/book.curl.php">cURL</a> library, which I&#8217;ve used in earlier posts as well.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">curl_setopt_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><br />
<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; CURLOPT_URL <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$url</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; CURLOPT_RETURNTRANSFER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_HEADER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; CURLOPT_SSL_VERIFYPEER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_CAINFO <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'cacert.pem'</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; CURLOPT_FOLLOWLOCATION <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_MAXREDIRS <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">curl_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>We just create and execute a request for the supplied URL. The response is stored in a variable so we can use it later.</p>
<p> <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':idea:' class='wp-smiley smiley-24' /> We won&#8217;t bother with any fancy error handling or anywhere else. If it doesn&#8217;t work, we&#8217;ll just give an empty list back. Bad URLs, faulty HTML, not our problem <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':P' class='wp-smiley smiley-13' /> </p>
<p> <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':idea:' class='wp-smiley smiley-24' /> The SSL and cacert.pem stuff is explained in <a href="/?p=1413" title="cURL SSL Verification">an earlier post</a>.</p>
<h2>Parsing the HTML</h2>
<p>You might have seen examples on how to find things in HTML using regular expressions. This is by most experienced developers regarded as <a href="http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html">A Bad Idea™</a>. What we can, and probably should, use instead is the <a href="http://php.net/manual/en/class.domdocument.php">DOMDocument</a> class you find in PHP. This class can parse XML and HTML into a neat <a href="http://en.wiktionary.org/wiki/Document_Object_Model" title="Document Object Model">DOM</a> which is a lot easier to work with.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$document</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMDocument<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #990000;">libxml_use_internal_errors</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$document</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadHTML</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #990000;">libxml_clear_errors</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Not everyone writes perfectly formed HTML without errors so we load the HTML, the DOMDocument class will do its best to plow through the HTML and figure it all out. When it does come across things that are a bit out of wack, it will let us know by spitting out warnings. There&#8217;s a big chance it managed to deal with it fine, but just for our information. However, like I mentioned earlier, we don&#8217;t care about errors here and we definitely don&#8217;t want those warnings messing up our output. </p>
<p>So, what we do here is to tell libxml (which is used internally) to <a href="http://php.net/manual/en/function.libxml-use-internal-errors.php">enable user error handling</a> instead. When we now load the HTML, those errors and warnings are then instead collected quietly. We can get to them afterwards by calling <a href="http://php.net/manual/en/function.libxml-get-errors.php">libxml_get_errors</a>, but since we don&#8217;t care about them at all we just <a href="http://php.net/manual/en/function.libxml-clear-errors.php">clear them out</a> instead. Easy peasy.</p>
<h2>Dealing with relative URLs</h2>
<p>As you perhaps know you can have both <a href="http://en.wikipedia.org/wiki/Uniform_Resource_Locator#Absolute_vs_relative_URLs">absolute and relative URLs</a> in HTML. The relative URLs are relative to the base path of the HTML page. Unless the HTML page has a <a href="http://www.w3.org/TR/html-markup/base.html">base tag</a>. In that case we need to use whatever that specifies instead. So, how do we deal with all of that?</p>
<p>Well, I decided to stick that in <a href="/?p=1587" title="Dealing with absolute and relative URLs">a different post</a>. What&#8217;s important here is that we can get the base tag from the DOM like this:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$tags</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$document</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'base'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tags</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$tag</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Of course if there is a base tag, it should only be one, but since we get a collection back from <code class="codecolorer text default"><span class="text">getElementsByTagName</span></code> I just use <code class="codecolorer text default"><span class="text">foreach</span></code> for simplicity. </p>
<p>Next up we have a function which turn a relative URL into an absolute one. The signature looks like the following and the content you can read more about in <a href="/?p=1587" title="Dealing with absolute and relative URLs">that earlier mentioned post</a>.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> make_absolute<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$base</span><span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// &quot;Magic&quot;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h2>Getting the images</h2>
<p>Now to the fun part. With the HTML loaded up and the base path figured out, we just need to fetch the images.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$images</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$document</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'img'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$img</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Extract what we want</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'src'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">make_absolute</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$base</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Skip images without src</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #000088;">$image</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Add to collection. Use src as key to prevent duplicates.</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$images</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$image</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000088;">$images</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_values</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$images</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Now that was pretty simple, wasn&#8217;t it? The perhaps weird thing here is that I first collect them in an array, using the image source as a key. This way we won&#8217;t end up with duplicate image URLs. We also skip images which for some reason were to not have any URL. </p>
<p>We could of course also get other stuff from the image tag here, like the height, width, alt text or title, or we could do some more elaborate filtering to try to weed out uninteresting images. For example really tiny ones or whatever else we might think of.</p>
<h2>Echo it all out</h2>
<p>Now we just need to echo it all out in a format we can use easily on the client side. And we will, surprise, surprise, of course use <a href="/?p=1021" title="How to easily provide JSON and JSONP">our good friend JSON</a> for this <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'content-type: application/json; charset=utf-8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'images'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$images</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>We set the appropriate header, wrap it up in a result array, encode it, and spit it out. And that&#8217;s pretty much all there is to that part.</p>
<h2>Working sample</h2>
<p>When I implemented this I decided to wrap most of this up in a class I called Image_Finder. I have also created a tiny interface for this so you can test it out for yourself. Will go through that interface (or a variant of it) later, but since that&#8217;s all HTML and JavaScript you are of course more than welcome to have a peek at the source of it <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>Either way, you can find it all, code and sample, at <a href="http://samples.geekality.net/image-fetcher/">samples.geekality.net/image-fetcher</a>. Let me know if you like it. And definitely let me know if you find any bugs ;)</p>
<p>Bugs, improvements, suggestions, praise; please leave a comment. I like to learn <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1585&amp;md5=456c7dcc2bfe97beb4d0c5962e3648a6" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/05/12/php-how-to-get-all-images-from-an-html-page/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>PHP: How to proportionally resize an uploaded image</title>
		<link>http://www.geekality.net/2011/05/01/php-how-to-proportionally-resize-an-uploaded-image/</link>
		<comments>http://www.geekality.net/2011/05/01/php-how-to-proportionally-resize-an-uploaded-image/#comments</comments>
		<pubDate>Sun, 01 May 2011 19:40:19 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Images]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Resize]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1564</guid>
		<description><![CDATA[Say you have a form where someone can upload a profile image. The uploaded image can be of any size of course, but you want all the profile images to fit inside a certain frame. You could just set the &#8230; <a href="http://www.geekality.net/2011/05/01/php-how-to-proportionally-resize-an-uploaded-image/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_1568" class="wp-caption alignright" style="width: 210px"><a href="http://www.rgbstock.com/photo/mtFDaGc/Mugs"><img src="http://www.geekality.net/wp-content/uploads/2011/05/Mug-200x300.jpg" alt="Big mug and tiny mug" title="Mugs" width="200" height="300" class="size-medium wp-image-1568" /></a><p class="wp-caption-text">rgbstock.com</p></div>Say you have a form where someone can upload a profile image. The uploaded image can be of any size of course, but you want all the profile images to fit inside a certain frame. You could just set the dimensions on the image tag to this size, but in most browsers that would look ugly, and it would also most likely stretch the image. It would look awful. In addition you would be serving a image which most likely was a lot larger than you wanted it to be. This would cost you bandwidth.</p>
<p>In this case you might want to proportionally resize the image to the appropriate size when you get it uploaded. You can then store the resized image instead and serve it directly with no problems afterwards. It doesn&#8217;t have to be difficult! Here&#8217;s how <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p><span id="more-1564"></span></p>
<h2>The form</h2>
<p>To keep this ultra simple, we will just have a tiny form with one field and a submit button.</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;upload.php&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span> <span style="color: #000066;">enctype</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;multipart/form-data&quot;</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;file&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;image&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Upload&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></div>
<p>Notice that the form has <code class="codecolorer text default"><span class="text">enctype=&quot;multipart/form-data&quot;</span></code>. If it&#8217;s not, the file upload won&#8217;t work. Up next is the file which catches the uploaded data.</p>
<h2>Processing the upload</h2>
<p>First thing we need to do is to check that the upload went alright.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Check if file was uploaded ok</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">is_uploaded_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tmp_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'error'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">!==</span> UPLOAD_ERR_OK<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'File not uploaded. Possibly too large.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>If all good, we can turn the uploaded file into an image resource.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Create image from file</span><br />
<span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'image/jpeg'</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #990000;">imagecreatefromjpeg</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tmp_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'image/png'</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #990000;">imagecreatefrompng</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tmp_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'image/gif'</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #990000;">imagecreatefromgif</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tmp_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Unsupported type: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Before we can actually resize this image, we need to figure out a couple of things. We need the size of the frame we want to fit this image into, the current size, and the size it should have to fit inside the frame without messing up its <a href="http://en.wikipedia.org/wiki/Aspect_ratio">aspect ratio</a>.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Target dimensions</span><br />
<span style="color: #000088;">$max_width</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">240</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$max_height</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">180</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Get current dimensions</span><br />
<span style="color: #000088;">$old_width</span>&nbsp; <span style="color: #339933;">=</span> <span style="color: #990000;">imagesx</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$old_height</span> <span style="color: #339933;">=</span> <span style="color: #990000;">imagesy</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Calculate the scaling we need to do to fit the image inside our frame</span><br />
<span style="color: #000088;">$scale</span>&nbsp; &nbsp; &nbsp; <span style="color: #339933;">=</span> <span style="color: #990000;">min</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$max_width</span><span style="color: #339933;">/</span><span style="color: #000088;">$old_width</span><span style="color: #339933;">,</span> <span style="color: #000088;">$max_height</span><span style="color: #339933;">/</span><span style="color: #000088;">$old_height</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Get the new dimensions</span><br />
<span style="color: #000088;">$new_width</span>&nbsp; <span style="color: #339933;">=</span> <span style="color: #990000;">ceil</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$scale</span><span style="color: #339933;">*</span><span style="color: #000088;">$old_width</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$new_height</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ceil</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$scale</span><span style="color: #339933;">*</span><span style="color: #000088;">$old_height</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>We calculate the scaling by dividing the wanted dimension with the current one. I do this for both the width and the height, and then choose the lesser of the two. This makes sure that both wide and tall images will fit into our frame. When we have the scale, we simply multiply it with the current height and width to get our new dimensions.</p>
<p>With that calculated, we can simply create a new empty image resource and fill it with a resized copy of the original image.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Create new empty image</span><br />
<span style="color: #000088;">$new</span> <span style="color: #339933;">=</span> <span style="color: #990000;">imagecreatetruecolor</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$new_width</span><span style="color: #339933;">,</span> <span style="color: #000088;">$new_height</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Resize old image into new</span><br />
<span style="color: #990000;">imagecopyresampled</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$new</span><span style="color: #339933;">,</span> <span style="color: #000088;">$image</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; <span style="color: #000088;">$new_width</span><span style="color: #339933;">,</span> <span style="color: #000088;">$new_height</span><span style="color: #339933;">,</span> <span style="color: #000088;">$old_width</span><span style="color: #339933;">,</span> <span style="color: #000088;">$old_height</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Where you go from here is a bit up to you. You could turn the image resource into a PNG or a JPEG and then store it as a file, in a database, or whatever you feel like. Just as an example I&#8217;ll turn it into a JPEG, catch the data in a versatile variable and output it to the browser.</p>
<p>First I create a JPEG image out of it and catch it using output buffering. With the data in a variable it can easily be stored in a database, dumped to a file or to the browser. If you wanted to dump it to a file, you&#8217;d probably want to swap <code class="codecolorer text default"><span class="text">NULL</span></code> with the filename. And if you wanted to output it to the browser, you could just skip the output buffering and let the data flow to the browser freely. But, just so you can see how to catch the data in a variable, I will do it the hard way <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':p' class='wp-smiley smiley-13' /> </p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Catch the imagedata</span><br />
<span style="color: #990000;">ob_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">imagejpeg</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$new</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">90</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ob_get_clean</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Next up we need to clean up after ourselves. Never forget that!</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Destroy resources</span><br />
<span style="color: #990000;">imagedestroy</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">imagedestroy</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$new</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Finally we&#8217;ll set a proper content-type so the browser understands what it gets and output the data.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Set new content-type and status code</span><br />
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: image/jpeg&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Output data</span><br />
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span></div></div>
<p>And that&#8217;s all <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<h2>Working sample</h2>
<p>You can check out a working sample and complete source code at <a href="http://samples.geekality.net/image-resize/">samples.geekality.net/image-resize</a>. Don&#8217;t abuse it ;)</p>
<p>Let me know if this was useful or if you have some ideas for improvement. Also, if I have messed up somewhere, please do let me know so I can fix it and possibly learn something new <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1564&amp;md5=f24d98ed2da188da63824d0db699260d" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/05/01/php-how-to-proportionally-resize-an-uploaded-image/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Unix: How to redirect stderr to stdout</title>
		<link>http://www.geekality.net/2011/02/02/unix-how-to-redirect-stderr-to-stdout/</link>
		<comments>http://www.geekality.net/2011/02/02/unix-how-to-redirect-stderr-to-stdout/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 12:52:10 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Command]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1473</guid>
		<description><![CDATA[Today I ran a Java application in a Unix console. It printed out some messages before it crashed with an exception and a loong stack trace. Too long to see the top of. So, I figured I&#8217;d just pipeline it &#8230; <a href="http://www.geekality.net/2011/02/02/unix-how-to-redirect-stderr-to-stdout/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today I ran a Java application in a Unix console. It printed out some messages before it crashed with an exception and a loong stack trace. Too long to see the top of. So, I figured I&#8217;d just <a href="http://en.wikipedia.org/wiki/Pipeline_(Unix)">pipeline</a> it into the lovely <code class="codecolorer text default"><span class="text">less</span></code> like this:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>java <span style="color: #660033;">-jar</span> foobar.jar <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">less</span></div></div>
<p>The result was not what I expected however. All I got to see was the messages that had been printed out. No exception or stack trace to be seen.</p>
<p><span id="more-1473"></span></p>
<p>The reason for this is quite simply that a Unix process has three different <a href="http://en.wikipedia.org/wiki/Standard_streams">streams</a>: stdin(0), stdout(1) and stderr(2). When we pipe output from one process into another we sort of connect stdout of the first one to stdin of the second.</p>
<p>So, to be able to see my giant stack trace, we can for example redirect stderr to stdout. This way we will get both streams into stdin of the next process.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>java <span style="color: #660033;">-jar</span> foobar.jar <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">less</span></div></div>
<p>Fancy, huh? We can also direct these streams into files, which might come in handy.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>java <span style="color: #660033;">-jar</span> foobar.jar <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">&gt;</span>out.log <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;</span>err.log</div></div>
<p>If you want the output to be appended to the log files instead of replacing them, you can do adjust the command to this:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>java <span style="color: #660033;">-jar</span> foobar.jar <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">&gt;&gt;</span>out.log <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&gt;</span>err.log</div></div>
<p> <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1473&amp;md5=345a2ba043a55f0bdf321592159cc850" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/02/02/unix-how-to-redirect-stderr-to-stdout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Win7: Automatic login for lazy single user</title>
		<link>http://www.geekality.net/2010/12/13/win7-automatic-login-for-lazy-single-user/</link>
		<comments>http://www.geekality.net/2010/12/13/win7-automatic-login-for-lazy-single-user/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 09:47:44 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Laziness]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1443</guid>
		<description><![CDATA[I&#8217;m the only one who use my computer and it&#8217;s in my room and I don&#8217;t really care about locking it or anything like that. I just find it annoying that I have to type a password everytime I boot &#8230; <a href="http://www.geekality.net/2010/12/13/win7-automatic-login-for-lazy-single-user/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m the only one who use my computer and it&#8217;s in my room and I don&#8217;t really care about locking it or anything like that. I just find it annoying that I have to type a password everytime I boot it up or it comes back from sleep or screen saver mode.</p>
<p>I usually do this whenever I reinstall Windows. At least on my desktop computer. My laptops usually have password protection enabled. Anyways, I don&#8217;t reinstall that often so I always forget how to do it. Even though it&#8217;s very simple&#8230; Decided to share the procedure here, so I know where to find it <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p><span id="more-1443"></span></p>
<ol>
<li>Press <var>Win+R</var> to open up your Run dialog</li>
<li>Type in <var>control userpasswords2</var> and hit enter</li>
<li>Under the Users tab, uncheck the checkbox that says <cite>&#8220;Users must enter a user name and password to use this computer&#8221;</cite></li>
<li>Click the Ok button</li>
<li>Enter your current password, and you&#8217;re done</li>
</ol>
<p>The next time you reboot it should go straight into Windows instead of stopping at the Welcome screen, waiting for you to type your password.</p>
<p class="wp-flattr-button"></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2010/12/13/win7-automatic-login-for-lazy-single-user/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to backup a folder with Robocopy</title>
		<link>http://www.geekality.net/2010/11/15/how-to-backup-a-folder-with-robocopy/</link>
		<comments>http://www.geekality.net/2010/11/15/how-to-backup-a-folder-with-robocopy/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 01:57:17 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[RoboCopy]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1137</guid>
		<description><![CDATA[As a simple way to keep my computer backed up I copy all that I care about onto external hard drives twice a day. I mostly do this in case my internal hard drives would die or something like that, &#8230; <a href="http://www.geekality.net/2010/11/15/how-to-backup-a-folder-with-robocopy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.geekality.net/wp-content/uploads/2010/11/Harddrive-300x224.jpg" alt="Harddrive" title="Harddrive" width="300" height="224" class="alignright size-medium wp-image-1362" />As a simple way to keep my computer backed up I copy all that I care about onto external hard drives twice a day. I mostly do this in case my internal hard drives would die or something like that, so I haven&#8217;t cared too much about finding anything more fancy with incremental history and such. What I have is a simple <a href="http://en.wikipedia.org/wiki/Batch_file">batch file</a> that I have set to run periodically using the Task Scheduler in Windows.</p>
<p><span id="more-1137"></span></p>
<p>The batch file simply looks like this:</p>
<div class="codecolorer-container dos default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="dos codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #33cc33;">@</span><span style="color: #b1b100; font-weight: bold;">echo</span> off<br />
<br />
robocopy D:\ X:\D /<span style="color: #b1b100; font-weight: bold;">COPY</span>:DAT /MIR /B /XJ /R:0 /NP /LOG:&quot;X:\D.log&quot;<br />
attrib -S -H X:\D</div></div>
<p>You can duplicate those two last lines for other folders you want to back up as well. I have one copying my D drive to external drive X, one copying my E drive to another external drive Y, and one copying some folders on my C drive to external drive Y.</p>
<h2>Robocopy</h2>
<p><a href="http://en.wikipedia.org/wiki/Robocopy">Robocopy</a> is of course the command that does the backing up. The options I use here are as follows:</p>
<ol>
<li>Source (directory we want to back up)</li>
<li>Destination (where we want the backup to be stored)</li>
<li>Copy Data, Attributes and Timestamps</li>
<li>Mirror (Copy all subdirectories, even empty ones, and delete files no longer in the source directory)</li>
<li>Copy files in Backup mode (assert the Windows NT &#8220;backup right&#8221; so an administrator may copy an entire directory, including files denied readability to the administrator)</li>
<li>Exclude Junction points</li>
<li>Retry zero times on failed copies (prevents spending lots of time on locked files for example)</li>
<li>Don&#8217;t display any progress</li>
<li>Log what happens to the given file instead of printing it out in the console</li>
</ol>
<h3>Don&#8217;t get stuck in a loop!</h3>
<p>The robocopy switch, /XJ, is <strong>very</strong> important to remember if you copy for example your user directory. The reason is that some folders in Windows are something called junction points and some of these will cause robocopy to enter a never ending loop. The copying will basically never finish until the target device run out of space or something else happens. Happened to me. Not very fun to clean up <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':P' class='wp-smiley smiley-13' /> </p>
<h2>Attrib</h2>
<p>In my case I am copying a whole drive, and the attributes on the resulting folder is a bit weird. So, to have the folder show up in Explorer without having to make it show system files and hidden files, I remove the system- and hidden-attribute from the folder.</p>
<h2>How to run it</h2>
<p>You can either run this yourself in a Command Prompt or schedule it using the <a href="http://windows.microsoft.com/en-US/windows7/schedule-a-task">Task Scheduler</a>. What is important to remember is that you should run this using Administrator rights.</p>
<p>So, if you use a Command Prompt: Remember to use an <a href="http://www.geekality.net/2010/08/16/how-to-open-an-elevated-command-prompt-window/">elevated Command Prompt</a>. And if you use the Task Scheduler, remember to select that the task should <em>Run with highest privileges</em> in the task properties.</p>
<p>If you just want to run it in the command prompt and see the progress a bit easier, you can remove the /NP and /LOG options. You will then see what happens as it goes through your files <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2010/11/15/how-to-backup-a-folder-with-robocopy/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>PHP Tutorial: PayPal Payment Data Transfers (PDT)</title>
		<link>http://www.geekality.net/2010/10/19/php-tutorial-paypal-payment-data-transfers-pdt/</link>
		<comments>http://www.geekality.net/2010/10/19/php-tutorial-paypal-payment-data-transfers-pdt/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 21:14:34 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[PayPal]]></category>
		<category><![CDATA[PDT]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1210</guid>
		<description><![CDATA[Say you have a PayPal &#8220;Buy Now&#8221;-button on your website and you have assigned return URLs like http://example.com/order?done and http://example.com/order?canceled. You can then welcome the user back after a successful payment. But what if you wanted to say something more &#8230; <a href="http://www.geekality.net/2010/10/19/php-tutorial-paypal-payment-data-transfers-pdt/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.geekality.net/wp-content/uploads/2010/10/Money-300x200.jpg" alt="Money" title="Money" width="300" height="200" class="alignright size-medium wp-image-1265" />Say you have a PayPal &#8220;Buy Now&#8221;-button on your website and you have assigned return URLs like <code class="codecolorer text default"><span class="text">http://example.com/order?done</span></code> and <code class="codecolorer text default"><span class="text">http://example.com/order?canceled</span></code>. You can then welcome the user back after a successful payment. But what if you wanted to say something more interesting than just &#8220;hey, welcome back&#8221; when they click on that &#8220;Return to Merchant&#8221;-button? And can you know if the order was <em>actually</em> done or canceled? Maybe you&#8217;d like to log the transaction in your database and mark a payment as complete or something like that too? In that case you sure can&#8217;t trust a simple flag in the address bar&#8230;</p>
<blockquote><p>Payment Data Transfer (PDT) is a secure method to retrieve the details about a PayPal transaction so that you can display them to your customer. It is used in combination with Website Payments Standard, so that after a customer returns to your website after paying on the PayPal site, they can instantly view a confirmation message with the details of the transaction. &#8212; <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;content_ID=developer/howto_html_paymentdatatransfer">PayPal</a></p></blockquote>
<p>I&#8217;ve tried to figure out how to use PDT and found that most samples and classes to build from are usually quite ugly, old or outdated. I didn&#8217;t find them too useful anyways&#8230; So, therefore, I&#8217;ve tried to do my own thing based on the documentation found on the PayPal Developer websites. (Seriously, how many versions of documents and developer websites do they have anyways? It&#8217;s like a complete jungle&#8230;)</p>
<p>Since the documentation was a bit of a mess, I thought I make a small tutorial on the steps needed to get started. That way I can learn it better myself and hopefully help some other poor souls that need to figure this stuff out as well. Please provide feedback if you have any! Would love to make this page nicer and clearer if possible <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p><span id="more-1210"></span></p>
<h2>Step 0: Sign up for a Developer Account</h2>
<p>Before you start playing around with PayPal stuff, I would recommend that you <a href="/?p=1176">get a PayPal developer account</a>. You should also set up a business account in the PayPal Sandbox which you can then use instead of your real account. A lot safer, cheaper and easier than using a real one.</p>
<h2>Step 1: Enable PDT for your PayPal account</h2>
<p><del datetime="2011-08-01T18:52:38+00:00">For this step I&#8217;ll just quote their <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;content_ID=developer/howto_html_paymentdatatransfer">PDT page</a> (one of many, it seems):</del></p>
<p><ins datetime="2011-08-01T18:52:38+00:00">Apparently they have changed their UI now, so the instructions in their PDT documentation is wrong&#8230; Thanks for the heads up Yuriy! The description below should be correct now <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </ins></p>
<p>To use PDT, you must activate PDT and Auto Return in your PayPal account profile. You must also acquire a PDT <em>identity token</em>, which is used in all PDT communication you send to PayPal.</p>
<p>Follow these steps to configure your account for PDT:</p>
<ol>
<li>Log in to your PayPal account.</li>
<li>Click the <strong>Profile</strong> subtab.</li>
<li>Click the <strong>My Selling Tools</strong> button in the left column.</li>
<li>Find the <strong>Selling online</strong> section and click <strong>Update</strong> in the <strong>Website preferences</strong> row.</li>
<li>Under Auto Return for Website Payments, click the <strong>On</strong> radio button.</li>
<li>For the Return URL, enter the URL on your site that will receive the transaction ID posted by PayPal after a customer payment. </li>
<li>Under Payment Data Transfer, click the <strong>On</strong> radio button.</li>
<li>Click <strong>Save</strong>.</li>
<li>Find the <strong>Selling online</strong> section and click <strong>Update</strong> in the <strong>Website preferences</strong> row again.</li>
<li>Scroll down to the Payment Data Transfer section of the page and take note of your PDT identity token.</li>
</ol>
<p>The last point is particularly important and you should not only view the token, but note it down. Reason being that you need this in your code when we&#8217;re going to talk to PayPal later.</p>
<p><a href="http://www.geekality.net/wp-content/uploads/2010/10/Capture.jpg"><img src="http://www.geekality.net/wp-content/uploads/2010/10/Capture-122x300.jpg" alt="Screenshot of PayPal Payment Preferences" title="PayPal Payment Preferences" width="122" height="300" class="alignright size-medium wp-image-1214" /></a>As an aside, I would also recommend you turn off the &#8220;Block Non-encrypted Website Payment&#8221;, at least while testing, since it&#8217;s a lot easier to make PayPal buttons on the fly without encrypting them. I currently don&#8217;t know how, but I&#8217;ll probably try to figure out soon. I would also recommend that you set PayPal Account Optional, so that people can make payments without signing up (since some people don&#8217;t want to be bothered with that). To the right I have put a screen shot of that page with the mentioned options marked in yellow. Click on it for full-size view <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<h2>Step 2: Create a button</h2>
<p>The PayPal buttons consist of a form which has a number of hidden key/value pairs and a submit button. You can find info on how to make those in their <a href="https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_WebsitePaymentsStandard_IntegrationGuide.pdf">Website Payments Standard Integration Guide</a> so I won&#8217;t explain how to do that here. What I would like to mention in this case though, is that you can, if you need to, override the return URL that you set in the previous step for specific buttons. For example you can return them to the order they paid for rather than just a general return page.</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;return&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://business.example.com/order/123/&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;cancel_return&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://business.example.com/order/123/&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></div></div>
<p>I use the same URL for both since we will check things with PDT anyways. Here is an example button with the data I use in this tutorial:</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;https://www.sandbox.paypal.com/cgi-bin/webscr&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span> <span style="color: #000066;">accept-charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;cmd&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;_xclick&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;charset&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;business&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;paypal@business.example.com&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;item_name&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Stuffed bear&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;item_number&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;BEAR05&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;amount&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20.00&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;currency_code&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;USD&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;return&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://business.example.com/order/123/&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;cancel_return&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://business.example.com/order/123/&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;bn&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Business_BuyNow_WPS_SE&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;image&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;https://www.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Buy Now&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span> <br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></div>
<p>So, the user will click the button, go through the payment procedure, and at the end there will be a link/button to return to the merchant. When that is clicked, we get to the next step.</p>
<h2>Step 3: Catch the return</h2>
<p>The URL they are returned to could for example look like this (split for easier reading):</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">http://business.example.com/order/123/?tx=6BC88318RN685282M<br />
&amp;st=Completed<br />
&amp;amt=20.00<br />
&amp;cc=USD<br />
&amp;cm=<br />
&amp;item_number=BEAR05</div></div>
<p>As you can see we get some GET parameters to work with here, but the only one you need is the Transaction ID, <code class="codecolorer text default"><span class="text">tx</span></code>:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tx'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000088;">$tx</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tx'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// Further processing</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>The reason we don&#8217;t care about the rest is that they&#8217;re not trustworthy at all. Since they are GET parameters we can easily tamper with them in the address bar of our browser, and we just can&#8217;t have any of that, can we?</p>
<p>To get good and trustworthy data we need to send this transaction id back to PayPal together with our PDT Identity Token. If the id and token are valid, we will get real and actual transaction details back in return.</p>
<h2>Step 4: Do a POST request back to PayPal</h2>
<p>Sending the Transaction ID and our PDT Identity Token back to PayPal can be done in various ways from PHP. I used <a href="http://www.php.net/manual/en/ref.curl.php">cURL</a> which I found to be pretty clean and easy to use.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Init cURL</span><br />
<span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Set request options</span><br />
<span style="color: #990000;">curl_setopt_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><br />
<span style="color: #009900;">&#40;</span><br />
&nbsp; CURLOPT_URL <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'https://www.sandbox.paypal.com/cgi-bin/webscr'</span><span style="color: #339933;">,</span><br />
&nbsp; CURLOPT_POST <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; CURLOPT_POSTFIELDS <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">http_build_query</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'cmd'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'_notify-synch'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'tx'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$tx</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'at'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$your_pdt_identity_token</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; CURLOPT_RETURNTRANSFER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; CURLOPT_HEADER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">,</span><br />
&nbsp; CURLOPT_SSL_VERIFYPEER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; CURLOPT_CAINFO <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'cacert.pem'</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Execute request and get response and status code</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$status</span> &nbsp; <span style="color: #339933;">=</span> <span style="color: #990000;">curl_getinfo</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> CURLINFO_HTTP_CODE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Close connection</span><br />
<span style="color: #990000;">curl_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>The cURL options we set means roughly: Use this URL, do a POST, send these variables, return the transfer as a string when I call <code class="codecolorer text default"><span class="text">curl_exec</span></code> and do not include the HTTP headers in that string. The last two you can most likely leave out, but I explain why I added them <a href="/?p=1413">in this post</a>.</p>
<blockquote><p><strong>Note:</strong> For security reasons, PayPal will only allow you to use the transaction id to get a response up to 5 times. After that it will be invalidated and you will get an error back instead of the transaction data. Fair enough for regular use, but found it a bit annoying while developing since it took some tries to get the result I wanted <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':P' class='wp-smiley smiley-13' /> </p></blockquote>
<h2>Step 5: Check the response</h2>
<p>The response will be a string that looks something like this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SUCCESS<br />
mc_gross=20.00<br />
invoice=AF000001<br />
protection_eligibility=Eligible<br />
address_status=confirmed<br />
payer_id=ADSZV7LHTCJM4<br />
tax=0.00<br />
address_street=Candy+Road+77<br />
payment_date=12%3A04%3A18+Oct+19%2C+2010+PDT<br />
payment_status=Completed<br />
charset=windows-1252<br />
address_zip=99501<br />
first_name=Alice<br />
mc_fee=0.88<br />
address_country_code=US<br />
address_name=Alice+Foobar<br />
custom=<br />
payer_status=unverified<br />
business=paypal%40business.example.com<br />
address_country=United+States<br />
address_city=Anchorage<br />
quantity=1<br />
payer_email=alice.foobar%40example.com<br />
txn_id=6BC88318RN685282M<br />
payment_type=instant<br />
last_name=Foobar<br />
address_state=AK<br />
receiver_email=paypal%40business.example.com<br />
payment_fee=0.88<br />
receiver_id=JNNUMM42GJB9U<br />
txn_type=web_accept<br />
item_name=Stuffed+bear<br />
mc_currency=USD<br />
item_number=BEAR05<br />
residence_country=US<br />
receipt_id=3354-8100-5749-2926<br />
handling_amount=0.00<br />
transaction_subject=Stuffed+bear<br />
payment_gross=20.00<br />
shipping=0.00</div></div>
<p>To make sure everything is well we must check that the status code is 200 and that the first line says SUCCESS. On failure it would say FAIL, or something like that. We can do that like this:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$status</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">200</span> AND <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'SUCCESS'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Further processing</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #b1b100;">else</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Log the error, ignore it, whatever </span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>That response is not very useful right now though. Even if it is valid, the string is just, well, a long string. Not to mention it&#8217;s URL encoded and possibly in the wrong character encoding. We want to clean it up and turn it into a much more handy associative array.</p>
<h2>Step 6: Clean up the response</h2>
<p>We want to remove the first line, URL decode the string, turn it into an associative array and convert the encoding if needed. This is how you might do that:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Remove SUCCESS part (7 characters long)</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// URL decode</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">urldecode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Turn into associative array</span><br />
<span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^([^=\s]++)=(.*+)/m'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$response</span><span style="color: #339933;">,</span> <span style="color: #000088;">$m</span><span style="color: #339933;">,</span> PREG_PATTERN_ORDER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_combine</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$m</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$m</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Fix character encoding if different from UTF-8 (in my case)</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> AND <span style="color: #990000;">strtoupper</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #0000ff;">'UTF-8'</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mb_convert_encoding</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'UTF-8'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset_original'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'UTF-8'</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Sort on keys for readability (handy when debugging)</span><br />
<span style="color: #990000;">ksort</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>The <code class="codecolorer text default"><span class="text">$response</span></code> should now contain a nice and sorted associative array with the correct encoding and it&#8217;s ready to be used for whatever purpose you need.</p>
<h2>Step 7: What now?</h2>
<p>What you do with the validated and cleaned up data depends on what you need and what you want. You could use it to display a nice helpful message to the user, store it somewhere, maybe mark something as paid in your database, et cetera. You should also most likely check that the data you have gotten corresponds to what you expected. For example if the amount they paid matches the amount they should have paid and so on.</p>
<h2>Important thing to remember about PDT</h2>
<p>You are actually <strong>not guaranteed</strong> to get this PDT data. Unless the user clicks that last button in the payment process at PayPal and returns to your page, you will get nothing. They could for example close the browser tab when the payment is done or the power could go out just before they had the opportunity to. Theoretically it could happen!</p>
<p>If you want something that is fully reliable, you need to have a look at <a href="https://cms.paypal.com/cms_content/US/en_US/files/developer/IPNGuide.pdf">PayPal Instant Payment Notifications</a> (IPN). PayPal sends these notifications to a certain URL you have provided behind the scenes and it is not part what the user does or does not do. They may not be instantaneous, but you are guaranteed to eventually get them.</p>
<p>What you most likely want is a combination of these two. Use PDT to give the returning users a quick response and store what you can/need in the database. Then use IPN to fill out the gaps of missed PDTs or missing transaction details (IPN will give you many more details than PDT does).</p>
<p><ins datetime="2011-05-28T21:14:32+00:00">It took some time, but I have finally finished a <a href="http://www.geekality.net/?p=1420">tutorial on IPN</a> Check it out if you&#8217;re interested <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt='8)' class='wp-smiley smiley-3' /> </ins></p>
<h2>Working sample</h2>
<p>Since the code above was a bit broken up, I have gathered it all in a single example page that should be operational. It contains a simple Buy Now button and it will display the PDT response when you return from the fake purchase. Since it uses the PayPal Sandbox you need to be logged in to your developer account. For the payment you can use one of your existing test accounts or you can pretend to be a person that just wants to use his credit card without an account (If you need help coming up with a fake credit card number that validates, have a look at <a href="http://www.darkcoding.net/credit-card-numbers/">darkcoding.net/credit-card-numbers</a>).</p>
<p>You find it over at <a href="http://samples.geekality.net/pdt">samples.geekality.net/pdt</a>.</p>
<p>The <code class="codecolorer text default"><span class="text">process_pdt</span></code> function you can see in the source code should be pretty self-contained and you should be able to just drop it in to whatever you are working on and use it out of the box. Just remember to fill in <em>your</em> actual identity token ;)</p>
<p>And that&#8217;s the end of this tutorial! </p>
<p>Think this was my first longish in-depth post, so if you have any feedback, found it helpful, please leave a comment. Also do that if something is unclear, could be improved or is flat out wrong. Especially if it&#8217;s flat out wrong. There&#8217;s <em>a lot</em> of <em>wrong</em> stuff on the Internet, and I don&#8217;t want to contribute to that <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':P' class='wp-smiley smiley-13' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1210&amp;md5=2148753a87528912f0607319e9a1e354" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2010/10/19/php-tutorial-paypal-payment-data-transfers-pdt/feed/</wfw:commentRss>
		<slash:comments>76</slash:comments>
		</item>
	</channel>
</rss>

