Captchas are images that are meant to tell the difference between a person and a computer. They are often used as an anti-spam device when someone submits content to a public website. Because a computer has a very difficult time parsing the contents of an image, captcha’s are very effective.
Below is an easy to implement PHP captcha script and example implementation. Spammers have even developed software to read as captchas like this too, and I’ll mention some strategies to strengthen your catpcha later.
Requirements
To use this captcha script, you will need PHP enabled on your server with the Image (GD) extension enabled.
Setup
On the page where your users are submitting content, you want to display the captcha and an input box for the user to enter the text as seen in the captcha. To use the PHP script below to you need to include it as an image on the page you want it to display - save the script as something like “captcha_script.php” and use the following html to display it on the page.
Include this html code inside your form tag:
<!-- display the script as an image -->
<img src="captcha_script.php" />
<!-- an input box to input the captcha text -->
<input name="captcha_input" id="captcha_input" />
The Script
<?php
session_start(); //MUST START SESSION
$string_length=5; //NUMBER OF CHARS TO DISPLAY
$rand_string='';
for($i=0;$i<$string_length;$i++)
{
 //PICK A RANDOM UPPERCASE LETTER USING ASCII CODE
 $rand_string.=chr(rand(65,90));
}//IMAGE VARIABLES
$width=100;
$height=36;
//INIT IMAGE
$img=imagecreatetruecolor($width, $height);
//ALLOCATE COLORS
$black=imagecolorallocate($img, 0, 0, 0);
$gray=imagecolorallocate($img, 200, 200, 200);
imagefilledrectangle($img, 0, 0, $width, $height, $gray);
//REPLACE THIS WITH THE FONT YOU UPLOAD
$font='BELLB.TTF';
$font_size=16;
//CALC APPROX LOCATION FOR TEXT
$y_value=($height/2)+($font_size/2);
$x_value=($width-($string_length*$font_size))/2;
//DRAW STRING USING TRUE TYPE FUNCTION
imagettftext($img, $font_size, 0, $x_value,
 $y_value, $black, $font, $rand_string);
$_SESSION['encoded_captcha']=md5($rand_string);
//OUTPUT IMAGE HEADER AND SEND TO BROWSER
header("Content-Type: image/png");
imagepng($img);
?>
Here’s an example of what the captcha looks like (refresh the page to generate a new captcha):

Script Notes
Instead of using a default font of PHP’s image extension, we are using a true-type font that is available to our script. You need to change this to a font that you upload to your site. To do this, pick a font that you like and find the font file on your computer. In Windows, fonts are usually located in the C:\WINDOWS\Fonts folder. Find a .TTF font file, which is the True Type extension and then upload that file to the same directory as the captcha image script. Then, change the code in the script from $font=”BELLB.TTF”; to $font=”MYUPLOADEDFONT.TTF” to make this font work with your captcha.
Checking The Result
After the user has submitted the form, we still have to validate their captcha text entry. Without validation, our captcha security is useless. The general flow of things after the form has been submitted is:
- Compare the user entry to the captcha text
- If they are the same, enter the user’s content into your database
- If they are different, display an error message to the user.
If you examine the PHP script above you will notice that we are storing the generated captcha as a session variable. If we use the PHP function session_start() on the next page after the form has been submitted, we will be able to access that stored session variable. We do not store it as plain text, or else a spam bot might be able to access the stored text in the session variable and then type the correct captcha text in the input box, bypassing our security. Instead, we store it a an md5() hash, which is a one-way encryption method. All md5() encrypted strings by their nature cannot be decrypted, so to validate the user entry we need to md5() encrypt the user’s input and compare it to the already encrypted session variable. Below is some PHP code that shows how we could validate the captcha:
<?php
session_start();
$user_content=trim($_POST['user_content']);
$user_captcha_input=trim($_POST['user_captcha_input']);
if(isset($_SESSION['encoded_captcha']))
{
 if($_SESSION['encoded_captcha'] == md5($user_captcha_input))
 {
 //..THE USER IS TRUSTED, STORE THEIR CONTENT
 }
 else
 {
 //THE USER ENTERED THE WRONG CAPTCHA
 //DISPLAY AN ERROR MESSAGE
 }
}
?>
Additional Modifications
This captcha is not immune to a computer script that could parse and read the image, so we could make it a little more secure. One optimization is to make it harder for a bot to parse is to add noise and lines to the background. This makes it harder for bots to perform segmentation on the image, which is the process of splitting up the image into individual characters.
GoDaddy.com has really gotten their act together lately. To be fair GoDaddy.com has had their act together for awhile, but only now have I chosen to write about it. Almost all of my domainnames are registered through GoDaddy.com and I have moved over most of my hosting plans to them as well from Fortune City, which had terrible customer service.
At the lean price of $3.99 per month for the economy hosting plan, you can host a full featured site with plenty of bandwidth and storage space. The bandwidth is so high for a general purpose site, compared to other rival services, that you would have to be an extremely successful website to need to move up to the next level of hosting. You also get full PHP functionality and 10 MySQL databases. Other options available at the next level of hosting ($6.99 month) include support for PERL, Ruby, Java, Python, and Cold Fusion. If you choose a Windows-based hosting plan, you can also use ASP.net and MSSQL. For most websites, this will be more than enough.
One of the more useful features of all GoDaddy.com hosting accounts are free add-on apps that GoDaddy supplies. You can choose from a list of well known, free frameworks and applications like Drupal, Wordpress, Serendipity, Joomla, Mambo, PostNuke and others. Using the supplied GoDaddy application GUI, you can install any or all of the apps to your site in the folders you designate, and the database setup is moderated as well. Testing different content management systems has never been so easy.
Administering MySQL is not an easy task. The cryptic my.ini database settings file is hard to set correctly. Also, using the MySQL command line is rather intimidating if you don’t know exactly what you’re doing. Thankfully the good people at MySQL have provided us (the general public) with the MySQL GUI Tools to solve both of these problems for their community MySQL database server. If you haven’t used these tools before, you’re not alone - they are not included with the MySQL distribution and are often overlooked. They are available for Windows, Mac, and Linux and you can download the package here: http://dev.mysql.com/downloads/gui-tools/5.0.html.
One popular database administration tool is PHPMyAdmin. While very useful, PHPMyAdmin is web based and therefore requires a working PHP enabled server to function properly. MySQL GUI tools are very useful in this regard - they install anywhere (even the database server itself) and access your databases through a visual client. No web server needed!
The MySQL GUI Tools consist of the MySQL Administrator, Query Browser, Migration Toolkit, and the Tray Monitor. The most interesting and useful of the two (in my opinion) are the Administrator and the Query Browser.
The Administrator combines many useful features into one interface. You can completely administer your database settings through its menus - it will update the my.ini file for you automatically. It also gives you hints as to what these values should be. You can also administrate database users, view database activity, view database logs. The most useful feature of the Administrator is the ability to backup and restore databases using an easy user interface. You can even go as far to schedule backups, and the program will insert an item into your Windows scheduled tasks that will trigger a database backup at intervals of your choice. There are many commercial applications that charge for this capability.

AÂ screenshot of the database settings feature of MySQL Administrator

AÂ screenshot of the backup feature of MySQL Administrator
The MySQL Query Browser allows the execution of queries and the browsing of database structure of multiple databases at once. You can open up new tabs and have the results of different queries displayed in each one. You can even bookmark a query so it can be executed later. This feature would be perfect for the manual execution of various maintenance queries by database administrators.
You are also allowed to edit data using this tool, and it is done in a very intelligent way. You must go into edit mode before you are allowed to change data, preventing stray clicks from compromising data. When an item is changed, the surrounding box turns red. Your changes are not executed however until you click the apply changes button, adding a way of backing out of your changes easily.

A screenshot of the MySQL Query Browser
The entire MySQL GUI Tools package shares a common connection manager allowing you to keep multiple database’s connection information saved and at your fingertips.
Today during the course of some work, I came across a situation where I had to delete all tables from a MySQL database. Normally when working locally or on a machine where I have full access, I execute the “DROP DATABASE my_data” and then “CREATE DATABASE my_data” statements to completely delete all the tables in it. This works perfectly in this situation, as these statements will also drop all tables, leaving you with a fresh new database.
However, the database account I was issued on this MySQL server did not have the permissions to drop and create a database. In MySQL there is no
“DROP ALL TABLES” statement - this doesn’t exist in MySQL. There were over 100 tables that I had to delete, making manually executing the drop table statment for each table both time consuming and error prone.
To resolve the issue I came up with the following PHP script that will do this operation for you when executed.
Requirements: PHP 4+ and the MySQL extension enabled.
Note:Â If you are using views, this script will be unable to drop them along with the tables. If you don’t know what views are, don’t worry about this notice.
/* fill in your database name */
$database_name = "my_db";
/* connect to MySQL */
if (!$link = mysql_connect("db_host_name", "username", "pass")) {
die("Could not connect: " . mysql_error());
}
/* query all tables */
$sql = "SHOW TABLES FROM $database_name";
if($result = mysql_query($sql)){
/* add table name to array */
while($row = mysql_fetch_row($result)){
$found_tables[]=$row[0];
}
}
else{
die("Error, could not list tables. MySQL Error: " . mysql_error());
}
/* loop through and drop each table */
foreach($found_tables as $table_name){
$sql = "DROP TABLE $database_name.$table_name";
if($result = mysql_query($sql)){
echo "Success - table $table_name deleted.";
  }
  else{
    echo "Error deleting $table_name. MySQL Error: " . mysql_error() . "";
  }
}
Remember not to leave this script sitting on your server longer than needed, as it is a serious security risk.
If you’re a seasoned PHP developer, and you initially learned PHP a few years ago, you may not be familiar with the new functions that PHP 5 (5.1+) provides for date manipulation. PHP has changed to an object based format, where you create an initial date object, modify if desired, and then output using a format you specify. This is a great step for PHP, which prior to these new functions, had many separate yet similar functions to do the same things.
Example code:
date_default_timezone_set ("America/New_York");
$date_object=date_create("9/18/2007");
$date_object->modify("+5 day");
echo $date_object->format("Y-m-d");
This will print 2007-09-23.
Note that we call the date_default_timezone_set() function before executing any date related code. This is a good idea when you are using a hosted site, where you do not have access to the php.ini file to set the master PHP timezone setting. List of available timezones.
The date_create() function takes any descriptive time string, identical to the older strtotime() function. See the manual page for date_create, strtotime and GNU Date Input Formats for more information on how to specify a date related string for the date_create() function.
The date_format() function takes a format argument identical to the syntax that the date() function accepts. See the date_format and date PHP manual pages for more information.
|