<?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>Juozas devBlog &#187; Websites</title>
	<atom:link href="http://dev.juokaz.com/category/websites/feed" rel="self" type="application/rss+xml" />
	<link>http://dev.juokaz.com</link>
	<description>Random ideas, scripts and facts</description>
	<lastBuildDate>Mon, 22 Mar 2010 10:48:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>HTML filtering and XSS protection</title>
		<link>http://dev.juokaz.com/php/html-filtering-and-xss-protection</link>
		<comments>http://dev.juokaz.com/php/html-filtering-and-xss-protection#comments</comments>
		<pubDate>Sat, 21 Mar 2009 20:40:24 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[autoloader]]></category>
		<category><![CDATA[cleanup]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[htmlpurifier]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[scraping]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tidy]]></category>
		<category><![CDATA[tinymce]]></category>
		<category><![CDATA[validate]]></category>
		<category><![CDATA[web scraper]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=396</guid>
		<description><![CDATA[If you have been programming websites long enough you would know that user input is first think to worry about when thinking about security. It&#8217;s really hard to decide what data is acceptable, especially when user has permission to insert HTML content through form.
For example, if you are developing CMS you need to make sure [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://htmlpurifier.org/"><img class="size-thumbnail wp-image-402" style="float: left;" title="HTML Purifier" src="http://dev.juokaz.com/wp-content/uploads/2009/03/logo-large-150x150.png" alt="HTML Purifier" width="150" height="150" /></a>If you have been programming websites long enough you would know that user input is first think to worry about when thinking about security. It&#8217;s really hard to decide what data is acceptable, especially when user has permission to insert HTML content through form.</p>
<p>For example, if you are developing CMS you need to make sure that user input don&#8217;t break whole template. But that&#8217;s not so easy, because you need very clever HTML validations as even one missing closing tag for &lt;div&gt; or &lt;p&gt; can brake website&#8217;s layout completely. Editors like <a href="http://tinymce.moxiecode.com/">TinyMCE</a> can check and try to fix errors, but in my experience, they sometimes create more of them.</p>
<p>However, problem can be solved, and quite easily. Almost a year ago I was reading some random blog when I find out about <a href="http://htmlpurifier.org/">HTML Purifier</a>. Basically, it&#8217;s library which can filter and fix <strong>any</strong> HTML. <a href="http://htmlpurifier.org/comparison.html">Compared</a> to other libraries, it looks very promising, but since then I haven&#8217;t had a chance to test it &#8211; other libraries have been working fine.</p>
<p>Today I was working with <a href="http://dev.juokaz.com/php/web-scraping-with-php-and-xpath">web scrapper</a> again and ended up stuck because of very badly formatted HTML. When regular expressions are used, code validity isn&#8217;t (shouldn&#8217;t) a case at all, but XPath fails immediately. I tried simplifying queries, hard-coded source fixing, but all that required so many effort that I introduced Purifier filter between source fetching and <a href="http://en.wikipedia.org/wiki/Document_Object_Model">DOM</a> constructing. It worked!</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'HTMLPurifier.includes.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> HTMLPurifier_Config<span style="color: #339933;">::</span><span style="color: #004000;">createDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTML'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Doctype'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'XHTML 1.0 Transitional'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTML'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'TidyLevel'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'heavy'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Don't remove IDs (&lt;div id=&quot;first&quot; /&gt;)</span>
<span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Attr'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'EnableID'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$obj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HTMLPurifier<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$clean_html</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$obj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">purify</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>In this example I chose worst way &#8211; include all files. Library uses <a href="http://pear.php.net">PEAR</a>-like directory structure so simple auto-loader  can include all required files in background, but for simplicity it&#8217;s not used here. This sample code filters <em>$html</em> variable using XHTML 1.0 and does heavy level <a href="http://en.wikipedia.org/wiki/HTML_Tidy">tidying</a> (quite clear from source code itself).</p>
<p><a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a>? Purifier protects from them also &#8211; <a href="http://htmlpurifier.org/live/smoketests/xssAttacks.php">full list</a> of tests. Library is also highly customizable (<a href="http://htmlpurifier.org/live/configdoc/plain.html">configuration manual</a>), but documentation is not very clear &#8211; I have spent more than a hour trying to make it to return HTML with  <em>&lt;head&gt;</em> part. I haven&#8217;t found any nice solution (maybe because the library is not made for such things).</p>
<p>HTML Purifier contains about 350 files so it&#8217;s relatively big library, however it performs good and shouldn&#8217;t kill you web server. Today I Purified and using XPath extracted information from more than 1000 pages and it worked really stable &#8211; none of the results where filtered unexpectedly. I definitely recommend it for HTML inputs filtering because it just does wonderful job &#8211; you can try it online <a href="http://htmlpurifier.org/demo.php">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/html-filtering-and-xss-protection/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Debugging with FirePHP and Firebug</title>
		<link>http://dev.juokaz.com/php/debugging-with-firephp-and-firebug</link>
		<comments>http://dev.juokaz.com/php/debugging-with-firephp-and-firebug#comments</comments>
		<pubDate>Thu, 12 Mar 2009 15:09:43 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[execution time]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[firephp]]></category>
		<category><![CDATA[headers]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[profile]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=355</guid>
		<description><![CDATA[One may debug his application with print(&#8221;) statements all other the place or alert(&#8221;) for JavaScript. Luckily some years ago Firebug extension for Firefox was introduced, which introduced (?) console. Console works absolutely the same as in Linux and can be used not only to execute commands, but receive information from various sources.
To start with, [...]]]></description>
			<content:encoded><![CDATA[<p>One may debug his application with print(&#8221;) statements all other the place or alert(&#8221;) for JavaScript. Luckily some years ago <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a> extension for Firefox was introduced, which introduced (?) console. Console works absolutely the same as in Linux and can be used not only to execute commands, but receive information from various sources.</p>
<p>To start with, I just love <a href="https://addons.mozilla.org/en-US/firefox/addon/6149">FirePHP</a>. This extension extends Firebug itself and allows PHP to show messages in the console.</p>
<p><img class="size-full wp-image-356" style="float: right;" title="FirePHP" src="http://dev.juokaz.com/wp-content/uploads/2009/03/firephp.png" alt="FirePHP" width="402" height="127" />FirePHP use special headers to send required information, so browses without FirePHP doesn&#8217;t feel any difference, but others can easily extract information. It doesn&#8217;t mean that DB profiling information should be visible in production server, but it definitely helps in development stages. If you look at normal website&#8217;s headers you would see something like this:</p>
<pre>HTTP/1.x 200 OK
Date: Thu, 12 Mar 2009 14:29:29 GMT
Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4.1 ...
X-powered-by: PHP/5.2.6-2ubuntu4.1
Content-Length: 0
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html</pre>
<p>where FirePHP modifies it to:</p>
<pre>HTTP/1.x 200 OK
Date: Thu, 12 Mar 2009 14:28:39 GMT
Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4.1 ...
X-powered-by: PHP/5.2.6-2ubuntu4.1
X-Wf-Protocol-1: http://meta.wildfirehq.org/Protocol/JsonStream/0.2
X-Wf-1-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1
X-Wf-1-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/ZendFramework/FirePHP/1.6.2
X-Wf-1-1-1-1: 56|[{"Type":"INFO","File":"","Line":""},"This is a debug!"]|
X-Wf-1-1-1-2: 58|[{"Type":"ERROR","File":"","Line":""},"This is an error!"]|
Content-Length: 0
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html</pre>
<p><a href="http://www.firephp.org/">FirePHP</a> website has libraries for sending these headers, but since I was trying it when using Zend Framework, I chose Zend_Log_Writer_Firebug module. It works as writer interface for Zend_Log and since Zend_Log is (or should be) used for all logging in ZF, you can get very nice access to all information (execution time, queries, warnings, etc.) from browser. For example, to send something with Zend Framework, code would look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Place this in your bootstrap</span>
<span style="color: #000088;">$writer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Log_Writer_Firebug<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$logger</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Log<span style="color: #009900;">&#40;</span><span style="color: #000088;">$writer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Use this in your model, view and controller files</span>
<span style="color: #000088;">$logger</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">log</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This is a log message!'</span><span style="color: #339933;">,</span> Zend_Log<span style="color: #339933;">::</span><span style="color: #004000;">INFO</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Simple and clean (it won&#8217;t work if Zend_Controller_Front is not used, look at <a href="http://framework.zend.com/manual/en/zend.log.writers.html#zend.log.writers.firebug">manual</a>).</p>
<p>Logging to files still should be used for information which will be required for further analysis, eg. payment gateway errors, but such information as execution time works perfectly in FirePHP. Users doesn&#8217;t care how fast page was rendered, but developers sometimes needs this information and in my opinion, using FirePHP sounds most reasonable. Have you tried it?</p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/debugging-with-firephp-and-firebug/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Scraping login requiring websites with cURL</title>
		<link>http://dev.juokaz.com/php/scraping-login-requiring-websites-with-curl</link>
		<comments>http://dev.juokaz.com/php/scraping-login-requiring-websites-with-curl#comments</comments>
		<pubDate>Mon, 23 Feb 2009 20:50:19 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[crawling]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[post]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[scraping]]></category>
		<category><![CDATA[secure]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[xml-rpc]]></category>
		<category><![CDATA[xpath]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=245</guid>
		<description><![CDATA[Scraping websites with XPath is very easy (read here), but how to scrape user&#8217;s friends list from social website if it can be viewed only when user is logged in?
What we need to do is to implement algorithm, which posts login and password fields to website login form and uses the same PHPSESSID id for [...]]]></description>
			<content:encoded><![CDATA[<p>Scraping websites with XPath is very easy (read <a href="http://dev.juokaz.com/php/web-scraping-with-php-and-xpath">here</a>), but how to scrape user&#8217;s friends list from social website if it can be viewed only when user is logged in?</p>
<p>What we need to do is to implement algorithm, which posts login and password fields to website login form and uses the same PHPSESSID id for further calls. For example, if login form is POSTed with 123 session id, then all requests with 123 session id could access users-only pages. This works because PHP (or other language) sets session data to loggedin=true for given session id.</p>
<p>But how you are going to do all this work with cookies and session id? Luckily, PHP has <a href="http://uk.php.net/curl">cURL extension</a> which simplifies connecting to remote addresses, using cookies, staying in one session, POSTing data, etc. It&#8217;s really powerful library, which basically allows you to use all HTTP headers functionality.</p>
<p>For secure pages crawling, I&#8217;ve created very simple <a href="http://dev.juokaz.com/examples/crawler/crawler.phps">Secure_Crawler</a> class, which works like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">include</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;crawler.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$crawler</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Secure_Crawler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Login to website</span>
<span style="color: #000088;">$crawler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">login</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'my_username'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'secure_password'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get Content</span>
<span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$crawler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://www.example.com/secure/profile.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// modifications...</span></pre></div></div>

<p>If you look at class source code, you would see that class has these specifications:</p>
<ol>
<li>When Secure_Crawler instance is created, default cURL options are set</li>
<li>Login() method POSTs given credentials to login page (<em>hard-coded</em>)</li>
<li>Get(url) method loads page by given URL (previous session data is used)</li>
</ol>
<p>Class itself is very easily extendible &#8211; as long as you pass Cookies file to cURL object, login information will (should) be used and all users-only content would be available.</p>
<p>Using similar class, I&#8217;ve pseudo-reverse engineered API. I needed to enter information to other website multiple times per day by hand because they didn&#8217;t offered any remote services (like XML-RPC or REST), so I created class which mimics API functionality. From outside it looks like normal API object, but inside code actually POSTs everything to actual website.</p>
<p>All websites works differently so you need to spend some time analysing how login form submission is handled on that specifix website. For example, maybe you need to use SSL protocol or even you own certificate. It depends and differs from site to site, but basics are the same &#8211; it will work as long as you are calm enough to tweak it&#8217;s work-flow. </p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/scraping-login-requiring-websites-with-curl/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PayPal payment with encryption</title>
		<link>http://dev.juokaz.com/php/paypal-payment-with-encryption</link>
		<comments>http://dev.juokaz.com/php/paypal-payment-with-encryption#comments</comments>
		<pubDate>Sun, 22 Feb 2009 14:34:40 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[ivor durham]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[payment gateway]]></category>
		<category><![CDATA[paypal]]></category>
		<category><![CDATA[phpfour.com]]></category>
		<category><![CDATA[private key]]></category>
		<category><![CDATA[rsa]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=224</guid>
		<description><![CDATA[Recently phpfour.com posted very interesting library for payment gateways. In my situation, PayPal is only used to pay for orders &#8211; cart and order setup is done in our shop, so I do not want to have additional problems with users changing orders numbers, amount to be paid, etc. Today I&#8217;m going to show how [...]]]></description>
			<content:encoded><![CDATA[<p>Recently phpfour.com posted very interesting <a href="http://www.phpfour.com/blog/2009/02/php-payment-gateway-library-for-paypal-authorizenet-and-2checkout/">library for payment gateways</a>. In my situation, PayPal is only used to pay for orders &#8211; cart and order setup is done in our shop, so I do not want to have additional problems with users changing orders numbers, amount to be paid, etc. Today I&#8217;m going to show how to encrypt PayPal transactions.</p>
<p>I chose to use <a href="https://www.paypal.com/us/cgi-bin/webscr?cmd=p/xcl/rec/ewp-intro-outside">Encrypted Website Payment</a>, which allows you to encrypt all form fields and send them as one encrypted parameter. Only PayPal knows how to decrypt it, because it uses public key encryption technology (you need to upload your certificate in PayPal account).</p>
<p>My recommended PHP library for creating such buttons is written by Ivor Durham and is available on-line <a href="http://www.pdncommunity.com/pdn/attachments/pdn/ewp/87/1/paypalewp.php">here</a>. It&#8217;s not as flexible as phpfour.com one and is probably old, but it does what it needs to do. I have been using it for over a year now and haven&#8217;t had any problems (some hundreds payments).</p>
<p>To create encrypted button you need to write something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$paypal</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PayPalEWP<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$paypal</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTempFileDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/tmp'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Certificate and private key</span>
<span style="color: #000088;">$paypal</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCertificate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mycompany_cert.pem'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mycompany_key.pem'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Uploaded certificate id</span>
<span style="color: #000088;">$paypal</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCertificateID</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ABCDEFGHIJKL'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// PayPal certificate</span>
<span style="color: #000088;">$paypal</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setPayPalCertificate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'paypal_cert_sandbox.pem'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$parameters</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cmd&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;_xclick&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;business&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;sales@mycompany.com&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;item_name&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;Order #ID&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;amount&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;12.95&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;no_shipping&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;1&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;return&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;http://mycompany.com/paypal_ok.php&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;cancel_return&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;http://mycompany.com/paypal_cancel.php&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;no_note&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;1&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;currency_code&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;USD&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">&quot;bn&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;PP-BuyNowBF&quot;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$encryptedButton</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$paypal</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">encryptButton</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$parameters</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">echo</span> <span style="color: #0000cc; font-style: italic;">&lt;&lt;&lt;END_HTML
&lt;form action=&quot;https://www.sandbox.paypal.com/cgi-bin/webscr&quot;
method=&quot;post&quot;&gt;
&nbsp;
&lt;input type=&quot;hidden&quot; name=&quot;cmd&quot; value=&quot;_s-xclick&quot;&gt;
&lt;input type=&quot;image&quot;
src=&quot;https://www.sandbox.paypal.com/en_US/i/btn/x-click-but23.gif&quot;
border=&quot;0&quot; name=&quot;submit&quot; alt=&quot;Make payments with PayPal&quot;&gt;
&lt;input type=&quot;hidden&quot; name=&quot;encrypted&quot; value=&quot;
-----BEGIN PKCS7-----
{$encryptedButton}
-----END PKCS7-----
&quot;&gt;
&lt;/form&gt;
END</span>_HTML<span style="color: #339933;">;</span></pre></div></div>

<p>I have customized it a little bit to be modular (I use over 5 different payment gateways), but main concepts left the same. If you just starting PayPal integration, I recommend rewriting it to be more object-oriented and maybe integrating payments validation (which works the same as normal payments).</p>
<p>PayPal has <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;content_ID=developer/howto_testing_sandbox">sandbox</a> mode and big manuals <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;content_ID=developer/e_howto_html_encryptedwebpayments">library</a> &#8211; testing PayPal gateway is very easy and shouldn&#8217;t be a problem. I definitely recommend creating sandbox users (merchant and buyer) and playing with virtual money &#8211; it not only allows you to test gateway&#8217;s functionality, but feels very good to have unlimited amount of money.</p>
<p>To finish with, I recommend using encrypted PayPal buttons &#8211; additional security is not bad. How do you handle payments?</p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/paypal-payment-with-encryption/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Web scraping with PHP and XPath</title>
		<link>http://dev.juokaz.com/php/web-scraping-with-php-and-xpath</link>
		<comments>http://dev.juokaz.com/php/web-scraping-with-php-and-xpath#comments</comments>
		<pubDate>Tue, 17 Feb 2009 20:23:04 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[crawler]]></category>
		<category><![CDATA[easy]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[legal]]></category>
		<category><![CDATA[scraping]]></category>
		<category><![CDATA[spider]]></category>
		<category><![CDATA[ssssscpripting]]></category>
		<category><![CDATA[w3schools]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web scraping]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xpath]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=176</guid>
		<description><![CDATA[When I was writing about how I use web scraping, I was still hadn&#8217;t tried using Xpath (shame on me). sssscripting blog responded to my article with very good and rich post about all sorts of different techniques for scraping (with Ruby examples) and after reading this post in Kore Nordmann blog I finally decided [...]]]></description>
			<content:encoded><![CDATA[<p>When I was writing about <a href="http://dev.juokaz.com/php/web-scraping-easy-way-to-monitor-market">how I use web scraping</a>, I was still hadn&#8217;t tried using Xpath (shame on me). <a href="http://ssscripting.wordpress.com/">sssscripting blog</a> responded to my article with very good and rich <a href="http://ssscripting.wordpress.com/2009/02/15/web-scraping-techniques/">post</a> about all sorts of different techniques for scraping (with Ruby examples) and after reading this <a href="http://kore-nordmann.de/blog/0081_parse_html_extract_data_from_html.html">post in Kore Nordmann blog</a> I finally decided to try making something with Xpath.</p>
<p>It turned out, that using Xpath is <strong>extremely easy</strong>, really. When you master it, you can do everything in seconds. Yes, you need to know how XML works and how to write correct Xpath queries (brief explanation of Xpath syntax is available at <a href="http://www.w3schools.com/XPath/xpath_syntax.asp">W3Schools</a>), but hey &#8211; these topics are in 1st year of university. </p>
<p>Also, there are good tools like <a href="https://addons.mozilla.org/en-US/firefox/addon/1095">XPath checker</a> for Firefox which allows you to debug and test your queries without writing any code. Stupid to say, but XPath queries looks a lot like CSS selectors, but with much more power and flexibility. Without further talking, lets look at example (idea from Kore&#8217;s article):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> 
&nbsp;
<span style="color: #000088;">$oldSetting</span> <span style="color: #339933;">=</span> <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> 
<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> 
&nbsp;
<span style="color: #000088;">$html</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> 
<span style="color: #000088;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadHtmlFile</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'http://www.bhphotovideo.com/c/shop/6222/SLR_Digital_Cameras.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #000088;">$xpath</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMXPath<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$html</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #000088;">$links</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$xpath</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;//div[@class='productBlock clearfix']&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #000088;">$return</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>
&nbsp;
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$links</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$newDom</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMDocument<span style="color: #339933;">;</span>
	<span style="color: #000088;">$newDom</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">appendChild</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$newDom</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">importNode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$item</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$xpath</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMXPath<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$newDom</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$xpath</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;//div[@id='productTitle']&quot;</span><span style="color: #009900;">&#41;</span>
                   <span style="color: #339933;">-&gt;</span><span style="color: #004000;">item</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nodeValue</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$price</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$xpath</span>
                   <span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;//li[@class='price']/span[@class='value']&quot;</span><span style="color: #009900;">&#41;</span>
                   <span style="color: #339933;">-&gt;</span><span style="color: #004000;">item</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nodeValue</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$return</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">'title'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$title</span><span style="color: #339933;">,</span>
		<span style="color: #0000ff;">'price'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$price</span><span style="color: #339933;">,</span>
		<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> 
&nbsp;
<span style="color: #666666; font-style: italic;">// Products array with title and price</span>
<span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$return</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&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> 
<span style="color: #990000;">libxml_use_internal_errors</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$oldSetting</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>This code gets all products titles and prices from <a href="http://www.bhphotovideo.com/">Bhphotovideo.com</a> (read below) category page. You must have noticed that XPath queries are really simple: one selects all products, others selects only specific elements of each product. How fast you can get same results with plain regexp? I made this in 3 minutes (downloading XPath extension for Firefox, reading php manual, etc. included).</p>
<p>I used to write queries as regular expressions, but now I see that I&#8217;ve been just wasting time &#8211; using XPath is much more easier. I don&#8217;t know why I haven&#8217;t tried them sooner (maybe because of my believing, that XPath only works with correctly structured documents), but now I see that this technology is just awesome. I don&#8217;t know what to say more &#8211; <strong>web scraping with XPath is supper easy</strong>.</p>
<p><em><a href="http://www.bhphotovideo.com">Bhphotovideo.com</a> is really good shop and I chose it as example of scraping. I don&#8217;t encourage you to steal their information and it&#8217;s your responsibility to scrape only these sites, which allows it. My code it&#8217;s just an example and shouldn&#8217;t be used to affect Bhphotovideo.com sales.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/web-scraping-with-php-and-xpath/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Correct headers for dynamically generated content</title>
		<link>http://dev.juokaz.com/php/correct-headers-for-dynamically-generated-content</link>
		<comments>http://dev.juokaz.com/php/correct-headers-for-dynamically-generated-content#comments</comments>
		<pubDate>Sun, 15 Feb 2009 19:00:39 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[headers]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[load time]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[uahoo]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=155</guid>
		<description><![CDATA[Static images have correct headers &#8211; Apache sends them by default. Different story is with all dynamic generating content &#8211; if you don&#8217;t send correct headers user&#8217;s browser will load it every time. It&#8217;s not always good, because generated thumbnails doesn&#8217;t change every time and should be cached in browser&#8217;s cache. If you want to [...]]]></description>
			<content:encoded><![CDATA[<p>Static images have correct headers &#8211; Apache sends them by default. Different story is with all dynamic generating content &#8211; if you don&#8217;t send correct headers user&#8217;s browser will load it every time. It&#8217;s not always good, because generated thumbnails doesn&#8217;t change every time and should be cached in browser&#8217;s cache. If you want to reduce server load and increase loading speed you definitely need to send correct headers.</p>
<p>Our task is to give browser enough information to identify content, which later can be used to decided if content has changed, and if not &#8211; say it to browser without sending content again. Bigger picture is explained <a href="http://thoughtpad.net/alan-dean/http-headers-status.jpg">here</a>, I really recommend analysing it a little bit &#8211; it gives better understanding how headers work and what they mean.</p>
<p>As you saw in <a href="http://thoughtpad.net/alan-dean/http-headers-status.jpg">headers map</a>, there are many possible headers to send, but we can focus on three of them:</p>
<ol>
<li>Etag. Unique identified for output data (maybe hash)</li>
<li>Last-Modified. Date of last data modification</li>
<li>Expires. When to expire content</li>
</ol>
<p>Constructing algorithm is pretty simple, it can be explained in pseudo-code:</p>
<pre>get request headers
   is content expired
      send content, new headers
   else is content different (Etag)
      send content, new headers
   else
      304 header, no content</pre>
<p>I&#8217;ve created <em>outputCacheHeaders(&#8230;)</em> function which (available <a href="http://dev.juokaz.com/examples/expires-etag/headers.phps">here</a>) outputs all required headers and returns true if you need to output content or false if not. All you need to do is pass modification time, live time and data (two last ones are not required). Live time says how long should cache be kept and data is used to generate Etag. Very simple!</p>
<p>After enabling correct headers sending, my websites started to feel much faster, because HTTP requests takes much less time. Also, <a href="http://developer.yahoo.com/performance/rules.html">Yahoo performance tips</a> are really worth reading, really. There are many great tips and I have been using many of them for a long time. These tricks are much much more significant than 0.1 s. faster PHP rendering time.</p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/correct-headers-for-dynamically-generated-content/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web scraping &#8211; easy way to monitor market</title>
		<link>http://dev.juokaz.com/php/web-scraping-easy-way-to-monitor-market</link>
		<comments>http://dev.juokaz.com/php/web-scraping-easy-way-to-monitor-market#comments</comments>
		<pubDate>Sat, 14 Feb 2009 15:54:52 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[legal iseus]]></category>
		<category><![CDATA[prices]]></category>
		<category><![CDATA[rivals]]></category>
		<category><![CDATA[spider]]></category>
		<category><![CDATA[ssssscpripting]]></category>
		<category><![CDATA[web crawler]]></category>
		<category><![CDATA[web scraper]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=145</guid>
		<description><![CDATA[Sssssssscripting blog yesterday wrote about writing your own web crawler (in Ruby) and I immediately remember that I have done similar projects in past. Only difference is, I had developed web scrappers which were used to monitor e-commerce websites market. Believe me, when you run online shop, having ability to look at rivals prices in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://ssscripting.wordpress.com/">Sssssssscripting</a> blog yesterday wrote about <a href="http://ssscripting.wordpress.com/2009/02/13/how-to-write-a-spider/">writing your own web crawler</a> (in Ruby) and I immediately remember that I have done similar projects in past. Only difference is, I had developed web scrappers which were used to monitor e-commerce websites market. Believe me, when you run online shop, having ability to look at rivals prices in simple way is priceless.</p>
<p><a href="http://en.wikipedia.org/wiki/Web_scraping">Web scrapers</a> which I wrote were not very dynamic &#8211; everyone of them was made for specific website. It may seem not very good practice, but having different spiders for different sites helps a lot &#8211; source code is dramatically simpler and tweaking one doesn&#8217;t affect others.</p>
<p>Currently, I have two spiders running every week (they have been running for half year). They have one task: go to website X and get all information about products they sell. Products price is most valuable information, so I cache it for later use (for information &#8220;price on other stores&#8221;, etc.).</p>
<p>Generally, writing web scraper is not very hard if you know how to write <a href="http://uk2.php.net/manual/en/book.pcre.php">regexp</a>&#8217;s fast (currently running web scrappers are only 100 lines each). Getting information from website is extremely easy if you know how to use regular expressions &#8211; website structure doesn&#8217;t change frequently, so correctly written expressions can last years. Or until server administrator blocks you, but if you really need this information, you can use N anonymous proxies.</p>
<p>Creating such spider involves analysing website structure and HTML source code &#8211; web scraper is basically &#8220;automatic copy paste&#8221; so if you know where to search for information in website, then you can simulate it code. For example, pseudo-code for price getting spider could look like this:</p>
<pre>foreach category in categories
   goto category page
       pages = get {category} pages list
       foreach page in pages
           information = extract products from {pages}</pre>
<p>Some people may think that it&#8217;s not legal. Probably it is. If you look at Legal issues in <a href="http://en.wikipedia.org/wiki/Web_scraping">this</a> article, you will find that:</p>
<blockquote><p>Web scraping may be against the terms of use of some websites. The enforceability of these terms is unclear.</p></blockquote>
<p>In my opinion, web scraping should be treated as legal thing if and only if you don&#8217;t directly use scraped information in your website. Scraping news, blog entries, etc. and showing them in your site is bad thing, but scraping information and using it somewhere in your back-end script is perfectly legal by me. What do you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/web-scraping-easy-way-to-monitor-market/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Easy javascript packing with PHP</title>
		<link>http://dev.juokaz.com/php/easy-javascript-packing-with-php</link>
		<comments>http://dev.juokaz.com/php/easy-javascript-packing-with-php#comments</comments>
		<pubDate>Thu, 05 Feb 2009 00:14:00 +0000</pubDate>
		<dc:creator>Juozas</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[packed]]></category>
		<category><![CDATA[requests]]></category>
		<category><![CDATA[website speed]]></category>

		<guid isPermaLink="false">http://dev.juokaz.com/?p=24</guid>
		<description><![CDATA[&#8220;JavaScript packing&#8221; is method for reducing JavaScript files size by removing all unnecessary data (obfuscating) and compressing it&#8217;s contents. Most popular is Dean Edward&#8217;s packer, which transforms JavaScripts into something like this:

eval&#40;function&#40;p,a,c,k,e,r&#41;&#123;...

To start with, it&#8217;s very easy to have dynamically packed files (no one wants to pack them by hand, packed versions are only useful [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;JavaScript packing&#8221; is method for reducing JavaScript files size by removing all unnecessary data (<em>obfuscating</em>) and compressing it&#8217;s contents. Most popular is <a href="http://dean.edwards.name/packer/">Dean Edward&#8217;s packer</a>, which transforms JavaScripts into something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">eval</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>p<span style="color: #339933;">,</span>a<span style="color: #339933;">,</span>c<span style="color: #339933;">,</span>k<span style="color: #339933;">,</span>e<span style="color: #339933;">,</span>r<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>...</pre></div></div>

<p>To start with, it&#8217;s very easy to have dynamically packed files (no one wants to pack them by hand, packed versions are only useful for production, debugging them is harder) with PHP. One of many PHP packers is available on-line at <a href="http://joliclic.free.fr/php/javascript-packer/en/">http://joliclic.free.fr/php/javascript-packer/en/</a>. It&#8217;s simple one-file script which works really well.</p>
<p>JavaScript packing is as simple as:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'class.JavaScriptPacker.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$src</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'my_script.js'</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Script file</span>
<span style="color: #000088;">$script</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$src</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$packer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JavaScriptPacker<span style="color: #009900;">&#40;</span><span style="color: #000088;">$script</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Normal'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$packed</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$packer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pack</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #990000;">header</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: text/javascript; charset=utf-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-Length: &quot;</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$packed</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$packed</span><span style="color: #339933;">;</span></pre></div></div>

<p><em>* Parameters for JavaScriptPacker object can be easily tested in project <a href="http://joliclic.free.fr/php/javascript-packer/en/">website</a>. </em><em>Sometimes packed javascripts don&#8217;t work because of missing &#8220;;&#8221; symbols. I used <a href="http://www.getfirebug.com">FireBug</a> extension for Firefox to find actual problematic lines in unpacked version and correct them. </em></p>
<p>Using this class I created controller for all my JavaScripts, which gets JavaScript name from GET call, checks for cached version and if packed version is not cached &#8211; creates <em>1 day</em> cache and outputs it. Also, I pass JavaScript name in special form: &#8220;filename1-filename2-&#8230; .js&#8221; what let&#8217;s me merge multiple files into one packed version. (<em>it can be optimized even more by storing cached versions as static files and accessing them directly</em>)</p>
<p>Packer alone cannot make a big difference, but by combining it with:</p>
<ul>
<li>multiple files merging</li>
<li>caching (correct headers)</li>
<li>then packing</li>
<li>putting JavaScripts at the bottom of document</li>
</ul>
<p>gives very good results, not only decreasing HTTP calls count, but also time required to render whole website. Still, it&#8217;s very easy to implement whole system since all required libraries (packer, caching, etc.) are available on-line for free.</p>
]]></content:encoded>
			<wfw:commentRss>http://dev.juokaz.com/php/easy-javascript-packing-with-php/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
