The Theo Spears Blog
Blogging Considered Harmful (Considered Harmful)?
First posted 2007-12-19 23:22:00.000002+00:00
As anyone who reads www.netlamers.org will have noticed by the sudden arrival of lots of planet-spam (sorry guys) my blog is back online, this time using some custom written blogging software. I'll post more on who it works in the future, but the most important feature is that it lets me write blog posts in my editor of choice - VIM.
First posted 2007-08-13 01:00:00+00:00
In preparation for migrating away fully from university servers I have started to rent a VPS. One of the first things I did was install a firewall, and I have now written some quick scripts to process the ulog mysql information and product a statistics page on what is being blocked. I will probably add more stats over the coming weeks and months
For anyone interested here is the page.
First posted 2007-08-13 00:00:00+00:00
Yesterday I blogged about implementing an enterprise version of FizzBuzz in C#. Here's one possibly python version to compare.
#!/usr/bin/python
x = [""] * 100
for i in range(2,100,3): x[i] = "Fizz"
for i in range(4,100,5): x[i] += "Buzz"
print "".join(x[i] if x[i] else str(i+1) for i in range(0,100))
Before anyone comments, I know it is possible to make the C# version shorter, and the python version more enterprise-like. This is intended more as a parody of the styles of coding common in different languages.
First posted 2007-08-11 00:00:00.000005+00:00
There is a very simple programming challenge called FizzBuzz that Imram reports using to screen out poor programmers. The task is simple. Write a program that counts from 1 to 100 obeying the following rules.
-
For multiples of 3 output "Fizz"
-
For multiples of 5 output "Buzz"
-
For multiples of both 3 and 5 output "FizzBuzz"
-
For all other numbers output the number itself
Over on the codinghorror blog there are lots of people proving how clever they are by solving this challenging problem. It's pretty straightforward.
However, many propsed solutions lack proper extensibility and flexibility. Here's a properly enterprise solution.
using System;
using System.Reflection;
using System.Collections.Generic;
namespace TheoSpears
{
public class Program
{
public static int Main(string[] args)
{
for(int i = 1; i < = 100; i++ )
{
NumberDisplay display = NumberDisplayFactory.Instance.CreateNumberDisplay(i);
Console.Write(display);
}
return 0;
}
}
public class NumberDisplayFactory
{
private class NumberDisplayTemplate : IComparable
{
public int Priority;
public Type Type;
public int CompareTo(object obj)
{
if (! (obj is NumberDisplayTemplate) )
{
throw new Exception("Comparing to invalid type");
}
return Priority.CompareTo((obj as NumberDisplayTemplate).Priority);
}
}
public static readonly NumberDisplayFactory Instance = new NumberDisplayFactory();
private List templateList = new List();
private NumberDisplayFactory()
{
Assembly a = this.GetType().Assembly;
foreach(Type t in a.GetTypes())
{
object[] attribs = t.GetCustomAttributes(typeof(NumberHandlerAttribute), false);
if ( attribs.Length > 0 )
{
NumberDisplayTemplate template = new NumberDisplayTemplate();
template.Priority = (attribs[0] as NumberHandlerAttribute).Priority;
template.Type = t;
templateList.Add(template);
}
}
templateList.Sort();
templateList.Reverse();
}
public NumberDisplay CreateNumberDisplay(int number)
{
foreach(NumberDisplayTemplate template in templateList)
{
NumberDisplay candidate =
(NumberDisplay)Activator.CreateInstance(template.Type, new object[] {number});
if (candidate.Matches())
{
return candidate;
}
}
throw new Exception("No matching class found");
}
}
public interface NumberDisplay
{
bool Matches();
}
public class MultipleOfNumber : NumberDisplay
{
private int number;
private int factor;
private string word;
protected MultipleOfNumber(int number, int factor, string word)
{
this.number = number;
this.factor = factor;
this.word = word;
}
public bool Matches()
{
return number % factor == 0;
}
public override string ToString()
{
return word;
}
}
public class NumberHandlerAttribute : Attribute
{
private int priority;
public int Priority
{
get { return priority; }
set { priority = value; }
}
}
[NumberHandler(Priority=50)]
public class MultipleOfFifteen : MultipleOfNumber
{
public MultipleOfFifteen(int number) : base(number, 15, "FizzBuzz") {}
}
[NumberHandler(Priority=10)]
public class MultipleOfFive : MultipleOfNumber
{
public MultipleOfFive(int number) : base(number, 5, "Buzz") {}
}
[NumberHandler(Priority=10)]
public class MultipleOfThree : MultipleOfNumber
{
public MultipleOfThree(int number) : base(number, 3, "Fizz") {}
}
[NumberHandler(Priority=0)]
public class DefaultNumber : NumberDisplay
{
private int number;
public DefaultNumber(int number)
{
this.number = number;
}
public bool Matches()
{
return true;
}
public override string ToString()
{
return number.ToString();
}
}
}
First posted 2007-08-10 00:00:00.000004+00:00
CMS Made Simple is a fairly nice PHP content management system. It allows you to define any number of templates which control the appearance of your pages. When you create a page you choose which of these templates to associate with that page.
Each template must have a {content} tag which is replaced with the main content of the page. However it is possible to have more than one content section, each with its own content. To do this give any subsequent content sections a name.
{content block='myblock'}
Note the quotes are necessary, and there must be no spaces around the =. Any sections created like this will automatically get their own section when editing the page on the admin panel. There must always also be an unnamed content block.
It is also possible to specify other attributes for content blocks. These are 'usewysiwyg', 'id', and 'oneline'.
First posted 2007-05-22 00:00:00.000001+00:00
There are lots of scripts that allow irssi to display the track currently playing in amarok. However an ultra-simple solution without any scripts is just:
/alias np /exec -out echo np: `dcop amarok player nowPlaying`
Which will create a /np command to show your current track.
dencrypt suggested a possible extension for anyone who has irssi running on a server and amarok running on your client. As long as your desktop is running sshd and has a publicly accessible IP address you can use the following recipe. I have made a few changes to dencrypt's recipe to make it more secure.
On the server create an ssh keypair. Leave the password blank.
(run this on your server)
ssh-keygen -f ~/.ssh/amarok_key
Copy the keyfile locally
(run this on your client)
scp YOUR_SERVER_HOSTNAME_HERE:.ssh/amarok_key.pub ~/.ssh/amarok_key.pub
Configure ssh to allow this key to run the now playing command
(do this on your client)
Open ~/.ssh/authorized_keys in your text editor and add the following to a new line at the bottom
command="dcop --user `whoami` amarok player nowPlaying",no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding
After this (but on the same line) add the contents of the file we just copied across (~/.ssh/amarok_key.pub)
Tell irssi to use this command
(do this in irssi)
/exec -out echo np: `ssh -i ~/.ssh/amarok_key YOUR_DESKTOP_IP_HERE `
First posted 2007-04-25 00:00:00.000002+00:00
Over Christmas I obtained an HP Compaq nc2400 laptop. It is a nice, compact device with a 12.1" screen, dual 1.2GHz processors and 1GB of ram.
It came with Windows XP Professional installed. This was quickly replaced with kubuntu edgy. Here is a brief outline of how well things work.
Graphics - WORKS
To get the correct screen resolution (1280x800) install the package 915resolution from universe.
Multimedia - WORKS
In order to support many of the video formats online it is necessary to install a number of extra packages. Add the following lines to your sources.list:
deb http://mirror.ubuntulinux.nl edgy-seveas all
deb-src http://mirror.ubuntulinux.nl edgy-seveas all
And to avoid messages about unsigned packages you may wish to run:
wget http://mirror.ubuntulinux.nl/1135D466.gpg -O- | sudo apt-key add -
You can now install the following packages (some from the repository above, some from multiverse).
libxine-extracodecs w32codecs libdvdread3 libdvdcss2
Fingerprint reader - NO SUPPORT
The fingerprint reader uses the AuthenTec AES2501 chip. There is some very beta software available you can find using Google - I haven't tried it. Allegedly the manufacturer should be releasing linux drivers some time this year
Wireless - WORKS
Wireless Assistant in edgy does not support DHCP. Either upgrade to the version in edgy-updates or (preferably) switch to KNetworkManager.
Suspend and Hibernate - WORKS
Edit /etc/defaults/apci-support adding psmouse and i8042 as modules to be reloaded. Add powernowd to the list of services to be restarted.
You will need to rebuild the kernel, see https://wiki.kubuntu.org/KernelCustomBuild. I suggest you install the following packages to do this:
linux-kernel-devel fakeroot kernel-wedge kernel-package linux-source
Edit the configuration file for your architecture so that X86_GENERIC=y, X86_PC is unset, and I8042=m. Then build a new kernel image and install it. You may also need to build and install the linux-restricted-modules package.
And that's all there is to it.
First posted 2006-10-20 00:00:00.000004+00:00
I may have absolutely no interest in reading the drivel you choose to post to your blog, but I will defend to the death your right to do so.
(with apologies to Evelyn Hall and Voltaire)
First posted 2006-09-18 00:00:00+00:00
I
am
getting
very
very
very
scared
First posted 2006-09-15 00:00:00.000004+00:00
For future evilness I need to have a page indexed by some major search engines. So in line with Web 2.0 I'm linking to it from my blog.
There is nothing interesting on the end of this link.
First posted 2006-09-03 00:00:00.000006+00:00
There is a general strike at my local sorting office, so post is not getting through reliably. As a result to exchange documents with people my Dad is having to scan them in as images and email them (before you mention OCR, I've tried, it just doesn't work well enough). The documents involved span multiple pages, so to avoid having to deal with lots and lots of image files we decided to combine the images for each document into a single pdf file.
I asked various people about the easiest way to take groups of images and turn them into pdfs. Most people suggested using openoffice, inserting each image individually, and then exporting to PDF. I guess this isn't too bad, there are only about 50 images spread across 7 documents or so. When I asked about automation some people suggested writing OOo macros.
Fortunately, KDE provides a far easier and quicker way. All you have to do is create an icon on the desktop which invokes the following command:
kprinter -P "Print to File (PDF)" %U
And then when you want to turn some images into a pdf you just select them and drag them onto the icon. Give the output file a name, click print, and you're done.
This exemplifies what it is I like about KDE. It is full of programs which contain features you don't need very often, but are incredibly useful when you do need them. The best example of this is DCOP, which allows scripting access to almost every KDE app in existence. Want to display the song currently playing in amarok in your display name in Kopete? No problem. Want to make a shortcut to minimise all open browser windows? No problem. Want to turn a bunch of images into a PDF file quickly and easily? No Problem at all.
First posted 2006-09-01 00:00:00.000004+00:00
Whilst not at university I spend some of my time working for a small bespoke software development company. On the whole it's great - I can live at home in a beautiful part of the country, the people I work with are cool, and what I do is reasonably interesting. However there is one thing that makes life much less pleasant for us all - customers.
The thing about customers is that they always want more than what you have agreed to give them. This is commonly known as feature creep, little change after little change is added until the tiny time tracking application they paid for has turned into a fully blown payrole and management application.
However, as it is a software company, it is understood that changes cost money. If the customer wants to add too many features, we start charging them more. Nothing cools someone's enthusiasm for adding new stuff than being told it will cost them thousands of pounds.
One of the problems I believe hobby projects run into is they don't have this tempering mechanism. As it is something you are making yourself there is no financial cost to new features. Of course there is a cost in time, but as hobby projects often don't involve detailed time estimating even this cost may not be made obvious.
It certainly can't compare to having an invoice for £2000 appear in the post.
As a result feature creep goes wild, even before the start of the project. People keep thinking of great new features to add, and don't fully weigh them against the time cost. Each little feature is small, but the overall result is that your little weekend project has become a massive undertaking that will take all of you several weeks full time to implement.
And of course you don't really want to undertake such a big project - that's why you initially started out thinking about something small for the weekend. As it is so big the project becomes daunting; you are unsure where to start, and ultimately nothing comes of it.
The essential irony is that by planning to do more, you end up doing less.
So how can this problem be overcome? To an extent I don't think it should be - part of what makes a hobby project fun is that it doesn't have all the economic considerations of coding as done for a job. However, a project that produces a result is far more fun and rewarding than one that doesn't, so perhaps learning something from the business world is beneficial.
The solution I will be trying is to decide on the scope of the project at the start, and then use this to limit features. First decide how big the project should be - do you want it to take you a weekend, or a few hours a night for a month, or all your free time for the next 3 years? Make this decision, and express it as a number of hours. Tell people; blog it; write it down.
Now for each feature estimate how long in hours you expect it to take. Be honest with yourself here; don't underestimate time to get more features in, it won't work. If the total time for all your features is more than the time you have allocated then some features have to be removed. Be brutal, decide which features you don't need and remove them. Don't be tempted to increase the time allocated to the project, if you start doing this soon you'll be looking at an unmanageably big project again. Remember, you can always add more features once the ones you have decided on are finished, if you still feel you want them.
What if you have reduced down to only features you feel you must have and it is still taking too long? Well maybe you shouldn't start the project, or maybe you should get someone else to help. Or you could go back and revise how much time you are willing to spend, but keep in mind how this will impact other plans and projects, and your social life.
First posted 2006-07-23 00:00:00.000006+00:00
As part of my course last term I did some direct research, focusing on the relationship between the internet and subjective well being. Here is an overview and a summary of the results.
This piece is the work of an undergraduate student and has not been subject to peer review in the same way that a full academic publication would be. All results here may as a result be completely wrong. Please bear this in mind when reading, and do not quote the results in any future work, discussion, or argument down the pub.
This study was principally inspired by one performed by Kraut et al. They gave families computers with internet access and looked at the effect this had on them. They initially found that greater internet usage seemed to lead to greated loneliness and depression (1998), but in a follow up study found there didn't seem to be any effect (2002). Other research has also given mixed results, for example DiMaggio et al. (2001) found internet users tend to have wider social networks, but Cummings, Butler and Kraut (2002) found online friendships were less valuable than offline ones. My working hypothesis for this study was that people benefit more from the internet when they have more online friends.
My results don't seem to support this. The results suggest that people who spend more time online are typically lonelier, however the quality and quantity of online friendships doesn't seem to have any effect. This is in constrast to the quality and quantity of real life friendships, whch had a significant impact on how lonely people are. People's online and real life friendships did not seem related at all.
If you want more details the full piece is available here.
First posted 2006-07-22 00:00:00.000005+00:00
Once I have finished my summer job (hopefully sometime early August) I plan to spend some of my mountains of free time (ahem) writing some tutorials and guides for web related topics (probably setting up LAMP, and Javascript). I've done a little technical tutorial writing in the past but not much, so I would appreciate any tips that people have on how to do it well.
In particular I would like to know whether you prefer to learn using self-contained examples that do useful things, but uses code features that have not yet been introduced, or whether you prefer starting with simple code fragments that don't do very much (e.g. Hello World!) and then using new features as they are introduced.
Replies on a postcard (or in the comments section).
First posted 2006-07-04 00:00:00.000001+00:00
I came across an interesting security hole today. Many php frameworks, both widely used and homegrown, use a single entry point for all pages, in other words to load the page 'members' you might point your browser at http://www.example.com/index.php?members. This is ugly so often it is hidden behind mod_rewrite, so http://www.example.com/members is silently translated behind the scenes. For example you might use
RewriteRule ^/(.*) /index.php?$1
This all works nicely for your PHP files. However most sites also have images, css, or javascript files to load. These static files typically should not be loaded through index.php. One common way to address the issue is to avoid rewriting if the url corresponds to a file that exists. e.g.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*) /index.php?$1
You can then happily link to all your images and scripts and it will work nicely. Another less common option people sometimes take is not to rewrite certain types of file, for example to avoid rewriting image and css files you might use
RewriteCond %{REQUEST_URI} ! /(.css)|(.jpeg)|(.png)$/
RewriteRule ^/(.*) /index.php?$1
This way image and css files aren't rewritten, but other URLs are. Again this is fine. This has the added advantage that people can't load your php files directly bypassing your framework because they will be rewritten.
Stop. This is not fine.
It is true that http://www.example.com/test.php will be rewritten, as will http://www.example.com/test.php?evil-evasion.css however PHP is a bit special. Whilst with apache going to http://www.example.com/myfile.html/some/random/path/that/is/not/real will cause a 404 error, this is not true with http://www.example.com/test.php/some/random/path. In fact the latter will invoke test.php and will ignore the rest of the path. This means if we load http://www.example.com/test.php/evil-evasion.css we can avoid the rewrite rule and invoke test.php directly.
The moral of all this is if you have files you don't want the user to load don't rely on clever methods to stop them being loaded. If at all possible keep them outside the webroot.
(n.b. mod rewrite lines here have not been tested, but you get the idea)
First posted 2006-06-30 00:00:00.000004+00:00
If you are presented with too many options at once it is very hard to pick the one you want (tab bars are especially bad in this respect, see Interface hall of shame for why). This is why Apple tries to have as few toolbar options as possible and Microsoft redesigned their start menu for windows XP. Whilst we can sometimes avoid this complexity often applications do need lots of information from the user. A popular way to collect this information is using wizards.
Wizards allow the user to provide a few bits of information at a time (often only a single choice between two options). In this respect wizard interfaces are rather similar to pre-GUI interfaces which prompted for a responses one by one. More relevantly however, the wizard approach (though not the metaphor) has been adopted for the web, with complicated web forms (particularly web site registrations or shopping carts) using such a sequential approach.
The topic I wish to address here is how such wizard-like web forms can be implemented cleanly in conjunction with MVC style web frameworks such as Ruby On Rails, cakePHP, and Footpath (my own framework, under heavy development, and the reason for these blogs). The problems to address are
-
How to keep track of information from all stages
-
How to easily re-use individual stages
Keeping track of information from all stages
One of the "features" of http that makes creating web applications challenging is that it is stateless (though AJAX is beginning to change that). There are a few ways that can be used to pass state between requests:
Cookies (and sessions)
Hidden fields
URL encoded data
Before considering which of these is best let's make explicit a few of the constraints of using an MVC style design. (These are not absolute constraints, but solutions which break them are likely to be ugly. at least with current frameworks).
A specific url corresponds to a specific controller and view.
For example the url /user/personaldetails could be a form requesting a user's contact details and age. Allowing a url like /user/register to correspond to one of a number of possible forms (e.g. username/password or address) typically requires some rather ugly code in the view template.
The same url as shows a form is used to process that form.
This is a result of the above. If the user has entered invalid data the form will need to be shown to them again, i.e. they need to be looking at the same url. Also from a design point of view it makes sense for there to be one controller action responsible for any view, i.e. for set up and processing. It would be possible to have two actions for any view, e.g. register_prepare and register_submit, but if there are errors the submit function is often involved in telling the view to display them.
This means after a successful form submission we need to forward the user on to a new URL so a new form can be displayed. For example consider the sequence below
-
--> User requests /user/register
-
<-- Server sends first registration page
-
--> Server submits results to /user/register
-
<-- Server sends redirect header to /user/personaldetails
-
--> User requests /user/personaldetails
-
<-- Server sends second registration page
-
--> User submits results to /user/personaldetails
-
<-- Server sends redirect header to /user/registrationcomplete
In theory it would be possible remove stages 4 & 5, making the redirect a purely server-side operation. Whilst from a technical perspective this is better, it would be potentially very confusing for the user, particularly if the form and the page were very different, imagine being asked to fill in your credit card details on a page called /forum/publicfeedback!
Returning to the problem of keeping track of information, in any situation where the user submits a form this is easy, we just include hidden fields (which we can validate using the techniques outlined in a previous post) for the values and pass them on each time. However we cannot do this with stages 4 & 5 as there is only a get request. We could urlencode the information, however this is a) ugly and b) doesn't work with very much data. We also cannot use simple sessions/cookies as the user may have multiple browser windows open, thus may potentially be working through the wizard multiple times at once.
The only option this really leaves (short of really ugly hacks with javascript) is an identifier in the url that maps to a collection of data on the server. As with any such mapping this raises the question of lifetime - if the user runs away half way through how long should we give them to come back? That depends on whether we are just using this map, or also using hidden fields. If we only use the server side map when doing a redirect and use hidden form fields the rest of the time then we can throw away the information as soon as the redirect is completed. Well almost - if we throw away the information the user will no longer be able to refresh the page, so we might want to keep it for an hour or so. We can definitely throw it away if the user finishes filling out the form before this time though.
Now, quick readers will have picked up on an inconsistency in what I am saying. (I'm kidding myself, quick readers will probably have noticed several.) Under MVC the controller is meant to have processed the data coming from the view, so how is it that this data still needs to be passed on? Who is going to process this data at the end of the day? The answer here is that actions associated with a single controller action (e.g. /user/personaldetails) are correct and fine for modifying a single object (or object type) or a collection of closely related objects. However when the interactions between several objects need to be regulated we need a higher level controller, a metacontroller if you like. This fits in neatly with our second stage.
Controller re-use
There are many controllers we can imagine fitting into any number of wizard-like html page sequences. For example logging in/registering is a needed step for almost any operation on most sites, it would be nice to be able to seemlessly integrate these (i.e. register for an account half way through your checkout without having to restart the checkout) with any number of wizard-like sequences (hereafter storyboard). This means a particular controller shouldn't know where to redirect to after it has finished its work.
So who should know?
To combine individual controllers into a storyboard we can introduce a new class, a metacontroller or storyboard class. Each storyboard will have a url like a standard controller action, however rather than displaying content it will specify a sequence of actions. It will also be responsible after each action has completed to specify what information should be passed on to future steps. The framework should provide facilities to make these easy to do. Following the principle of encapsulation, each controller should define what information is available for the storyboard to retain.
What about passing information the other way though? For example a storyboard might involve editting a certain object part way through, and the relevant controller will need to know which object to edit. Here the simplest answer is for the storyboard to make use of the existing input parameters each controller defines, specifying them through the url. Obviously the framework should provide helper functions to make this easier, so the storyboard author does not have to manually create urls.
Conclusion
Although there is no perfect solution to the problem of retaining data for wizard-like or multipage forms using a combination of hidden form fields and session values a reasonably good solution can be found. Such wizard-like interfaces cannot be defined simply through the existing MVC elements provided by existing frameworks, but could be implemented in a more simple fashion using the idea of a coordinator or "storyboard" class.
First posted 2006-06-28 00:00:00.000002+00:00
Abstract
It is very useful to be able to automatically process information provided by the user
in forms, based purely on the layout of the form. However any such automated
request processing is potentially vulnerable to malicious users manipulating
the request. Here we outline some of these problems and a way of overcoming
them.
The Goal
The maintainability of applications is greatly enhanced by cohesiveness,
keeping closely related functionality together, and separating it from less
strongly related functions. One example of this is separating the code
representing business objects from the code which displays these objects. A
popular way of achieving this separation is the Model-View-Controller (MVC)
framework.
With MVC it is common to map specific fields in the view (with html this
might be particular <span> or <input /> tags to particular members of the
objects comprising the model. A very common scenario is mapping particular
object members to particular <input /> tags in the form, and then updating the
members of the object with the new values the user has entered.
Whilst it is possible to write code to do this manually in each instance
it is far more convenient to indicate which fields map to which which object
members and have some generic code which can do this mapping for any form
and any object. Here I discuss various obstacles encountered in doing this
and how they may be overcome.
A naive solution
(All examples here are in PHP, as this is the language I am currently
working in, however the ideas expressed should translate to other web
environments.)
Assuming we do not want to make all fields of the object available to be
editted the view will specify which fields should be available to edit, and will
also need to specify where in the resulting page these fields are. In order to
facilitate binding the contents of the fields to existing values from the object
helper functions can be used to create the actual fields.
<form method="POST">
<?php objectId('Pizza'); ?>
Topping: <?php displayInputField('Pizza.Topping'); ?> <br />
Size: <?php displayInputField('Pizza.Size'); ?> <br />
Olives: <?php displayInputField('Pizza.Olives'); ?> <br />
<?php displaySubmitButtion(); ?>
</form>
displayInputField() is a helper function which looks at the value of the Pizza
object and displays an appropriate input element depending on its type, filling the default
value with the current value from the object. The input element is given a name according to
some naming scheme such that it can easily be identified afterward. The resulting html might
look like this.
<?php displayForm(); ?>
<input type="hidden" name="data__pizza__id" value="52" >
Topping: <input type="text" name="data__pizza__topping" value="Mozzarella"> <br />
Size: <input type="text" name="data__pizza__size" value="Large"> <br />
Olives: <input type="checkbox" name="data__pizza__olives" value="Yes"> <br />
<input type="submit" value="Update">
</form>
On submission the contents of the data array is examined. Each object submitted
is identified (in this case 'pizza') and the relevant object is fetched from the database
using the 'id' field. Then the values are updated using the fields starting with 'datapizza'
and the object is stored in the database again, with no manual code intervention.
Problems
This naive solution has a number of problems, mainly associated with how little
protection it has against malicious users.
By specifying additional entries in the result sent back, an attacker can edit object members which are not meant to be user-editable, e.g. setting the 'admin' flag for their profile.
By changing the 'id' parameter the user can change the values for other objects, potentially changing someone else's pizza order
By carefully constructing the right query, the user can in fact edit any value for any object in the system.
The Solution
We clearly need to put in place additional measures to
-
Make sure we only update fields which the user is allowed to update
-
Make sure only objects the user is meant to be updating are updated
As much as possible, we would like to do these without introducing additional
complexity into the view code.
Solving field spoofing
One way to solve field spoofing would be at the object level, specifying which fields
are read-write and which are read-only. This is not an acceptable solution as there are some
fields which should e.g. be only editable by some users. It is also non-ideal as it requires us
to add more information to the system. We have already specified which fields should be
editable through this form, so following the principle of Don't Repeat Yourself, we shouldn't
do so again.
The problem is information about what fields where included is available when the form is
being constructed (we can easily record it from the displayInputField calls) but it is not available
when the form is being processed. We need to store this information when the form is generated
and then recall it when processing the form.
Obviously different forms will have different fields available so we need to have some way to
identify the form. One solution is to generate a unique form identifier each time displayForm is called
and associate this with the list of fields on the server. However for a busy site this will result in a lot of
duplicate information being stored, and there is also the question of how long this information should be
kept for - a user will not want to leave their computer with a page open, come back a few hours later and
find they have lost their work because a form session has expired.
A second, better, solution is to store this information as part of the form, in a hidden input field
(the "signature string"). This information is non-sensitive (the user can already see the list of fields supplied) however it must be secure against tampering. To do this we can include a hash of the information with a secret on the server. e.g. for
the example above we might use a signature string of "pizza_id:pizza__topping:pizza_size:pizza_olives|4A3F98E0F" where "4A3F98E0F"
is the result of hashing "my_server_secret|pizza_id:pizza__topping:pizza_size:pizza_olives". By checking the
hash the server can be sure the client has not tampered with the supplied values.
(Note for the paranoid: As both the hash and part of the cleartext are sent to the client it is feasible
for the client to launch a brute force attack to try to determine the server secret. This could be avoided
by having a list of server secrets, generating a new secret for example every hour, and having each secret only
valid for up to 8 hours. This way the time available for a brute force attack is greatly reduced, whilst still
allowing a reasonable length of time for the user to complete the form. Needless to say, a long and unguessable
server secret should be used.)
Solving object spoofing
To an extend we have already solved object spoofing, in that a user cannot edit an object of a different
type to the one they are meant to be editting. However, it is still possible for the user to change the id field
and edit a different object. This problem is best tackled by solving a more general one - preventing users from
manipulating any hidden fields. We simply need to include the values of all hidden fields in the hash we
generate. We could for example hash the string "my_server_secret|pizza_id:pizza__topping:pizza_size:pizza_olives|pizza_id=52" instead. As only hidden field values are included in the hash we need to indicate in our signature string, for example we could use "pizza_id|pizza__topping:pizza_size:pizza_olives|4D4C32AF71".
First posted 2006-06-16 00:00:00.000004+00:00
Fedora uses a package management application called yum (in my view far less intuitive and nice than apt-get, but then I'm more familiar with apt). There are also a set of additional utilities called yum-utils which allow more complicated queries of the yum package database.
With a bit of python magic you can combine these to do useful things. I've just written a script that checks for updates, and on finding updates will mail you a list of updated packages, and the changes between your current package versions and the updated ones (from the changelog). It keeps track of what it has told you about, and will only produce output if there are new packages available that you haven't previously been told about. It is intended to be used in a cronjob.
For those who are interested it is available here.
First posted 2006-05-22 00:00:00+00:00
Seven months ago Apple released the iPod Video. Now linux support for transferring videos to it is beginning to arrive.
The first part is getting your videos into a form the iPod can play. You can find instructions on how to do this here. Now you need to transfer these videos to your iPod. The CVS version of GtkPod has support for this (and possibly some of the more recent released versions). Unfortunately the latest packages of GtkPod in Debian Unstable don't support this. I have hacked together (and I mean hacked, I am no packager) some debs of the cvs version of GtkPod. You can find them here.
First posted 2006-05-01 00:00:00+00:00
I shall pass this way but once; any good, therefore, that I can do or any kindness that I can show to any human being, let me do it now. Let me not defer nor neglect it, for I shall not pass this way again.
First posted 2006-04-14 00:00:00.000004+00:00
At 2am in the morning the obvious way to avoid doing work would be to go to bed. Instead somehow I seem to have found a more exotic way: trying to get video editing and linux to play nicely together.
Assuming that you want to do things graphically rather than with lots of command line invocations (which have their place, but which I get tired of rather quickly for anything graphical and creative) there are two options: kino and cinelerra. Cinelerra is the far more powerful of the two, supporting overlaying tracks on top of each other with masks and combinations, and lots of layer effects and transformations. However it is also rather difficult to use. For day to day combining of video clips Kino is far more appropriate.
Kino is in the debian main repository but if you want to be able to work with the file formats from typical low end digital cameras you will need mencoder. This isn't in debian main for legal reasons so I suggest you add
deb ftp://ftp.nerim.net/debian-marillat/ sid main
to your sources.list and pick up a copy of mplayer and mencoder, the w32codecs and ffmpeg. You may need some other packages, I just installed things at random that looked relevant until it worked. This should be all you need, however unfortunately the versions of Kino and mencoder don't play nicely together, at least with videos from my camera. To fix this I edited /usr/share/kino/scripts/import/media.sh. Find vstrict=-1 and replace it with vstrict=-2.
Now you should be able to run kino and start playing. It should all be fairly straight forward. One thing I didn't notice for a while is the Split Scene option. This is the two arrows pointing away from each other on the toolbar and is enabled in Edit mode when you are part way through a clip. It turns the clip into two clips, split where you want. This gives you lots more power to move around and assemble the bits of video footage you have.
Video composition can be a long and slow process, if you decide to give it a go be aware you may suddenly lose hours of your life without noticing. Most importantly though, have fun. :-)
If you are looking for some stock clips to include in your creations the BBC has some available.
First posted 2006-04-07 00:00:00.000004+00:00
phpBB is a popular free (as in speech) php based web forum supporting numerous features, themes, languages, etc. Raven is the University of Cambridge centralised login service. I've put together some hacks to phpBB in order to allow users to login using Raven. The source is available as a modified copy of phpBB, just download it and install it as you would a normal copy of phpBB. Unfortunately it is impossible to upgrade from existing versions of phpBB to this new version. I might add support for this in time if there is enough demand.
phpBB 2.0.19 with Raven support
First posted 2006-03-18 00:00:00.000005+00:00
Aren't statements that sound profound but are in fact completely obvious and devoid of meaning great?
First posted 2006-03-03 00:00:00.000004+00:00
First posted 2006-03-02 00:00:00.000003+00:00
First posted 2006-02-21 00:00:00.000001+00:00
Before I give anyone the wrong impression, no I am not a Christian (and before I start any flame wars, I have no problems with anyone who is).
The emphasis is not on the Jesus, the idea is when considering a situation to imagine you are not the actor, but instead an outside observer, and ask yourself what action you would have most respect for. Then do that.
It works for me. Try it sometime.
First posted 2006-02-18 00:00:00.000005+00:00
First posted 2005-12-20 00:00:00.000001+00:00
Debian, the linux distribution I use on my computers has three versions: stable, testing, and unstable. I run unstable as it has newer software versions than the other two. However, as the name suggests, it sometimes breaks in fairly horrible ways. Now is one of these times, so here's a heads up for anyone else running unstable:
linux-kernel-2.6.14-(2|5) is broken. It will not boot.