<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" 
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:admin="http://webns.net/mvcb/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<channel>
<title>Aquarionics - Category - PHP</title>
<link>http://www.aquarionics.com/category/PHP</link>
<description></description>
<dc:language>en-gb</dc:language>
<dc:creator>Aquarion (nicholas@aquarionics.com)</dc:creator>
<dc:rights>Copyright 2008 Aquarion</dc:rights>
<dc:date>2008-07-31T10:29:20+00:00</dc:date>
<admin:generatorAgent rdf:resource="http://www.aquarionics.com/epistula/?v=2.0.3" />
<admin:errorReportsTo rdf:resource="mailto:nicholas@aquarionics.com"/>
<sy:updatePeriod>daily</sy:updatePeriod>
<sy:updateFrequency>8</sy:updateFrequency>
<sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>
<item>
	<title>Uh-oh</title>
	<link>http://www.aquarionics.com/journal/2008/03/18/Uh-oh</link>
	<comments>http://www.aquarionics.com/journal/2008/03/18/Uh-oh</comments>
	<description></description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2008/03/18/Uh-oh</guid>
	<content:encoded><![CDATA[<a href="http://www.flickr.com/photos/aquarion/2342646227/" title="php.net syntax error by Aquarion, on Flickr"><img src="http://farm3.static.flickr.com/2267/2342646227_c14bf67983_o.jpg" width="669" height="412" alt="php.net syntax error" /></a>]]></content:encoded>
	<dc:date>2008-03-18T15:19:24+00:00</dc:date>
	<dc:subject>PHP</dc:subject>
	<slash:comments>2</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/2128</trackback:ping>
</item>
<item>
	<title>Debugging Ajax</title>
	<link>http://www.aquarionics.com/article/name/Debugging_Ajax</link>
	<comments>http://www.aquarionics.com/article/name/Debugging_Ajax</comments>
	<description>One of the problems with Ajax is that the server side of it becomes invisible. You send a request to the server with an ajax request object, and you can get output from the JS by firebug, or alert boxes, or whatever, but for the script running on the other side, there's no visible place for the output.

There are many ways around it, but my current favourite is Growl.

Growl is a...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/article/name/Debugging_Ajax</guid>
	<content:encoded><![CDATA[<p>One of the problems with Ajax is that the server side of it becomes invisible. You send a request to the server with an ajax request object, and you can get output from the JS by firebug, or alert boxes, or whatever, but for the script running on the other side, there's no visible place for the output.</p>

<p>There are many ways around it, but my current favourite is Growl.</p>

<p><a href="http://growl.info/">Growl</a> is a notification system for OS X, where programs send messages to the central demon, and it pops up a little dialog message that eventually fades away. They're nice for debug, so I have this:</p>


<pre><code>
<span style="color: #000;">&lt;?</span><span style="color: #000;">PHP</span><span style="color: #000;">
</span><span style="color: #00C;">require_once</span><span style="color: #000;">&nbsp;</span><span style="color: #F39;">'Net/Growl.php'</span><span style="color: #000;">;

</span><span style="color: #000;">$growl</span><span style="color: #000;">&nbsp;=&amp;&nbsp;</span><span style="color: #000;">Net_Growl</span><span style="color: #000;">::</span><span style="color: #000;">singleton</span><span style="color: #000;">(</span><span style="color: #F39;">'Net_Growl'</span><span style="color: #000;">,&nbsp;</span><span style="color: #00C;">array</span><span style="color: #000;">(</span><span style="color: #F39;">'Messages'</span><span style="color: #000;">),&nbsp;</span><span style="color: #F39;">'[Password]'</span><span style="color: #000;">);
</span><span style="color: #000;">$growl</span><span style="color: #000;">-&gt;</span><span style="color: #000;">_options</span><span style="color: #000;">[</span><span style="color: #F39;">'host'</span><span style="color: #000;">]&nbsp;=&nbsp;</span><span style="color: #F39;">'[MyIP]'</span><span style="color: #000;">;

</span><span style="color: #00C;">$GLOBALS</span><span style="color: #000;">[</span><span style="color: #F39;">'growl'</span><span style="color: #000;">]&nbsp;=&nbsp;</span><span style="color: #000;">$growl</span><span style="color: #000;">;

</span><span style="color: #00C;">function</span><span style="color: #000;">&nbsp;</span><span style="color: #000;">debug</span><span style="color: #000;">(</span><span style="color: #000;">$message</span><span style="color: #000;">){
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000;">$backtrace</span><span style="color: #000;">&nbsp;=&nbsp;</span><span style="color: #00C;">debug_backtrace</span><span style="color: #000;">();
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #00C;">array_shift</span><span style="color: #000;">(</span><span style="color: #000;">$backtrace</span><span style="color: #000;">);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #00C;">if</span><span style="color: #000;">&nbsp;(</span><span style="color: #00C;">is_array</span><span style="color: #000;">(</span><span style="color: #000;">$message</span><span style="color: #000;">)&nbsp;||&nbsp;</span><span style="color: #00C;">is_object</span><span style="color: #000;">(</span><span style="color: #000;">$message</span><span style="color: #000;">)){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000;">$message</span><span style="color: #000;">&nbsp;=&nbsp;</span><span style="color: #00C;">print_r</span><span style="color: #000;">(</span><span style="color: #000;">$message</span><span style="color: #000;">,</span><span style="color: #000;">1</span><span style="color: #000;">);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000;">$title</span><span style="color: #000;">&nbsp;=&nbsp;</span><span style="color: #00C;">sprintf</span><span style="color: #000;">(</span><span style="color: #F39;">"Debug&nbsp;-&nbsp;%s&nbsp;-&nbsp;%d"</span><span style="color: #000;">,&nbsp;</span><span style="color: #000;">$backtrace</span><span style="color: #000;">[</span><span style="color: #000;">0</span><span style="color: #000;">][</span><span style="color: #F39;">'function'</span><span style="color: #000;">],&nbsp;</span><span style="color: #000;">$backtrace</span><span style="color: #000;">[</span><span style="color: #000;">0</span><span style="color: #000;">][</span><span style="color: #F39;">'line'</span><span style="color: #000;">]);
&nbsp;&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #00C;">$GLOBALS</span><span style="color: #000;">[</span><span style="color: #F39;">'growl'</span><span style="color: #000;">]-&gt;</span><span style="color: #000;">notify</span><span style="color: #000;">(</span><span style="color: #F39;">'Messages'</span><span style="color: #000;">,&nbsp;</span><span style="color: #000;">$title</span><span style="color: #000;">,&nbsp;</span><span style="color: #000;">$message</span><span style="color: #000;">);
}

</span>


</code></pre>

With network notification enabled on Growl on my local machine, I get a little debug message without interrupting the application flow.

Of course, I could use log files, but that wouldn't be quite as pretty.]]></content:encoded>
	<dc:date>2007-03-06T17:41:35+00:00</dc:date>
	<dc:subject>Apple</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>1</slash:comments>
	<slash:section>article</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/article/86</trackback:ping>
</item>
<item>
	<title>Textile</title>
	<link>http://www.aquarionics.com/journal/2006/10/22/Textile</link>
	<comments>http://www.aquarionics.com/journal/2006/10/22/Textile</comments>
	<description>For the last couple of hours, Aquarionics has been using Jim and Lissa&amp;#8217;s TexilePHP system, which is a conversion to PHP of Brad Choate&amp;#8217;s conversion to Movable Type of Dean Allen&amp;#8217;s textile system (Once relased on its own, now part of Textpattern).

	It&amp;#8217;s the same system as AqWiki uses for text formating, and I used the Jim and Lissa version because it supports multiple...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2006/10/22/Textile</guid>
	<content:encoded><![CDATA[<p>For the last couple of hours, Aquarionics has been using <a href="http://jimandlissa.com/project/textilephp">Jim and Lissa&#8217;s TexilePHP</a> system, which is a conversion to <span class="caps">PHP</span> of <a href="http://www.bradchoate.com/mt-plugins/textile">Brad Choate&#8217;s</a> conversion to Movable Type of <a href="http://www.textism.com/tools/textile/">Dean Allen&#8217;s textile system</a> (Once relased on its own, now part of <a href="http://www.textpattern.com/">Textpattern</a>).</p>

	<p>It&#8217;s the same system as <a href="http://aqwiki.sf.net">AqWiki</a> uses for text formating, and I used the Jim and Lissa version because it supports multiple paragraph blockquotes. (I actually installed the Jim and Lissa version for the last entry about City of Villains, because it needed a multiple paragraph blockquote).</p>

	<p>I&#8217;ve removed it entirely from every single project I have.</p>

	<p>Why?</p>

	<p>Because it pushed the memory usage up by over megabytes.</p>

	<p>Six!</p>

	<p>The server has a limit of eight for <span class="caps">PHP</span> connections. Epistula, which is reasonably complicated, clocks in at 3.5 (Far less when visiting a cached page), AqWiki without textile is 1.9 &#8211; mostly due to the Pear stuff. But good grief. Textile was taking up more memory than the entire Epistula system, <b>doubled</b>.</p>]]></content:encoded>
	<dc:date>2006-10-22T13:18:58+00:00</dc:date>
	<dc:subject>PHP</dc:subject>
	<slash:comments>1</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1949</trackback:ping>
</item>
<item>
	<title>T Paamayim Nekudotayim</title>
	<link>http://www.aquarionics.com/journal/2006/08/16/T_Paamayim_Nekudotayim</link>
	<comments>http://www.aquarionics.com/journal/2006/08/16/T_Paamayim_Nekudotayim</comments>
	<description>Lesson of the day, PHP calls the &amp;#8221;::&amp;#8221; &amp;#8211; used to identify an uninstantiated class function &amp;#8211; a Paamayim Nekudotayim.

	A day when you learn something is a day not wasted.</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2006/08/16/T_Paamayim_Nekudotayim</guid>
	<content:encoded><![CDATA[<p>Lesson of the day, <span class="caps">PHP</span> calls the &#8221;::&#8221; &#8211; used to identify an uninstantiated class function &#8211; a Paamayim Nekudotayim.</p>

	<p>A day when you learn something is a day not wasted.</p>]]></content:encoded>
	<dc:date>2006-08-16T14:42:55+00:00</dc:date>
	<dc:subject>PHP</dc:subject>
	<slash:comments>2</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1919</trackback:ping>
</item>
<item>
	<title>PHP sessions in Debian Sarge</title>
	<link>http://www.aquarionics.com/journal/2005/12/22/PHP_sessions_in_Debian_Sarge</link>
	<comments>http://www.aquarionics.com/journal/2005/12/22/PHP_sessions_in_Debian_Sarge</comments>
	<description>This is how debian Woody (and all sane systems) clean up PHP disk based (the default) sessions:

	
	Every x (default: 1000) requests, PHP will delete all outdated sessions.
	

	This is how Debian Sarge does it:

	
	Every half hour (at 9 and 39 past) run a script
		This script runs a second shell script that parses the PHP config file with a regex to get the value for how long sessions should...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2005/12/22/PHP_sessions_in_Debian_Sarge</guid>
	<content:encoded><![CDATA[<p>This is how debian Woody (and all sane systems) clean up <span class="caps">PHP</span> disk based (the default) sessions:</p>

	<ol>
	<li>Every x (default: 1000) requests, <span class="caps">PHP</span> will delete all outdated sessions.</li>
	</ol>

	<p>This is how Debian Sarge does it:</p>

	<ol>
	<li>Every half hour (at 9 and 39 past) run a script</li>
		<li>This script runs a second shell script that parses the <span class="caps">PHP</span> config file with a regex to get the value for how long sessions should last (Which is odd, because a <span class="caps">PHP</span> script will get this automatically)</li>
		<li>The first script will then <code>find</code> all session files older than that value</li>
		<li>Delete them.</li>
	</ol>

	<p><span class="caps">WHY</span>? WHY <span class="caps">WHY WHY</span>?</p>

	<p>This is the kind of braindead overcomplication stuff I&#8217;d expect from Gentoo, but the whole point of Debian is that it&#8217;s /sane/. </p>]]></content:encoded>
	<dc:date>2005-12-22T10:15:40+00:00</dc:date>
	<dc:subject>linux</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>1</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1801</trackback:ping>
</item>
<item>
	<title>Handing 404s over to Google</title>
	<link>http://www.aquarionics.com/journal/2005/04/25/Handing_404s_over_to_Google</link>
	<comments>http://www.aquarionics.com/journal/2005/04/25/Handing_404s_over_to_Google</comments>
	<description>This site once won an award from a perl web hackers site &amp;#8211; now defunct &amp;#8211; for the 404 system.

	The system was really simple. If you hit a 404 on this site it would apologise, then redirect you to a google search of Aquarionics for whatever you were looking for. This has worked for a while now, with the apologies getting ever more extravagant and the redirections being turned into...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2005/04/25/Handing_404s_over_to_Google</guid>
	<content:encoded><![CDATA[<p>This site once won an award from a perl web hackers site &#8211; now defunct &#8211; for the 404 system.</p>

	<p>The system was really simple. If you hit a 404 on this site it would apologise, then redirect you to a google search of Aquarionics for whatever you were looking for. This has worked for a while now, with the apologies getting ever more extravagant and the redirections being turned into google links (Because I hate being redirected places without a chance to stop it).</p>

	<p>The <a href="/error/404">latest iteration</a> of this has just been finished (Yay the lunch break). It uses the Google <span class="caps">API</span> to display the first ten results alongside the apology. Finally a real use for the thing :-)</p>

	<p>The next stage is to automatically wander though the <a href="/projects/raoss/view.php?file=src/apache/apache2perl.pl">mysql table of my access logs</a> and automagically reply with <a href="/error/410">410 Gone</a> if it used to exist but doesn&#8217;t anymore</p>]]></content:encoded>
	<dc:date>2005-04-25T12:43:13+00:00</dc:date>
	<dc:subject>aqcom</dc:subject>
	<dc:subject>epistula</dc:subject>
	<dc:subject>PHP</dc:subject>
	<dc:subject>web development</dc:subject>
	<slash:comments>0</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1637</trackback:ping>
</item>
<item>
	<title>Instant Cat Pictures</title>
	<link>http://www.aquarionics.com/journal/2004/09/05/Instant_Cat_Pictures</link>
	<comments>http://www.aquarionics.com/journal/2004/09/05/Instant_Cat_Pictures</comments>
	<description>Since I&amp;#8217;ve had my new camera-phone, I&amp;#8217;ve been taking random shots occasionally. After a fairly brief stint using Gallery and moblog.co.uk I&amp;#8217;ve done my usual thing of writing an Epistula Module to do it a) the way I want it, and b) within my own site. (I started off adapting the webcam module, but that&amp;#8217;s bitrotted slightly and was never very good, so I rewrote a whole new...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2004/09/05/Instant_Cat_Pictures</guid>
	<content:encoded><![CDATA[<p>Since I&#8217;ve had my new camera-phone, I&#8217;ve been taking random shots occasionally. After a fairly brief stint using <a href="http://www.gkhs.net/gallery/moblog">Gallery</a> and <a href="http://moblog.co.uk/blogs.php?show=1175">moblog.co.uk</a> I&#8217;ve done my usual thing of writing an Epistula Module to do it a) the way I want it, and b) within my own site. (I started off adapting the <a href="/webcam">webcam</a> module, but that&#8217;s bitrotted slightly and was never very good, so I rewrote a whole new thing that uses <a href="http://www.exif.org/"><span class="caps">EXIF</span></a> data &#8211; which my mobile doesn&#8217;t do, but my full camera does &#8211; and pretty <span class="caps">CSS</span> effects.</p>

	<p>Anyway, the upshots of this are that to the left on the front page is &#8220;That Which Is Seen&#8221;, the latest moblog picture, and clicking on it will take you to <a href="/moblog">/moblog</a>, an archive of everything. I need to make the archiving better and make it generate thumbnails properly, but for now this end is working. Next end is the python script to take a piped email and send the graphic and caption to the right places, then I&#8217;ll fix the front end properly. Meanwhile, it&#8217;s half one and I have work in the morning&#8230;</p>]]></content:encoded>
	<dc:date>2004-09-05T23:32:52+00:00</dc:date>
	<dc:subject>aqcom</dc:subject>
	<dc:subject>epistula</dc:subject>
	<dc:subject>PHP</dc:subject>
	<dc:subject>programming</dc:subject>
	<slash:comments>0</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1500</trackback:ping>
</item>
<item>
	<title>Errands and the End Of PHP</title>
	<link>http://www.aquarionics.com/journal/2004/03/29/Errands_and_the_End_Of_PHP</link>
	<comments>http://www.aquarionics.com/journal/2004/03/29/Errands_and_the_End_Of_PHP</comments>
	<description>Got stuff done.

	In this case, the stuff was of a many and varied nature and involved:

	
	Sorting out bank accounts
		Joining Blockbuster
		Joining Library
		Posting Stuff
	

	But also:

	
	Resolving that I will never again begin a personal project written in PHP.
	

	Yesterday, you see, I managed to get PHP5 working on Atoll, my local server. It works fine, from a technical standpoint, it...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2004/03/29/Errands_and_the_End_Of_PHP</guid>
	<content:encoded><![CDATA[<p>Got stuff done.</p>

	<p>In this case, the stuff was of a many and varied nature and involved:</p>

	<ul>
	<li>Sorting out bank accounts</li>
		<li>Joining Blockbuster</li>
		<li>Joining Library</li>
		<li>Posting Stuff</li>
	</ul>

	<p>But also:</p>

	<ul>
	<li>Resolving that I will never again begin a personal project written in <span class="caps">PHP</span>.</li>
	</ul>

	<p>Yesterday, you see, I managed to get <span class="caps">PHP5</span> working on Atoll, my local server. It works fine, from a technical standpoint, it installed straight into the right place, it works, it access the databases and everything.</p>

	<p>Epistula, however, doesn&#8217;t. Neither did AqWiki, Aquaintances, Klind or Pareidol. Why?</p>

	<p>Because somewhere in the <span class="caps">PHP5</span> development process, somebody wrote a function to return the contents of a directory back as an array, and called it <code>scandir()</code> which, co-incidentally, is the name of my stock function for returning the contents of a directory as an array. It means that, as of <span class="caps">PHP5</span>&#8217;s full release, my code is broken. This is, in fact, wrong.</p>

	<p>One of the great benefits of <span class="caps">PHP</span> is it&#8217;s integration. Everything available  was in <a href="http://www.php.net/manual">the manual</a>, which was searchable and contained the wit and wisdom of several years of <span class="caps">PHP</span> developers who had been where you are before you were there.</p>

	<p>The greatest flaw <span class="caps">PHP</span> has is it&#8217;s integration. Functions have been added haphazardly over the five major revisions to the point where, given a two word function, it&#8217;s equal odds to be <code>firstSecond()</code> as <code>first_second()</code> depending on who coded it when. Also, the willingness of the development team to break every previous <span class="caps">PHP</span> tutorial in a minor revision (Witness the whole <span class="caps">REGISTER GLOBALS</span> debacle), Perl &#8211; the language with the most established collection of modules on the market &#8211; has a namespace system for added on functionality which works so well even Python copied it. <span class="caps">PHP</span>, however, is no longer a stable platform to develop releasable code on, since your code may stop working at any point. Worst, this will manifest itself as a <span class="caps">PHP</span> syntax error, and you cannot guard against new internal functions unless you check the existence of every function before you use it.</p>

	<p>So, <span class="caps">PHP</span>, it&#8217;s been nice using you, but until you stop fucking around with the namespaces, it&#8217;s time to try something new.</p>

	<p>Suggestions, anyone?</p>

	<p><!-- --></p>]]></content:encoded>
	<dc:date>2004-03-29T16:59:40+00:00</dc:date>
	<dc:subject>programming</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>12</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1360</trackback:ping>
</item>
<item>
	<title>Comment as mucked</title>
	<link>http://www.aquarionics.com/journal/2004/02/06/Comment_as_mucked</link>
	<comments>http://www.aquarionics.com/journal/2004/02/06/Comment_as_mucked</comments>
	<description>So, whilst other people have been attacked by comment spammers, I &amp;#8211; in my Epistula fortified ivory tower &amp;#8211; have recieved two, which I have then deleted. More of a problem for me is that Google has placed my review of Broken Sword III in the top of it&amp;#8217;s rankings for that phrase, meaning I&amp;#8217;ve had a couple of people saying how much it sucks.

	This full and frank exchange of...</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2004/02/06/Comment_as_mucked</guid>
	<content:encoded><![CDATA[<p>So, whilst other people have been <a href="http://philringnalda.com/blog/2004/01/thinking_about_comment_spam.php">attacked by comment spammers</a>, I &#8211; in my Epistula fortified ivory tower &#8211; have recieved two, which I have then deleted. More of a problem for me is that Google has placed my <a href="http://www.aquarionics.com/article/name/Broken_Sword_3_-_The_Sleeping_Dragon">review of Broken Sword <span class="caps">III</span></a> in the top of it&#8217;s rankings for that phrase, meaning I&#8217;ve had a couple of people saying how much it sucks.</p>

	<p>This full and frank exchange of views (If they ever come back to the site I&#8217;d be suprised) is exactly why I have comments, but both of them decided to put forth their views in <span class="caps">CAPS</span>-LOCK <span class="caps">FOR EMPHASIS</span>.</p>

	<p>Grr. Just reading the comments makes my ears hurt.</p>

	<p>So, given that this is a social problem, there must be a technical solution to it, mustn&#8217;t there? This is, after all, a weblog. And yes, of course there is. A couple of quick regexes later, and I have <a href="http://www.aquarionics.com/showcode/include/library.php#funccheckCaps">checkCaps</a> to do this fun job for me.</p>

	<p>Also, since I&#8217;ve got a couple of reports that my comments validation thing was a little odd, I&#8217;ve recoded it a bit so it highlights if there&#8217;s been a problem submiting your comment (Originally it just changed the status message, but this is apparently not obvious enough, so now it colours it red)</p>

	<p>Next trick is going to make the &#8220;Email me when someone replies&#8221; thing actually work&#8230;</p>]]></content:encoded>
	<dc:date>2004-02-06T14:55:55+00:00</dc:date>
	<dc:subject>epistula</dc:subject>
	<dc:subject>Metablog</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>0</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1312</trackback:ping>
</item>
<item>
	<title>Wiki wiki wild, wiki wiki wild wild web.</title>
	<link>http://www.aquarionics.com/journal/2003/07/21/Wiki_wiki_wild%2C_wiki_wiki_wild_wild_web.</link>
	<comments>http://www.aquarionics.com/journal/2003/07/21/Wiki_wiki_wild%2C_wiki_wiki_wild_wild_web.</comments>
	<description>In which Aquarion wikifies stuff</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2003/07/21/Wiki_wiki_wild%2C_wiki_wiki_wild_wild_web.</guid>
	<content:encoded><![CDATA[<p>About a month ago, I concieved a Project.</p>

	<p>Basically, it was when <span class="caps">ESR</span> shifted the focus of the Jargon File by changing the &#8220;J Random Hacker&#8221; entry to more reflect his own beliefs. My plan to combat this was &#8211; and is &#8211; to file the whole Jargon File into a Wiki and let the world at it. Think an entry is biased? Change it.</p>

	<p>All I needed to do was to get it out of the Jargon File format and into something that I could import into a wiki. Then I discovered something really, really fundermental.</p>

	<p>All wikis suck.</p>

	<p>In fact, the particular way all these Wiki&#8217;s sucked was two fold. The first was the most important: No existing wiki that I could install on this server could import data from an external source. All the ones that backed onto plain text files I couldn&#8217;t &#8211; for various reasons &#8211; install. All the ones that backed onto a mysql database had data structures six feet deep that I couldn&#8217;t hack my way around.</p>

	<p>The second reason all wikis suck is the really, really horribly <b>nasty</b> text formatting that has become standard. &#8216;&#8217;&#8216;&#8217;this is italic&#8217;&#8216;&#8217;&#8217; &#8216;&#8217;&#8216;&#8217;&#8216;&#8217;&#8216;&#8217;this is bold&#8217;&#8216;&#8217;&#8216;&#8217;&#8216;&#8217;&#8217; is a little too baroque, verbose, and nasty for my liking.</p>

	<p>This weekend, my project was to play around with <a href="http://pear.php.net"><span class="caps">PEAR</span></a> (The <span class="caps">PHP</span> equivlient of <span class="caps">CPAN</span>, crossed with apt-get. It rocks), for which I needed a project. Plus, <a href="http://www.textism.com">Dean Allen</a> has just released <a href="http://www.textism.com/tools/textile/">Textile 2 beta</a>, the best text-formatting library for <span class="caps">PHP </span>(and now perl) bar none. Aha, I thought. This will solve several problems.</p>

	<p>So, this afternoon about 16:00 I started coding my own Wikilike, and now at 1am, I&#8217;ve finished the first cut. It uses textile for formatting, it does Wikilike things, and it backs on to the Aquarionics User System (currently only used for <a href="/misc/story">Forever</a>, so if you had an account on Forever at about 8pm this evening &#8211; when I copied the database locally &#8211; you have an account on the Wiki. I haven&#8217;t gotten around to writing an account creation system for the wiki locally yet, so you&#8217;ll have to be anonymous if you don&#8217;t).</p>

	<p>The current Wiki is up <a href="http://aqua.water.gkhs.net/aqWiki">on my local server</a>, it inherantly supports mulitple wiki&#8217;s per server, but I&#8217;ve still got to put in the really cool bits, like the <span class="caps">XML</span>-RPC interface, the ability for admins to lock pages, and stuff.</p>

	<p>And the name? Well, it was done quickly (A Qwiki), it&#8217;s mine (Aq Wiki) and it&#8217;s slightly sick (Aqw Iki) </p>

	<p>But it&#8217;s there, it&#8217;s working, and since I&#8217;m working in the morning, I&#8217;d better head to bed&#8230;</p>]]></content:encoded>
	<dc:date>2003-07-21T00:29:09+00:00</dc:date>
	<dc:subject>PHP</dc:subject>
	<dc:subject>aqWiki</dc:subject>
	<slash:comments>4</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1162</trackback:ping>
</item>
<item>
	<title>Gzip Compression with PHP</title>
	<link>http://www.aquarionics.com/journal/2003/07/09/Gzip_Compression_with_PHP</link>
	<comments>http://www.aquarionics.com/journal/2003/07/09/Gzip_Compression_with_PHP</comments>
	<description>In which Aquarion makes his site smaller</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2003/07/09/Gzip_Compression_with_PHP</guid>
	<content:encoded><![CDATA[<p><a href="http://diveintomark.org/archives/2003/07/09/bandwidthsaving_tip_of_the_day.html">Mark</a> re-recommended compressing pages today, which is always a useful idea. Sneaky (The server Aqcom wallows on) has <code>mod_gzip</code> installed, which automagically compresses all static pages before sending them. Great, but not so cool for the dynamic <span class="caps">PHP</span> pages that the rest of the site works on.</p>

	<p>My solution to this was to kill two birds with one stone. The first is that since Aquarionics caches every page the first time it&#8217;s loaded the cache directory can get quite large &#8211; esspecially when something like Google comes in and looks at (and therefore generates) <em>all</em> the pages on the site. First thing was then to modify my cache generation system as follows:</p>

	<p>The cache-save system &#8211; which writes the contents of the output buffer to a file &#8211; just used <a href="http://php.net/manual/en/function.gzopen.php">@gzopen@</a> and <a href="http://php.net/manual/en/function.gzwrite.php">@gzwrite@</a> instead of the standard <span class="caps">PHP</span> file-write code, and the cache-load decompressed it.</p>

	<p>Next, testing for compression and sending if possible. First was simple, <span class="caps">PHP</span> gives you an array <code>$HTTP_SERVER_VARS</code> containing all the stuff the client sends, so I just needed to check the <code>HTTP_ACCEPT_ENCODING</code> variable for the string &#8220;gzip&#8221;:</p>

<code lang="PHP"><pre>if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], "gzip")){
$compress = true;
} else {
$compress = false;
}</pre></code>

	<p>and then the complicated bit, sending the right version. If the compression was on, all I needed to do was send the right headers and pass through the contents of the cache. If not, I would decompress the cache and pass that. Note that while there is a function to directly output the contents of a gzip file (<a href="http://uk.php.net/manual/en/function.gzpassthru.php">gzpassthru</a>) I tend to avoid it because I want to send a content-length header too, and I can&#8217;t get that if I only know the length after the output. <code>gzpassthru</code> returns the number of bytes out, but <code>header("Content-Length: ".gzpassthru($cachename))</code> was abandoned for readiblity, though it&#8217;s prefectly valid. Anyway, the code:</p>

<code lang="PHP"><pre>header ("ETag: "$etag""); 
if ($etagval==$etag || $HTTP_IF_MODIFIED_SINCE == $gmt_mtime) {
header("HTTP/1.1 304 Not Modified");
} elseif ($compress){
header("X-Compression: gzip");
header("Content-Encoding: gzip");
header("Content-Length: ".filesize($_EP['cachedir']."/".$cachename));
readfile($_EP['cachedir']."/".$cachename) or die("Couldn't open cache");
} else {
header("X-Compression: None");
$zd = gzopen ($_EP['cachedir']."/".$cachename, "r") or die("Couldn't open cache");
$contents = gzread ($zd, 1000000);
header("Content-Length: ".strlen($contents));
echo $contents;
gzclose ($zd);
}</pre></code>

	<p>(I&#8217;ve left the <code>etag</code> code in for context), so now all pages should be gzipped any time they are accessed after the first (First time it generates the content, echos it, then compresses it and writes it to the cache) The full code for all this is at the top and bottom of <a href="http://www.aquarionics.com/showcode/">Epistula.php</a></p>]]></content:encoded>
	<dc:date>2003-07-09T17:25:12+00:00</dc:date>
	<dc:subject>epistula</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>2</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1154</trackback:ping>
</item>
<item>
	<title>Everyone loves Spam Statistics</title>
	<link>http://www.aquarionics.com/journal/2003/06/09/Everyone_loves_Spam_Statistics</link>
	<comments>http://www.aquarionics.com/journal/2003/06/09/Everyone_loves_Spam_Statistics</comments>
	<description>In which Aquarion sings about lovely spam! wonderful spam spam spam spam, spam spam spam, lovely Spam! wonderful spam spam spam spam&amp;#8230;</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2003/06/09/Everyone_loves_Spam_Statistics</guid>
	<content:encoded><![CDATA[<p>This is a graph of my spam-count:</p>

	<p><img src="/diarystuff/2003/06/graph.png" width="480" height="320" border="0" alt="A graph of aquarion's spam"></p>

	<p>This is how I created my spam-count. It&#8217;s a combination of spamassassin, procmail, shell-script and <span class="caps">PHP</span>, and therefore full of Stuff Wot No Man Was To Wot Of. Or something.</p>

	<p>First, I run <a href="http://www.spamassassin.org">spamassassin</a>, which just generally rocks. All my email comes into one mailbox, aq which is at gkhs dot net. That includes every mailing list, every aquarionics dot com address, all my suespammers mail, and my hotmail account (via the really quite nice program, <a href="http://www.nongnu.org/gotmail/">gotmail</a>. It then gets fed though <a href="http://www.procmail.org/">procmail</a> which uses various script-fu to deposit mailing-lists into newsgroups on the local news server (I prefer reading discussion via usenet), and everything else gets sent though Spamassassin like this:</p>

<code>:0fw:/home/aquarion/logs/sa.lock
	<p>| /usr/local/bin/spamassassin</p>

	<p>:0:</p>
	<ul>
	<li>^X-Spam-Status: YES<br>
$MAILDIR/spam/`date +%Y-%m-%d`</code>

	<p>meaning that everything that SA thinks is spam gets forwarded to a mailbox within my spam folder with the name as the date. Most solutions I saw for this kind of statistics generation put all the mail into one box and then grab the date from it. For the way I&#8217;m doing it, that&#8217;s a waste of processing, plus it ignores Rule One: Spammers Lie. The date on the spam usually has no relation to the date you got it.</p>

	<p>So, we now have a box called &#8211; for example &#8211; 2003-06-09 containing today&#8217;s Spam (On the second day of every month, a cron-job wraps all the last-month&#8217;s spam into a tarball and dumps it somewhere to rot). Every morning at 1:12am, the following runs:</p>

<code>#!/bin/sh<br>
DATE=`date +%Y-%m-%d`<br>
SPAMTODAY=`from -f ~/Mail/spam/$DATE | wc -l`

	<p>echo $DATE, $SPAMTODAY &gt;&gt; ~/logs/spam.log<br>
</code></p>

	<p>(<code>from</code> is a program that displays the from: header of every mail in a mailbox. In this case, it generates one line per mail which is what we want). Giving us a file like this:</p>

<code>-&lt;del&gt;snip&lt;/del&gt;-<br>
2003-06-02, 328<br>
2003-06-03, 134<br>
2003-06-04, 130<br>
2003-06-05, 152<br>
2003-06-06, 125<br>
2003-06-07, 123<br>
2003-06-08, 267<br>
-&lt;del&gt;snip&lt;/del&gt;-</code>.

	<p>Which we can do whatever we want with. In this case, a <a href="http://www.aquarionics.com/projects/raoss/src/graph.php.txt"><span class="caps">PHP</span> script</a> (or you can view that <a href="http://www.aquarionics.com/projects/raoss/code.php?file=src/graph.php.txt">nicely formatted</a>) which generates a graph.</p>

	<p>And thats how I know I get about 100 to 300 pieces of spam <em>every day</em>.</p>

	<p>Best yet, that&#8217;s the <b>only</b> way I know I get 100 -> 300 pieces of spam a day :-)</p>]]></content:encoded>
	<dc:date>2003-06-09T17:46:42+00:00</dc:date>
	<dc:subject>linux</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>0</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1119</trackback:ping>
</item>
<item>
	<title>MusicDB</title>
	<link>http://www.aquarionics.com/journal/2003/05/22/MusicDB</link>
	<comments>http://www.aquarionics.com/journal/2003/05/22/MusicDB</comments>
	<description>In which Aquarion announces some new software: MusicDB</description>
	<guid isPermaLink="true">http://www.aquarionics.com/journal/2003/05/22/MusicDB</guid>
	<content:encoded><![CDATA[<p>New software release for all y&#8217;all, and it&#8217;s not even a weblog-related thing. Be afraid.</p>

	<p>It says on my <a href="http://www.aquarionics.com/article/name/about">About</a> page that I &#8220;write things to put things into databases and take them out again.&#8221; and <a href="/projects/musicdb">MusicDB</a> is no exception. It&#8217;s entire purpose in life is to put things (In this case, references to <span class="caps">MP3</span> files) into a MySQL database, and then take them out again according to the criteria you specify via the command-line or web-based client.</p>

	<p>It&#8217;s in Perl, and <span class="caps">SQL</span>, and <span class="caps">PHP</span>. It runs my <a href="http://www.aquarionics.com/fun/mp3s.html">somewhat excessive</a> MP3 playlists, and it&#8217;s reached 1.0 and been thrown into the universe with nothing but a <span class="caps">GPL</span> to it&#8217; name.  Go have fun.</p>]]></content:encoded>
	<dc:date>2003-05-22T12:43:35+00:00</dc:date>
	<dc:subject>projects</dc:subject>
	<dc:subject>PHP</dc:subject>
	<slash:comments>0</slash:comments>
	<slash:section>journal</slash:section>
	<trackback:ping>http://www.aquarionics.com/trackback/journal/1104</trackback:ping>
</item>
</channel>
</rss>