<?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>Andy Thompson</title>
	<atom:link href="http://andytson.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://andytson.com</link>
	<description>Just another Webtatic.com site</description>
	<lastBuildDate>Sun, 29 Apr 2012 11:04:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Daemonising a PHP cli script on a posix system</title>
		<link>http://andytson.com/blog/2010/05/daemonising-a-php-cli-script-on-a-posix-system/</link>
		<comments>http://andytson.com/blog/2010/05/daemonising-a-php-cli-script-on-a-posix-system/#comments</comments>
		<pubDate>Mon, 24 May 2010 14:38:03 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[POSIX]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=30</guid>
		<description><![CDATA[I’ve been researching how to best write a long running PHP script executed on the command-line, and whilst there are Linux commands you can use to daemonise a command, these can also be written into a php script as well. The easiest way to daemonise a command on a posix system is to run: nohup [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been researching how to best write a long running PHP script  executed on the command-line, and whilst there are Linux commands you  can use to daemonise a command, these can also be written into a php  script as well.</p>
<p>The easiest way to daemonise a command on a posix system is to run:</p>
<pre language="BASH">
nohup command &lt; /dev/null &gt; /dev/null 2&gt;&amp;1 &amp;
</pre>
<p><span id="more-30"></span></p>
<p>This simply calls nohup to execute the command, which in effect  disables the SIGHUP signal (used to tell a child its parent terminal is  closing), and backgrounds the process. All standard file descriptors are  set to /dev/null to stop the command from reading/outputting anything  back to the terminal, and so that when the terminal is closed, reads and  writes from stdin/stdout/stderr do not fail.</p>
<p>This is a bit clunky, but the same can be achieved in PHP either by default, or via a command-line argument.</p>
<h3>Daemonise</h3>
<p>First, to achieve backgrounding, you must <a href="http://php.net/manual/en/function.pcntl-fork.php">fork</a> the process as the current process wont be able to background. Forking  will create a new process with the same memory as the parent, which will  carry on on the same line the parent forked on. Then detatch it from  the terminal using <a href="http://php.net/manual/en/function.posix-setsid.php">posix_setsid</a>().</p>
<pre language="PHP">
switch (pcntl_fork()) {
    case -1:
        die('unable to fork');
    case 0: // this is the child process
        break;
    default: // otherwise this is the parent process
        exit;
}
 
if (posix_setsid() === -1) {
     die('could not setsid');
}
</pre>
<p>Next, we will replace the duplicated file descriptors (stdin, stdout  and stderr) with /dev/null. When a standard file descriptor is closed,  it can be replaced with one opened by php. The variables are not  important, just the ordering of the fopen calls.</p>
<pre language="PHP">
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
 
$stdIn = fopen('/dev/null', 'r'); // set fd/0
$stdOut = fopen('/dev/null', 'w'); // set fd/1
$stdErr = fopen('php://stdout', 'w'); // a hack to duplicate fd/1 to 2
</pre>
<p>You may want to switch stderr to a log file instead e.g.  fopen(‘/path/to/errorlog’, ‘a’). PHP errors will output to this file as  they happen.</p>
<p>Lastly SIGHUP, along with a few additional terminal signals, can be ignored by the process:</p>
<pre language="PHP">
pcntl_signal(SIGTSTP, SIG_IGN);
pcntl_signal(SIGTTOU, SIG_IGN);
pcntl_signal(SIGTTIN, SIG_IGN);
pcntl_signal(SIGHUP, SIG_IGN);
</pre>
<p>So that gives us the basic daemonising effect. The terminal can now  be closed, and the process will continue to run until terminated either  internally or externally.</p>
<h3>Single Instance</h3>
<p>Now with most daemon programs you want to make sure that there can be  only one instance, and that instance can be tracked for termination  later. To do this we can use a locked file that contains the process id.  If the file is locked for write, the daemon is running, otherwise it  isn’t. Also the file can be read by other scripts to get the process id,  which can be used to send signals to the process.</p>
<p>This you would do before any other code.</p>
<pre language="PHP">
$lock = fopen('/path/to/pid', 'c+');
if (!flock($lock, LOCK_EX | LOCK_NB)) {
    die('already running');
}
 
switch ($pid = pcntl_fork()) {
    case -1:
        die('unable to fork');
    case 0: // this is the child process
        break;
    default: // otherwise this is the parent process
        fseek($lock, 0);
        ftruncate($lock, 0);
    	fwrite($lock, $pid);
        fflush($lock);
        exit;
}
</pre>
<p>The lock will prevent another script from continuing. Once the script  terminates, the lock will automatically be released allowing the script  to be called again.</p>
<h3>The full code</h3>
<p>The end result is as follows:</p>
<pre language="PHP">
$lock = fopen('/path/to/pid', 'c+');
if (!flock($lock, LOCK_EX | LOCK_NB)) {
    die('already running');
}
 
switch ($pid = pcntl_fork()) {
    case -1:
        die('unable to fork');
    case 0: // this is the child process
        break;
    default: // otherwise this is the parent process
        fseek($lock, 0);
        ftruncate($lock, 0);
    	fwrite($lock, $pid);
        fflush($lock);
        exit;
}
 
if (posix_setsid() === -1) {
     die('could not setsid');
}
 
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
 
$stdIn = fopen('/dev/null', 'r'); // set fd/0
$stdOut = fopen('/dev/null', 'w'); // set fd/1
$stdErr = fopen('php://stdout', 'w'); // a hack to duplicate fd/1 to 2
 
pcntl_signal(SIGTSTP, SIG_IGN);
pcntl_signal(SIGTTOU, SIG_IGN);
pcntl_signal(SIGTTIN, SIG_IGN);
pcntl_signal(SIGHUP, SIG_IGN);
 
// do some long running work
sleep(300);
</pre>
<p>To see the replaced file descriptors have a look at the process’ proc entry.</p>
<pre language="BASH">
ls -al /proc/`cat /path/to/pid`/fd
 
total 0
dr-x------ 2 root root  0 May 23 09:41 .
dr-xr-xr-x 5 root root  0 May 23 09:34 ..
lr-x------ 1 root root 64 May 23 09:41 0 -&gt; /dev/null
l-wx------ 1 root root 64 May 23 09:41 1 -&gt; /dev/null
l-wx------ 1 root root 64 May 23 09:41 2 -&gt; /dev/null
lrwx------ 1 root root 64 May 23 09:41 3 -&gt; /path/to/pid
</pre>
<p>Here is a script that will then kill this daemon:</p>
<pre language="PHP">
$lock = fopen('/path/to/pid', 'c+');
if (flock($lock, LOCK_EX | LOCK_NB)) {
	die('process not running');
}
$pid = fgets($lock);
 
posix_kill($pid, SIGTERM);
</pre>
<h3>How about Windows?</h3>
<p>None of the versions of Windows support the posix api, however Microsoft have provided a <a href="http://en.wikipedia.org/wiki/Windows_service">service architecture</a> in all versions of Windows since XP. There is a PECL module <a href="http://docs.php.net/manual/en/win32service.installation.php">win32service</a>, which can help you with dealing with setting up and controlling a PHP service. An <a href="http://docs.php.net/manual/en/win32service.examples-service.php">example</a> can be seen in the PHP.net documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/05/daemonising-a-php-cli-script-on-a-posix-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Travelling Elephpant challenge, my two solutions</title>
		<link>http://andytson.com/blog/2010/05/travelling-elephpant-solutions/</link>
		<comments>http://andytson.com/blog/2010/05/travelling-elephpant-solutions/#comments</comments>
		<pubDate>Mon, 17 May 2010 12:47:41 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[elephpant]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=7</guid>
		<description><![CDATA[Ibuildings, a PHP development company with offices in the Netherlands, UK and Italy, have been running a series of challenges, with prizes such as iPads and tickets to the Dutch PHP Conference (DPC, of which they host). The latest completed challenge, the Elephpant challenge, was in the form of a code contest to write the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ibuildings.com/">Ibuildings</a>, a PHP development company with offices in the Netherlands, UK and Italy, have been running a series of <a href="http://ibuildings.com/challenge/">challenges</a>, with prizes such as iPads and tickets to the <a href="http://phpconference.nl/">Dutch PHP Conference</a> (DPC, of which they host). The latest completed challenge, the <a href="http://techportal.ibuildings.com/2010/05/17/the-elephpant-challenge-winners-and-results/">Elephpant challenge</a>, was in the form of a code contest to write the fastest, shortest and least complex algorithm in PHP to solve a <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">Travelling Salesman problem</a>.</p>
<p>I’m happy to say that I was one of the winners for this task, getting  30 points (10 in each scoring method), which was the maximum points  possible, for the medium category (people with 2 to 4 years experience),  and winning a ticket to the DPC.</p>
<p>Here I will describe the two solutions I researched and completed. I  only submitted the one which I thought would give me the biggest chance  of winning, but each had their own specialities.</p>
<p><span id="more-7"></span></p>
<p><img src="/files/2010/05/elephpant.jpg" alt="" width="500" height="333" /><br />
Picture under <a href="http://creativecommons.org/licenses/by-nc/2.0/deed.en_GB">Creative Commons Attribution Non-commercial license</a> by <a href="http://www.flickr.com/photos/drewm/3191872515/in/pool-elephpants">drewm</a> on Flicker.</p>
<p>First, to understand the problem you must research TSP. There are two  types of algorithms, exact and approximate, and a TSP can be asymetric  (costs different depending on the direction of travel) or symetric. In  the challenge I needed a <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem#Exact_algorithms">exact symetric algorithm</a>, of which Wikipedia briefly mentions several different algorithms.</p>
<p>I picked the two most promising algorithms, one based on dynamic  programming, and one branch and bound algorithm. The former being  shorter and least complex, and the latter being faster and more  scalable.</p>
<h3>Dynamic Programming</h3>
<p>I wont go into too much detail of this one. Although it was the one I  picked to submit for the competition it is in fact extremely simple,  based on a single premise that a optimal tour can be calculated by  finding the minimum tour length of each unvisited node added to the  optimal subtour of the remaining nodes. It is recursive in nature,  dividing up into smaller subtours until there is a single cost for  traveling from one node to another.</p>
<p>Where i is the last landmark and S is the set of landmarks excluding the first and last.</p>
<p>This I managed to write in a total of 33 (PHP_CodeCoverage) / 38  (result) lines of executable code, a C.R.A.P index of 6 (as Ivo mentions  in the comments, my result would have been in fact 4 for his  calculations), and according to the Ibuildings test a time of 333  seconds. I however recorded the speed at 54 seconds on my laptop (not  particularly high spec) with xdebug disabled.</p>
<p><a href="http://andytson.com/files/2010/05/contest.php">Here is the solution</a>,  of which I have fully commented. Please consider this script with  having a New BSD license if you wish to use a derivative of it.</p>
<h3>Branch and bound</h3>
<p>Wikipedia mentions branch and bound algorithms in relation to TSP as  being the best algorithm short of cutting-plane algorithms. I ignored  the latter due to lack of information found in my research, and the  likelyhood of it being much too complex for the challenge.</p>
<p>Branch and bound algorithms, it states as being an improvement in  speed over other algorithms such as the dynamic programming one above.  It can handle a lot more landmarks on top of this, however the challenge  only needed to visit a total of 12 landmarks (including the start and  end nodes).</p>
<p>When first testing the dynamic programming algorithm, I found it to  be much too slow, and wanted to try a branch and bound algorithm to  compete with it. This proved challenging and much harder to research and  understand. I finally came across an <a href="http://lcm.csa.iisc.ernet.in/dsa/node187.html">extremely helpful web page</a> describing a mathematical description of an algorithm.</p>
<p>When writing a branch and bound algorithm, it is important to select a  good function to calculate the lower bound (something that is lower  cost or equal to the best solution). If a tour is found to be the best  calculated so far, all branches with higher lower bounds can be  discarded.</p>
<p>The lower bound I used was simply based on the premise that the best  tour is the sum of the edges of the tour, and therefore the lower bound  must be equal to or less than this.</p>
<p>The rest of the algorithm is to choose the branches, add constraints  that better select the lower bound, and check through them, picking each  edge one at a time, testing whether to include or exclude it from the  list of edges that make up the lower bound. Eventually enough edges will  be included to get a tour. This I leave for you to read in the article I  mentioned.</p>
<p>Now when I had written this, there were several slow areas, such as  calculating the lower bound, and checking to eliminate subtours (tours  that do not go through every point, but form clusters of smaller tours).  As the article didn’t go into detail on how to do this, I had to come  up with an inovative fast check. I researched subtour elimination, and  came across <a href="http://www.tsp.gatech.edu/methods/opt/subtour.htm">this article</a>, which although did not give the exact answer in a way I could understand, gave me an idea.</p>
<p>My previous subtour checks were scanning through the list of included  nodes, tracing each path to see if it went back to the start or was too  short. This was slow (although twice the speed of my dynamic  programming algorithm). My idea was to instead track each cluster of  joined edges as they get added, and check the constraints on the ones  affected by the addition, making sure they didn’t hit the required edge  count for each node without completing a full tour.</p>
<p>This proved to be much faster, totalling a time of 20 seconds to  calculate the best tour, however the end result was a large amount of  code, with many functions, loops and if checks. I’d have been lucky to  get 10 points with an attempt at the fastest algorithm. Anyone who  scored less than me in each section (speed, lines of code, and  complexity) could have scored better. So it was back to optimising the  dynamic programming algorithm above for me.</p>
<p>The <a href="http://andytson.com/files/2010/05/contest-bab.php">solution can be seen here</a>, which also I will license under New BSD. Sorry that there are no comments in the code at the moment.</p>
<h3>Speed, lines of executable code and complexity</h3>
<p>These were the categories of scoring, which award 10 points for each.</p>
<p>Speed varies a lot with algorithms, and the choice could lead to 0  points if choosing a brute force search, or 10 if choosing the best  algorithm. I’d recommend anyone who tries to then optimise the code  should make use of <a href="http://xdebug.org/docs/profiler">xdebug’s profiler</a> to see which bits of code are sub-optimal. Trying to optimise the code  without this is just a guessing game, and you may end up wasting time  changing code that cannot be optimised further.</p>
<p>Lines of executable code I don’t consider the most important aspect  of programming, but it does add to complexity in maintaining code, and  shorter code can often be easier to understand. In a challenge, however,  it can easily be abused at the expense of readability.</p>
<p>Complexity was calculated using a similar method to <a href="http://sebastian-bergmann.de/archives/877-CRAP-in-PHPUnit-3.5.html">Change Risk Analysis and Predictions</a> (CRAP) index. This was new to me as I had not come across it before. It  is calculated based on the code coverage of a piece of code and the  number of code branches in the code (functions, ifs, loops, logical ands  and ors etc). This can also be abused to a point. As you can see in my  winning code, when printing out a list of the landmarks for the best  tour, I chose rather than to write a foreach to loop through and print  out the names of the landmarks, I wrote a single line function to splice  the landmarks names onto an ordered list of identifiers.</p>
<h3>Conclusion</h3>
<p>In the end I submitted my first solution, which ended up winning as I  had hoped. The effort gone into the second solution I don’t consider  wasted even if it was not quicker than the results. It has the  capability to run on a much larger set of landmarks with a good time,  although not good enough to <a href="http://www.tsp.gatech.edu/sweden/">tour Sweden</a>.</p>
<p>As for the <a href="http://techportal.ibuildings.com/2010/05/17/the-elephpant-challenge-winners-and-results">challenge results</a>,  you can see that this was a difficult challenge. None of the entries  with the 0-2 years work experience fit the requirements, and even in my  category many people failed the test.</p>
<p>One thing I must consider is that in a few months I’ll no longer be  in the medium category, and challenges such as this will be much more  competitive. I have already completed Ibuildings next challenge, and it  may be the last before I can only enter into the senior category.</p>
<p>I congratulate the winner for the senior category, Michiel  Brandenburg, winning the iPad, who scored 26. 10 for both lines of code  and complexity, and 6 for being the 3rd fastest in his category (which  was faster than mine as well).</p>
<p>Also, thanks to Ibuildings for running this challenge. I found it  both interesting and challenging. Ibuildings have already started a <a href="http://ibuildings.com/challenge/">new challenge you can enter</a> into, based on Test Driven Development.</p>
<p>For any of you reading who are going to the Dutch PHP Conference, I hope to see you there <img src="http://andytson.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" /></p>
<p>Now all I need is to somehow win my own stuffed elephpant to complete my own journey from London to the DPC.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/05/travelling-elephpant-solutions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Page-level caching with Nginx</title>
		<link>http://andytson.com/blog/2010/04/page-level-caching-with-nginx/</link>
		<comments>http://andytson.com/blog/2010/04/page-level-caching-with-nginx/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 23:22:54 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Nginx]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=76</guid>
		<description><![CDATA[Since my last post on using Nginx to cache proxied content, they have added proper cache handling via their proxy_cache* directives. These are much more suitable for use, as they capture the HTTP response headers and also use more advanced Cache-Control checks. To start, install the latest stable Nginx avaliable at http://wiki.nginx.org/NginxInstall. Next edit your [...]]]></description>
			<content:encoded><![CDATA[<p>Since my <a href="http://andytson.com/blog/2008/04/page-level-caching-with-nginx/">last post</a> on using <a href="http://wiki.nginx.org/Main">Nginx</a> to cache proxied content, they have added proper cache handling via  their proxy_cache* directives. These are much more suitable for use, as  they capture the HTTP response headers and also use more advanced  Cache-Control checks.</p>
<p>To start, install the latest stable Nginx avaliable at <a href="http://wiki.nginx.org/NginxInstall">http://wiki.nginx.org/NginxInstall</a>.</p>
<p><span id="more-76"></span></p>
<p>Next edit your nginx.conf  and add the proxy_cache_path directive to define a named cache storage.  These are independant of servers and locations, and can be reused  inside each later on.</p>
<pre>
...
http {
    ...
 
    proxy_cache_path /var/cache/nginx keys_zone=anonymous:10m;
 
    include vhosts/*.conf
}
</pre>
<p>Next create the directory for the cache:</p>
<pre>mkdir -p /var/cache/nginx</pre>
<p>Next define your server configuration, which can be done for example  in conf/vhosts/example.com.conf if you defined the include above.</p>
<pre>server {
    listen            80;
    servername        example.com;
 
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  Host       $host;
 
    location / {
        proxy_pass    http://localhost:8080/;
        proxy_cache   anonymous;
    }
 
    # don't cache admin folder, send all requests through the proxy
    location /admin {
        proxy_pass    http://localhost:8080/;
    }
 
    # handle static files directly. Set their expiry time to max, so they'll
    # always use the browser cache after first request
    location ~* (css|js|png|jpe?g|gif|ico)$ {
        root          /var/www/${host}/http;
        expires       max;
    }
}
</pre>
<p>As we don’t want the nginx worker processes to have root permissions when in use, add to the start of conf/nginx.conf:</p>
<pre>user nginx
 
...
</pre>
<p>Then sort out the user and permissions:</p>
<pre>
useradd nginx
chown nginx:nginx /var/cache/nginx /usr/local/nginx/{fastcgi_temp,logs,proxy_temp}
</pre>
<p>To start nginx on bootup, add the following to the end of /etc/rc.local:</p>
<pre>/usr/local/nginx/sbin/nginx</pre>
<p>Then also run this command to start nginx now.</p>
<p>That is all that is needed, no patches this time. There are several  more proxy_cache* directives avaliable that you can use to tweak its  behaviour, see the <a href="http://wiki.nginx.org/NginxHttpProxyModule#proxy_cache">proxy module documentation</a> for more details.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/04/page-level-caching-with-nginx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OData, a RESTful contender for your API</title>
		<link>http://andytson.com/blog/2010/03/odata-a-restful-contender-for-your-api/</link>
		<comments>http://andytson.com/blog/2010/03/odata-a-restful-contender-for-your-api/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 13:37:22 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Web Services]]></category>
		<category><![CDATA[OData]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[RPC]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=20</guid>
		<description><![CDATA[OData is a new API protocol that has recently been released by Microsoft, along with the launch of their new site on the 16th March 2010. It is a RESTful standard, which adds a lot of its own goods to the table. As a RESTful standard, it exposes a web service in the form of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.odata.org/">OData</a> is a new API protocol that  has recently been released by Microsoft, along with the launch of their  new site on the 16th March 2010. It is a <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>ful standard, which adds a lot of its own goods to the table.</p>
<p>As a RESTful standard, it exposes a web service in the form of  resources accessible via discrete HTTP urls, representing actions via  the HTTP methods. It fills in the gaps that the REST style of  architecture leaves open, giving a full specification, from the request  to the response (although omitting authentication and authorisation).  OData surprisingly also allows <a href="http://www.odata.org/developers/protocols/operations#InvokingServiceOperations">RPC-style operations as well</a>.</p>
<p><span id="more-20"></span></p>
<p>In essence, OData is as to RESTful service style as <a href="http://www.w3.org/TR/soap/">SOAP</a> is to RPC. Before this, I had a hard time taking REST seriously, given  the lack of protocol specifications meaning that each implementation of a  RESTful service tends to handle things differently.<br />
It also includes features that make it much more ready for the enterprise environment, supporting:</p>
<ul>
<li><a href="http://www.odata.org/media/5986/%5Bmc-edmx%5D.htm">a service definition language</a></li>
<li>error message formatting – missing from the documentation at the moment</li>
<li><a href="http://www.odata.org/developers/protocols/uri-conventions#InlinecountSystemQueryOption">dataset paging</a></li>
<li><a href="http://www.odata.org/developers/protocols/uri-conventions">advanced queries</a></li>
<li><a href="http://www.odata.org/developers/protocols/batch">batch requests</a></li>
</ul>
<p>There are two request and response body formats which are supported, <a href="http://bitworking.org/projects/atom/rfc5023.html">AtomPub</a> and <a href="http://www.json.org/">JSON</a>.</p>
<h3>Features</h3>
<p>Providing a web-service description language, it allows automatic  creation of proxy classes for clients to quickly consume with little  knowledge of the service. It also allows a level of client-side  validation of a request before it is sent out.</p>
<p>If an error occurs, as with the REST architecture style, OData producers will use <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP error statuses</a> 4xx/5xx to notify of an error, however this information is not usually  enough to help the consumer bug fix, so OData defines an error message  specification which is sent in the response body.</p>
<p>A frequent problem faced when building a web-service that lists  entries is that it becomes a problem when the number of entries gets  large. Asside from the fact that not all HTTP servers are built for long  streams of data, the consumer does not need all of that information at  once, so paging is required to limit the response. OData defines this  ability in its specification.</p>
<p>Web services in a REST architecture tend to have limited  functionality in an individual request. As such, additional resources  are needed to define complex transactions. This means that the  web-service needs multiple calls to different resource actions. OData  improves this by allowing multiple calls to be batched into one request,  removing the HTTP overhead associated.</p>
<h3>GData protocol</h3>
<p>If you have ever used any of Google’s API’s you may think this sounds very similar to the <a href="http://code.google.com/apis/gdata/">Google GData protocol</a>,  which has similar features. Google released the GData protocol for  access to it’s services, such as Calendar, Docs, and YouTube API.</p>
<p>GData is really only pushed as a protocol to be consumed for Google’s  services, however OData appears to be an attempt to open the server  side of the protocol for other companies to use, providing much more for  developers who wish to develop a OData producer, including .Net  libraries to help expose data in the protocol.</p>
<h3>OData SDK</h3>
<p>Microsoft has also provided as part of it’s OData SDK, along with the  .Net server libraries, client libraries for most major languages  (Javascript, PHP, Java, Objective-C, Silverlight, and obviously .Net),  so is ready immediately for several of Microsoft’s services, including  Azure.</p>
<p>Aside from the disappointment of no PHP server libraries for this (of  which I may try to rectify myself by creating my own), the new  web-service protocol appears to be the best thing since SOAP, if not  better, and may even replace it as my prefered choice in web-service  development.</p>
<p>See more information at:</p>
<ul>
<li><a href="http://www.odata.org/">http://www.odata.org/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/03/odata-a-restful-contender-for-your-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Techniques for creating a secure shared web server</title>
		<link>http://andytson.com/blog/2010/01/techniques-for-creating-a-secure-shared-web-server/</link>
		<comments>http://andytson.com/blog/2010/01/techniques-for-creating-a-secure-shared-web-server/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 13:05:54 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[mod_apparmor]]></category>
		<category><![CDATA[mpm-itk]]></category>
		<category><![CDATA[open_basedir]]></category>
		<category><![CDATA[suEXEC]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=12</guid>
		<description><![CDATA[Here are several techniques for creating a secure shared web server. Update 2010-03-14 – Revised opinion about APC and eAccellerator, which possibly do use memory-mapped files, also added detail about mpm_worker not working with mod_apparmor. PHP open_basedir ini setting PHP provides this setting in order to limit the access of functions which use PHP’s fopen [...]]]></description>
			<content:encoded><![CDATA[<p>Here are several techniques for creating a secure shared web server.</p>
<p><strong>Update 2010-03-14</strong> – Revised opinion about APC and  eAccellerator, which possibly do use memory-mapped files, also added  detail about mpm_worker not working with mod_apparmor.</p>
<p><span id="more-12"></span></p>
<h3>PHP open_basedir ini setting</h3>
<p>PHP provides this setting in order to limit the access of functions  which use PHP’s fopen to a specified directory. PHP extensions may not  always use this, instead using the standard fopen, which wont be  protected. Shell functions, such as exec, will also be unable to  restrict external programs, so should be disabled.</p>
<p>If you are using mod_php, you will need to use php_admin_value rather  than php_value, as .htaccess files can override php_value or php.ini  settings:</p>
<pre>
&lt;vhost *:80&gt;
...

php_admin_value open_basedir /path/to/project
&lt;/vhost&gt;
</pre>
<h3>suEXEC CGI/suPHP</h3>
<p>This technique involves the use of setuid, which allows the  super-user to change to any other user. The way suEXEC does this is  providing a program with the user sticky bit set. With the right  configuration, Apache will call this, passing in a script to execute,  and the user and group id for which to run from.</p>
<p>Suexec will check a few conditions against it’s compiled settings,  such as the base directory from which scripts are allowed to run from,  and directory permissions. If these pass, it will execute the script.</p>
<p>Using suExec in CGI mode, or when using suPHP, you will get the same  disadvantages of using CGI normally, and so would not be suitable for a  server.</p>
<h3>suEXEC FCGI</h3>
<p>suEXEC can also initialise a program supporting FastCGI, allowing  better utilisation of resources. The FastCGI server can then be  connected to from Apache. It does not have the benefit of Apache’s  process pooling, and you may not be able to modify the FastCGI pool once  running.</p>
<p>For more information check out <a href="http://blog.chty.org/post/2007/10/28/Apache2-mod_fastcgi-suexec-on-debian-etch">this blog post</a> on setting it up.</p>
<h3>mpm_itk</h3>
<p><a>mpm_itk</a> is an Apache process model based on mpm_prefork, which  instead runs its master process as root, giving it the ability to fork  and setuid Apache itself. This gives many advantages over the above  techniques, allowing use of any Apache modules and process pooling.</p>
<p>It however has a tradeoff. Firstly, the connection is established by a  process running as super-user. This, the module’s creator mentions,  would be a problem if there was a mod_ssl security hole.</p>
<p>Secondly, since processes using setuid cannot return to super-user,  the only realistic possibility is to terminate the fork. From a  performance viewpoint of forking and terminating, this isn’t a big deal,  however there is no way to persist modified shared memory between  requests, as forks <a href="http://en.wikipedia.org/wiki/Copy-on-write">copy-on-write</a>. Memory-mapped file support should still work, as well as regular file caching.</p>
<p>To use, install the mpm-itk, and add the configuration to your vhost:</p>
<pre>&lt;vhost *:80&gt;
...

AssignUserID myproject-apache myproject-apache
&lt;/vhost&gt;
</pre>
<p>For more information checkout the <a href="http://mpm-itk.sesse.net/">mpm-itk project page</a>.</p>
<h3>mod_apparmor</h3>
<p>This is an Apache module which comes with <a href="http://forge.novell.com/modules/xfmod/project/?apparmor">AppArmor</a>.  AppArmor is a kernel-level access control module, which allows  processes to run under different configurations (called hats).  mod_apparmor can change the hat a vhost is running under, giving  kernel-level access control to all calls to files to all Apache modules.</p>
<p>This, unlike mpm-itk, isn’t restricted to a request fork and terminate processing model, so should work on more Apache2 mpms.</p>
<p>Mpm_worker, however will have problems with changing hats per  process, as multiple requests to different vhosts share the same hat, so  mod_apparmor shouldn’t be used. This doesn’t stop you from just using  AppArmor by itself to provide a global policy.</p>
<pre>&lt;vhost *:80&gt;
...

AAHatName MY_HAT_NAME
&lt;/vhost&gt;
</pre>
<p>See the following link for more information on using mod_apparmor and configuring hats for it: <a href="http://www.mpipks-dresden.mpg.de/%7Emueller/docs/suse10.3/opensuse-manual_de/manual/bx5dh07.html">5.2. Configuring Apache for mod_apparmor</a></p>
<p>As mentioned, mod_apparmor needs AppArmor to be compiled into the  kernel, which may rule out some Linux distributions. Distributions like  Ubuntu have AppArmor integrated into their kernel, so if compiling your  kernel is not an option, you could switch distribution.</p>
<h3>Conclusion</h3>
<p>mod_apparmor may be the best option for a secure shared web server,  as it would seem the most secure whilst allowing shared cache modules to  work correctly, which give languages like PHP a huge boost in  performance.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/01/techniques-for-creating-a-secure-shared-web-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Minimous – Posterous’ minimalist look in WordPress</title>
		<link>http://andytson.com/blog/2010/01/minimous-posterous-minimalist-look-in-wordpress/</link>
		<comments>http://andytson.com/blog/2010/01/minimous-posterous-minimalist-look-in-wordpress/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 13:30:54 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Content management and blogs]]></category>
		<category><![CDATA[Posterous]]></category>
		<category><![CDATA[theme]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=16</guid>
		<description><![CDATA[If you’ve ever searched for a WordPress theme on WordPress.org, you’ve probably found that none of them are suitable for your personal blog. Most tend to be complex designs that you’re sure someone created with a specific look in mind, but they don’t suit you. A friend from work mentioned something similar almost 6 months [...]]]></description>
			<content:encoded><![CDATA[<p>If you’ve ever searched for a WordPress theme on WordPress.org,  you’ve probably found that none of them are suitable for your personal  blog. Most tend to be complex designs that you’re sure someone created with a specific look in mind, but they don’t suit you.</p>
<p>A friend from work mentioned something similar almost 6 months ago, so when she tweeted a suggestion to design something like the Posterous look (it’s a very nice simple but popular look), I offered to help, figuring it would take no time at all to create something similar in WordPress.</p>
<p><span id="more-16"></span></p>
<p>So I copied the Kubrick theme and stripped out the styles, adding new  ones in place, and 15 minutes later I had something beginning to take  shape to show. In the end it took me about 2 hours, having never written  a WordPress theme before, to get it to what it largely looks like now.</p>
<p>I submitted it to the WordPress.org theme directory, and a couple of weeks later it was <a href="http://wordpress.org/extend/themes/minimous">approved</a> and many people started downloading it. WordPress.org lists new and updated themes on the <a href="http://wordpress.org/extend/themes/">theme portal</a> front page, giving them a much needed boost in promotion until they fall off those lists (“Newest Themes” about 1.5 weeks at the time, and “Updated Themes” about a day or two).</p>
<p>Since then, people have tweeted, blogged, and even contacted me on Facebook about the theme. It has now had over 2000 downloads.</p>
<p>One thing that I regret is not having put a link in the footer in the  initial release (missing almost 1000 of the first downloads). When I had added that, I could easily see who’s using the theme.</p>
<p>As for what the theme looks like, you’re looking at it right now.  Unless of course you are reading this in the future and I’ve changed the theme for some reason, in which case you could <a href="http://wp-themes.com/minimous/">preview the theme on WordPress.org</a>. I’ve written a web page describing how to sort out the sidebar <a href="http://www.webtatic.com/projects/minimous/">over here</a>, so be sure to check that out if you are thinking of using the theme.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/01/minimous-posterous-minimalist-look-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Justifying your choice in web service infrastructure</title>
		<link>http://andytson.com/blog/2010/01/justifying-your-choice-in-web-service-infrastructure/</link>
		<comments>http://andytson.com/blog/2010/01/justifying-your-choice-in-web-service-infrastructure/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 13:44:32 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Web Services]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[SOAP]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=24</guid>
		<description><![CDATA[First up, there is no silver bullet in building a web service infrastructure. There are two prevailant types, however, that you should ideally be choosing from: RPC (remote procedure call) – e.g. SOAP, XML-RPC REST (Representational state transfer) – e.g. umm? REST? What I strongly suggest is using one of these, and not designing your [...]]]></description>
			<content:encoded><![CDATA[<p>First up, there is no silver bullet in building a web service  infrastructure. There are two prevailant types, however, that you should  ideally be choosing from:</p>
<ul>
<li>RPC (remote procedure call) – e.g. SOAP, XML-RPC</li>
<li>REST (Representational state transfer) – e.g. umm? REST?</li>
</ul>
<p>What I strongly suggest is using one of these, and not designing your  own protocol, or proprietry XML straight-up. As for which you should  choose…</p>
<p><span id="more-24"></span></p>
<h3>REST</h3>
<p>One thing you’ll notice when developing a REST web service is that  there isn’t an exact specification of the protocol and structure,  however the suggested way is to use discrete urls as resources, and use  HTTP (GET, POST, PUT, DELETE) methods to determine the action to  perform.</p>
<p>Looking at the Twitter API, it instead forgoes the discrete resource  urls and HTTP methods in favour of using verbs in the url to determine  the action to perform on the resource, and just HTTP GET and POST to  determine whether it gets or sets data. This hasn’t stopped it from  being successful however, and its use of “REST” standards has attributed  to the success of many of its third-party sites.</p>
<p>Would that have been true if they had used SOAP instead? Obviously  not, as Twitter can also be used in javascript mashups, which SOAP would  be a big pain to use.</p>
<p>Since the idea in REST is to use the HTTP specification in designing  the implementation, there is only a small amount of error reporting that  can be done using HTTP status codes,  the HTTP methods may not be  enough to represent complex actions, and the input protocol  (application/www-form-urlencoded) is only a simple key-value structure  (sure PHP improves on it with the use of [] to represent  multi-dimensional data, but not all servers and clients are written in  PHP, so this should factor into your decision).</p>
<p>However, the HTTP specification includes extra features such as caching that the web service can be coded to benefit from.</p>
<h3>RPC</h3>
<p>As for RPC web services, I’ll stick to talking about SOAP as its  better featured than others. This instead entirely uses HTTP POST on a  single url (endpoint), and uses verbs that determine actions and  parameters. Yes it can have multiple endpoints, but for simplicity just  consider them as other web services.</p>
<p>This is a protocol with a fixed specification, which can be relied  upon to be the same. Both the request and response are simliarly  structured with a header and body. It even has a specification for error  reporting. Once you’ve seen one SOAP service, you’ve seen them all  (well not exactly, different vendors sadly sometimes have their own  nuances).</p>
<h3>Your choice</h3>
<p>So I’ve already mentioned that there is no silver bullet. Each may be  better suited depending on the situation. But what situtation?</p>
<p>The simplist answer some may jump to conclusions is that SOAP should  be used in inter-application communication and REST for third-parties.  That may be mostly true.</p>
<p>Some points to consider:</p>
<ul>
<li>Where a language has support, SOAP is easier to consume, with a  standardised interface that can allow a language to make calls via a  proxy that acts as if it were a local call.</li>
<li>A language only supplies a HTTP client more often than SOAP (e.g.  Javascript), however a REST client which helps with resource locations  and detecting and decoding the response is rare.</li>
<li>Any web service written in REST could also be written in SOAP,  however the reverse is not as easily done due to the restriction on  request complexity of resources and single-dimensional data</li>
<li>REST is only suitable for sending key -&gt; value pairs as input due  to the nature of its input protocol (application/www-form-urlencoded),  and would need additional resource urls to represent multi-dimensional  and batch data, meaning multiple calls to create, insert and commit as a  single transaction, when SOAP can do that all in one call.</li>
<li>REST is tied to HTTP over the web, however SOAP can be used in  different transports. A bit moot however if you only ever need to  create/consume web services.</li>
<li>REST has additional transport specifications that can be used for  caching and conditional gets. However SOAP can still code this into a  RPC function, or a SOAP header.</li>
<li>SOAP has additional specification extensions such as WSDL and WS-* (too many to list)</li>
</ul>
<h3>Conclusion</h3>
<p>In all, I favour SOAP myself, but then all the web services I have  coded so far I believe to be necissarly complex enough to justify it  over REST. In PHP it is extremely easy to create and consume SOAP using  SoapServer/SoapClient, and it automatically throws SOAP faults as  Exceptions, which I wouldn’t want to live without.</p>
<p>I can see the attraction of REST due to it’s language support and  most services using it support JSON. Zend Framework also makes it easy  to reuse your controllers, which should already be in resource  structure, for serving REST views.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2010/01/justifying-your-choice-in-web-service-infrastructure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recovering a broken Subversion working copy</title>
		<link>http://andytson.com/blog/2009/12/recovering-a-broken-subversion-working-copy/</link>
		<comments>http://andytson.com/blog/2009/12/recovering-a-broken-subversion-working-copy/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 22:28:09 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=49</guid>
		<description><![CDATA[There are times when a Subversion working copy can mess up. This is usually due to human error, for example due to permissions problems or moving files or folders incorrectly These can usually be easily recoverable, although at times it can seem there’s no solution. Here are a few examples and their solutions. Incorrectly deleting [...]]]></description>
			<content:encoded><![CDATA[<p>There are times when a Subversion working copy can mess up. This is  usually due to human error, for example due to permissions problems or  moving files or folders incorrectly</p>
<p>These can usually be easily recoverable, although at times it can  seem there’s no solution. Here are a few examples and their solutions.</p>
<p><span id="more-49"></span></p>
<h3>Incorrectly deleting files/folders without using svn rm</h3>
<p>This will usually result in subversion complaining when you attempt  to commit. The symptom of this is the svn status giving something like:</p>
<pre language="BASH">
!       path/to/missing/file
</pre>
<p>To fix this, simply issue the svn rm command for the file, and Subversion will fix and mark it as deleted.</p>
<h3>Incorrectly moving files/folders without using svn mv</h3>
<p>Sometimes someone may forget to run the subversion move command, and  move files/folders manually. If you attempt to add a file after this,  you will lose the history of the file. If you attempt with a folder, it  will give an error:</p>
<pre language="BASH">
svn: warning: 'path/to/moved/folder' is already under version control
</pre>
<p>The symptom of this is an svn status of:</p>
<pre language="BASH">
?       path/to/moved/folder
!       path/to/old/folder
</pre>
<p>The best solution for this is to simply move it back and run the svn mv command instead.</p>
<h3>Adding a folder with permission problems</h3>
<p>Sometimes either the group or permissions of a folder will be  incorrect. If you add the folder, it will usually issue an error like:</p>
<pre language="BASH">
svn: Can't create directory 'new/folder/.svn': Permission denied
</pre>
<p>Whats worse is that the working copy now registers the folder in a  half-added state. The parent folder metadata says the folder is added,  but the child folder is missing its .svn metadata. The symptom of this  is an svn status of:</p>
<pre language="BASH">
~       new/folder
</pre>
<p>The solution is to first fix the permissions of the folder, then move the folder to a temporary location, and revert the add:</p>
<pre language="BASH">
# first fix the permissions
# ...
 
mv new/folder new/folder2
svn revert new/folder
 
mv new/folder2 new/folder
svn add new/folder
</pre>
<h3>An .svn metadata transplant</h3>
<p>There are sometimes some cases that can’t be explained. The best  solution I’ve found for this is to do a .svn folder lobotomy and restore  with fresh .svn folders. To do this:</p>
<pre language="BASH">
# backup your project in case you run into trouble
cp -Rp /path/to/project /temporary/location
 
# strip out the old .svn folders
find /path/to/project -name .svn -print0 | xargs -0 rm -rf
 
# check out a clean copy
svn co http://repo/location /temporary/location2
 
# move the .svn folders from the clean copy into the correct relative
# place in the <strong>broken</strong> copy
cd /temporary/location2
find . -name .svn -print0 | xargs -0 -I {} mv '{}' '/path/to/project/{}'
 
# remove the clean copy
rm -rf /temporary/location2
</pre>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2009/12/recovering-a-broken-subversion-working-copy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get an “A” in YSlow with Webtatic Optimizer</title>
		<link>http://andytson.com/blog/2009/08/get-an-a-in-yslow-with-webtatic-optimizer/</link>
		<comments>http://andytson.com/blog/2009/08/get-an-a-in-yslow-with-webtatic-optimizer/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 23:14:02 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=72</guid>
		<description><![CDATA[The performance of a website is an important issue. Even fast responding dynamic pages can be hit with problems with sub-optimal static content such as high overhead on many HTTP requests and large javascript/css files. Tools like YSlow, and Google Page Speed help identify these problem areas. Webtatic Optimizer is a tool that can be [...]]]></description>
			<content:encoded><![CDATA[<p>The performance of a website is an important issue. Even fast  responding dynamic pages can be hit with problems with sub-optimal  static content such as high overhead on many HTTP requests and large  javascript/css files. Tools like <a href="http://developer.yahoo.com/yslow/">YSlow</a>, and <a href="http://code.google.com/speed/page-speed/">Google Page Speed</a> help identify these problem areas.</p>
<p><a href="http://www.webtatic.com/projects/optimizer/">Webtatic Optimizer</a> is a tool that can be used to improve these areas, and can help get an almost perfect score.</p>
<p><span id="more-72"></span></p>
<h3>Make fewer HTTP requests</h3>
<p>JavaScript and Css files are naturally loaded individually. Having  multiples of them being used across an entire site, e.g. including the  JQuery library along with your own javascript, adds to the time the user  has to wait for the files to download.</p>
<p>The Optimizer can concatenate these files and store in a new static  file, so loading this instead will mean less requests, resulting in an  “A” in this category. (images may decrease the score if you use many of  them, but I will add in a future release the ability to easily create  CSS sprites which rewrite the css file to accomidate the position of an  image within its sprite).</p>
<h3>Add Expires headers</h3>
<p>Whilst you can force an expiry of X hours in apache, this means that  changes to these files wont be reflected in the browser until the image  has expired. However, browsers cache files based on their entire request  url (including query string), so simply concatenating onto the  referenced url a unique query string that changes when the contents are  modified, is enough to be able to set a year’s expiry whilst changes are  reflected immediately.</p>
<p>The Optimizer does this by rewriting css url() urls, calculating the  last-modified date of the physical file, and appending this onto the  url. There is also a php function helper to do this for static files  included in dynamic pages. With this you can get an “A” in this section.</p>
<h3>Compress components with gzip</h3>
<p>Text-based http requests can be reduced in size significantly using  gzip when the browser supports it as a content encoding. The Optimizer  does this when creating the concatenated files, also creating a gzipped  version at the same time.</p>
<p>This will give an “A” in YSlow.</p>
<h3>Minify JavaScript and CSS</h3>
<p>If a browser is not able to use the gzipped version of a file,  optimized versions of the original JavaScript or CSS can be used  instead. This is done at the same time as concatenating the files, using  JsMin for JavaScript, and a simple CSS minifier, giving you an “A” for  this category in YSlow.</p>
<h3>Example</h3>
<p>Using a configuration such as below, enables the above optimizations to be incorporated into the generated files:</p>
<pre>
[config]
version = 1.0.0
 
[javascript]
config.workingPath = http
defaults.output = site.js
files = "
  + javascript/jquery.min.js
  + javascript/my-javascript.js
"
 
[css]
config.workingPath = http
defaults.output = site.css
files = "
  + css/layout.css
  + css/global/**.css
"
</pre>
<p>The above configuration can passed to the optimizer command-line script:</p>
<pre>optimizer-compile optimizer.ini</pre>
<p>This will concatenate http/javascript/jquery.min.js and  http/javascript/my-javascript.js, minimise it, and store it in  http/site.js and a gzipped version in http/site.js.gz. It will also  concatentate, minify, and rewrite url()’s for http/css/layout.css and  any CSS files in http/css/global and sub-directories, and store it in  http/site.css and a gzipped version in http/site.css.gz.</p>
<h3>Advanced features</h3>
<p>There are much more advanced features that can be configured, which  you can find out more about in the documentation. The Webtatic Optimizer  is a fully extensible library, using plugins and filters to achieve the  above. You can enable/disable any features or can even write your own.</p>
<h3>An example in use</h3>
<p>Using each of the Webtatic Optimizer’s features above, I have managed to get the <a href="https://passport.fubra.com/">Fubra Passport</a>, an authentication gateway and payment system for the sites <a href="http://www.fubra.com/">Fubra Limited</a> runs/is affiliated with, a score of “B”. It fails at getting an “A” as  it doesn’t have a CDN, and cookies are passed for static content.</p>
<p>I will address the latter, along with making it easy to automatically  rewrite local static file urls to a CDN, in a future release.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2009/08/get-an-a-in-yslow-with-webtatic-optimizer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP public key cryptography using OpenSSL</title>
		<link>http://andytson.com/blog/2009/07/php-public-key-cryptography-using-openssl/</link>
		<comments>http://andytson.com/blog/2009/07/php-public-key-cryptography-using-openssl/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 13:27:15 +0000</pubDate>
		<dc:creator>Andy Thompson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webtatic.com/andytson/?p=14</guid>
		<description><![CDATA[Recently I have been handling the security of some sensitive data. I had originally been encrypting/decrypting data with a symmetric-key system using mcrypt for PHP. This was due to the web frontend and the backend existing on the same server. However for security purposes I am now separating the frontend and backend onto different servers, [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been handling the security of some sensitive data. I had originally been encrypting/decrypting data with a <a href="http://en.wikipedia.org/wiki/Symmetric-key_algorithm">symmetric-key system</a> using <a href="http://uk3.php.net/manual/en/function.mcrypt-encrypt.php">mcrypt</a> for PHP. This was due to the web frontend and the backend existing on  the same server. However for security purposes I am now separating the  frontend and backend onto different servers, so that there is no way the  web accessible frontend, whether compromised or not, can get at the  data it inserts into the database.</p>
<p>In order to do this, a asymmetric-key system is needed, such as <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">public-key cryptography</a>. Googling for examples of this in PHP, there doesn’t seem to be any results of this other than the <a href="http://uk3.php.net/manual/en/book.openssl.php">php OpenSSL extension documentation</a>, and systems that try to reinvent the wheel with their own implementations.</p>
<p>Using the PHP OpenSSL extension it is fairly easy to sort out a  secure system for encrypting data with one key that only can be  decrypted with another.</p>
<p><span id="more-14"></span></p>
<p>First, you need to generate your private and public keys. You can either  do this yourself with the openssl command-line application:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># generate a 1024 bit rsa private key, ask for a passphrase to encrypt it and save to file</span>
openssl genrsa <span style="color: #660033;">-des3</span> <span style="color: #660033;">-out</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>privatekey <span style="color: #000000;">1024</span>
 
<span style="color: #666666; font-style: italic;"># generate the public key for the private key and save to file</span>
openssl rsa <span style="color: #660033;">-in</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>privatekey <span style="color: #660033;">-pubout</span> <span style="color: #660033;">-out</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>publickey</pre></div></div>

<p>or programatically using php-openssl:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// generate a 1024 bit rsa private key, returns a php resource, save to file</span>
<span style="color: #000088;">$privateKey</span> <span style="color: #339933;">=</span> <span style="color: #990000;">openssl_pkey_new</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'private_key_bits'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1024</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'private_key_type'</span> <span style="color: #339933;">=&gt;</span> OPENSSL_KEYTYPE_RSA<span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">openssl_pkey_export_to_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$privateKey</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/path/to/privatekey'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$passphrase</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 
<span style="color: #666666; font-style: italic;">// get the public key $keyDetails['key'] from the private key;</span>
<span style="color: #000088;">$keyDetails</span> <span style="color: #339933;">=</span> <span style="color: #990000;">openssl_pkey_get_details</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$privateKey</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">file_put_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/path/to/publickey'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$keyDetails</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'key'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Next, you can load the public key, and encrypt the data:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$pubKey</span> <span style="color: #339933;">=</span> <span style="color: #990000;">openssl_pkey_get_public</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'file:///path/to/publickey'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">openssl_public_encrypt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sensitiveData</span><span style="color: #339933;">,</span> <span style="color: #000088;">$encryptedData</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pubKey</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 
<span style="color: #666666; font-style: italic;">// store $encryptedData ...</span></pre></div></div>

<p>When you need to get the sensitive data again, you can load the private key and decrypt:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// retrieve $encryptedData from storage ...</span>
 
<span style="color: #666666; font-style: italic;">// load the private key and decrypt the encrypted data</span>
<span style="color: #000088;">$privateKey</span> <span style="color: #339933;">=</span> <span style="color: #990000;">openssl_pkey_get_private</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'file:///path/to/privatekey'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$passphrase</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">openssl_private_decrypt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$encryptedData</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sensitiveData</span><span style="color: #339933;">,</span> <span style="color: #000088;">$privateKey</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Alternatively you can use the private key to encrypt data, sign data  or seal it against multiple other public keys, but that is beyond the  scope of this article.</p>
]]></content:encoded>
			<wfw:commentRss>http://andytson.com/blog/2009/07/php-public-key-cryptography-using-openssl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

