Tag Archives: PHP

My Web App in the News

ANOTHER UPDATE: Whoops.  Fixed the links to the auction and the St. Catharines Standard article.

UPDATE: Apparently, the Feds are getting in on the online auction circuit too.

Over the past three summers, I’ve been employed by the District School Board of Niagara as an internal web application developer.

One of my first jobs in the summer of 2006 was to rebuild the online auction application that the DSBN Purchasing department ran.  The original auction let the Board dispose of old equipment quickly and easily, and was quite popular.  Unfortunately, it was also written in (almost) unintelligible/unmaintainable Perl.

So I rewrote it by myself, and learned PHP/MSSQL along the way.  We called this new auction site The Government Surplus Online Auction, and we opened it up so that other government agencies could also post items for auction.

Things went along fine until last summer, when the site got attacked by an SQL Injection bot.  Back in 2006, I had no idea what SQL injection was, or how to guard myself.

So there I am – I’ve just come back from a camping trip, my inbox is packed with complaints, and I’ve got three weeks until school begins.  Crap.

Luckily, I had plenty of tools at my disposal.  My web app development skills and practices had evolved dramatically since 2006, and I had been itching to reimplement the auction anyhow.  The SQL Injection attack was a perfect excuse for me to gut the entire application, and rebuild from scratch.

And I did.  I rebuilt the whole thing from the ground up in three weeks.  It’s been almost a year since it was deployed, and I’m still very happy with its performance, and the code that runs it.

I’m not happy with its overall UI design.  I think there are plenty of improvements to be made in that regard.  Luckily, it’s coded using a light MVC framework that I designed/built myself, so reskinning shouldn’t be too hard for whoever decides to work on it…

Apparently, I’m not the only one happy with the auction site.  Check out this article (now without annoying print dialog).

I just checked the logs today – we hit a new record: an aerial truck went for $22,000 dollars.  With the Board receiving 5% ($1100) of that simply for hosting, I think everybody is walking away happy.

Here’s the auction.

Proof that I wrote it?  This’ll have to do.

SQL Injection Prevention in PHP – Tip 1

It’s amazing – I’ve been going around, Googling for anything with “index.php?id=”…and that’s really all it takes.  Now, granted, SQL Injection isn’t new, and a lot of the top hits have taken some steps to protect themselves, but if you go deep – like, Google search page 23 deep – you’ll find ones that break if you put a semi-colon after the id # – and if it breaks, it’s vulnerable.

So, here’s my first tip on preventing SQL Injection – when you’re asking for an ID number, make sure it’s a number, and nothing else. Also consider using prepared statements – database wrappers like MDB2 for PHP make this easy.

Check this out – this might be how I would have done it 3 years ago:

<?php
  //Assume we're already connected to a MySQL database...
  $id = $_GET['id'];

  $result = mysql_query('SELECT * from pages where id='.$id);
  if (!$result) {
     die('Invalid query: ' . mysql_error());
  }
  ... //Code to print out my result to the page
?>

I’d do it this way now:

Note: My use of MDB2 might be a little rusty – I haven’t tested this code, and I usually compose RowDataGateway objects with MDB2 to represent my data.  So pay more attention to the structure than the actual syntax.

<?php
  require 'View.php';
  require 'MDB2.php';  //An excellent DB layer from the PEAR libs

  //Code to set $mdb2 as our DB connection variable
  //See http://pear.php.net/package/MDB2 for details
  $id = $_GET['id'];

  try {
    if(!is_int($id)) {
      //ID wasn't an int, it's no good, let's bail
      throw new Exception('Could not recognize the id that you passed');
    }
    //ID was an int, let's see if we can find the record
    $sql = 'SELECT * from pages where id=:id";
    $statement = $mdb2->prepare($sql);
    $statement->bindParam('id', $id);
    $result = $statement->execute();
    if(PEAR::isError($result)) {
      //Uh oh - our result was an error on the PEAR library level
      throw new Exception('There was an error communicating with the database');
    }
    //Insert the database result into the view, render, and die.
    $content = new View('templates/page.tpl', array('page' => $result->fetchOne()));
    $content->render();
    die;
  }
  catch(Exception $e) {
    //We must have caught an exception - put this into our
    //error page template with the error message, render, die.
    $content = new View('templates/error.tpl', array('message' => $e->getMessage()));
    $content->render();
    die;
  }
?>

Yes, it’s quite a bit more code. But I feel safer just looking at it.
Did I miss anything on this? Please post a comment if you  notice that I’ve left a gaping hole.  Learning is good.

Model-View-Controller in PHP: Model

(Notes:

)

I have one thing to say for all of those PHP developers who look at Rails’ ActiveRecord class and get all excited about implementing it in PHP:

It can’t be done.  Yet.

Here’s why:

Until PHP5.3, PHP does not implement a feature called “late static binding”.  What is late static binding?  Well, how about I show you what it’s like to NOT have late static binding:

class A {
   public static function who() {
     echo __CLASS__;
   }
   public static function test() {
     self::who();
  }
}
class B extends A {
  public static function who() {
    echo __CLASS__;
  }
}
B::test();  //Outputs:  'A'

That’s right:  B::test() outputs ‘A’.  This is a problem, because while it is true that B is a subclass of A, B is still B.  When I call a static method of B, I want it to know that it’s B.

With late static binding (only available in PHp5.3 and onward), this goes away:

<?php
class A {
  public static function who() {
    echo __CLASS__;
  }
  public static function test() {
    static::who(); // Here comes Late Static Bindings
  }
}
class B extends A {
  public static function who() {
    echo __CLASS__;
  }
}
B::test();  //Outputs 'B'
?>

Why is this a problem for ActiveRecord?  Well, say we define a class called ActiveRecord, and create a subclass of ActiveRecord called Person.  When I call Person::find_all(), PHP5.2 is going to run find_all in ActiveRecord – and ActiveRecord’s find_all() will not know what kind of subclass I am.  It won’t know if I’m a Person, Dog, Pizza, or any of that jazz.  Essentially, ActiveRecord is now dead in the water.

Now, you could just make find_all a standard method instead of a static one, but then for every find operation, you’d have to do this:

$p = new Person();
$persons = $p->find_all();

Semantically, this doesn’t make much sense.

But, PHP coders, take heart –  there are two silver linings:

Model-View-Controller in PHP: View

I’ve been programming in PHP for a few years now, and after being exposed to MVC through Ruby on Rails back in 2007, I came to realize that I liked the idea of keeping the presentation of data separate from the manipulation of data.

So I built a View class.  Download View Class

Usage:

$view = new View('views/main_page.tpl', array(
       'some_var' => 'This will be assigned to $some_var in the view'));
$view->render();

And like that, data presentation is separated from data manipulation.

Piece of cake.