<?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>actionshrimp.com</title>
	<atom:link href="http://www.actionshrimp.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.actionshrimp.com</link>
	<description>fun and geekery</description>
	<lastBuildDate>Sun, 18 Apr 2010 12:42:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>CakePHP: PagesController with Admin Routing</title>
		<link>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/</link>
		<comments>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 17:46:14 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[pagescontroller]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=272</guid>
		<description><![CDATA[For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass:


function beforeFilter(){
    $admin = Configure::read(&#039;Routing.admin&#039;);
    if (isset($this-&#62;params[$admin]) and $this-&#62;params[$admin]){
     [...]]]></description>
			<content:encoded><![CDATA[<p>For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass:</p>
<pre class="brush: php">

function beforeFilter(){
    $admin = Configure::read(&#039;Routing.admin&#039;);
    if (isset($this-&gt;params[$admin]) and $this-&gt;params[$admin]){
        $this-&gt;layout = &#039;admin&#039;;
    }
    else {
        $this-&gt;Auth-&gt;allow();
    }
}
</pre>
<p>The problem with this however is static pages handled by the pages controller cannot be password protected. To resolve this problem, I had to overload the PagesController class that Cake comes with, and add in the required functionality. Part of the reason for doing this for me was to allow a setup where there was a password protected admin welcome page or control panel located at my_app_URL/admin, so I&#8217;ll show you the necessary routing to achieve that too.</p>
<p><span id="more-272"></span></p>
<h3>Adding a route and overloading PagesController</h3>
<p>First of all, copy your_app_dir/cake/libs/controller/pages_controller.php into your_app_dir/app/controllers with the rest of your application&#8217;s controllers. Then fire up an editor and take a look at your newly copied version.  You&#8217;ll see there is a function called display, this is what the pages controller uses to display pages. There is a route in app/config/routes.php that maps /pages/* to /pages/display/* to make the URL easier on the eyes, so if we&#8217;re gonna have /admin/pages/* working properly, we&#8217;ll need a similar route. Open up app/config/routes.php, and underneath the line</p>
<pre class="brush: php">

Router::connect(&#039;/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;));
</pre>
<p>add in the following route:</p>
<pre class="brush: php">

Router::connect(&#039;/admin/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true));
</pre>
<p>Now, when admin routing is enabled, Cake looks for controller actions appened with &#8220;admin_&#8221;, so we&#8217;d better add in the function to handle this in PagesController. Open it up, and underneath the display function, add the following:</p>
<pre class="brush: php">

function admin_display() {
    $path = func_get_args();
    $temp = null;

    $count = count($path);

    if ($path[0] != &#039;admin&#039;) {
        //This adds admin to the beginning of the path so the pages controller will look in the &#039;admin&#039; folder in pages directory
        $path = array_merge((array)&#039;admin&#039;, $path);
    } else {
        //This removes admin from the beginning if it&#039;s there already, and sends the request round again so we end up with URLs that look like app/admin/pages/x
        //when app/admin/pages/admin/x is requested somehow.
        $path = array_slice($path, 1);
        $this-&gt;redirect(array_merge(array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true), $path));
    }

    if (!$count) {
        $this-&gt;redirect(&#039;/&#039;);
    }
    $page = $subpage = $title = null;

    if (!empty($path[0])) {
        $page = $path[0];
    }
    if (!empty($path[1])) {
        $subpage = $path[1];
    }
    if (!empty($path[$count - 1])) {
        $title = Inflector::humanize($path[$count - 1]);
    }
    $this-&gt;set(compact(&#039;page&#039;, &#039;subpage&#039;, &#039;title&#039;));
    $this-&gt;render(join(&#039;/&#039;, $path));
}
</pre>
<p>As you can see it&#8217;s fairly similar to the display function, with a few extra lines added in that handle admin pages. There are a few subtleties here which I will explain in a second. Before that however, we also require a slight change to the existing, non-admin display function. Look for the if statement below:</p>
<pre class="brush: php">

if (!empty($path[0])) {
    $page = $path[0];
}
</pre>
<p>and change it to:</p>
<pre class="brush: php">

if (!empty($path[0])) {
    $page = $path[0];
    if ($page == &#039;admin&#039;) {
        //Sends admin page requests to their proper place to stop sneaky access attempts
        $this-&gt;redirect(array_merge(array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true), $path));
    }
}
</pre>
<p>Ok so what have we done?</p>
<ol>
<li>The added nested if statement in the display() function redirects requests for /pages/admin/x to their proper place, /admin/pages/x.</li>
<li>The &#8216;else&#8217; clause of the if ($path[0] == &#8216;admin&#8217;) in admin_display redirects requests for /admin/pages/admin/x to /admin/pages/x, which just tidies up a URL aesthetics issue.</li>
<li>Finally, the first part of the same if statement is what handles the /admin/pages/x requests proper &#8211; it adds the &#8216;admin&#8217; part back to the beginning of the $path variable that point 2 removes. This is actually just exploiting a subtlety of the pages controller, &#8217;subpages&#8217; (this seems to be quite hard to find in the documentation actually) &#8211; requests sent to /pages/a/b will display a page b stored in the folder your_app_dir/app/views/pages/a, rather than a page b stored in the pages root. Adding this additional logic helps organisation a bit by storing all admin pages in you_app_dir/app/views/pages/admin/.</li>
</ol>
<p>So now this is all in place, everything should work correctly. Requests to /pages/admin/x and /admin/pages/admin/x both get sent to /admin/pages/x, and these require proper authentication.</p>
<p>The final step is to add in a route that allows my original use for this whole setup to work properly &#8211; displaying an admin homepage or control panel that requires authentication when a user visits your_app_URL/admin, i.e. without referring to any controllers or actions. First, create a page in your_app_dir/app/views/pages/admin/, called home.ctp that contains the content you want. You can now access this from your_app_URL/admin/pages/home, but the shorter URL works after adding the route:</p>
<pre class="brush: php">

Router::connect(&#039;/admin&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true, &#039;home&#039;));
</pre>
<p>Hooray! We now have an admin homepage. Hope everything worked for you, hit me with a comment if you have an issues and I&#8217;ll try and help out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>CakePHP Tutorial Part 2: Authentication and Tweaking</title>
		<link>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/</link>
		<comments>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 19:51:59 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=178</guid>
		<description><![CDATA[In the first part of my CakePHP tutorial, I showed you how to use Cake&#8217;s Bake utility to set up the basic back end of an online illustration portfolio. In this part, I&#8217;ll tweak the automatically generated code into useable website and admin section and show you how to use some of Cake&#8217;s features along [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/cake-logo1.png"><img class="alignleft size-full wp-image-252" title="cake-logo1" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/cake-logo1.png" alt="cake-logo1" width="180" height="180" /></a>In the <a href="http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/">first part of my CakePHP tutorial</a>, I showed you how to use Cake&#8217;s Bake utility to set up the basic back end of an online illustration portfolio. In this part, I&#8217;ll tweak the automatically generated code into useable website and admin section and show you how to use some of Cake&#8217;s features along the way, including the Authentication component.<br />
<span id="more-178"></span></p>
<h3>Joining the sections together</h3>
<p>If you followed the first part of the tutorial, we currently have a few sections that we&#8217;ve generated models, controllers and views for. By navigating to your_app/controllername/action in your browser, you can access the different functions of the application. But unless your users know this in advance, they have no way of accessing them.</p>
<p>The easiest way of implementing navigation common to all pages is to use Cake&#8217;s built in templating system, the page &#8220;layout&#8221;. Cake uses its built-in layout if it finds no user defined layout default available. To add one, create the file your_app_dir/app/views/layouts/default.ctp, and put in your basic page layout. Mine looked like this:</p>
<pre class="brush: php">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;&lt;?php echo $title_for_layout ?&gt;&lt;/title&gt;
&lt;link href=&quot;favicon.ico&quot; type=&quot;image/x-icon&quot; rel=&quot;shortcut icon&quot; /&gt;
&lt;?php echo $html-&gt;css(&#039;default&#039;) ?&gt;
&lt;?php echo $scripts_for_layout ?&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id=&quot;container&quot;&gt;
&lt;div id=&quot;header&quot;&gt;
&lt;h1&gt;King-Jon Illustration&lt;/h1&gt;
&lt;/div&gt;
&lt;div id=&quot;navigation&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;News&#039;, array(&#039;controller&#039;=&gt;&#039;News&#039;))?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;Works&#039;, array(&#039;controller&#039;=&gt;&#039;Works&#039;))?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;Sketches&#039;, array(&#039;controller&#039;=&gt;&#039;Sketches&#039;))?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;Friends&#039;, array(&#039;controller&#039;=&gt;&#039;Friends&#039;))?&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;content&quot;&gt;
&lt;?php echo $content_for_layout ?&gt;
&lt;/div&gt;
&lt;div id=&quot;footer&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>You&#8217;ll notice this looks like a pretty normal basic page skeleton, with a few extra bits of PHP inserted. The $title_for_layout, $scripts_for_layout and $content_for_layout variables are filled in by Cake automatically depending on what the current page request is and the title and content are fairly self-explanitory.  The scripts variable lets you specify scripts on a per-page basis but still include them in the &lt;head&gt; section.  The $html-&gt;xxx code snippets are part of the <a href="http://book.cakephp.org/view/206/Inserting-Well-Formatted-elements">Cake HtmlHelper</a>. This allows you to insert well formatted elements easily &#8211; the $html-&gt;css(&#8216;default&#8217;) includes the stylesheet &#8220;css/default.css&#8221; (this is stored in the your_app_dir/app/webroot/css directory), and the $html-&gt;link lines let you point to different parts of your app easily. You could just add normal links, such as &lt;a href=&#8221;/news/&#8221;&gt;, but pointing to the controller allows a bit of flexibility if you want to change anything further down the line.</p>
<h3>Adding a splash page</h3>
<p>As it was an art portfolio website, it was decided a splash page would be useful to have, to give a good first impact when entering the site and the ability to show off a bit of artwork right away. Cake uses its built-in pages controller to handle static pages, and the different pages are stored in the folder your_app_dir/app/views/pages. To view a page, you navigate to the URL your_app/pages/pagename. Here, the pages controller doesn&#8217;t take an action, so the additional directory level on the URL is an argument passed to the controller, in this case the name of the page to display.</p>
<p>Cake also automatically serves up a default page, called &#8220;home&#8221;, when a user requests the root of your_app. The name of this page is set by Cake&#8217;s router, and if we look in your_app_dir/app/config/routes.php, we see at the bottom, the lines:</p>
<pre class="brush: php">
/**
* Here, we are connecting &#039;/&#039; (base path) to controller called &#039;Pages&#039;,
* its action called &#039;display&#039;, and we pass a param to select the view file
* to use (in this case, /app/views/pages/home.ctp)...
*/
Router::connect(&#039;/&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;home&#039;));
/**
* ...and connect the rest of &#039;Pages&#039; controller&#039;s urls.
*/
Router::connect(&#039;/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;));
</pre>
<p>The comments tell us what&#8217;s going on &#8211; this is what maps the pages to the locations I have talked about. You can add your own mappings here too if you like.  For our splash screen however, we can just make use of the already defined &#8220;home&#8221; page, so edit this to make it look how you want, you&#8217;ll find it in your_app_dir/app/views/pages/home.ctp. Mine looked like this:</p>
<pre class="brush: php">
&lt;?php $this-&gt;layout = &quot;splash&quot; ?&gt;
&lt;div id=&quot;splash&quot;&gt;
&lt;?php echo $html-&gt;image(&quot;splash.png&quot;,
array(&quot;alt&quot; =&gt; &quot;King Jon Illustration&quot;,
&quot;url&quot; =&gt; array(&quot;controller&quot; =&gt; &quot;news&quot;)));?&gt;
&lt;/div&gt;
</pre>
<p>A couple of things to note here. The first line $this-&gt;layout = &#8220;splash&#8221;, tells Cake not to use the &#8220;default&#8221; layout we created earlier, but to instead use one called &#8220;splash&#8221;.  I sneakily created a splash layout without telling you here, but it is in fact just an exact copy of the default layout with the navigation div removed, to give the page a more &#8220;splashy&#8221; feel.</p>
<p>Next, I used the image HtmlHelper to include an image called &#8220;splash.png&#8221; &#8211; this is located in my_app_dir/app/webroot/img, the location the image helper looks in. The second argument is an array of additional attributes, &#8220;alt&#8221; being the alt text, and &#8220;url&#8221; puts an &lt;a&gt; element around the image, creating a link to the specified address.</p>
<h3>Admin section authentication</h3>
<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/authentic-screen.png"><img class="alignleft size-medium wp-image-251" title="auth-screen" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/authentic-screen-300x187.png" alt="auth-screen" width="300" height="187" /></a>At the minute, all our sections are wide open for anyone to just stroll in and start adding news, posting works, and generally delete or edit existing pieces of data. This clearly isn&#8217;t ideal, so next on the agenda is sorting this out. We&#8217;ll use the <a href="http://book.cakephp.org/view/172/Authentication">Authentication component</a> for this.</p>
<p>First of all, we want all add/edit capabilities to be kept within the admin section, so the first step is to remove the non-admin versions of these. Go through all five of the your_app_dir/app/controllers/*_controller.php, and delete the functions &#8220;add&#8221; and &#8220;edit&#8221; that were automatically generated. Next, clean up the views associated with these functions &#8211; delete the two files your_app_dir/app/views/*/add.ctp and edit.ctp in all five of the view directories. This means now we can only add and edit our data by navigating to your_app/<strong>admin</strong>/controller/add etc.</p>
<p>We&#8217;re going to want to use authentication for all our controllers, as all of them have an admin section that we need to login for. Instead of telling each controller to use this component individually, we can tell the whole controller superclass that we want to use it, to save repetition. Open the file your_app_dir/app/app_controller.php and add the line in the class definition like so:</p>
<pre class="brush: php">

class AppController extends Controller {
var $components = array(&#039;Auth&#039;);
}
</pre>
<p>Now if you try and visit an admin page in your_app, you&#8217;ll be greeted with an error messages telling you there&#8217;s no login action in the Users controller, which is where the Auth component looks by default, so we&#8217;d better add this in. Edit the file your_app_dir/app/controllers/users_controller.php, and right at the bottom of the class definition, add these two functions:</p>
<pre class="brush: php">

function admin_login() {
}
function admin_logout() {
$this-&gt;Redirect($this-&gt;Auth-&gt;logout());
}
</pre>
<p>Now try and navigate to an admin section again. You&#8217;re told that there&#8217;s a missing view this time! Better do what Cake says and add one in. Create the new file your_app_dir/app/views/users/admin_login.ctp, and fill it with the following skeleton login form:</p>
<pre class="brush: php">

&lt;?php
if  ($session-&gt;check(&#039;Message.auth&#039;)) $session-&gt;flash(&#039;auth&#039;);
echo $form-&gt;create(&#039;User&#039;, array(&#039;action&#039; =&gt; &#039;admin_login&#039;));
echo $form-&gt;input(&#039;username&#039;);
echo $form-&gt;input(&#039;password&#039;);
echo $form-&gt;end(&#039;Login&#039;);
?&gt;
</pre>
<p>Now there are two problems: we&#8217;re greeted with a login for all the admin sections &#8211; a slight problem as we don&#8217;t have credentials&#8230; we&#8217;ve locked ourselves out of the whole website! There are also some error messages when we try and view the non-admin sections of the site, which seem to want us to login but can&#8217;t find a login() action (remember we only created admin_login, and didnt bother with login). Fortunately, we can get around these problems by adding exceptions to the authentication. Open up the users controller, your_app_dir/app/controllers/users_controller.php, and then add in the following <a href="http://book.cakephp.org/view/60/Callbacks">controller callback function</a> (I added it in near the top):</p>
<pre class="brush: php">

function beforeFilter() {
$this-&gt;Auth-&gt;allow(&#039;admin_add&#039;, &#039;admin_index&#039;);
}
</pre>
<p>This gives access to the admin add and index (which lists all users) actions of the users controller. So now, navigate to your_app/admin/users/add, and create a login for yourself! You&#8217;ll probably want to remove the allow line once you&#8217;ve added yourself to prevent anyone else creating a login for themselves when you&#8217;re not looking.</p>
<p>We&#8217;re still however stuck with the problem that none of the non-admin sections work, so we need to add an Auth exception to all non-admin sections. The best way to do this is by adding the following into the your_app_dir/app/app_controller.php AppController class definition, underneath where we told it to load the Auth component earlier:</p>
<pre class="brush: php">

function beforeFilter(){
$admin = Configure::read(&#039;Routing.admin&#039;);
if (isset($this-&gt;params[$admin]) and $this-&gt;params[$admin]){
//$this-&gt;layout = &#039;admin&#039;;
}
else {
$this-&gt;Auth-&gt;allow();
}
}
</pre>
<p>Now we should be able to navigate the site without any problems. The commented out line above allows the future addition of an admin.ctp layout file that will automatically be loaded when viewing admin sections &#8211; I haven&#8217;t done this yet though.</p>
<p>The next phase of the project is to go through and edit all the views, layouts &amp; CSS and get them looking how you want, and this is largely an exercise in usual web development &#8211; you can take a look at the default views to see how to include data provided by Cake  fairly easily. If I come across anything else I think might be of help while I&#8217;m building the rest of the site, I&#8217;ll make small posts for those too. Hopefully you&#8217;ve been able to follow this introduction to Cake so far, but if not drop me a line in the comments below and I&#8217;ll try and give you a hand where I can. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>CakePHP Tutorial Part 1: Bake Utility</title>
		<link>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/</link>
		<comments>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 17:42:35 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[bake]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=129</guid>
		<description><![CDATA[A friend of mine recently asked me to help him build an online portfolio for his illustration pieces, and I decided to use CakePHP 1.2 to get the back end up and running quickly. I thought someone might find a tutorial taking a simple website through from start to finish useful, so this tutorial series [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-130" title="cake-logo" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/cake-logo.png" alt="cake-logo" width="180" height="180" />A friend of mine recently asked me to help him build an online portfolio for his illustration pieces, and I decided to use <a href="http://cakephp.org/" target="_blank">CakePHP 1.2</a> to get the back end up and running quickly. I thought someone might find a tutorial taking a simple website through from start to finish useful, so this tutorial series will do just that. This part of the series takes you through the first few steps I took to get the basic code together.  You&#8217;ll need a web server and database server such as MySQL, and some basic PHP and webserver management knowledge. We&#8217;ll be using Cake&#8217;s &#8220;bake&#8221; utility to create the basic code as well, so you&#8217;ll need console access to your webserver, and PHP&#8217;s command line utility (in Ubuntu/PHP5 you can just install the package php5-cli).</p>
<p><span id="more-129"></span></p>
<h3>Downloading and setting up CakePHP</h3>
<p>Create a new directory on your webserver where your cake website will reside (or just use the web root if this is going to be the main webpage).  Next, we&#8217;ll need to actually download CakePHP.  If you have shell access to your webserver, you can use SVN to get the latest stable release automatically: navigate to the directory and use the command (note the &#8220;.&#8221; at the end of the command)</p>
<pre>$ svn checkout https://svn.cakephp.org/repo/trunk/cake/1.2.x.x/ .</pre>
<p>to do so.  If you don&#8217;t know what any of this means, just download the latest stable release from the CakePHP website and extract the files into the directory you created &#8211; make sure the various .htaccess files don&#8217;t go astray in the process.</p>
<p>Some standard setup is also required: we need to tell cake how to connect to our database server, to do this follow the steps on <a href="http://book.cakephp.org/view/331/Cake-Database-Configuration">this page</a>. There&#8217;s also a couple of optional (but recommended) configuration steps <a href="http://book.cakephp.org/view/332/Optional-Configuration">here</a>. After this, you should be able to browse to the directory in a web browser and see the default page &#8211; there shouldn&#8217;t be any errors or warnings if all configuration has been completed correctly (N.B. if the default page looks a bit plain &#8211; no colours, CSS styles etc., then you probably have a mod_rewrite issue, check out <a href="http://book.cakephp.org/view/333/A-Note-on-mod_rewrite">this page</a>).</p>
<p>Now we can begin work on the site.</p>
<h3>Bake a cake</h3>
<p>Cake&#8217;s bake utility is a handy way of generating the basic code structure for a web application, saving a lot of the tedious grunt work that often comes with setting up a new project. The general idea is often seen in frameworks that take advantage of the MVC (model-view-controller) programming pattern (such as Ruby on Rails, and others). It involves creating a database structure that describes the various data entites &#8211; or &#8220;models&#8221; &#8211; of our application, then running a script that reads this structure and generates the framework code for the models. It can then generate standard interfaces (or &#8220;views&#8221;) for displaying the data, and &#8220;controllers&#8221; which tie our interfaces and models together, allowing data to be input and manipulated. Of course, these standard pieces of generated code probably won&#8217;t be exactly what we want, but they can provide a great starting point to work from and then tweak.</p>
<p>First of all, we&#8217;ll create our database structure. I&#8217;m using an empty database for this project, although if you&#8217;re using a database with tables from other projects in, you can set Cake to work with a table prefix fairly easily. Let&#8217;s get to work building the tables.</p>
<p>The first model will be &#8220;News&#8221;, containing data for a news section where the owner can post updates and information onto the site.  To represent this, I created a table &#8220;news&#8221;, with four fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key <em>(A unique identifier for each record)</em></li>
<li><strong>date</strong> &#8211; type: date</li>
<li><strong>title</strong> &#8211; type: text</li>
<li><strong>body</strong> &#8211; type: text</li>
</ul>
<p>The next model is for representing finished works placed onto the site &#8211; the main part of the portfolio. Create a table called &#8220;works&#8221; with the four fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key</li>
<li><strong>date</strong> &#8211; type: date</li>
<li><strong>title</strong> &#8211; type: text</li>
<li><strong>desc</strong> &#8211; type: text</li>
</ul>
<p>Next up, a sketches model. This is pretty much the same as &#8220;works&#8221; but will contain sketches as opposed to finished pieces. Create a table called &#8220;sketches&#8221; with the same four fields as above.</p>
<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-1.png"><img class="alignright size-medium wp-image-153" title="database-screenshot" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-1-300x187.png" alt="database-screenshot" width="300" height="187" /></a>A friends model for a page that will contain links to websites belonging to friends of the owner, along with a thumbnail and description. Create the table &#8220;friends&#8221;, with the fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key</li>
<li><strong>name</strong> &#8211; type: text</li>
<li><strong>url</strong> &#8211; type:  text</li>
<li><strong>desc</strong> &#8211; type:  text</li>
</ul>
<p>There is one last model we&#8217;ll need: &#8220;users&#8221;. By creating a table with a username/password, we can let the owner login to manage the site, add new works, sketches and friends. Multiple users will mean we can also have a login to test out the site. So create the &#8220;users&#8221; table, with fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key</li>
<li><strong>username</strong> &#8211; type: varchar(20)</li>
<li><strong>password</strong> &#8211; type:  varchar(50)</li>
<li><strong>displayname</strong> &#8211; type:  varchar(20) (Name shown when making posts etc &#8211; can be different from login name)</li>
</ul>
<p>Now all our tables are created, we can get to baking. In a console, navigate to yourdir/cake/console, and then run the command</p>
<pre>$ ./cake bake</pre>
<p>and you&#8217;ll be presented with:</p>
<pre><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-2.png"><img class="alignright size-medium wp-image-154" title="console-screenshot" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-2-300x187.png" alt="console-screenshot" width="300" height="187" /></a>Welcome to CakePHP v1.2.2.8120 Console
---------------------------------------------------------------
App : app
Path: /home/dave/public_html/kingjon/app
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
&gt;</pre>
<p>at this point, if you haven&#8217;t setup your database configuration yet, you can create it with the &#8220;[D]atabase Configuration&#8221; option. We&#8217;ll be choosing the &#8220;[M]odel&#8221; option however:</p>
<pre>&gt; m
---------------------------------------------------------------
Bake Model
Path: /home/dave/public_html/kingjon/app/models/
---------------------------------------------------------------
Possible Models based on your current database:
1. Friend
2. News
3. Sketch
4. User
5. Work
Enter a number from the list above, type in the name of another model, or 'q' to exit
[q] &gt;</pre>
<p>notice our database tables have been read, and cake has automatically figured out that an entry in &#8220;works&#8221; will be a &#8220;Work&#8221;,  &#8220;sketches&#8221; give a &#8220;Sketch&#8221; and so on, but &#8220;news&#8221; is still &#8220;News&#8221;.  We may as well start with the first entry, so enter 1, and hit enter. You&#8217;ll be asked the following:</p>
<pre>[q] &gt; 1
Would you like to supply validation criteria for the fields in your model? (y/n)
[y] &gt;</pre>
<p>Cake has a set of predefined validation criteria to make sure that data entered for a model is correct. We may as well take advantage of these, so hit &#8220;y&#8221; and press return.</p>
<p>Next Cake goes through each of the fields in our table, and asks what validation criteria we want for each. <strong>id</strong> is first, and I chose &#8220;blank&#8221; (number 3 in my case, athough I guess this number may change depending on which version of cake you&#8217;re using). This ensures that no data is entered for the id, which is what we want as the field is auto generated by mySQL&#8217;s auto_increment. For <strong>name</strong> I chose &#8220;Do not do any validation on this field&#8221; as the name can contain any text. For <strong>url</strong> I chose the rather fitting &#8220;url&#8221; (number 27) validation type. Finally, for <strong>desc</strong> I chose &#8220;Do not do any validation on this field&#8221; as well.</p>
<p>A final couple of questions now pop up: model associations &#8211; for this I just hit &#8220;n&#8221; as our model is simple and has no relational properties &#8211; and a confirmation to check your settings are ok:</p>
<pre>---------------------------------------------------------------
The following Model will be created:
---------------------------------------------------------------
Name:       Friend
Validation: Array
(
    [id] =&gt; blank
    [url] =&gt; url
)

Associations:
---------------------------------------------------------------
Look okay? (y/n)
[y] &gt;</pre>
<p>Confirm this and there&#8217;s a final question about SimpleTest and unit test files. This is to do with Cake&#8217;s testing framework which I personally haven&#8217;t tried, and as this is just a simple project I won&#8217;t other using it, so just hit &#8220;n&#8221; here.  Congratulations, you&#8217;ve successfully baked your first model!</p>
<p>Continue the process now, and bake the other models with appropriate validation criteria (I used &#8220;blank&#8221; for all the IDs, &#8220;date&#8221; for the date fields, and no validation for all the title/description fields &#8211; although for the users table, I chose &#8220;notEmpty&#8221; for the username, password and displayname fields as blank entries here would cause problems).</p>
<p>Next up, time to bake some controllers. I&#8217;ll show you the output from my run through first including the options I chose, and explain to you afterwards what some of them mean and why I chose them:</p>
<pre>What would you like to Bake? (D/M/V/C/P/Q)
&gt; c
---------------------------------------------------------------
Bake Controller
Path: /home/dave/public_html/kingjon/app/controllers/
---------------------------------------------------------------
Possible Controllers based on your current database:
1. Friends
2. News
3. Sketches
4. Users
5. Works
Enter a number from the list above, type in the name of another controller, or 'q' to exit
[q] &gt; 1
---------------------------------------------------------------
Baking FriendsController
---------------------------------------------------------------
Would you like to build your controller interactively? (y/n)
[y] &gt; y
Would you like to use scaffolding? (y/n)
[n] &gt; n
Would you like to include some basic class methods (index(), add(), view(), edit())? (y/n)
[n] &gt; y
Would you like to create the methods for admin routing? (y/n)
[n] &gt; y
Would you like this controller to use other helpers besides HtmlHelper and FormHelper? (y/n)
[n] &gt; n
Would you like this controller to use any components? (y/n)
[n] &gt; n
Would you like to use Sessions? (y/n)
[y] &gt; y
You need to enable Configure::write('Routing.admin','admin') in /app/config/core.php to use admin routing.
What would you like the admin route to be?
Example: www.example.com/admin/controller
What would you like the admin route to be?
[admin] &gt; 

---------------------------------------------------------------
The following controller will be created:
---------------------------------------------------------------
Controller Name:  Friends
---------------------------------------------------------------
Look okay? (y/n)
[y] &gt;

Creating file /home/dave/public_html/kingjon/app/controllers/friends_controller.php
Wrote /home/dave/public_html/kingjon/app/controllers/friends_controller.php
SimpleTest is not installed.  Do you want to bake unit test files anyway? (y/n)
[y] &gt; n</pre>
<p>Ok, I started by building the controller for the friends section again. Building interactively gives you access to more options in the setup, so I went for that. <a href="http://book.cakephp.org/view/105/Scaffolding">Scaffolding</a> is basically a flag you set in your controller telling cake that you want basic skeleton app behaviour to be created at runtime. By baking we are given the advantage of pre-generating code that does more or less the same thing, but that we can also edit later, so choosing &#8220;n&#8221; for scaffolding is a wise plan in our case. The next question about basic methods is where our pre-generated skeleton code comes from, so choose &#8220;y&#8221; here. Admin routing creates an admin section for adding/deleting/modifying records. As we don&#8217;t want visitors to the website to be able to do this, but the portfolio owner will be wanting to do this, an admin section is a good idea, so &#8220;y&#8221; to this question as well. We are now asked about <a href="http://book.cakephp.org/view/181/Core-Helpers">helpers</a>. Helpers are libraries built into cake that add functionality and generally make your life easier. At the minute we&#8217;ll just use the default two, so choose &#8220;n&#8221;, although more can be added later easily if we need them. Next up are <a href="http://book.cakephp.org/view/170/Core-Components">components</a> which are similar to helpers, although these are more at a behind-the-scenes level, and helpers are used more for displaying and formatting data on the interface side of things. Again we may use some of these later, but at the minute just hit &#8220;n&#8221; for components. Finally hit &#8220;y&#8221; for sessions, and I agreed to the default name for the admin section, &#8220;admin&#8221;, although you may wish to change this.  Hit &#8220;y&#8221; for the confirmation, and then &#8220;n&#8221; for the testing question again.</p>
<p>Repeat this for the other controllers.</p>
<p>Finally we have to make some views, so here we go again, although this step is a lot quicker. Choose &#8220;[V]iew&#8221; from the main menu, and I&#8217;m starting off with Friends again. The first question it asks is seemly about the scaffolding again:</p>
<pre>Would you like to create some scaffolded views (index, add, view, edit) for this controller?
NOTE: Before doing so, you'll need to create your controller and model classes (including associated models). (y/n)
[n] &gt; y</pre>
<p>Before we wanted nothing to do with scaffolding, but here we hit &#8220;y&#8221;: this generates the views for the basic class methods we agreed to in the controller generation. We&#8217;re then asked about admin routing views, and we press &#8220;y&#8221; again, and the script tells us it&#8217;s generated the files we need.</p>
<p>Repeat this process for the other views, and then we&#8217;re done with baking.</p>
<h3>Let&#8217;s see what we&#8217;ve done so far&#8230;</h3>
<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot.png"><img class="alignleft size-medium wp-image-143" title="defaut-news-screenshot" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-300x187.png" alt="defaut-news-screenshot" width="300" height="187" /></a>Now what exactly has all that baking achieved? If you go to the index page of your app directory in the web browser, you&#8217;ll just be greeted with the same welcome page. But try navigating to your_app_folder/news or your_app_folder/works and a new page comes up. You can give adding a piece of a news a go with the &#8220;New News&#8221; link on the news page. A form pops up letting you fill in the date, title and post body, and you&#8217;ll notice the entry form lets you fill in the date correctly and so on.  We aren&#8217;t prompted to enter an ID because our validation criteria said we wanted this to be blank as it would be generated automatically. Once the post has been added, an entry comes up on the main page, letting us view the individual post, edit it or delete it.</p>
<p>In fact, if you&#8217;ve been keeping an eye on the URLs, you&#8217;ll have noticed that they take the form your_app_folder/controller/action. The actions were generated automatically by our baking process, and we&#8217;ll take a look at them in a bit more detail later on.</p>
<p>You&#8217;ll notice you can also go to your_app_folder/admin/news to get the same page &#8211; this is our admin routing. At the minute there is no difference between the two sections, but we&#8217;ll edit it so that you wont be able to add/edit/delete thing unless you&#8217;re in the admin section, and logged in correctly.</p>
<p>As you can see, baking has set up all the basic logic for our various sections, we just need to tweak it and glue it together a bit, and I&#8217;ll deal with that in the <a href="http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/">next part of the tutorial</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Using Lightbox with Apache directory listings as an image gallery</title>
		<link>http://www.actionshrimp.com/2009/03/using-lightbox-with-apache-directory-listings-as-an-image-gallery/</link>
		<comments>http://www.actionshrimp.com/2009/03/using-lightbox-with-apache-directory-listings-as-an-image-gallery/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 21:48:22 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[directory]]></category>
		<category><![CDATA[gallery]]></category>
		<category><![CDATA[lightbox]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=79</guid>
		<description><![CDATA[As you may know, if it can&#8217;t find an index.html the apache web server will show a list of files in the current directory. I was browsing through lists of images on my file server the other day and I thought, wouldn&#8217;t it be nice to have a next button? So I started digging around.
In [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/lightbox.jpg"><img class="alignleft size-medium wp-image-114" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/lightbox-300x184.jpg" alt="Screenshot" width="300" height="184" /></a>As you may know, if it can&#8217;t find an <code>index.html</code> the apache web server will show a list of files in the current directory. I was browsing through lists of images on my file server the other day and I thought, wouldn&#8217;t it be nice to have a next button? So I started digging around.</p>
<p>In the end I used a wonderful little script called <a href="http://www.lokeshdhakar.com/projects/lightbox2/">Lightbox 2</a> and a bit of JavaScript <a href="http://prototypejs.org">Prototype</a> magic to produce <a href="http://files.mattjbray.com/lightbox_images">this</a> (try clicking on the image files).</p>
<p>The directory listings are provided by an apache module going by the name of <code>mod_autoindex</code>. This module allows you to insert a custom header and footer through the directives <code>HeaderName</code> and <code>ReadmeName</code>. The plan is to insert some HTML that includes the Lightbox code and tags all the links to images with the <code>rel=lightbox</code> attribute that Lightbox uses to function.</p>
<p><span id="more-79"></span></p>
<p>Create a directory called <code>lightbox</code> in your server&#8217;s document root. Download <a href="http://www.lokeshdhakar.com/projects/lightbox2/#download">Lightbox 2</a> and extract it to that directory (go to http://www.yourwebsite.com/lightbox to try it out). To get the Lightbox &#8216;loading&#8217; and &#8216;next&#8217; images to show up, you need to edit a couple of lines in the configuration section of <code>js/lightbox.js</code> that comes with Lightbox. Change the following</p>
<blockquote>
<pre>LightboxOptions = Object.extend({
    fileLoadingImage:        'images/loading.gif',
    fileBottomNavCloseImage: 'images/closelabel.gif',</pre>
</blockquote>
<p>to look like</p>
<blockquote>
<pre>LightboxOptions = Object.extend({
    fileLoadingImage:        '/lightbox/images/loading.gif',
    fileBottomNavCloseImage: '/lightbox/images/closelabel.gif',</pre>
</blockquote>
<p>I also adjusted <code>resizeSpeed</code> to 9 to make it feel a little snappier, change this to your taste.</p>
<p>Now create a new file called <code>lightbox.html</code> in your <code>/lightbox</code> directory and copy and paste the following:</p>
<blockquote>
<pre>&lt;script src="/lightbox/js/prototype.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="/lightbox/js/scriptaculous.js?load=effects,builder" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="/lightbox/js/lightbox.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;!--
    // Insert the lightbox stylesheet into &lt;head&gt;
    var stylesheet = new Element('link', {  'rel': 'stylesheet',
                                            'href': '/lightbox/css/lightbox.css',
                                            'type': 'text/css',
                                            'media': 'screen'
                                         });
    $$('head')[0].appendChild(stylesheet);

    // Check for links preceded by the image icon provided by mod_autoindex.
    // On my setup the src attribute in the img tag preceding a link to an image
    // is "/icons/image2.gif". This is used to identify links to images.
    $$("a").each( function(elmt) {
            // The default output is tabular, so check the previous cell for the img tag
            imgelmt = elmt.up().previous().down()
            // If the FancyIndexes option is set, the output is formatted differently
            if (imgelmt == undefined) { imgelmt = elmt.previous('img') }
            if (imgelmt.readAttribute('src') == "/icons/image2.gif")
            {
                elmt.setAttribute('rel', 'lightbox[images]');

                // As ps suggested, provide a link to the image in the lightbox description
                link = "&lt;a href='" + elmt.readAttribute('href') + "'&gt;" +
                        elmt.innerHTML.stripScripts().stripTags() + "&lt;/a&gt;";
                elmt.setAttribute('title', link );
            }
        } );
// --&gt;&lt;/script&gt;</pre>
</blockquote>
<p>Now all you have to do is tell apache to include this file in its directory listing page. Simply paste the following two lines into a file named <code>.htaccess</code> and copy it to any directory that you want Lightbox to appear in.</p>
<blockquote>
<pre>Options Indexes
ReadmeName /lightbox/lightbox.html</pre>
</blockquote>
<p>Et voila! No php, no databases to maintain. Image galleries don&#8217;t get much simpler than that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/03/using-lightbox-with-apache-directory-listings-as-an-image-gallery/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Installing awesome Window Manager on Ubuntu Intrepid</title>
		<link>http://www.actionshrimp.com/2009/02/installing-awesome-window-manager-on-ubuntu-intrepid/</link>
		<comments>http://www.actionshrimp.com/2009/02/installing-awesome-window-manager-on-ubuntu-intrepid/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 21:33:08 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[awesome]]></category>
		<category><![CDATA[awm]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[window]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=52</guid>
		<description><![CDATA[Today I had a go at installing awesome window manager. awesome is a great tiling window manager, useful if you have a large monitor and are fed up with having one window taking up all the space when it doesn&#8217;t really need it all. For example, having firefox maximised on a 1920&#215;1200 resolution monitor can [...]]]></description>
			<content:encoded><![CDATA[<p>Today I had a go at installing <a href="http://awesome.naquadah.org/">awesome window manager</a>. awesome is a great tiling window manager, useful if you have a large monitor and are fed up with having one window taking up all the space when it doesn&#8217;t really need it all. For example, having firefox maximised on a 1920&#215;1200 resolution monitor can mean you end up with very large sentences that spread across the screen, decreasing readability. Unfortunately the version of awesome in the Interpid repos is 2.3.2-1, which is now deprecated, and the current stable release is version 3.1-1.</p>
<p><img class="aligncenter size-full wp-image-67" title="awesomescreenmini" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/02/awesomescreenmini.png" alt="awesomescreenmini" width="200" height="98" /></p>
<p>The website suggests building from source &#8211; I attempted this but there are currently a couple of issues with compilation mentioned in the wiki, and even with the fix suggested I couldn&#8217;t quite get it to work &#8211; although I didn&#8217;t try too hard it must be said; instead I found another method which I will walk you through now.</p>
<p><span id="more-52"></span></p>
<h2>Installing and Trying It Out</h2>
<p>The method I ended up using (thanks to my buddy Matt for figuring this out) revolves using binaries from the Debian experimental repository, which seem to work perfectly. First, you can download the awesome 3.1-1 package (N.B. The binaries I&#8217;m linking to here from Debian&#8217;s website are for i386, for others just search for them on the site), and try and install it with:</p>
<pre>wget http://ftp.uk.debian.org/debian/pool/main/a/awesome/awesome_3.1-1_i386.deb
sudo dpkg -i awesome_3.1-1_i386.deb</pre>
<p>However, it will spit out a list of dependencies it couldn&#8217;t manage &#8211; these are packages that are also outdated in the current Ubuntu repos. So next, fetch the ones you need which are listed below:</p>
<pre>wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-atom1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-aux0_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-event1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-icccm1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-keysyms0_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-property1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-render-util0_0.3.2-1_i386.deb</pre>
<p>Then try and install them all with dpkg:</p>
<pre>sudo dpkg -i awesome_3.1-1_i386.deb libxcb-atom1_0.3.2-1_i386.deb libxcb-aux0_0.3.2-1_i386.deb \
libxcb-event1_0.3.2-1_i386.deb libxcb-icccm1_0.3.2-1_i386.deb libxcb-property1_0.3.2-1_i386.deb \
libxcb-render-util0_0.3.2-1_i386.deb libxcb-keysyms0_0.3.2-1_i386.deb</pre>
<p>At this point, it might spit out that it needs some extra packages &#8211; these are packages that you should just be able to install normally with synaptic or apt: I had to install menu for example,  you may have to install some others as I had a few other dependencies installed from trying to build from source earlier on.  Once you have all the packages, run the above command again to install awesome.</p>
<p>Once awesome is installed, we need a configuration file. A default config file is provided, so go ahead and copy it to your home dir:</p>
<pre>mkdir ~/.config/awesome
cp /etc/xdg/awesome/rc.lua ~/.config/awesome/rc.lua</pre>
<p>Now we can see if awesome works &#8211; kill your current window manager (in my case compiz), then fire up awesome:</p>
<pre>killall compiz.real &amp;&amp; awesome&amp;</pre>
<p>Hopefully everything has gone to plan, and awesome should now be running! Hooray! Have a little play around with it, mess with the config file a bit and see if you like it. Some useful key-bindings are:</p>
<ul>
<li>Win + Enter &#8211; launch a terminal</li>
<li>Win + F1 &#8211; run a command</li>
<li>Win + J/K &#8211; switch windows (à la vim)</li>
<li>Win + H/L &#8211; resize major/minor divide</li>
<li>Win + Shift + J/K &#8211; move windows</li>
<li>Win + Space &#8211; change layout</li>
<li>Win + Ctrl + r &#8211; restart awesome, for example to update if you change the config file</li>
</ul>
<p>There are loads more keybindings that you can find/change in the config file if you wanna know what they all do exactly.</p>
<p>If after using awesome for a while you decide you want to keep it, there are a few loose ends to tie up.</p>
<h2>Setting awesome as the Default Window Manager</h2>
<p>First, fire up gconf-editor:</p>
<pre>gconf-editor</pre>
<p>On the list on the left, goto:</p>
<pre> desktop &gt; gnome &gt; session</pre>
<p>First of all, we&#8217;ll get rid of the gnome-panels &#8211; awesome already has its own. On the right, there is a <strong>name/value pair</strong> with name &#8216;required_components_list&#8217;, containing &#8220;[windowmanager, panel, filemanager]&#8220;. Remove panel, so it becomes &#8220;[windowmanager, filemanager]&#8220;.</p>
<p>Next we actually tell gnome to load in awesome instead of compiz. On the list on the left, choose the <strong>folder</strong> required_components. Change the windowmanager field from &#8221;compiz&#8217; to &#8216;awesome&#8217;.</p>
<p>Finally, you&#8217;ll probably wan&#8217;t to disable nautilus&#8217;s desktop (where the desktop icons live etc.) as it can do funny things, and with your magical new tiling windows you will probably never see the desktop. To do this, from the list on the left choose</p>
<pre>apps &gt; nautilus &gt; preferences</pre>
<p>and when here, uncheck show_desktop.</p>
<p>Now you can kiss sweet goodbye to all the remnants of your old desktop &#8211; log out of your system and log back in again to see it take effect. WARNING: If something has gone wrong and awesome doesn&#8217;t load (maybe you mispelt it in gconf-editor or something), you should still be able to find a way to edit the gconf preferences, but it took me a while to figure out how to logout when the normal gnome logout button had disappeared. To logout in this situation, type gnome-session-save &#8211;kill.</p>
<h2>Customising and Configuring</h2>
<p>Due to the highly keyboard oriented nature of awesome, you may now want to install a launcher. A couple of good ones are Gnome-Do (if you opt for this, you will have to change the binding from Win+Space in the awesome preferences, or reconfigure awesome&#8217;s binding for this combination), an all singing all dancing affair which I used for a while, or dmenu which is quite a lot simpler and I&#8217;ve opted for in this case.</p>
<p>To install dmenu:</p>
<pre>sudo apt-get install dmenu</pre>
<p>Next we setup a keybinding for it to launch in the awesome config file. Underneath the line:</p>
<pre>-- {{{ Keybindings</pre>
<p>Add (here it is mapped to Win+P &#8211; change this if you like):</p>
<pre>-- dmenu
keybinding({ modkey }, "p", function () awful.util.spawn("`dmenu_path | dmenu -b`") end):add()</pre>
<p>Also, as awesome is aimed at uber geeks the time is displayed by default as&#8230;. unix time_t. Unless you&#8217;re some kind of magician, hunt down the section in the config file that looks like this, and comment/uncomment accordingly:</p>
<pre>-- For unix time_t lovers
--mytextbox.text = " " .. os.time() .. " time_t "
-- Otherwise use:
mytextbox.text = " " .. os.date() .. " "</pre>
<p>Finally, I missed my CPU monitor. There is however a set of widgets you can get that adds functionality like this called wicked.</p>
<p>Install wicked:</p>
<pre>git clone git://git.glacicle.com/awesome/wicked.git
sudo cp wicked/wicked.lua /usr/share/awesome/lib/
sudo cp wicked/wicked.7.gz /usr/share/man/man7/</pre>
<p>in config file, underneath:</p>
<pre>-- {{{ Wicked Widgets</pre>
<p>Add in:</p>
<pre>-- {{{ Wicked Widgets
-- CPU Usage Graph
cpugraphwidget = widget({
type = 'graph',
name = 'cpugraphwidget',
align = 'left'
})
cpugraphwidget.height = 0.85
cpugraphwidget.width = 45
cpugraphwidget.bg = '#333333'
cpugraphwidget.border_color = '#0a0a0a'
cpugraphwidget.grow = 'right'

cpugraphwidget:plot_properties_set('cpu', {
fg = '#AEC6D8',
fg_center = '#285577',
fg_end = '#285577',
vertical_gradient = false
})
wicked.register(cpugraphwidget, wicked.widgets.cpu, '$1', 1, 'cpu')</pre>
<p>Then add in the cpugraphwidget into the mywibox[s].widgets line:</p>
<pre>mywibox[s].widgets = { mylauncher,
mytaglist[s],
mytasklist[s],
mypromptbox[s],
cpugraphwidget,
mytextbox,
mylayoutbox[s],</pre>
<p>For full instructions on <a href="http://awesome.naquadah.org/wiki/index.php?title=Wicked">how to use wicked</a>, and configure awesome, check out the <a href="http://awesome.naquadah.org/wiki/index.php?title=Main_Page">awesome wiki</a>. Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/02/installing-awesome-window-manager-on-ubuntu-intrepid/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Cryptic Crossword Solver</title>
		<link>http://www.actionshrimp.com/2008/12/cryptic-crossword-solver/</link>
		<comments>http://www.actionshrimp.com/2008/12/cryptic-crossword-solver/#comments</comments>
		<pubDate>Wed, 31 Dec 2008 02:03:07 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Misc.]]></category>
		<category><![CDATA[crossword]]></category>
		<category><![CDATA[cryptic]]></category>
		<category><![CDATA[solver]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=17</guid>
		<description><![CDATA[Click here for the cryptic crossword solver.
I have recently been working on a free cryptic crossword solver to be used by my sister and parents who are fanatics. It is linked to a database of around 250,000 words, with the word list from the UKACD. It lacks a few useful phrases, so if anyone has [...]]]></description>
			<content:encoded><![CDATA[<h2><a title="Cryptic Crossword Solver" href="http://www.actionshrimp.com/crossword-solver/">Click here for the cryptic crossword solver.</a></h2>
<p>I have recently been working on a <a href="http://www.actionshrimp.com/crossword-solver/">free cryptic crossword solver</a> to be used by my sister and parents who are fanatics. It is linked to a database of around 250,000 words, with the word list from the <a title="UK Advanced Cryptics Dictionary " href="http://cfaj.freeshell.org/wordfinder/UKACD17.shtml">UKACD</a>. It lacks a few useful phrases, so if anyone has access to a free cryptic phrase list please let me know in the comments so I can add it to the database.</p>
<p>The solver allows you to get a list of words that match letters and space patterns that you may already have in the crossword, as well as easily get definitions for words. There is also an anagram solver &#8211; useful for cryptic crosswords.  It currently needs a bit of a makeover, something I&#8217;ll do at some point soon hopefully. Any other suggestions or improvements, let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/12/cryptic-crossword-solver/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Logitech QuickCam E2500 on Ubuntu Skype</title>
		<link>http://www.actionshrimp.com/2008/08/logitech-quickcam-e2500-on-ubuntu-skype/</link>
		<comments>http://www.actionshrimp.com/2008/08/logitech-quickcam-e2500-on-ubuntu-skype/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 00:12:57 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[e2500]]></category>
		<category><![CDATA[quickcam]]></category>
		<category><![CDATA[skype]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=8</guid>
		<description><![CDATA[I recently discovered the wonders of skype, and tried to get my new webcam working with it under linux, and of course this proved to be quite tricky. After much fiddling I eventually got it to work, hopefully these steps will work for you too.

The gspca drivers are available from here, I was using a [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-127 alignleft" title="193818" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2008/08/193818.jpg" alt="193818" width="170" height="170" />I recently discovered the wonders of skype, and tried to get my new webcam working with it under linux, and of course this proved to be quite tricky. After much fiddling I eventually got it to work, hopefully these steps will work for you too.</p>
<p><span id="more-8"></span></p>
<p>The gspca drivers are available from <a href="http://mxhaard.free.fr/download.html">here</a>, I was using a specific version dated 20071224 to work with a patch file I found &#8211; many thanks to <a href="http://forums.quickcamteam.net/showthread.php?tid=310">redeye on the QuickCam team forums</a>. If you use a different version of the drivers, you can just examine the patch file and insert the changes manually.</p>
<p>First, download the drivers and the patch:</p>
<pre>wget http://mxhaard.free.fr/spca50x/Download/gspcav1-20071224.tar.gz
wget http://forums.quickcamteam.net/attachment.php?aid=86 -O patch.tar.gz</pre>
<p>Then extract and apply the patch:</p>
<p>(UPDATE: For Ubuntu 8.10 users, this patch may no longer work. Try downloading the patch <a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/01/gspcapatch.gz">here</a> instead, and then extract it using gzip -d gspcapatch.gz. Apply the extracted file in the same was as below, just neglect the -p1 switch, (so do: patch &lt; gspcapatch), you can just ignore the tar -xvf patch.tar.gz command).</p>
<pre>tar -xvf gspcav1-20071224.tar.gz
tar -xvf patch.tar.gz
cd gspcav1-20071224
patch -p1 &lt; ../quickcamE2500.diff</pre>
<p>There&#8217;s a handy build script included with the drivers so just run that (requires root):</p>
<pre>sudo ./gspca_build</pre>
<p>This generates the file</p>
<pre>gspca.ko</pre>
<p>which we use to replace the old gspca module.<br />
Check to see if the old module is loaded, you should see something like:</p>
<pre>dave@baracus:~$ lsmod | grep gspca
gspca                 680656  0
videodev               29440  1 gspca
usbcore               146028  9 gspca,snd_usb_audio,snd_usb_lib,usb_storage,usbhid,libusual,ehci_hcd,ohci_hcd</pre>
<p>We want to find out where it is, so do the following:</p>
<pre>sudo rmmod gspca
sudo modprobe -v gspca</pre>
<p>You should see something like:</p>
<pre>insmod /lib/modules/2.6.24-20-generic/ubuntu/media/gspcav1/gspca.ko</pre>
<p>That is the location of the file we&#8217;re looking for, so, replacing where appropriate with what was output for you above, type:</p>
<pre>sudo rmmod gspca
sudo rm /lib/modules/2.6.24-20-generic/ubuntu/media/gspcav1/gspca.ko
sudo mv gspca.ko /lib/modules/2.6.24-20-generic/ubuntu/media/gspcav1/
sudo modprobe gspca</pre>
<p>This should have loaded the new module in place of the old one. See if you have a video device:</p>
<pre>dave@baracus:~$ ls /dev/video*
/dev/video0</pre>
<p>You can try and run Skype now, and in fact, if you&#8217;re not using the camera for Skype, this may well be enough. But for the Skype users: see if you get any picture by testing in the video devices option menu (be warned, it can take a little while to show up there after skype loads, and a little while for the picture to show when you press the test button, so be patient). If anything show&#8217;s up at all that&#8217;s a plus. (UPDATE: If you&#8217;re using Ubuntu 8.10, and have used the alternative patch I posted in the other &#8220;UPDATE:&#8221; bracket above, the webcam may still not work in Skype at this point. There seems to be some issue with permissions in this version of the driver, so you may need to run skype as root if it doesn&#8217;t appear to be working. In a terminal type &#8220;sudo skype&#8221; and hit enter. It&#8217;ll ask for your root password, then launch skype. See if the webcam works now).</p>
<p>Originally, I had a black image, so I assumed the camera wasn&#8217;t working, but I soon realised that the image was there, just very dark &#8211; shining a light on it showed this was the case. I tried fiddling around with gstfakevideo for a while to try and alter the output, but there was a much simpler solution. The gspca driver itself can take options, and an autoexposure setting was ruining my lighting. To fix this, edit the file /etc/modprobe.d/options, and add a line at the bottom:</p>
<pre>options gspca gamma=1 autoexpo=0</pre>
<p>The gamma=1 may not be necessary, but if it still appears too dark or too light for your taste you can change this parameter as you like. Finally, reload the module:</p>
<pre>sudo rmmod gspca
sudo modprobe gspca</pre>
<p>and try out skype again. Hopefully it works!</p>
<p>I ran into quite a lot of other problems while I was trying this out, so if you come across any errors, drop a comment below and I&#8217;ll try and get back to you asap.</p>
<p><strong>UPDATE</strong>: I found a large problem when using the camera in Skype was that CPU usage would shoot up to 100%, causing things to freeze up and conversations to crash after a while. I had played around with <a href="http://code.google.com/p/gstfakevideo">gstfakevideo</a> a bit when trying to get the camera to work originally, and it seems using this when the camera already &#8216;works&#8217; means it uses up far less CPU. I haven&#8217;t had a chance to test it for a long period yet but it seems like it should do the trick. Here&#8217;s what I did:</p>
<p>First, download gstfakevideo using subversion (you may need to install the subversion package, sudo apt-get subversion probably does the trick, and then the command below will make a directory called gstfakevideo in your current location, so make sure it&#8217;s somewhere nice), then compile and install it:</p>
<pre>svn checkout http://gstfakevideo.googlecode.com/svn/trunk/ gstfakevideo
cd gstfakevideo
make
sudo make install</pre>
<p>gstfakevideo creates a new video stream using your webcam, which is formatted differently and skype seems to get along with it more. The only problem is, it outputs its stream to /dev/video0 which is where our webcam currently lives. So we have to move the webcam, but this is easy enough:</p>
<pre>sudo mv /dev/video0 /dev/video1</pre>
<p>(Actually, gstfakevideo seems to work for me with lower CPU without moving this &#8211; but try it moved first anyway). Watch out though, every time you reboot, your webcam will probably go to /dev/video0 by default, assuming you have no other video devices, so you will have to move stuff about to make a space in video0 each time. Now we see if it works:</p>
<pre>gstfakevideo v4lsrc device=/dev/video1 ! ffmpegcolorspace</pre>
<p>What this does is runs gstfakevideo, telling it that the source we&#8217;re using is a v4l source, and its from /dev/video1. The ffmpegcolorspace argument seems to be for making the stream YUV instead of RGB for some cameras so may not be necessary. It then launches skype, with hopefully the output below:</p>
<pre>dave@baracus:~$ gstfakevideo v4lsrc device=/dev/video1 ! ffmpegcolorspace
gst.c create_pipeline (155): pipeline created
gst.c create_pipeline (159): pipeline linked</pre>
<p>If you look in the skype video options now there will be no camera listed. You have to wait a while (it can take 30s or so), until you get some output, ending with something like:</p>
<pre>gst.c shim_ioctl (201): request=803c7601 nr 1
gst.c shim_ioctl (208): VIDIOCGCAP
gst.c shim_ioctl (313): result=0 error=0 Success</pre>
<p>Now a camera should show up in the video menu in skype, with a name like GStreamer fake video (/dev/video0). Try it out, and compare your CPU performance to before. Also try exiting skype, and moving your video source from /dev/video1 back to video0, and running gstfakevideo again, only with device=/dev/video0, and see if it works (and let me know your findings below!).</p>
<p>Finally if gstfakevideo works, we can clean it up so the command isn&#8217;t so long to type. The script should be stored in:</p>
<pre>/usr/local/bin/gstfakevideo</pre>
<p>(Can check this using):</p>
<pre>dave@baracus:~$ whereis gstfakevideo
gstfakevideo: /usr/local/bin/gstfakevideo</pre>
<p>So we edit this file (requires root):</p>
<pre>sudo gedit /usr/local/bin/gstfakevideo</pre>
<p>Now, find the line that looks like this:</p>
<pre>export GST_PIPE="videotestsrc is-live=true ! video/x-raw-yuv,width=640,height=480,framerate=10/1 ! videoscale ! ffmpegcolorspace ! vertigotv ! ffmpegcolorspace"</pre>
<p>and change it to (remember where you put your webcam source &#8211; if you moved it back to /dev/video0, change the device parameter accordingly):</p>
<pre>export GST_PIPE="v4lsrc device=/dev/video1 ! ffmpegcolorspace"</pre>
<p>and finally look a bit further down, and delete the line:</p>
<pre>export GST_PIPE="$*"</pre>
<p>Now Skype will launch with your faked video stream, just from the command gstfakevideo. Good luck! Let me know how you get on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/08/logitech-quickcam-e2500-on-ubuntu-skype/feed/</wfw:commentRss>
		<slash:comments>124</slash:comments>
		</item>
		<item>
		<title>jsvi and TiddlyWiki</title>
		<link>http://www.actionshrimp.com/2008/05/jsvi-and-tiddlywiki/</link>
		<comments>http://www.actionshrimp.com/2008/05/jsvi-and-tiddlywiki/#comments</comments>
		<pubDate>Tue, 13 May 2008 15:26:28 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[TiddlyWiki]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[jsvi]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=6</guid>
		<description><![CDATA[Note: This is a bit out of date now, but Chris Peplin has built a proper plugin for tiddlywiki which does this for the latest versions of everything. So check it out! If you&#8217;re still interested in the old way then read on&#8230;
When adding posts to my TiddlyWiki, I oft found myself craving vi, rather [...]]]></description>
			<content:encoded><![CDATA[<p><i>Note: This is a bit out of date now, but Chris Peplin has built <a href="http://github.com/peplin/jsvim-tiddly">a proper plugin</a> for tiddlywiki which does this for the latest versions of everything. So check it out! If you&#8217;re still interested in the old way then read on&#8230;</i></p>
<p style="text-align: left;">When adding posts to my TiddlyWiki, I oft found myself craving <a title="vi" href="http://en.wikipedia.org/wiki/Vi" target="_blank">vi</a>, rather than a simple textarea. There were a few options that involved using a plugin for Firefox such as mozEx, and using an external program to edit textareas. However, I found a nice &#8216;integrated&#8217; option instead.</p>
<p style="text-align: left;"><span id="more-6"></span></p>
<p style="text-align: left;"><a title="jsvi" href="http://gpl.internetconnection.net/vi/" target="_blank">jsvi</a> is an excellent javascript implementation of vi. I decided to try and integrate it into my TiddlyWiki, and the steps I took are shown below. To try out the final result, use the edit mode on my <a title="PhysiWiki" href="http://www.actionshrimp.com/physiwiki/" target="_blank">wiki</a>.</p>
<p style="text-align: center;"><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2008/05/jsvi.png"><img class="size-medium wp-image-7" title="jsvi" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2008/05/jsvi-300x225.png" alt="jsvi in action on my wiki" width="300" height="225" /></a></p>
<p style="text-align: left;"><em><strong>Be warned:</strong></em> <em>this is a bit of a dirty hack, and requires a few files external to the TiddlyWiki file, which makes TiddlyWiki a bit less portable. At some point it&#8217;d be nice if this was build as a TiddlyWiki plugin instead, but at the minute I&#8217;m not experienced enough with writing plugins for TW. There is also a slight bug which means you can&#8217;t scroll up while editing. </em></p>
<p style="text-align: left;">First of all, I installed the <a title="iFrameEditorPlugin" href="http://visualtw.ouvaton.org/old/VisualTW.old.html#iFrameEditorPlugin" target="_blank">iFrameEditorPlugin</a> from an old version of the <a title="VisualTW" href="http://visualtw.ouvaton.org/VisualTW.html" target="_blank">VisualTW</a> site. I don&#8217;t think VisualTW uses the plugin anymore, and has instead changed it&#8217;s wysiwig editors to using plugins rather than iFrames &#8211; a far superior solution, but one I didn&#8217;t have the time or ability for. The plugin alone is not quite enough though, and a few changes to it are required.</p>
<p style="text-align: left;">iFrameEditorPlugin loads an iFrame containing your editor, passes the editor the text from the body of the tiddler, you edit it, and then when you save the page, the plugin gets your changes and saves them to the tiddler. However, it expects you to use a custom field rather than the default text field, which is a slight problem in our case. The function getContent() is what actually performs this:</p>
<pre style="text-align: left;">getContent=function(tiddler, field) {
    var t,f;
    t=store.getTiddler(tiddler);
    f = t ? t.fields[field] : "";
    f = f ? f : "";
    return f;
}</pre>
<p style="text-align: left;">As you can see, it reads the field of the tiddler with t.fields[field]. To read the default text field instead, I added a new function to the plugin:</p>
<pre style="text-align: left;">getContentText=function(tiddler) {
 var t,f;
 t=store.getTiddler(tiddler);
 f = t ? t.text : "";
 f = f ? f : "";
 return f;
}</pre>
<p style="text-align: left;">Great. So that&#8217;s set up. There&#8217;s also another problem with the plugin &#8211; it was originally intended for use with wysiwig html style editors, but I enjoy editing my wiki content raw. Also, the content has to be passed in a URL to the editor, so strange characters in the URL will mess it up, so there were problem with escaping html entities and things like that. To get around this, I found a handy javascript function that converted html entities back to their original form, and added this to the top of the plugin (thanks to The JavaScript Source):</p>
<pre style="text-align: left;">/* This script and many more are available free online at
The JavaScript Source!! http://javascript.internet.com
Created by: Ultimater | http://webdeveloper.com/forum/member.php?u=30185 */
function html_entity_decode(str) {
  var ta=document.createElement("textarea");
  ta.innerHTML=str.replace(/&lt;/g,"&lt;").replace(/&gt;/g,"&gt;");
  return ta.value;
}</pre>
<p style="text-align: left;">Ok, now we actually have to use this function, so we edit the plugin a bit more. Look for the line that reads the data back from the iFrame:</p>
<pre style="text-align: left;">if(f) fields[f] = e.contentWindow.getContent();</pre>
<p style="text-align: left;">and change it to:</p>
<pre style="text-align: left;">if(f) fields[f] = html_entity_decode(e.contentWindow.getContent());</pre>
<p style="text-align: left;">The plugin is all ready to go now, so we have to make the actual external editor that&#8217;s gonna go in the iFrame, using jsvi. Download these three files, and put them in the same folder as your TiddlyWiki html file.</p>
<blockquote style="text-align: left;"><p><a href="http://gpl.internetconnection.net/vi/vi.js" target="_blank">vi.js</a><br />
<a title="jsvi css file" href="http://gpl.internetconnection.net/vi/vi.css" target="_blank">vi.css</a><br />
<a title="editor" href="http://www.actionshrimp.com/physiwiki/editor.html" target="_blank">editor.html</a></p></blockquote>
<p style="text-align: left;">The first two are the actual jsvi javascript file and it&#8217;s style sheet, the second is my own editor iFrame. Let&#8217;s have a look at the important lines of the <em>editor.html</em> file:</p>
<pre style="text-align: left;">&lt;script type="text/javascript" src="vi.js"&gt;&lt;/script&gt;</pre>
<p style="text-align: left;">This includes the jsvi javascript file.</p>
<pre style="text-align: left;">&lt;textarea style="width: 99%" name="theEditor" onfocus="editor(this);"&gt;
&lt;/textarea&gt;</pre>
<p style="text-align: left;">This builds the actual textarea that&#8217;s gonna be edited by jsvi. Ok, now the javascript &#8220;meat&#8221; of the page:</p>
<pre style="text-align: left;">var oEditor = document.getElementsByName('theEditor')[0];
function getContent() {return oEditor.value;}
tiddlers=/[\?&amp;]tiddler=([^&amp;#]*)/.exec(unescape(window.location.href));
fields=/[\?&amp;]field=([^&amp;#]*)/.exec(unescape(window.location.href));
if (tiddlers&amp;&amp;fields) oEditor.value = parent.getContentText(tiddlers[1]);
oEditor.focus();</pre>
<p style="text-align: left;">All that happens here is we write the getContent() function that the iFrameEditorPlugin calls to read your changes. The tiddlers line reads the URL to get which tiddler you&#8217;re editing, and the fields line does the same for the field (actually this isn&#8217;t even necessary with our getContentText() function). The last two lines read the tiddler&#8217;s content, so we can edit it, and set the focus to the textarea to launch jsvi automatically when the iFrame loads.</p>
<p style="text-align: left;">That&#8217;s everything setup now, so all we need to do is tell Tiddlywiki when we want to make our edits with the iFrameEditor instead of with it&#8217;s default text field. I made a plugin (based on code from VisualTW&#8217;s EasyEditPlugin &#8211; thanks a lot!). <a title="jsviPlugin" href="http://www.actionshrimp.com/physiwiki/#jsviPlugin">You can view the plugin here</a>. Hopefully it should add a &#8216;vi&#8217; button next to the edit button on each tiddler. If no button appears, add &#8216;jsvi&#8217; to the first line of the ViewTemplate tiddler to look like this:</p>
<pre>&lt;div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler jsvi &gt; fields syncing ....</pre>
<p style="text-align: left;">To make jsvi the default, remove the + from in front of editTiddler and put it in front of jsvi.</p>
<p style="text-align: left;">Now when you press the vi button, you should be presented with a rather gorgeous vi interface! <em><strong>One note, when you&#8217;re done editing a tiddler with jsvi, you must save it using the usual vi write command, :w, or press the &#8220;Save and Close&#8221; button. Otherwise the textarea does not get updated, and the iFrameEditorPlugin cannot read your changes. Also beware editing config shadow tiddlers with jsvi, as the line &#8220;macro=stuff&#8221; in some of the tooldbars etc. is interpreted by jsvi as it&#8217;s own command and it can end up destroying certain things.<br />
</strong></em></p>
<p style="text-align: left;">Update: I found a small problem with focusing using this in Firefox (didn&#8217;t test in other platforms) &#8211; after editing a post I was unable to select other fields and items in the window. This was fixed by changing one line in the vi.js file, line <strong>3588</strong>, which needs to be uncommented (the comment line before even refers to a bug in Firefox, possibly in an older version?) to look like this:</p>
<pre>document.body.removeChild(backing);</pre>
<p style="text-align: left;">Now it should work perfectly, apart from a few kinks: being able to edit the tiddler title the first time jsvi launches. Save and close vi, and it&#8217;s editable again, and still editable when you relaunch jsvi by clicking on the text area. If you cant get focus back on jsvi, right click it.</p>
<p style="text-align: left;">Hope you enjoy this as much as I do, and hopefully at some point soon when I have a bit more free time, I&#8217;ll have it in plugin format so it&#8217;s all incorporated into TW. Any problems, leave a comment and I&#8217;ll try and get back to you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/05/jsvi-and-tiddlywiki/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Integrating LatexRender into TiddlyWiki</title>
		<link>http://www.actionshrimp.com/2008/05/integrating-latexrender-into-tiddlywiki/</link>
		<comments>http://www.actionshrimp.com/2008/05/integrating-latexrender-into-tiddlywiki/#comments</comments>
		<pubDate>Tue, 13 May 2008 13:17:49 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[TiddlyWiki]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[latexrender]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=5</guid>
		<description><![CDATA[This post is adapted from my LatexRenderPluginDoc page on my wiki, so might contain a couple of errors on the copy over. If something doesn&#8217;t seem right, refer to that page, and please tell me in a comment below.
This uses LatexRender, my simple TiddlyWiki macro, LatexRenderPlugin, and a custom script I created for the purpose, [...]]]></description>
			<content:encoded><![CDATA[<p>This post is adapted from my <a title="LatexRenderPluginDoc" href="http://www.actionshrimp.com/physiwiki/index.html#LatexRenderPluginDoc" target="_blank">LatexRenderPluginDoc</a> page on my wiki, so might contain a couple of errors on the copy over. If something doesn&#8217;t seem right, refer to that page, and please tell me in a comment below.</p>
<p>This uses <a class="externalLink" title="External link to http://www.mayer.dial.pipex.com/tex.htm" href="http://www.mayer.dial.pipex.com/tex.htm" target="_blank">LatexRender</a>, my simple TiddlyWiki macro, <a href="http://www.actionshrimp.com/physiwiki#LatexRenderPlugin"><span class="tiddlyLink tiddlyLinkExisting">LatexRenderPlugin</span></a>, and a custom script I created for the purpose, render.php, which renders LaTeX fed to it as an argument. You&#8217;ll need imagemagick enabled on your server.</p>
<p><span id="more-5"></span></p>
<p>First you need access to a server with the ability to run LatexRender. Download the <a class="externalLink" title="External link to http://www.mayer.dial.pipex.com/latexrender.zip" href="http://www.mayer.dial.pipex.com/latexrender.zip" target="_blank">latexrender.zip</a>, and extract the &#8220;otherPHP&#8221; directory. Copy the class.latexrender.php, and latex.php files to a folder on your webserver. Set up the directories in each file accordingly. For example, I have my wiki set up like so:</p>
<blockquote><p>webroot/physiwiki/latexrender:<br />
<em>class.latexrender.php</em><br />
<em>latex.php</em></p></blockquote>
<p>and two subdirectories (which the webserver needs write access to, chmod 777):</p>
<blockquote><p>webroot/physiwiki/latexrender/pictures<br />
webroot/physiwiki/latexrender/tmp</p></blockquote>
<p>So in <em>class.latexrender.php</em>, I have:</p>
<pre>var $_picture_path = "/absolue/path/to/physiwiki/latexrender/pictures";
var $_picture_path_httpd = "/physiwiki/latexrender/pictures";
var $_tmp_dir = "/absolute/path/to/physiwiki/latexrender/tmp";</pre>
<p>Also, make sure the paths to <strong>latex</strong>, <strong>dvips</strong>, <strong>convert</strong>, <strong>identify</strong> are setup correctly on the lines below. You can also make changes to the other settings in this file if you want including image format. The default is <strong>gif</strong>, I changed it to <strong>png</strong>.</p>
<p>Now <em>latex.php</em> by default generates the html to show an image, like:</p>
<pre>&lt;img src="blah"&gt;</pre>
<p>We dont want this. So some changes to <em>latex.php</em> are required. First adjust the paths in <em>latex.php</em>:</p>
<pre>$latexrender_path = "/absolute/path/to/physiwiki/latexrender";
$latexrender_path_http = ".";</pre>
<p>The &#8216;.&#8217; is used as <em>latex.php</em> resides in the same directory as class.latexrender.php.<br />
Next, scroll right to the bottom of the file, and you can comment out/delete the last few lines, and change the return value to $url instead of $text as below:</p>
<pre>    $url = $latex-&gt;getFormulaURL($latex_formula);

    /*
    $alt_latex_formula = htmlentities($latex_formula, ENT_QUOTES);
    $alt_latex_formula = ...
    $alt_latex_formula = ..

        if ($url != false) {
            $text = substr_replace($text, "&lt;img src='".$url."' title='".$alt_latex_formula."' alt='".$alt_latex_formula."' align=absmiddle&gt;",$pos,strlen($tex_matches[0][$i]));
        } else {
            $text = substr_replace($text, "[Unparseable or potentially dangerous latex formula. Error $latex-&gt;_errorcode $latex-&gt;_errorextra]",$pos,strlen($tex_matches[0][$i]));
        }
    */
    }
    return $url;
}</pre>
<p>Right, that&#8217;s LatexRender all setup. Now we need to make the <em>render.php</em> file. Put the code in a file and save it in the same directory as <em>class.latexrender.php</em> and <em>latex.php</em>.<br />
<em>render.php</em>:</p>
<pre>&lt;?
header("Content-type: image/png");
include_once('latex.php');

if (isset($_GET['l'])){

        $text = $_GET['l'];
        $text = stripslashes($text);
        $text = "[tex]" . $text . "[/tex]";

        $latex_img_file = latex_content($text);
        $handle = fopen($latex_img_file, "r");
        $contents = fread($handle, filesize($latex_img_file));
        fclose($handle);

        echo $contents;
}
?&gt;</pre>
<p>Obviously change the header function to match the content type you specified in <em>class.render.php</em>. This file accepts LaTeX formula code as an argument render.php?l=&lt;formula&gt;, puts it between [tex] tags so it can be messed around by <em>latex.php</em> and then renders it as the image file.</p>
<p>Now all that is left is to incorporate this into TiddlyWiki, using a simple macro. (Just change the src= section to match the location of your script):</p>
<pre>config.macros.tex = {};
config.macros.tex.handler = function (place,macroName,params,wikifier,paramString,tiddler) {

     var code = encodeURIComponent(params[0]);
     wikify("&lt;html&gt;&lt;img class="teximg" title="" + params[0] + "" src="latexrender/render.php?l=" + code + ""&gt;&lt;/html&gt;", place);

}</pre>
<p>To use this plugin just call it like so:</p>
<pre>&lt;&lt;tex 'int_{-5}^{5} x^2 dx'&gt;&gt;</pre>
<p>For some rendered examples just browse my <a title="PhysiWiki" href="http://www.actionshrimp.com/physiwiki/" target="_blank">wiki</a>!<br />
The macro also gives all equations the &#8220;teximg&#8221; css class, so they can be adjusted to be inline &#8220;nicely&#8221;, using the following CSS in the <span class="tiddlyLink tiddlyLinkExisting">StyleSheet</span> tiddler:</p>
<pre>.viewer {line-height: 2.0 ;} .viewer img.teximg { vertical-align: middle;}</pre>
<p>Hopefully you&#8217;ll now have easy LaTeX macro&#8217;s working on your TiddlyWiki! Any problems just leave me a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/05/integrating-latexrender-into-tiddlywiki/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Laptop hard drive clicking in Hardy</title>
		<link>http://www.actionshrimp.com/2008/05/laptop-hard-drive-clicking-in-hardy/</link>
		<comments>http://www.actionshrimp.com/2008/05/laptop-hard-drive-clicking-in-hardy/#comments</comments>
		<pubDate>Sat, 03 May 2008 15:09:37 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[clicking]]></category>
		<category><![CDATA[harddrive]]></category>
		<category><![CDATA[hardy]]></category>
		<category><![CDATA[hdd]]></category>
		<category><![CDATA[laptop]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/wordpress/?p=4</guid>
		<description><![CDATA[Since I installed Hardy a week or so ago, I noticed the hard drive in my laptop was making a strange clicking noise every 5 seconds or so. At first I thought it must be slowly dying, and I was starting to get a bit worried, but then realised it seemed a bit suspicious that [...]]]></description>
			<content:encoded><![CDATA[<p>Since I installed Hardy a week or so ago, I noticed the hard drive in my laptop was making a strange clicking noise every 5 seconds or so. At first I thought it must be slowly dying, and I was starting to get a bit worried, but then realised it seemed a bit suspicious that it coincided with Hardy so closely, so I searched around.</p>
<p><span id="more-4"></span></p>
<p>Turns out I wasn&#8217;t the only one with the problem, and I found a solution <a href="http://ubuntuforums.org/showthread.php?t=531866">here</a>. (Thanks to wieman01 on the Ubuntu forums for this.)</p>
<p>What was happening was Ubuntu&#8217;s power management was a bit over zealous and was making the hard drive spin up and down far too often. By changing the power settings this can be fixed, using the command:</p>
<blockquote><p><code>hdparm -B 254 /dev/xxx</code></p></blockquote>
<p>replacing xxx with your drive name, in my case for my SATA drive it was /dev/sda.</p>
<p><code>254</code> here is the lowest level of power management, and <code>255</code> is off completely. You can try playing with higher values if you like some kind of power management.</p>
<p>To make this run every time the computer starts, add it to a startup script. For example, save a plain text file containing the above line to:</p>
<blockquote><p><code>/etc/init.d/local_settings</code></p></blockquote>
<p>Then:</p>
<blockquote><p><code><br />
cd /etc/init.d<br />
sudo chmod +x local_settings<br />
sudo ln -s local_settings /etc/rc2.d/S99local_settings<br />
</code></p></blockquote>
<p>This makes the file executable, and creates a symbolic link to it in the folder which contains the start-up scripts, giving it priority 99.</p>
<p>Hopefully your clicking noise will now be gone!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/05/laptop-hard-drive-clicking-in-hardy/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
