Posts Tagged ‘PHP’

Design patterns: Singleton

Monday, August 23rd, 2010

Since I’m now finally graduated from university, I am supposed to know everything from writing code at CPU level to managing a full blown information system project, but I think I’ll start off with something a little lighter; design patterns.

Design patters are tested and proven solutions to specific problems. It’s sort of a blueprint to solve the problem for you, which means you don’t have to reinvent a solution for the same problem over and over. The idea of using patterns in software development was first coined by” the Gang of Four” (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides) in their book “Design Patterns: Elements of Reusable Object-Oriented Software.  This book is considered a bible to many design pattern evangelists, don’t let that deter you from reading it though. It is an excellent book on design patterns and object oriented development.

Singleton is one of the patterns that were included in “the Gang of Four” book. It is a pattern that is probably the easiest one to understand, but also one that is very easy to misuse. And because of that it is not very popular in some circles. Singleton is a way of making sure there is only one instance of the given class, no matter how many times it’s called. This way you can use it to share resources, like a database connection, between different objects.

public class A
{
    Singleton single = Singleton.getInstance();
    single.number = 12;
}
public class B
{
    Singleton single = Singleton.getInstance();
    Console.Print(single.number); // prints 12
}

Even though both classes in the above generates an instance of the Singleton class, they get the same instance, this way you don’t have to pass the singleton instance between classes to use it. Though, they will still have access to the same resources, so you can e.g. limit the number of persistent connections to the database with one.

There are some disadvantages with using the singleton, the biggest being that once implemented; it will take a lot of work to change away from it. Let us say you have to add a second database to your web application. If your database manager is a singleton, it can become very hard. A second problem is that it can hide implementation details, which can make maintenance and bug finding harder; it is often referred to as a “super global” because of this.

There are a couple of key points to making a singleton. You will have to disable the creation of new instances from outside of the class itself. If you are allowed to create new instances with the ‘new’ keyword, you can end up with several instances of the singleton class. Also, any clone methods have to be disabled.

Implementation in php

class Example
{
    // Hold an instance of the class
    private static $instance;

    // A private constructor; prevents direct creation of object
    private function __construct()
    {
        echo 'I am constructed';
    }

    // The singleton method
    public static function singleton()
    {
        if (!isset(self::$instance)) 
        {
            $c = __CLASS__;
            self::$instance = new $c;
        }
        return self::$instance;
    }

    // Example method
    public function bark()
    {
        echo 'Woof!';
    }

    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }
}

Implementation in C#

public sealed class Singleton
{
    private static readonly Singleton instance=new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

Implementation in Java

public class ClassicSingleton {
   private static ClassicSingleton instance = null;
   protected ClassicSingleton() {
      // Exists only to defeat instantiation.
   }
   public static ClassicSingleton getInstance() {
      if(instance == null) {
         instance = new ClassicSingleton();
      }
      return instance;
   }
}

Weighted raiting

Wednesday, February 11th, 2009

Every website that gives its users access to rate items by a scale comes across a choice in how to best handle the calculation of ratings. There are some pretty advanced algorithms used to handle this. From algorithms based on the Bayesian prinsiple or using social networking(pdf) as a base, like digg.com

The easiest choice is to calculate the average rating and leave it at that. This means that an item which has been rated once as 10 will be ranked higher then an item which has been rated over a thousand times, and has an average of 9.8. There is of course an upside and a downside to this. For a website with a lot of activity, items voted up like this get an opportunity to be viewed and if it isn’t up to standard, it will be rated down. Though, this system has its downsides.

Lets say a website with user created content like youtube.com had this system running. This would mean every user could vote their own (or get a friend to vote – just to preempt you guys) item as a 10 and be on the top of the top-rated list. The result would be that the top-rated list would be filled by bad quality videos, and the top-rated list wouldn’t be very useful.

To combat this, we have weighted rating. Its main purpose is to give items with a low number of ratings a handicap. How weighted rating is implemented varies a lot, but a good place to start is by using the average number of votes for all items as a base for the weighting.
Here is an example of a simple algorithm that can be used.

0<= weight >= 3
weight = AVG(votes) / COUNT(ratings)
rating =( SUM(ratings) / COUNT(ratings) ) – weight

The first line says that weight cannot be smaller then 0 and not bigger then 3. If we do not set this kind of a limit we would get some unexpected results. Lets say AVG(votes) is 30, the item has one rating of nine on a scale from one to ten. This would give us:

weight = 30 / 1 = 30
rating = 9 / 1 – 30 = -29

Though, there is a problem with that algorithm. New items are treated the same as very old items. The way I see it, old items with few ratings should be weighted down a lot, while new items, with few ratings, should not be rated down as much, as this would give them an unfairly bad start. So what we want can do is add a time based weight decreaser.

daysOfEffect = 180
rateOfDecrease = daysOfEffect / 2

0<= timeWeightDecreaser => 2
timeWeightDecreaser = 2 – ( daysOnSite / rateOfDecrease )

0<=weight=>3
weight = (AVG(votes) / COUNT(ratings)) – timeWeightDecreaser

1<=rating=>10
rating = (SUM(ratings) / COUNT(ratings)) – weight

This is the timebased weight decreasing algorithm

This is the timebased weight decreasing algorithm

daysOfEffect denotes how long an item should be considered new. A small period of time before the the time based weight decreaser kicks in can be a good idea. A visual on how this is done can be seen in the picture on the left. I used to grapher utility you get in OS X to create it. Never thought I’d get use for that :)

I also implemented a static function in php so you can see how this algorithm can be implemented in code.

<?php
  /**
  * Calculates weighted rating
  * Uses a time and vote amoun based algorithm
  *
  * @param $avg avarage number of votes for all items
  * @param $sum sum of ratings for item to be rated
  * @param $count number of ratings for item to be rated
  * @param $freePeriod number of days until the time based algorith will start having an effect
  * @param $daysOfEffect total number of days the time based algorithm will have an effect
  * @param $daysOnSite number of days the item has been on the site
  * @param $debug optional, default = false, set to true to see debug message
  * @return decimal weighted rating
  **/
  public static function CalculateWeightedRating($avg,
                                                 $sum,
                                                 $count,
                                                 $freePeriod,
                                                 $daysOfEffect,
                                                 $daysOnSite,
                                                 $debug = false )
  {
	  if( $count == 0) return 0;

	  $rating = $sum / $count;

	  if($count > $avg)
	  {
		  $weight = 0;
		  $timeWeightDecreaser = 0;
	  }
	  else
	  {
		  $weight = $avg / $count;

		  if( $weight > 3)
		  {
			    $weight = 3;
		  }

		  $rateOfDecrease = ($daysOfEffect - $freePeriod) / 2;
		  $timeWeightDecreaser = 2.3 - (($daysOnSite - $freePeriod) / $rateOfDecrease);

		  if( $timeWeightDecreaser > 2.3 ) $timeWeightDecreaser = 2.3;
		  if( $timeWeightDecreaser < 0 ) $timeWeightDecreaser = 0;

	  }

	  $weightedRating = $rating - ($weight - $timeWeightDecreaser);

	  if( $weightedRating < 1) $weightedRating = 1;
	  if( $weightedRating > 10) $weightedRating = 10;

    if( $debug == true)
    {
	    echo "<p>";
	    echo   "Average votes: " . $avg . "<br/>";
	    echo   "Sum rating: " . $sum . "<br/>";
	    echo   "Num votes: " . $count . "<br/>";
	    echo   "Days on site: " . $daysOnSite . "<br/>";
	    echo   "Rating: " . $rating . "<br/>";
	    echo   "Weight: " . $weight . "<br/>";
	    echo   "Time weight decrease: " . $timeWeightDecreaser . "<br/>";
	    echo   "Weighted Rating: " . $weightedRating;
	    echo "</p>";
    }

    return $weightedRating;
  }

Variable as a function-call

Sunday, December 14th, 2008

In PHP there is one really cool thing you can do. You can use a variable as a function call. Microsoft created a sort of a similar thing in C#, but it’s not as easy to use.

It’s easier to show you with an example then trying to explain it, so that is what I will do

<?php
  function foo()
  {
    echo "Hello World!";
  }

  $bar = "foo";
  $bar(); // this calls foo()
?>

Neat eh?

This can be used to call different classes depending on the URI. New example for this:

<?php

  $uri = explode('/', $_SERVER['REQUEST_URI']);

  if( is_file($publicClassesPath . "/" . $this->uri[1] . ".php"))
  {
    include_once( $publicClassesPath. "/" . $this->uri[1] . ".php");

    $RunningClass = new $uri[1](); // initiate the class and bind an instance
                                   // to the variable $RunningClass
  }
?>

Cross-site request forgery prevention

Thursday, October 16th, 2008

Cross-Site Request Forgeries is the new buzzword in web-security these days. What it is? Why it’s dangerous? How to prevent it?

Bill Zeller offers a good description of what this is

CSRF vulnerabilities occur when a website allows an authenticated user to perform a sensitive action but does not verify that the user herself is invoking that action. The key to understanding CSRF attacks is to recognize that websites typically don’t verify that a request came from an authorized user. Instead they verify only that the request came from the browser of an authorized user. Because browsers run code sent by multiple sites, there is a danger that one site will (unbeknownst to the user) send a request to a second site, and the second site will mistakenly think that the user authorized the request.

This means the potential hacker will insert a bit of code into a page, or trick a user to load one of their pages up. Then they will be able to post forms as the user.

GMail has been hit by several of these flaws, one being users having filters added to their gmail account (fixed now). With this, the hijacker could e.g. filter all emails from Godaddy.com to his own account and then take over the targets’ domain names. They are easy to do, and can be automated.

Google isn’t alone, many of the major websites have these kinds of vulnerabilities. Do you?

Luckily it is easy to stop these attacks

One way of doing it is to generate a random string and add that to a cookie and a hidden form element. Then make sure that they match before you process the form. This way the hacker has to guess what the random string is to be able to post the form. The chance of this happening is slim to none, so it is a pretty good way of doing it

Now, how do we do this in php?

First off, we have to generate a random string, this is easily done with the random function. Keep in mind, this string doesn’t have to be very random before it becomes difficult to impossible for the hacker to guess. I’ll keep it simple

$randomString = md5(rand(0,100000));

That should give us about 100 000 possibilities.

Next step is to send the cookie to the user

setcookie("XSRF_filter",
$randomString,
time() + 3600,
"/",
".yourdomain.com",
0);

And the hidden form element would look something like this

<form action="" method="POST">
<input type="hidden" name="XSRF_filter" value="<? echo $randomString; ?>">
<br>...other form elements
<br><input type="submit" name="submit" value="submit">
</form>

Pretty simple so far right? Good, now comes the validation checking

if ($_POST['XSRF_filter'] != $_COOKIE['XSRF_filter'])
{
echo "You're trying to do an XSRF attack! Can't allow you to post this form";
}
else
{
//process form
}

That’s it!

Demo and complete source code can be found in the playground

Here is a tool for testing for XSRF vulnerabilities