Programming

Embedding Parrot in Perl 6

Posted by Daniel on June 20, 2009
Perl 6, Programming / No Comments

One of the interesting things about Rakudo is that you can embed Parrot assembly code (PIR to be exact) into Perl 6 code. With this you can optimize critical parts of the code and you can expose additional Parrot features to Perl 6. Let’s start with a hello-world example:

Q:PIR {
	say "Hello world"
};

Though it is not obvious right now, the stuff inside the Q:PIR { ... }; is parrot code.

Parameters

Of course, embedded Parrot code would be pretty useless if you couldn’t send parameters in and get results out. Here is a simple Parrot routine that takes two parameters, adds then and returns the result:

sub ($a,$a) = (3,4);
sub $result = Q:PIR {
	# Input.
	$P0 = find_lex '$a'
	$P1 = find_lex '$b'

	# Compute the sum.
	$I0 = $P0
	$I1 = $P1
	$I2 = $I0 + $I1

	# Return it.
	%r = box $I2
};
say $result;

Yes, that’s quite verbose. PIR is not much higher level than an assembly language. The $P0, $P1, … are Parrot registers. The $P* registers hold Parrot objects, and the $I* registers hold integers. A more interesting example would be a factorial function:

sub factorial(Int $n where {$n >= 0}) {
	return 1 if $n == 0;
	return Q:PIR {
		# Define variables.
		.local int ans, n

		# Input.
		$P0 = find_lex '$n'
		n = $P0

		# Compute the answer.
		ans = 1
		LOOP:
			ans *= n
			n -= 1
			if n > 1 goto LOOP

		# Return it.
		%r = box ans
	};
}
say "5! = " ~ factorial(5);

Exposing Parrot libraries to Perl

A specially neat feature of embedded Parrot is that you can expose Parrot libraries to Perl. For example, Parrot comes with support for the MD5 digest function, which itself comes from the OpenSSL library:

sub md5(Str $text) {
	my $binary = Q:PIR {
		.local string text
		.local pmc digest

		# Input.
		$P0 = find_lex '$text'
		text = $P0

		# Load digest library.
		$P1 = loadlib 'digest_group'
		digest = new 'MD5'

		# Calculate the digest.
		digest.'Init'()
		digest.'Update'(text)
		$S0 = digest.'Final'()

		%r = box $S0
	};
	# Convert to hex.
	return join '', map {sprintf '%02x', (ord $^a)}, $binary.comb;
}
say md5("The quick brown fox jumps over the lazy dog");

The resulting library is of course much simpler and runs much faster than anything we could code in pure Perl. And this will run wherever Rakudo is available, without the need for a separate compilation step.

Perl 6 and the Josephus problem

Posted by Daniel on June 12, 2009
Perl 6, Programming / 6 Comments

The Josephus problem in Perl 6, Python and Ruby

In today’s post, I would like to compare the OOP syntax of Perl 6, Python and Ruby. To this effect, I decided to show you an implementation of the Josephus problem in each language. Wikipedia describes the Josephus problem:

There are people standing in a circle waiting to be executed. After the first man is executed, certain number of people are skipped and one man is executed. Then again, people are skipped and a man is executed. The elimination proceeds around the circle (which is becoming smaller and smaller as the executed people are removed), until only the last man remains, who is given freedom. The task is to choose the place in the initial circle so that you survive (are the last one remaining).

The problem is named after Flavius Josephus, a Jewish historian living in the 1st century. As the legend goes, he and his 40 comrade soldiers were trapped in a cave, surrounded by Romans. They chose suicide over capture and decided that they would form a circle and start killing themselves using a step of three. As Josephus did not want to die, he was able to find the safe place, and stayed alive.

Acknowledgement

The idea to use the Josephus problem to compare these languages is not my own. The idea comes from danvk.org who used it to compare Perl 5, Python and Ruby. I have copied his Python and Ruby code and I added the Perl 6 code of my own.

A quick note

I have tried to normalize the code as much as possible, so that you can get a better impression of the OOP syntax in each language. I will not benchmark the code, and I will keep my commentary to a minimum. The idea is that you see the OOP syntax of each language, with minimum influence from me.

Writing the class

Perl 6 (tested with Rakudo)

class Person {
	# $. means "public", "is rw" means it is writable.
	has ($.position, $.succ is rw);
	has $.alive is rw = True;

	# Stringify
	method Str() {
		"Person $.position, " ~ ($.alive ?? "alive" !! "dead")
	}
	# Create a linked chain of people.
	method createChain($n) {
		return self unless $n > 0;
		$.succ = Person.new(position => $.position + 1);
		$.succ.createChain($n-1);
	}
	# Kill every nth person. Stop killing if I'm the last one.
	method kill($pos is rw, $n, $remaining is rw) {
		return $.succ.kill($pos, $n, $remaining) if !$.alive;
		return self if $remaining == 1;

		if $pos == $n {
			$.alive = False;
			$pos = 0;
			$remaining -= 1;
		}
		$.succ.kill($pos+1,$n, $remaining);
	}
}

Python (tested with 2.5.2)

class Person:
	# Initialize
	def __init__(self,pos):
		self.position = pos
		self.alive = True

	# Stringify
	def __str__(self):
		status = "alive" if self.alive else "dead"
		return "Person #%d, %s" % (self.position, status)

	# Create a linked chain of people.
	def createChain(self,n):
		if n > 0:
			self.succ = Person(self.position+1)
			return self.succ.createChain(n-1)
		else:
			return self

	# Kill every nth person. Stop killing if I'm the last one.
	def kill(self,pos,n,remaining):
		if not self.alive:
			return self.succ.kill(pos,n,remaining)
		if remaining == 1:
			return self
		if pos == n:
			self.alive = False
			pos = 0
			remaining -= 1
		return self.succ.kill(pos+1,n,remaining)

Ruby (tested with 1.8.7)

class Person
	# Accessor and mutator methods
	attr_reader :position, :succ, :alive
	attr_writer :position, :succ, :alive

	# Initialize
	def initialize(pos)
		@position = pos
		@alive = true
	end
	# Stringify
	def to_s
		"Person \##@position, #{@alive ? 'alive' : 'dead'}"
	end
	# Create a linked chain of people.
	def createChain(n)
		return self unless n > 0
		@succ = Person.new(@position + 1)
		@succ.createChain(n-1)
	end
	# Kill every nth person. Stop killing if I'm the last one.
	def kill(pos,n,remaining)
		return @succ.kill(pos,n,remaining) if !@alive
		return self if (remaining == 1)

		if pos == n
			@alive = false
			pos = 0
			remaining -= 1
		end
		@succ.kill(pos+1,n,remaining)
	end
end

Comments

All three classes are straight forward, and almost exactly the same size. Perl 6 is a bit shorter, but the differences are insignificant:

Perl 6 Python Ruby
Lines of code* 23 25 27
Characters* 546 578 549

* Not including comments.

Note: A reader mentioned that a better way to do Ruby is to replace “attr_reader” and “attr_writer” by a single “attr_accessor”. With this change, Ruby is the shortest by character count.

There are things I could have done to make each language shorter, but my goal was to make each code sample clear and legible. Besides, you shouldn’t pick a language because you can save 3 lines of code. It makes more sense to see if you like the syntax and the over-all “feel” of the language, and that is a much more personal decision.

On a personal note, I don’t like the Python syntax as much… passing “self” explicitly, double underscores… it feels a bit hackish, but that’s just me. In turn, I like the Ruby and Perl 6 syntax. I can’t decide which I like better. Both look very clean and very clear.

Using the classes

Finally, this is how you would use these classes:

Perl 6

my $orig = 40;
my $nth = 3;

my $first = Person.new(position => 1);
my $last = $first.createChain($orig-1);
$last.succ = $first;

my $winner = $first.kill(1,$nth,$orig);
say "Winner: ", $winner;

Python

orig = 40
nth = 3

first = Person(1)
last = first.createChain(orig-1)
last.succ = first

winner = first.kill(1,nth,orig)
print "Winner: ", winner

Ruby

orig = 40
nth = 3

first = Person.new(1)
last  = first.createChain(orig-1)
last.succ = first

winner = first.kill(1,nth,orig)
puts "Winner: " + winner.to_s

RPN calculator in Perl 6

Posted by Daniel on June 06, 2009
Perl 6, Programming / 6 Comments

Here is something fun. Let’s make a full RPN calculator in Perl 6. In the process we’ll learn a lot about Perl 6’s cool grammar features.

Regexes on steroids

Perl 6 extends Perl 5’s regular expressions to make a full grammar language. Btw, we no longer say “regular expression”, we just say “regex”. The first feature I’ll introduce is the token. A token is basically a regex with a name so you can refer to it later. For example:

token Op {'/' || '*' || '+' || '-'};
token Value { \d+[\.\d+]? };

The first token matches the arithmetic operators + – * /. The second token matches numeric values. You can use these tokens inside a regex. For example, the following matches one or more Ops:

$str ~~ / <Op> + /

Changes compared to Perl 5:

  • Space is not significant in a P6 regex. You can space things out to make the regex more readable.
  • If you put single quotes around any text, the regex matches that text literally. So instead of writing \* you can write ‘*’
  • Now we use ~~ instead of =~

An RPN grammar

We can write tokens that refer to other tokens in order to build more complex grammars. A RPN calculator is basically a list of values and operators. Thus, we can complete the RPN grammar with:

# An "item" is either a value or an operator.
token Item { <Value> || <Op> };

# An "expression" is one or more items separated by white space.
token Expr { [<ws> <Item> <ws>]+ };

The <ws> token is provided by Perl 6. It is similar to \s* but it does not match the inside of a word. For example, the string “hello” does not match <ws> but the string “2+2″ does. Using tokens that refer to other tokens (including recursive definitions) you can build very complex grammars with Perl 6. In fact, the reference grammar of Perl 6 itself is written in Perl 6.

Procedures and control flow

At some point we’ll need a function to compute the result of two values and an operator. In Perl 6 you write procedure parameters explicitly, as you do in other languages:

sub do_op($lhs, $rhs, $op) {
	given $op {
		when '*' { $lhs * $rhs }
		when '+' { $lhs + $rhs }
		when '-' { $lhs - $rhs }
		when '/' { $lhs / $rhs }
	}
}

And here you can see Perl 6’s brand new switch statement. The keywords given and when may be less familiar than switch and case, but they are more natural and read better.

This would be a good time to see the new syntax for for loops:

for @array -> $elem {
	say $elem;
}

Here you can also see the say keyword which is very much like print except that it automatically adds the \n character at the end of the string.

Main program

Now we are ready for the main program logic. Start with an skeleton:

# Read from the command line.
my $str = @*ARGS[0];

if $str ~~ /^ <Expr> $/ {
	# Do something.
} else {
	say "This is not an RPN expression.";
}

A few things merit mention:

  • The array @*ARGS contains the command arguments.
  • In Perl 6, when you get a value of an array, you keep the @ symbol. So the first command argument is @*ARGS[0].
  • The round brackets in an if-statement are now optional.

After a successful match, the match result is put in the $/ variable. This variable is similar to Perl 5’s $1, $2, … but more powerful. In particular, you can refer to token matches by name:

if $str ~~ /^ <Expr> $/ {
	$/<Expr>;            # <-- The Expr matched.
	$/<Expr><Item>;      # <-- A list of Item tokens.
	$/<Expr><Item>[0];   # <-- The first Item token.
}

We saw earlier how to step through an array using a for loop. We can use $/<Expr><Item> the same way:

if $str ~~ /^ <Expr> $/ {
	for $/<Expr><Item> -> $item {
		# Do something with $item.
	}
}

Now we know enough Perl 6 syntax to finish the program:

if $str ~~ /^ <Expr> $/ {
	my @stack;
	for $/<Expr><Item> -> $item {
		if $item<Value> {
			@stack.push($item<Value>);
		} else {
			my $v1 = @stack.pop;
			my $v0 = @stack.pop;
			@stack.push(do_op($v0,$v1,$item<Op>));
		}
	}
	say @stack[0];
}

I trust that you can follow the algorithm. If not, see the Wikipedia page on RPN.

The full program

Now we are ready to see the entire program together.

token Op {'/' || '*' || '+' || '-'};
token Value { \d+[\.\d+]? };
token Item { <Value> || <Op> };
token Expr { [<ws> <Item> <ws>]+ };

# Read from the command line.
my $str = @*ARGS[0];

if $str ~~ /^ <Expr> $/ {
	my @stack;
	for $/<Expr><Item> -> $item {
		if $item<Value> {
			@stack.push($item<Value>);
		} else {
			my $v1 = @stack.pop;
			my $v0 = @stack.pop;
			@stack.push(do_op($v0,$v1,$item<Op>));
		}
	}
	say @stack[0];
} else {
	say "This is not an RPN expression.";
}

sub do_op($lhs, $rhs, $op) {
	given $op {
		when '*' { $lhs * $rhs }
		when '+' { $lhs + $rhs }
		when '-' { $lhs - $rhs }
		when '/' { $lhs / $rhs }
	}
}

Now you can save this to a file (RPN.pl) and run it with:

perl6 RPN.pl  "5 4 + 3 / 5 3 - *"

Exercise

Modify the program to add error checking: Check that @stack has size at least 2 before running an operator and that it has size 1 before returning a result. Use +@array to get the size of an array.

Perl 6 First Steps

Posted by Daniel on June 05, 2009
Perl 6, Programming / No Comments

I have been working more with Perl 6 / Rakudo. I have contributed a few bug reports, and I have now ported six of the Debian shootout benchmarks to Perl 6. I’m adding all the benchmarks to the perl6-examples git repository:

git clone git://github.com/perl6/perl6-examples.git

The benchmarks are located in the ’shootout’ directory. The benchmarks implemented include Fasta, Regex-DNA, K-Nucleotide, N-Body and Reverse-Complement.

Performance

Since I mentioned benchmarks, I guess I have to mention performance…

As you might expect for a project at this stage, Rakudo is very slow. Most benchmarks run about 500 times slower than Perl 5. But that’s normal. There has been no optimization work on Rakudo, since the focus is to get the functionality done (and premature optimization is the root of all evil). In the long term, there is no reason why Perl 6 couldn’t be faster than Perl 5, thanks to its simpler grammar and its type system.

Personally I wouldn’t worry about the performance of Rakudo at this point. Besides, Rakudo is more than fast enough for a lot of simple tasks like admin scripts. I plan to rewrite my backup script in Perl 6 and run it on Rakudo.

The Perl 6 experience

So far, the experience of writing Perl 6 code has been quite pleasant. I really like the Perl 6 syntax. When I convert Perl 5 code to Perl 6 I find that the result is always clearer, always easier to read, usually shorter, never longer. The syntax is more regular (a traditional problem with Perl) and yet it is more succinct and flexible (Perl’s traditional strengths). I feel that with Perl 6 it is easier to just say what I mean. I’m impressed.

Brainfuck interpreter in Perl 6

Posted by Daniel on May 30, 2009
Perl 6, Programming / No Comments

I wrote a Brainfuck interpreter in Perl 6 (largely inspired by Acme::Brainfuck). Here it is in its entirety:

# Read the program.
my $program = $*IN.slurp;

# Compile to Perl 6.
$program .= subst(/\$/, 'P; };', :g);
$program .= subst(/(\++)/, { 'P += ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/(\-+)/, { 'P -= ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/(\>+)/, { '$ptr += ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/(\<+)/, { '$ptr -= ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/\./, 'print chr P;', :g);
$program .= subst(/\,/, 'P = ord getc;', :g);
$program .= subst(/\[/, 'while (P) {', :g);
$program .= subst(/\]/, '};', :g);
$program .= subst(/P/, '@P[$ptr]', :g);
$program  = 'my @P = (); my $ptr = 0;' ~ $program;

# Run
eval $program;

Here is “Hello world” in Brainfuck (taken from Wikipedia):

++++++++++    initializes cell zero to 10
[
   >+++++++>++++++++++>+++>+<<<<-
]             loop sets the next four cells to 70/100/30/10
>++.          print   'H'
>+.           print   'e'
+++++++.              'l'
.                     'l'
+++.                  'o'
>++.                  space
<<+++++++++++++++.    'W'
>.                    'o'
+++.                  'r'
------.               'l'
--------.             'd'
>+.                   '!'
>.                    newline

To run the program, just do: perl6 brainfuck.pl < hello.bf

Perl 6

Posted by Daniel on May 27, 2009
Perl 6, Programming / No Comments

This week I’ve been experimenting a little with Perl 6. It began as a quick question on IRC and somehow I ended up writing sample scripts in Perl 6. This week I ported the regex-dna benchmark to Perl 6, and I intend to port a few others. You can download it here.

One thing that’s new about Perl 6 is that it is a specification, similar to C, C++ and Java. Any product that meets the spec and passes the test suite can be called Perl 6 (there are many C compilers, and none of them is “the official C compiler”).

The implementation I have been experimenting with is Rakudo (compiler written in Perl 6 and Parrot assembly language) which seems to be the most active and the most complete. You can already write some Perl 6 programs with the Rakudo compiler. There is a wiki called November, a board game called druid, and a few others. Other notable implementations include Pugs (interpreter written in Haskell) and SMOP (interpreter written in C).

Comparison of PHP frameworks – Part I

Posted by Daniel on January 21, 2009
Programming / 28 Comments

This is part I of a two-part comparison of PHP frameworks: CakePHP, CodeIgniter and Yii:

  • Part 0 explains my comparison criteria.
  • Part I is this part. I evaluate each framework after reading nearly all their documentation and writing a Hello World application.
  • Part II will be the result of my experience as I use each framework to write a prototype for my real-world application. Sorry. Part II is cancelled due to lack of time (this kind of article takes a lot of time).

I have spent 4 weeks studying each framework carefully. This document is long. I tried very hard to make it as short as possible without compromising on fairness, clarity or completeness with regards to my initial criteria

Part II will also take a few weeks, as I write an application prototype with each framework.

Contents

Simplicity

^Back to contents

It is hard to judge framework simplicity before making an application, but I can make some initial comments based on the documentation:

CakePHP

Installation: I had a problem with Apache that was not documented. I had to edit three .htaccess files to add a “RewriteBase” command.

Usage: Helpers, Actions, Behaviours, Layouts, Components… Do I need to know all that to make my program? Cake seems to have a higher barrier to entry and at the moment I don’t see any special feature it provides that the others don’t.

All frameworks come with a default layout and CSS. For my benchmark I had to remove this so all frameworks are doing the same work. With CakePHP I had a very hard time finding the layout file Cake was using. It was not in a logical place (inside my app directory).

CodeIgniter

Installation: Trivial. Just unzip the file and you are good to go.

Usage: CodeIgniter looks quite simple. The documentation never makes it look complex. My hello-world program was done a lot faster with CI than with Cake. Over-all, CI seems to have a low barrier to entry.

All frameworks come with a default layout and CSS. For my benchmark I had to remove this so all frameworks are doing the same work. With CI this was automatic when I made a new view. CI doesn’t insert layout unless you ask it to.

Yii

Installation: Easy. You have to run yiic to create the web root directory. There is also a PHP version (yiic.php) which is good if you don’t have ssh access. Yiic is well documented.

Usage: Yii also looks simple and straight forward, though a bit less so than CodeIgniter. My hello-world program was done almost as quickly as with CI.

All frameworks come with a default layout and CSS. For my benchmark I had to remove this so all frameworks are doing the same work. With Yii this was very easy. The layout file is in a logical place and it is well documented.

I am pleased to report that none of these frameworks require you to learn a templating language like Smarty. PHP itself makes a great templating language. I have used Smarty for several years, and honestly I think it’s more trouble than it’s worth. I note that Yii and CodeIgniter both come with an optional templating language for those who like templating languages. But as I said, it is optional.

Result: CodeIgniter seems the simplest, followed closely by Yii.
I’ll reserve a final verdict until I write the application prototypes in Part II.

Documentation

^Back to contents

Please take the following with a grain of salt. Docs often look different when you try to actually write an application. If the docs are inaccurate, or incomplete, you won’t know until you start writing. So far the only program I’ve written with these frameworks is hello world.

CakePHP
My first impression was quite positive. The documentation looks complete and easy to read. The tutorials were a bit hard to find (they are under “Example Applications”). When I wrote hello-world I hit a snag (404 error) and the problem was not documented. I had to edit Cake’s .htaccess files to fix it. I would have liked to see a trouble shooting section in the manual. I also had a very hard time figuring out how to remove the extra stuff (header, footer, style) that Cake includes by default.
CodeIgniter
My first impression was again positive. I note that it took me a lot less time to write hello-world with CodeIgniter than with Cake. I think this is mostly because CI is simpler, but I do think that the documentation had something to do with it.
Yii
Again, my first impression was positive, and I wrote hello-world very quickly. When I wrote hello-world I had to remove the extra things that Yii includes in the page to make the benchmark fair. Finding out how to do this was quick and easy.
Result: Hard to judge at this point.
All seem to have good documentation. I had a couple of problems with Cake’s, but I can’t make a strong statement yet.

Performance

^Back to contents

In this section I will discuss two different benchmarks. One carried out by myself, and one carried out by the Yii team. I believe that both are worth considering.

Key similarities:

  • Both benchmarks try to measure the minimum overhead of each framework. They get the framework to print “Hello World” and nothing more.

Key differences:

  • I use the default configuration of each framework. The Yii team tried to optimize each framework to print “Hello World” as fast as possible.
  • Yii’s benchmark just runs die(). Mine uses the MVC: A controller puts “Hello World” in a variable which is passed to the view to print inside a basic HTML page.
  • Yii used a dedicated server for the tests. I used the shared hosting service where I’m going to deploy my actual application.

Thus, Yii’s benchmark is more technically fair, but mine might give a better impression of real world behaviour. As always, all benchmarks should be taken with a grain of salt. The benchmarks are expressed in terms of Requests Per Second (RPS) so more is better.

Version Yii’s test: RPS with APC
CakePHP 1.2.0  41
CodeIgniter 1.7.0  146
Yii 1.0.1  331


Version Yii’s test: RPS without APC
CakePHP 1.2.0  31
CodeIgniter 1.7.0  77
Yii 1.0.1  98


Version My test: RPS without APC
CakePHP 1.2.0  32
CodeIgniter 1.7.0  52
Yii 1.0.1  50


Benchmark details:
Yii’s page describes their benchmark. For my benchmark, each framework had to run the following PHP code in a view:

<html>
<head>
  <title>Greetings</title>
</head>
<body>
  <h1>Greetings from XYZ</h1>
  <p>The greeting message is: "<?= $message ?>"</p>
</body>
</html>

Where $message is provided by the controller and its value is “Hello World”. The requests per second were obtained using the ApacheBench tool with the command “ab -t 30 -c 10 URL”. My testing environment is a shared hosting account running on:

  • CentOS 4 Enterprise Linux.
  • Apache 2
  • PHP 5.2.6
  • CPU: Quad-Core AMD Opteron(tm) Processor 2350
  • Memory: 8GB
Conclusion: Yii and CI both stand out for speed. Yii may have an edge, but it’s hard to say for sure.

Flexibility

^Back to contents

CakePHP
CakePHP is very focused on conventions. It has a lot of expectations as to how you name your files, your classes, your database, your methods, etc. I can’t yet say whether this will present a problem for me, but I worry that it might.
CodeIgniter and Yii
CodeIgniter and Yii both look quite flexible. It is difficult to look at the documentation and say that one is definitely more flexible than the other. Both follow the MVC pattern, but they don’t feel rigid. CakePHP relies more heavily on conventions than Yii and CI.

Some examples of similarities and differences:

  • All frameworks expect you to follow certain naming conventions for your controller.
  • CakePHP requires that you create a model, a database and a table even if your program doesn’t require one.
  • Cake calls a view automatically, based on the name of the controller. With CI and Yii you call the view explicitly. So Cake has a little more “convention over configuration”. But in turn, with CI and Yii you can call multiple view files.

Here is a code example:

/* CakePHP */
class GreetingsController extends AppController {
	var $name = 'Greetings';
	function index()
      {
		$this->set('message', 'Hello world');
	}
}

/* CodeIgniter */
class Greeting extends Controller {
	function index()
	{
		$data = array('message' => 'Hello world');
		$this->load->view('greeting', $data);
	}
}

/* Yii */
class GreetingController extends CController {
      public function actionIndex()
	{
		$data = array('message' => 'Hello world');
		$this->render('greeting', $data);
	}
}

As you can see, the CI and Yii versions don’t really look more complicated than the CakePHP version, but they give you an extra feature: you can load more than one view file. For example, you can load a special header, insert a widget, etc.

Result: CodeIgniter and Yii both look quite flexible.
At the moment I cannot judge which is more flexible.

Security

^Back to contents

Security is complex because there are many possible attacks. This section is a bit long. I’ll try to stick to the point. This section is divided according to features or attacks.

Access control

For background, see Authentication and Authorization.

CakePHP

I found CakePHP’s access control complicated. You use a code generator (”cake bake”) to generate schema files and ACLs. The process generally felt complicated. Some of the terms (ACOs, AROs, Requester) threw me off initially.

I expect access control to be somewhat complex, but Cake’s was more complicated than I expected. It looks powerful, but hard to use. I felt I didn’t know what was going on and didn’t have control. And security is a place where I want to know what’s going on and want control.

Quick Test: I didn’t see an obvious way to add password strengthening. The tutorial says that if you hash passwords yourself the system won’t work.

CodeIgniter
As far as I can tell, CI does not offer access control features. Access control can be complex (groups, roles, etc) and it’s nice if the framework can help you.
Yii

I had a much easier time understanding Yii’s access control system. I won’t call it “simple”, but that’s because access control is not simple. I’d say that Yii’s access control is as simple as possible – but not simpler. As I read through the docs, I felt I knew what was going on and I felt I could modify it to fit my needs.

Quick Test: I could immediately see how to add password strengthening.

Some Yii features that I like

  • Flexible: You can have access rules based on user IP or request type (GET vs POST) or rules that match anonymous or authenticated users.
  • Return Url: You click on a link but the session has expired. You are sent to the login page. You login, and the system automatically takes you to the page you were trying to access. For me, this is very useful.
  • Role Based Access Control: RBAC is more flexible and powerful than the traditional ACL. With Yii you can write your whole application ignoring RBAC and only use it when it solves a specific problem. So the system is as flexible as it needs to be, but your access rules are never more complex than they need to be.

Dictionary attacks

A dictionary attack consists of trying a large number of common passwords from a password dictionary. For a web app, this attack can be very effective. The recent attack on Twitter was a dictionary attack.

There are many ways to block dictionary attacks: Lock the account after X failed logins, time delays, CAPTCHAs. Each has its pros and cons. Locking accounts is easy and effective, but it opens a denial of service attack: Someone can try many logins, not to gain access, but to lock out users. Here is one I like: After 5 failed logins, you must solve a CAPTCHA to attempt additional logins. It balances dictionary attacks, DoS and user convenience.

None of the frameworks have features specific to dictionary or DoS attacks, nor do I expect them to. The real issue is, Can you implement your preferred login method with this framework? So it’s a question of control and flexibility. With CI and Yii I’m confident I can do it, but I’m not so confident I can do it with CakePHP.

Cross-site scripting attacks (XSS)

XSS has overtaken buffer overflows as the most common security hole. It works like this: Someone posts a comment on your blog and that post includes malicious JavaScript. When you view the blog, the JS code is executed. Since the JS code is coming from your domain it is “trusted” by the browser. It can read your cookies, or manipulate the page contents (e.g. “Session expired. Please enter your password”).

CodeIgniter and Yii both come with HTML filters that can remove JavaScript code from the user input. I am sad to report that CakePHP does not seem to include an XSS filter.

SQL injection attacks

SQL injection is one of the most common security flaws on web apps (funny comic). It happens when user input is interpreted as executable SQL code. For example:

$q = "SELECT * FROM users WHERE l = '$user' AND p = '$pass'";
$result = mysql_query($q);

Suppose the user enters the password foo' OR 1='1 Then the query becomes:

SELECT * FROM users WHERE u = 'foo' AND p = 'foo' OR 1='1'

Since 1='1' is always true, this query returns all users. The most common (and wrong) solution is to escape strings using a function like addslashes() or mysql_real_escape_string():

$pass = mysql_real_escape_string($pass);
$user = mysql_real_escape_string($user);

What’s wrong with this solution?

  • It is error-prone, since you have to remember to escape every parameter.
  • It depends on someone being able to find every possible character that can be exploited. The good guys have to find every attack, while the bad guys only have to find one. This is a losers game.

Chris Shiflett shows how to use a Chinese character to get an SQL injection through addslashes. How do we know that there isn’t some Tamil character that will get through mysql_real_escape_string?

The right solution: prepared statements

The right solution is to circumvent the problem entirely by compiling the SQL query separately from the user input. That is, to use prepared statements (aka parametrized statements, aka bound parameters). Prepared statements separate the SQL logic from user data (see here and here).

Does the PHP framework support prepared statements?

Unfortunately, of the three frameworks, only Yii offers prepared statements. I think that the lack of prepared statements is a major problem for CakePHP and CodeIgniter.

Cross-site request forgery attacks (CSRF)

Cross-site request forgery (CSRF) attacks are in some ways complementary to cross-site scripting (XSS) attacks. XSS abuses the client’s trust on the server. CSRF abuses the server’s trust on the client. Imagine that Bob visits a malicious website with the following image tag:

<img
src="http://mybank.com/transfer?from=Bob&to=Eva&USD=10000">

If Bob is currently logged in to his bank the bank’s server will receive a request from Bob to transfer $10,000 to Eva’s account.

What can you do to protect against CSRF? Other than expiring cookies sooner, the main solution is to use a secret token to authenticate any GET and POST parameters that can modify server data.

CakePHP and CodeIgniter do not seem to have any features for CSRF. Yii offers CSRF protection for POST requests using secret tokens (you have to enable this feature). To complete the CSRF protection you must make sure that GET requests cannot modify server data.

Cookie hijacking attacks

Cookies are routinely used to store sensitive information such as session IDs, user name or a password hash. Cookie hijacking is when a third party gets access to your cookie. This might be through cross site scripting (XSS) or through a packet sniffer.

How do you protect against cookie hijacking? SSL will protect you against packet sniffers. And you should take measures to prevent XSS. You can make the cookie data less useful by not storing long-term sensitive data in it. For example, instead of storing md5(passwd), use a hash that expires like HMAC(date,md5(passwd)).

To my knowledge, CakePHP and CI don’t offer any features against cookie hijacks. Yii has a cookie validation feature that uses HMAC to authenticate cookie data, so an attacker can’t modify an old cookie (e.g. change the expiration date) without detection.

Of course, this won’t help you if you do something dumb like store the plain text password in the cookie.

Winner: Yii

Yii has a strong edge in security, with better access control and protection against XSS, SQL injection, cross-site forgery and cookie hijacking.

CakePHP and CodeIgniter are a bit disappointing in this area. CI gets a point for being flexible, so it’s easier to add security features yourself.

Other Notes

^Back to contents

These are some things which are not part of my core criteria, but I feel are worth mentioning.

Prototype
CakePHP uses the Prototype library. I have concerns with Prototype. Basically it pollutes the global name space and it can break valid JavaScript code. So Prototype doesn’t play well with your code or other libraries.
Scheduled Releases
Yii has scheduled releases. I wish all open source projects would do that.
Filtered Input
CodeIgniter has a very nice Input Class that sanitizes some of the input. It destroys the GET array, and all global variables except POST and COOKIE. This feature doesn’t fit exactly into any of my criteria, but it promotes good code and I think it deserves mentioning. I mentioned XSS filtering in the security section.

Summary So Far

^Back to contents

My experience with CakePHP was distinctly worse than with CI and Yii. The docs are generally good, but not better than CI or Yii. I can’t see any area where Cake clearly stands out above CI or Yii. It might be better for simple apps that do everything the way Cake expects. But generally Cake is more complex than CI or Yii and you don’t seem to get much in return.

Yii and CodeIgniter are a closer match. They are about equal on performance, documentation and flexibility. They are both fast, clearly documented and quite flexible. CodeIgniter seems somewhat simpler, but Yii has a strong edge in security features. I’ll have to wait until I write an application prototype with each before I form a strong opinion.

Generally I don’t like comparison tables because they over-simplify things, but I realize that people often want a quick summary table, so here is a rough one:

CakePHP CodeIgniter Yii
Simplicity Not great Excellent Very good
Documentation Good [1] Very good [1] Very good [1]
Performance
Flexibility Poor Very good Very good
Security features Not great So so [2] Excellent

[1] Take this with a grain of salt. It’s hard to judge docs until you actually write your app.
[2] CodeIgniter gets a point for filtering XSS and for over-all flexibility.

Comparison of PHP frameworks – Part 0

Posted by Daniel on December 27, 2008
Programming / 3 Comments

For my next project I have decided to use a PHP framework. There are far too many PHP frameworks to evaluate them all carefully, so after a modest look, I narrowed my choices down to CakePHP, CodeIgniter and Yii. One can’t make a good comparison without actually using each framework in a real project, so that’s what I will do. This comparison will have two parts:

Project description:
I want to rewrite a legacy PHP application that has outgrown its design. The application is very database-oriented. Our customers are UK schools and the core of the system is a database with student data (marks (grades), awards, teaching groups, etc).

My Criteria

There is no universal, absolute “best” PHP framework. It depends on your particular needs and preferences. Here is a list of the key things that I will be looking for in selecting a PHP framework. The criteria are not in any particular order:

Simplicity
I value simplicity above having every possible feature. I like to understand the tools I use. I certainly don’t mind if the framework has every possible feature, but not at the expense of simplicity.
Documentation
I value clarity and organization above documenting every detail. Maybe it’s my background as a teacher and author, but I do set a high standard for documentation. Above all else, I expect it to be clear and well organized.
Performance
I value code quality and correctness above speed. Although I will not use a fast but otherwise poor framework, the reality is that for my application performance is a real concern. Thus, I must seriously consider performance in my analysis.
Flexibility
I value flexibility above conventions. I have a legacy database that I must use. I am replacing a legacy application that was not well designed. Some of the business logic is a bit complex. I need a tool that can cope with this without making my life difficult.
Security
I value security above most things. I take security seriously and I want my tools to be likewise. For example, to avoid SQL Injection attacks, most frameworks are content to simply escape strings so they can support PHP4. I am not satisfied with that. I want good security (prepared statements) and to heck with PHP4.

Get a free space shuttle

Posted by Daniel on December 18, 2008
Programming / No Comments

If you are an educational institution you can sign up to get a U.S. space shuttle from NASA entirely free of charge *

* Offer does not include $42,000,000 shipping and handling. :-)

My first AIR application

Posted by Daniel on May 31, 2008
Programming / 2 Comments

A while ago I made my first Adobe AIR application. It is a “desktop version” of a web-based markbook (gradebook) that I wrote for the INGOTs.

Go to the application web page. You can login using the guest account “Guest 1″. The password is “zepplin2″.

Comments

Converting my existing Ajax application into an Adobe AIR application was very easy. I only had to make minor modifications. I had to upgrade to the current version of Dojo and I had to modify a few files that used PHP (AIR doesn’t include PHP).

Actually, what took me the longest was figuring out how to self-sign a application. It’s in the manual, but it took me a long time to see it.

Hint: go to the manual and select AIR development tools > Creating an AIR application using the command line tools > Creating a self-signed certificate with ADT.

xanax 2mg