Articles
Although I think in numbers there are times when I just write, it doesn’t happen very much but it does occur at times. I target what I write to fellow technology developers and designers as it allows me to describe the things that I am thinking without needing to “dumb them down” too much. If you have any questions or feedback about any of these articles feel free to contact me, the more feedback I receive the better the chances of me writing more often will become.
All articles
Hiragana and Katakana charts17th February, 2008
While moving furniture around today I came across my old Japanese hiragana and katakana charts that I used to use as a cheat sheet for my self-teaching Japanese studies. As I’ve completely forgotten everything again (This is like the third time now) I decided to replace the charts with higher quality ones and put them up somewhere where I can see them. After spending a good ten to fifteen minutes searching around the web I came to the realization that no good charts exist for printing purposes that don’t require a credit card to access. So I ended up making my own.
Choose your format:
- OpenOffice.org ODT (25KB)
- Adobe Acrobat PDF (58KB, recommended)
- Image PNGs (146KB and 118KB each) available below:
User init scripts16th February, 2008
While porting my Apache development server configuration over to Lighttpd I needed a script that would maintain Django FastCGI daemons even after a reboot of the host server. Even though I could have done this by just starting the daemons in an init script directly there where two problems with this approach:
- Running a web-server CGI script as root is massive security risk, and
- Users would require root access to restart the daemons if they made a change to the instance.
To get around these problems I wrote the following script that will automatically execute a script in the user’s home directory with their permissions on system boot. This also allows the user to manually restart the daemons at any time without being a security hazard if they require it, as well as not interfering with daemons of other users. The user init script itself should behave just like a normal one, meaning it should respect the “start”, “stop” and “restart” arguments and not require any user input to execute to completion.
By default the the script will search each subdirectory in /home/ non-recursively for a script called .init and then attempt to execute it as the user defined by the subdirectory’s name. I.e. the script /home/bob/.init will be executed as the “bob” user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/bin/sh
HOMEROOT="/home"
INITFILE=".init"
case "$1" in
start)
echo -n "Starting user scripts..."
for USER in `ls $HOMEROOT`; do
[ -d $HOMEROOT/$USER ] && [ -f $HOMEROOT/$USER/$INITFILE ] && \
sudo -u $USER $HOMEROOT/$USER/$INITFILE start >> /dev/null &
done
echo " Done"
;;
stop)
echo -n "Stopping user scripts..."
for USER in `ls $HOMEROOT`; do
[ -d $HOMEROOT/$USER ] && [ -f $HOMEROOT/$USER/$INITFILE ] && \
sudo -u $USER $HOMEROOT/$USER/$INITFILE stop >> /dev/null &
done
echo " Done"
;;
restart)
echo -n "Restarting user scripts..."
for USER in `ls $HOMEROOT`; do
[ -d $HOMEROOT/$USER ] && [ -f $HOMEROOT/$USER/$INITFILE ] && \
sudo -u $USER $HOMEROOT/$USER/$INITFILE restart >> /dev/null &
done
echo " Done"
;;
*)
echo "Usage: $0 {start|stop|restart}"
;;
esac
|
Recursion in Django templates10th February, 2008
When I first designed Undefined Fire v4 seven months ago I had planned to use a category tree to categorize all the articles instead of using the tagging system that is now used. This category tree system required the use of a recursive template system to be displayed correctly, unfortunately Django does not have this functionality so I did what any good developer would do—I wrote my own implementation.
Below is the template tag code that I came up with, just download the file and save it in your application’s “templatetags/” directory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | ###############################################################################
# Recurse template tag for Django v1.1
# Copyright (C) 2008 Lucas Murray
# http://www.undefinedfire.com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
###############################################################################
from django import template
register = template.Library()
class RecurseNode(template.Node):
def __init__(self, var, name, child, nodeList):
self.var = var
self.name = name
self.child = child
self.nodeList = nodeList
def __repr__(self):
return '<RecurseNode>'
def renderCallback(self, context, vals, level):
output = []
try:
if len(vals):
pass
except:
vals = [vals]
if len(vals):
if 'loop' in self.nodeList:
output.append(self.nodeList['loop'].render(context))
for val in vals:
context.push()
context['level'] = level
context[self.name] = val
if 'child' in self.nodeList:
output.append(self.nodeList['child'].render(context))
child = self.child.resolve(context)
if child:
output.append(self.renderCallback(context, child, level + 1))
if 'endloop' in self.nodeList:
output.append(self.nodeList['endloop'].render(context))
else:
output.append(self.nodeList['endrecurse'].render(context))
context.pop()
if 'endloop' in self.nodeList:
output.append(self.nodeList['endrecurse'].render(context))
return ''.join(output)
def render(self, context):
vals = self.var.resolve(context)
output = self.renderCallback(context, vals, 1)
return output
def do_recurse(parser, token):
bits = list(token.split_contents())
if len(bits) != 6 and bits[2] != 'with' and bits[4] != 'as':
raise template.TemplateSyntaxError, "Invalid tag syxtax expected '{% recurse [childVar] with [parents] as [parent] %}'"
child = parser.compile_filter(bits[1])
var = parser.compile_filter(bits[3])
name = bits[5]
nodeList = {}
while len(nodeList) < 4:
temp = parser.parse(('child','loop','endloop','endrecurse'))
tag = parser.tokens[0].contents
nodeList[tag] = temp
parser.delete_first_token()
if tag == 'endrecurse':
break
return RecurseNode(var, name, child, nodeList)
do_recurse = register.tag('recurse', do_recurse)
|
Unlike other developer’s implementations this one allows the recursive element to be embedded in the same file as the main template instead of forcing the designer to use a separate file. Another benefit is that the template file is only loaded and parsed once, making is theoretically slightly more efficient as well (I haven’t actually confirmed this though).
Most of the tags are self explanatory, the only one that may cause confusion is the main {% recurse %} one. The format for this tag is {% recurse [children] with [parent] as [child] %} where “[children]” is the property that contains the children of the current element, “[parent]” is your starting element and “[child]” is the variable named used in the loop.
Here is an example of how you can implement a category tree using this template tag. As you can see it’s fairly simple and with a couple of modifications can be used for just about anything.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | {% load recurse %}
... Headers and stuff ...
{% recurse category.category_set.all with categories as category %}
<ul>
{% loop %}
<li>
<h{{ level }}>{{ category.title }}</h{{ level }}>
{% child %}
</li>
{% endloop %}
</ul>
{% endrecurse %}
... The rest of the page ...
|
Undefined Fire v42nd February, 2008
After seven long months in development, Undefined Fire v4 is finally here. I have to apologise for the long delay but to be completely honest I had lost 100% of my motivation to continue website development, even though I wanted to get it out sooner I just couldn’t open my editor.
With all major version releases of the site there is a design and back-end change. As I’m a spontaneous designer I can’t really make any comments on why I designed the site the way it is as I completely threw away my plan a few hours after I started creating the mock-up in The GIMP (Yes, I’ve finally decided to move to free software, however it was not a smooth transition and I’ll be outlining the reasons why in a future post). Usability-wise I’ve tried to address the common problems with general blogs and personal websites by adding different graphical emphasis to different parts of each article as well as adding a lot more links between pages on the site.
“Using a DRY programming philosophy with the object-orientated Python language rewriting the entire site from scratch went quickly and smoothly.”
On the back-end site of things I’ve thrown out all my ugly PHP and carefully replaced it with beautiful Django code. I have to say that as soon as I saw Django I was in love as everything just made sense. Using a DRY programming philosophy with the object-orientated Python language rewriting the entire site from scratch went quickly and smoothly. Django’s built-in admin panel was just icing on the cake, no longer do I need to spend half my time writing pages that only I will see. There was a slight problem with the first revision of Undefined Fire v4 as the article section and code library (Which I merged with the article section in the second revision) required recursion-compatible code. As Django does not support this out-of-the-box I ended up writing a stupidly simple template tag that did it all for me. After doing a quick Google search it looks like Django still doesn’t really support it (This looks interesting though) so I’ll release the tag sometime in the near future.
Well I guess that’s it for now, I hope this post has brought happiness to those select few that still have me in their feed readers (My daily visits have dropped to almost nothing due to my inactivity). I will be doing a lot more non-website software development and electronic design this year than in the past so hopefully I’ll have more to write about. One of the other main reasons why I never posted anything last year was because everything I decided to write about was already described adequately on other sites. Oh well, I guess I need to compete with others to get up in the world.
Wikipedian flow of mind19th May, 2007
Earlier today Blizzard announced StarCraft II at their 2007 Worldwide Invitational event in South Korea. Initial reports state that it will be real-time strategy similar to the original with the same three playable races: The Terran, the Protoss and the Zerg. Although that is all good what surprised me the most was that the game has been in production since 2003, talk about keeping a secret.
Although there has been no information released about the story IGN is speculating that Kerrigan will be back as well as the official website saying that it picks up where StarCraft: Brood War left off. With this in mind I also believe there also may be an opening for the return of the Xel’Naga, the ancient race that was supposedly destroyed by the Zerg after they gave them intelligence. Maybe Kerrigan found out where they were hiding and decided to finish the job that the Overmind started? Who knows, I wasn’t really into the whole StarCraft thing so most of my knowledge on the game comes from the pages of Wikipedia.
Speaking of Wikipedia I managed to get so caught up in the knowledge database that three hours of my day vanished with only a Firefox history log to prove that I didn’t manage to break the space-time continuum. This is not the first time this has happened to me and I’m sure that some of you that are reading this has lost many hours to the wiki god. Does anyone know if there is a Firefox extension that records the user’s Wikipedian journey? After doing a quick search I couldn’t find any but I am sure one exists somewhere.
Going from seven to eight5th May, 2007
I have always favoured the number 7 for as long as I can remember. Why is it my favourite? I wouldn’t have a clue. After pondering on this question for a while I came to a startling realisation - The number 8 is better than 7.
What things does 7 have going towards it? All I can think of is that it’s a prime number. The number 8 however has quite a few good points:
- its glyph is symmetrical,
- it can be flipped and is still an 8,
- it can be rotated 90 degrees to form the infinity glyph,
- it is a key number in binary, and
- it is a part of the Fibonacci sequence.
Not bad is it? These definitely prove that the design-friendly number of 8 is overall more useful than the lopsided 7.
Welcome to the new world1st May, 2007
Once again I have felt the need to change the direction of this site, so here it is, Undefined Fire v3. You will notice quite a few modifications with this version, including but not limited to:
- a new design,
- a change of point-of-view from third- to first-person,
- content will be more about what I do and not just things related to website development and design,
- an about page (Finally!), and
- the informal blogging as returned.
I will be adding a commenting system whenever I believe it would be useful. The system I have planned is more of a mixture of your traditional blog comments and a forum, this way it’s possible to have visitors add extra information to the entry/article yet also allow multiple discussions to be held without confusion. Maybe I’m just thinking too big? Will Undefined Fire really get that popular that everyone wants to comment? It’s unlikely, but I still like to be one step ahead of everyone else.
The old Undefined Fire v2 in it’s final state can be found here.
Apache 2 Configuration6th March, 2007
After upgrading one of my private servers a little while ago I decided to expand upon the web-server that was being happily hosted on it for the last year or so. As I cannot find any sample configuration files online that do something similar to what this server does I present to you the configuration files that I used on my server. Hopefully they will be of use to somebody.
Statistics: Tracking and Storing6th July, 2006
Knowing your visitors is one of the most important things about creating a website, both its layout and its design. One of the best things you can do is to research your visitors constantly. This article outlines multiple ways of storing visitor data, how to register page requests and how to work out how many unique visitors a site gets.
Strings vs Output Buffering in PHP3rd July, 2006
When working with programming project, both large and small, it is a good technique to split data representation and output into separate parts of the program. For website content management systems the section of code that generates the actual output of the page is commonly called a template, theme or skin engine. These all work in the same basic way, they receive a data stream and output HTML code. Now, in PHP there are multiple ways of parsing strings so this means that the data stream can be converted in multiple ways. Which way is the best way?
I did a little bit of research in this area to find out if it was more efficient to let the template engine output the HTML code directly and capture it using output buffering to make a cache of it or to make the engine generate a string that could be cached directly and also sent to the visitor. Here are my findings.