student :: geek :: photographer :: legend

xkcd: A few favourites - Part 3

August 7th, 2008 Denham Coote


PHP howto - Sanitize database inputs

July 24th, 2008 Denham Coote

When accepting data from a user, any data at all, it should be sanitized before making its way to your database.

What does this mean? Well, for one, you’re going to inspect the data and make sure that it doesn’t contain any malicious code such as ill-intentioned javascript.  Another is to prepare the data so that when it gets added to your insert/update SQL it doesn’t break the SQL (or do other nasty actions). Otherwise know as a SQL injection attack.

The technical details of the types of attacks we’re protecting against are a bit out of the scope of this post, but there are numerous resources available which will explain far better than I am able to.

After a form has been submitted (via get or post) it gets stored in the global array $_GET or $_POST.  Once we have this data, we can and should do a bunch of things to it, such as:

Stripping out malicious code

We’ll scan through the input, searching for anything that shouldn’t be there, like html code, <script> tags, etc.

<?
function cleanInput($input) {
 
$search = array(
    '@<script[^>]*?>.*?</script>@si',   // Strip out javascript
    '@<[\/\!]*?[^<>]*?>@si',            // Strip out HTML tags
    '@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
    '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments
);
 
    $output = preg_replace($search, '', $input);
    return $output;
}
?>

’slashing

This part can sometimes get tricky, but not to worry, the code’s not too bad.  Basically we’re adding a backslash before any of the following: (single-quote), (double quote), \ (backslash) and NULL characters.  Depending on your server configuration, there are a bunch of ways of getting this done.  PHP has something called magic_quotes, which does this automatically.  Note, however, that as of PHP 6 this feature has been deprecated and removed.  Another PHP function, addslashes(), is the manual version of magic_quotes.  addslashes(”Where’s Wally”); will return “Where\’s Wally”.  A better option, if your server supports it, is mysql_real_escape_string().  It performs pretty much the same function, but is apparently better.

<?
function sanitize($input) {
    if (is_array($input)) {
        foreach($input as $var=>$val) {
            $output[$var] = sanitize($val);
        }
    }
    else {
        if (get_magic_quotes_gpc()) {
            $input = stripslashes($input);
        }
        $input  = cleanInput($input);
        $output = mysql_real_escape_string($input);
    }
    return $output;
}
?>

To use, we simply pass any input to the function. The function works on single strings, as well as deep arrays.

<?
$bad_string = "Hi! <script src='http://www.evilsite.com/bad_script.js'></script> It's a good day!";
 
$_POST = sanitize($_POST);
$_GET  = sanitize($_GET);
$good_string = sanitize($bad_string);
// $good_string returns "Hi! It\'s a good day!"
?>

Typecasting

Making sure that the data we’re inserting matches the expected type;  i.e, someone’s age should be received as an integer value, and not a string.

<?
$age = (int) $_GET['age'];
?>

This is a very gentle introduction to sanitizing your database input, and I would certainly recommend that you do a lot more research on these methods in order to use them correctly in your given environment.

That’s it for today. If you found this useful, of would like to improve it, comments are always appreciated!


Update: Hunting for the ideal laptop

July 14th, 2008 Denham Coote

Pricing on the Dell Studio 17 is available. The Studio 17 looks like a great machine. The pricing is even better! It sells for less than the Vostro, looks nicer, and has more features. Awesome.

I’ve ordered the following:

Intel Core 2 Duo T9300 (2.5 GHz, 800 MHz FSB, 6 MB L2 Cache)
4096MB 667MHz Dual Channel DDR2 SDRAM [2x2048]
17.0″ Widescreen WUXGA+ CCFL (1920×1200) TFT Display with TrueLife
160GB Free Fall Sensor (7200RPM) Hard Drive
8X DVD+/-RW Drive
256MB ATI Mobility RADEON HD 3650
9-cell 87 WHr Lithium Ion battery
Biometric Fingerprint Reader
Wireless 1510 Half Mini Card (802.11n)
Wireless 370 Bluetooth Module
AVerMedia AVerTV Hybrid NanoExpress DVB-T TV Tuner
2.0 Mega pixel Integrated Web Camera
Travel Remote Control Express Card

I can’t wait for it to arrive!


xkcd: A few favourites - Part 2

July 11th, 2008 Denham Coote


Sex sells.

July 10th, 2008 Denham Coote

Following my earlier post, titled ANASLEX, I did some monitoring.  My site traffic has spiked considerably.  This, based on a simple (intentional) misspelling.  Sure seems to be a lot of dyslexic folks out there looking for something other that Ana’s Lexus.


ANASLEX

July 9th, 2008 Denham Coote

So, who wants in?

For my truly dyslexic friends, that Ana’s Lex.  Get your minds out of the gutter.


Dell’s customer service stinks.

July 7th, 2008 Denham Coote

I have been trying for the last 4 hours to speak to a human being at Dell.  I have tried the sales dept.  I have tried placing a new order.  I have tried customer service - all 4 sub-options.  I have tried accounts.  Damn, I even tried the section for government officials.  Dell’s telephone system is an inescapable abyss of incorrectly routed calls to dead lines, incorrect mailboxes and in one case, the sounds of dogs barking in the background.  I shit you not.

A sign of things to come?  If so, I will likely cancel my order and purchase my laptop elsewhere. (If I’m lucky enough to get through to them, that is)

Dell, please get your act together, sort out your telephone system and for the love of small animals, SOMEONE PHONE ME ABOUT MY ORDER.


xkcd: A few favourites - Part 1

July 5th, 2008 Denham Coote

 

Your IDE's colour may vary.

 


Hunting for the ideal laptop

July 1st, 2008 Denham Coote

I am in the process of hunting for a laptop.  I’ve looked at countless offers from various vendors.  As with any purchase one makes, the usual barrage of “sweet deals” from every.single.person.you.know has accompanied the exercise.   Everyone and their uncle can get a great deal.   You gotta love capitalism. (Thank you, though - your offers served as good yard sticks)

The following specs have been the influencing factors:

CPU
Intel Core 2 Duo
- 2.2GHz or above. (Looking at around 2.5GHz)
- Preferably 800MHz FSB.
- Preferably 4MB+ cache.

Memory
2GB (1 x 2048)

Screen
17″ Wide.
- I don’t mind 1440×900 , though I would prefer larger (1680×1050) if it falls within budget, but this is not a “must”

GPU
I can live with the crappy Intel X3100, but would prefer an nVidia chipset.

HDD
Since I have a desktop with 1TB+, size not an issue, 250GB would be perfect, but 160GB is fine too.

Extras
DVD Writer, Wireless - essential.
Bluetooth - Nice to have

Software
If possible, I don’t even want an OS. I’m not going to be using windows, so would rather not have to pay for it.  Thing is, most vendors have to supply a Microsoft OS.   Sucks, but oh well.

At this point, the Dell Vostro 1710 is looking good.  The “best” option comes with nV GPU, and can be further customised to meet the above spec exactly.  As cool extras, it has a 1920×1200 screen, 6MB cache, nvidia gpu, biometric fingerprint reader, built in webcam and bluetooth.

Another contender is the HP 6820.  I think, however, that the Dell packs more punch.  Apart from that, HP never got back to me, so they can sit on a stick and rotate.

I would very seriously consider the HP 6830, but that’s not been released yet.  Looks awesome.

While writing this post, I came across the Dell Studio 17.  It looks decent enough, but at the time of writing I am unable to customise my own nor get a price.  I’ll have to make some calls tomorrow.

I’ll post an update in the coming days.


PHP howto - Database paging (pagination)

June 26th, 2008 Denham Coote

OK, so it’s not quite the nuclear bomb I promised, but it’s just as much fun :)

Database paging, for those of you who are interested, is when you split the number of results returned by a query into smaller chunks, and then show those one page at a time.  Think of how Google will display 10 results out of 4 236 735.  Same thing.

The basic idea is to:

  1. Run your query, limited to the number of desired results
  2. Get the number of results that there would have been, without the limit
  3. Display the first set of results
  4. Build and display <prev> and <next> links, which, when clicked…
  5. Display the prev/next set of results, moved down/up by the desired amount
  6. Repeat 4 & 5

The following code sample is a very basic implementation of this idea.  I have not checked the code, so apologies in advance if there are any bugs.

<?php
 
$no_results = TRUE;   // No results found yet
$howmany    = 10;     // Return 10 results per query
 
// Set default starting point of query to 0, or, if set, to $_GET['rs']
$row_start  = (isset($_GET['rs'])) ? $_GET['rs'] : 0;
 
 
// Do our SQL query, with something like LIMIT 0, 10
$sql    = "SELECT SQL_CALC_FOUND_ROWS id, name, surname FROM person LIMIT ". $row_start .", ". $howmany ."";
$result = mysql_query($sql);
 
 
// Get the number of rows that would have been returned WITHOUT a limit clause, to be used later for paging.
$count_sql        = "SELECT FOUND_ROWS() AS total";
$count_sql_result = mysql_query($count_sql);
$count_row 	  = mysql_fetch_array($count_sql_result);
$count_result 	  = $count_row['total'];
 
// Start looping through our result set
while($row = mysql_fetch_array($result)) {
    $no_results = FALSE;
 
    // Save results of query to $line_output
    $line_output .= "
        <div class=\"someclassname\">
            <div>". $row['id'] ."</div>
            <div>". $row['name'] ."</div>
            <div>". $row['surname'] ."</div>
        </div>";
}
 
// Don't bother building paging if we don't have records
if ($no_results) {
    $line_output = "No records found...";
    $page_output = "";
}
else {
    // Build <prev> and <next> links and save to $page_output
    $rs_prev = $row_start - $howmany; // where would prev page start, given current start less no. of records
    $rs_next = $row_start + $howmany; // where would next page start, given current start plus no. of records
 
    // If for some reason the next <prev> starting point is negative, do not display <prev>
    // This happens when our current starting point is already 0
    // This may happen if some smartass manually changes the rs= bit in the url
    $page_output_prev 	= ($rs_prev < 0) ? "" : "<a href='?rs=".$rs_prev."'>Previous</a>";
 
    // Will the next page jump start point exceed the number of records returned?
    // If so, don't display <next>'
    $page_output_next 	= ($rs_next >= $count_result) ? "" : "<a href='?rs=".$rs_next."'>Next</a>";
 
    // Just something to put between <prev> & <next>, IF they are both active
    if (($page_output_prev == "") || ($page_output_next == "")) {$page_output_breaker = "";}
    else { $page_output_breaker = " || ";}
 
    // Build final paging output
    $page_output = $page_output_prev . $page_output_breaker . $page_output_next;
}
 
// Write the outputs
echo $line_output;
echo $page_output;
 
?>

A few points worth taking note of:

Row counting

To get the total number of results, I have used

SELECT SQL_CALC_FOUND_ROWS

followed by a second query

SELECT FOUND_ROWS() AS total

As stated in the comments, this will return the number of results that there would have been without a limit clause.  There are other ways to achieve this, namely using count() in a second query, but this way is apparently quicker, and also slightly cleaner code.

Building the paging links

In the code I have used

$_GET['rs']

What this does is get the value from the part of the URL that looks something like http://www.yoursite.com/index.php?rs=10

That value then becomes our next starting point, and is injected into the SQL query.

I’ve seen some tutorials where page numbers are used instead of starting records.  This is fairly easy to achieve, and involves dividing the number of records returned by the size of the desired result set to get the number of pages, and then multiply again when determining the next starting point for the limit.  I’ve not done that in this tutorial for the sake of simplicity.  Besides, Google uses the records, and not pages, method.  Can’t be that terrible :)

Extending the functionality

In this example I’m echoing the result to screen.  You could instead wrap this up in a function and return the results.  Another easy modification would be to alternate the background colours, as shown in my previous howto.

And that’s it for today.  If you found this useful, of would like to improve it, comments are always appreciated!