Elliott Brueggeman - PHP and Web Development Info, Photography, and More
 
Home | Web Dev Blog & Articles | PHPGraphLib | PHPSimpleChat | SkinnyTip | PHPWeatherLib | Photography | Contact
Posted on February 18, 2009 in PHP, Wordpress, web hosting by Elliott BrueggemanNo Comments »

Often as a site grows, its performance degrades sharply. This can happen for many reasons, and is typical for a site that continually undergoes maintenance. As a project ages, the content often grows as well. More data, more code revisions, more ideas to turn into code for the site, etc.

I’m exploring this subject because a site of mine is in need of a performance boost. It was a snappy little site when I first launched it, but I’ve had many more ideas since then, and I’ve implemented almost all of them. Now regular browsing through the site is noticeable slower.

I’ve got a short list of performance enhancing ideas that I’m going to explore below.

Separating CSS and JS Files

For starters, if you have inline CSS or JS, you should separate these into separate files. This is a huge performance win, because a browser can cache mystyles.css or javastuff.js, but can’t cache it if it’s included inline in your page source code. Most performance wins happen client side – taking advantage of caching is often more efficient than making slight changes to server side code, though this isn’t a rule that’s set in stone; You could have terrible server side code that slows down the site too. My site in question already has the CSS and JS files separated, but it’s worth mentioning in case you haven’t done this.

Minifying CSS and JS Files

This is something that enterprise many sites do, so I thought I would go ahead and do this. Basically, it means removing spaces,tabs, and line returns wherever possible so that the file size is smaller, but the code executes as normal. When minifying a CSS file, I prefer to leave one CSS selector per line, and then listing each CSS property after it. This reduces file size, but makes the file still human readable/editable.

Here is an example of a fully minified CSS file from MSN – http://tk2.stc.s-msn.com/br/hp/11/en-us/css/hp_1.css – I think this is overdoing it, and doing it this way is probably done through an automated script, as this would be next to impossible for a developer to edit in a development environment.

For complex sites, this is going to be a better win than for simple sites. I saw about a 20% decrease in file size. For very, very simple sites (read very), using an external CSS file can slow things down because of the server disk access time of retrieving the external CSS file. The original Google page, for example, only has a few lines of CSS, and therefore uses inline CSS. For anything more complicated, include it in an external file.

Reducing Image Use

Many blogs and news oriented sites use too many images. This slows things down for first time readers, who don’t have the images cached. A good tool to examine load times of everything on your site is Firebug, a plugin for Firefox. You can get the latest version of Firebug here. The image below is a screen capture of one of the features in Firebug that lets you examine exactly how long everything took to load. If your site is nearing half a megabyte (~500kb), it’s time to put less on your pages, or use smaller images.

firebug-example

Using Less Database Queries

This is very important on some sites, and irrelevant on others. If you are using a basic installation of Wordpress, for example, there really aren’t too many ways for an average person to speed it up, without writing the developers and telling them to use less queries next release. For heavily customized sites based on existing platforms and fully custom database driven sites, database queries can be the make or break of your site performance. Basic rule: if you are writing your own queries, and you don’t know how they perform, then you shouldn’t be writing your own queries. Having said that, never outright trust queries from other somewhat experienced developers. Developing for my firm, a Fortune 500 company, we have often encountered popular plugins for Wordpress or modules for Drupal that have queries in them that are written poorly. Just because another developer made it, doesn’t mean they did it right.

Another way to use less queries, is to outright display less content. This is easy to accomplish if you’re using a blog platform. If you’ve got 20 posts a page, reduce this number. The number of queries your blog site makes is directly proportional to the number of posts or entries it is trying to display.

Better Hosting Plan or Better Hardware

This isn’t an option for me, because the next level of hosting plans with GoDaddy is out of my current budget range. For others, however, it may be an option. It’s worth looking into.

Posted on December 8, 2008 in MySQL, PHP by Elliott BrueggemanNo Comments »

Security is an important part of PHP programming, and PHP provides several tools for securing database queries and HTML display. However, knowing which function to use and when to use it can be somewhat confusing, as there’s many details to pay attention to. It’s important not to leave your website open to cross-site scripting or SQL injection attacks.

This example and explanation will focus on a common web scenario – a user submitting data via a form, being asked to confirm it, and then being displayed the data after it is stored in the database.

1. Initial User Input

In this scenario, a user will be presented an input box for which they can add a review about a particular product on a public facing website. The user is not allowed to use html, similar to the restrictions on product reviews on Amazon.com. The user inserts their review into the input box and then clicks submit.

2. User Input Preview and Cross Site Scripting Prevention

Now, we want to show the user their review and have them confirm it before we add it to the database. This is a prime example of a situation that leaves a website open for a XSS (cross-site scripting) attack. We don’t know what the user entered on the previous page, and they could be purposely entering malicious content. Because what they entered in going to be output to the screen, if they input raw PHP code, it could get executed unknowingly by our server. To prevent this, we need to html encode all potentially dangerous characters for display on the screen.

I would recommend using htmlentities() to do this, and use the ENT_QUOTES option as shown below, which means that both single and double quotes will also be encoded. Because we also decided that we wouldn’t allow HTML, we’ll want to strip that HTML before displaying the results, to give the user an accurate preview. Before doing any of this, we’ll have to grab the submitted data from the submitted form – this tutorial won’t cover this, but there are plenty of web tutorials available for doing this.

<?php
 
//strip HTML tags from input data
$input_data = strip_tags($input_data);
 
//turn all characters into their html equivalent
$preview_data = htmlentities($input_data, ENT_QUOTES);
 
//...display $preview_data 
 
?>

3. Database Insert and SQL Injection Protection

Now, let’s say the user previews above data, and clicks accept, which will send this data to another script for entry into the database. Protecting your database from SQL injection requires different steps than protecting against cross-site scripting.

It is very likely that you don’t want to store the user’s data in HTML encoded form. Let’s say you are using a varchar(32) column in your database, and you had an input box that was 32 characters long. If you were trying to store the HTML equivalent of this in your database, you would need a column that was much larger to guarantee that data didn’t get lost. This is because the HTML equivalent of a single character is often many characters long. For example, a double quote (”) becomes ", and an ampersand (&) becomes &. We need to guard against single quotes, because these can cause an SQL injection problem, depending on how your database is setup. Consider this example:

<?php
 
$name = "George'); DELETE FROM mytable; INSERT INTO mytable (name) VALUES ('you got hacked";
 
$sql = "INSERT INTO mytable (name) VALUES ('$name')";
 
//...run the $sql query
 
?>

If your SQL server allows more than one SQL command on a single query request, you’ve just lost lots of data. While it’s a good idea to lock down your database server so it doesn’t allow this, you always want to secure your code independently of the database, in case you change your hosting setup later.

To secure your script, you can use the addslashes() function which will escape both single and double quotes, by adding backslashes before them, to prevent multiple queries from being executed. You’ll also want to test for the length of the input field, as forged form requests are easy as can be using tools like Firebug. Here is example code that will accomplish that:

<?php
 
//escape trouble characters
$name = addslashes($name);
 
//make sure not longer than expected length
$name = substr($name, 0, 32);
 
$sql = "INSERT INTO mytable (name) VALUES ('$name')";
 
//...run the $sql query
 
?>

Note that there is the possibility of valid user input being cut off when being inserted into the database. If the user used all 32 characters in the input box, and a single quote was one of them, then the above code would trim off the last character. You may want to prevent this by using a 28 max character input box for a varchar(32) column, giving the user 4 opportunities to use an escaped character without having their input cut off.

4. Retrieving and Displaying the Data From the Database

Now that the data is safely in the database, everything is safe right? Wrong. We elected not to store HTML encoded data from users. This means that we are still at risk from a Cross Site Scripting attack every time we query and then display the data. What you’ll probably want to do is create a function that sanitizes database data before being displayed on the screen. No only should you HTML encode the data, but you’ll also want to remove the backslashes you added earlier, as these aren’t meant to be displayed. Here’s what your function could look like:

<?php 
 
function sanitize_data($input_data) {
  return htmlentities(stripslashes($input_data), ENT_QUOTES);
}
 
?>
Posted on November 25, 2008 in PHP, Wordpress by Elliott Brueggeman5 Comments »

Creating blog posts is extremely easy in Wordpress, but adding simple thumbnails to your posts is not. I’m not talking about adding images within the post content, but adding them to your theme so they display in a standardized way in your blog loop, and on individual post pages.

The problem is that though Wordpress allows inserting images within posts, there is no way to “attach” these images to the post, so that theme designers can pull standardized images out for display. By making a few changes to your Wordpress configuration and your theme templates, and by using the Post Thumbnails plugin that I have written, you will be able to add thumbnails to your site in an intelligent way.

Wordpress Configuration

First step is to login to your Wordpress admin dashboard and navigate to the Settings -> Miscellaneous page. Here you will need to change:

- Uncheck the “Organize my uploads into month- and year-based folders.”

- Change the Wordpress thumbnail size to your desired size. This is important! Take careful thought when making this decision – you will break old post’s thumbnails if you chose to change this value later. I recommend 50×50 pixels.

Plugin Installation

Download the Post Thumbnail plugin using this link. Unzip it and place the file within your wp-content/plugins/ directory. Navigate to the Plugins menu within the Wordpress admin dashboard and activate this plugin.

You’re going to need a default post thumbnail to be used when no image is associated with a post. Upload an image that is the same size as the thumbnail size you chose above to the wp-admin/uploads folder, or the same folder you have chosen for uploads if you’re using a custom location. On most installations that folder would be wp-content/uploads/.

After you’ve uploaded the image, paste the name into the first line of code in the plugin PHP file:

define('DEFAULT_POST_THUMBNAIL', 'default_thumbnail_file.jpg');

Change the above default_thumbnail_file.jpg to whatever your image was called.

Plugin Usage

After the plugin has been activated, you will notice a new box titled Post Thumbnail on the Wordpress Write and Edit screens. To get a thumbnail attached to your post, upload an image using Wordpress’ default image uploading mechanism, which is a button next to the Add Media label near the top of those screens. This opens up a popup window for uploading images. Upload your image, but you don’t need to insert it into the post. Instead copy the file name (ex. myimage.jpg) and then click on the X to close the window.

Next, paste the file name into the Source Image input field in the Post Thumbnail box and click save. After saving, you will notice that an image name will be displayed in the Generated Thumbnail box. This is the thumbnail version of your source image, that Wordpress resized for you when you initially uploaded the image.

Adding the Thumbnail to Your Theme

Now that thumbnails are being attached to posts, we need to modify our theme to display them. It’s up to you to decide where you want to place them, but I would recommend adding the thumbnail to your template wherever you use the Wordpress loop. Below is a code snippet that inserts a thumbnail into the Default Wordpress theme’s index.php file, so thumbnails will show up on the main page of your site. Only one new line needs to be added.

<?php while (have_posts()) : the_post(); ?>
  <div class="post" id="post-<?php the_ID(); ?>">
    <h2>
    <!-- Begin New Code-->
    <div style="float:left; margin:5px;">
      <?php echo get_post_thumbnail(get_the_ID()); ?>
    </div>
    <!-- End New Code-->
    <a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to 
    <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
    <small>
      <?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> -->
    </small>
 
    <div class="entry">
      <?php the_content('Read the rest of this entry &raquo;'); ?>
    </div>
 
    <p class="postmetadata"><?php the_tags('Tags: ', ', ', '<br />'); ?> 
    Posted in <?php the_category(', ') ?> | 
    <?php edit_post_link('Edit', '', ' | '); ?>  
    <?php comments_popup_link('No Comments &#187;', 
    '1 Comment &#187;', '% Comments &#187;'); ?>
    </p>
  </div>
<?php endwhile; ?>

Here’s what my above post looked like with the above template code:

Other templates like single.php and archive.php in the Default theme have very similar code where you can also insert the thumbnail. Your theme may differ, but usage is very simple. Just call the following function in your template wherever you want to display the thumbnail:

<?php echo get_post_thumbnail(get_the_ID()); ?>
Posted on November 9, 2008 in PHP, Wordpress by Elliott Brueggeman1 Comment »

There has been much discussion about a recent bug/issue with Wordpress that prevents scheduled posts from working properly. The problem is somewhat unrelated to Wordpress itself, and is primarily a hosting setup issue. Scheduled posts are published via the use of a cron script. Wordpress attempts to call the cron script with an fsockopen() function call. Many popular hosts disable the use of fopen() in their PHP configuration, which also disables the fsockopen() function, preventing your cron from firing which prevents your scheduled posts from being published.

A more robust way of programming this part of the code would be to try other functions like curl on failure of the original fsockopen() call. If curl is unavailable, then the calling script should just execute the code contained within the wp-cron.php file itself, instead of trying to make an http request to execute it.

I’ve put together a simple fix for sites that cannot use the fsockopen() function. It’s a simple addition, and just requires attention when upgrading. Steps for upgrading are detailed below the fix.

Open up your wp-cron.php file and copy the contents following the “if ( $_GET['check'] != wp_hash(’187425′) ) exit;” line.

Now you are going to have to paste these lines at the very end of the spawn_cron() function in wp-includes/cron.php. After pasting them in you are going to have to change the “if ( $argyle )” clause to be an if/else clause. This will cause the else clause to execute when fsockopen() fails.

In Wordpress 2.6.3, the spawn_cron() function within the wp-includes/cron.php file will now look like this:

function spawn_cron() {
  $crons = _get_cron_array();
 
  if ( !is_array($crons) )
    return;
 
  $keys = array_keys( $crons );
  if ( array_shift( $keys ) > time() )
    return;
 
  $cron_url = get_option( 'siteurl' ) . '/wp-cron.php';
  $parts = parse_url( $cron_url );
 
  if ($parts['scheme'] == 'https') {
    // support for SSL was added in 4.3.0
    if (version_compare(phpversion(), '4.3.0', '>=') && function_exists('openssl_open')) {
      $port = isset($parts['port']) ? $parts['port'] : 443;
      $argyle = @fsockopen('ssl://' . $parts['host'], $port, $errno, $errstr, 0.01);
    } else {
      return false;
    }
  } else {
    $port = isset($parts['port']) ? $parts['port'] : 80;
    $argyle = @ fsockopen( $parts['host'], $port, $errno, $errstr, 0.01 );
  }
 
  if ( $argyle ) {
    fputs( $argyle, 
      "GET {$parts['path']}?check=" . wp_hash('187425') . " HTTP/1.0\r\n"
      . "Host: {$_SERVER['HTTP_HOST']}\r\n\r\n"
    );
  }
  else {
    //BEGIN COPIED wp-cron.php CONTENTS
    if ( get_option('doing_cron') > time() )
      exit;
 
    update_option('doing_cron', time() + 30);
 
    $crons = _get_cron_array();
    $keys = array_keys($crons);
    if (!is_array($crons) || $keys[0] > time())
      return;
 
    foreach ($crons as $timestamp => $cronhooks) {
      if ($timestamp > time()) break;
      foreach ($cronhooks as $hook => $keys) {
        foreach ($keys as $key => $args) {
          $schedule = $args['schedule'];
          if ($schedule != false) {
            $new_args = array($timestamp, $schedule, $hook, $args['args']);
            call_user_func_array('wp_reschedule_event', $new_args);
          }
          wp_unschedule_event($timestamp, $hook, $args['args']);
          do_action_ref_array($hook, $args['args']);
        }
      }
    }
 
    update_option('doing_cron', 0);
    //END COPIED wp-cron.php CONTENTS
  }
}

Upgrading

It is very important to remember that you’ll have to take special precautions when upgrading. When upgrading, you are going to have to perform the same copy/paste and alter within the wp-includes/cron.php file. Take whatever the contents of the wp-cron.php file are and copy them after the above mentioned hash check line.

Posted on October 26, 2008 in PHP by Elliott Brueggeman2 Comments »

I recently came across the need to efficiently parse a string and find what was in between two “marker” strings. I was parsing a logfile with a particular preset format. The line looked like this:

$str = '2008-10-07_00:00:19 - ip:[213.21.198.231] page:[/phpsimplechat/documentation_usage.php]';

I wanted to be able to easily pull out the ip and page information in a straight-forward way without repeating code. After a little tinkering I came up with a get_token() function that accomplished my goal nicely. The function is below:

function get_token($start_token, $end_token, $haystack, $offset = 0) {
 
	$start = stripos($haystack, $start_token, $offset);
	$end = stripos(substr($haystack, $start), $end_token);
 
	if ($start !== false && $end !== false) {
		$start_pos = $start + strlen($start_token);
		$end_pos = $end - strlen($end_token);
		return substr($haystack, $start_pos, $end_pos);
	}
	return false;
}

Let’s take my above example – if I want to pull out the ip and page information from the given string, I only need to implement the below code:

$str = '2008-10-07_00:00:19 - ip:[213.21.198.231] page:[/phpsimplechat/documentation_usage.php]';
$ip = get_token('ip:[', ']', $str);
$page = get_token('page:[', ']', $str);

The optional offset argument allows you to specify how many characters into the $haystack that you want to start looking;

Here is another example usage in which we want to pull the title out of some HTML code.

$str = 'This is the body';
$title = get_token('', $str);
Posted on October 2, 2008 in PHP by Elliott Brueggeman2 Comments »

Those programmers who took computer science classes in C++ or Java and then started looking at popular open source PHP scripts may be surprised that the coding standards are somewhat different from what they are used to. Unfortunately, it’s hard to nail down good coding standards for PHP because it has so many syntaxes and does so many things. On one side, PHP is a serious object-oriented language and demanding of java-like syntax, but on another it’s a scripting language and very close to HTML.

One of the older and widely adopted PHP coding standards is based on Todd Hoff’s C++ Coding Standard and is available at http://www.dagbladet.no/development/phpcodingstandard/. Though it is widely used, and (as of the time of writing this) the number one result for “php coding standards” on Google, I give this the least cred because not only was it adopted from a C++ standard but it was not put together by an open source community or company.

The two “most official” coding standards are the PEAR PHP Standards (http://pear.php.net/manual/en/standards.php) and the Zend Framework Coding Standard for PHP (http://framework.zend.com/manual/en/coding-standard.html).

There are also other PHP Standards the are specific to certain projects, like Drupal (http://drupal.org/coding-standards) or Wordpress (http://codex.wordpress.org/WordPress_Coding_Standards), and are certainly valid as these frameworks have thousands of developers adding to their codebase, but they tend to be less detailed the above “official” coding standards.

I personally like the Zend standards the best, as they are the most detailed and easy to follow, but I actually prefer the variable and function naming convention of the Wordpress standard which uses all lowercase words separated by underscores (my_function()) as opposed to the more popular Java style function names (myFunction()) used by the other standards.

At some point in the future, I may write my own coding standards and publish them on this site, combining the best elements from each standard.

Posted on September 24, 2008 in PHP by Elliott BrueggemanNo Comments »

PHP provides the mail() function for easy sending of mail from your PHP server. The problem is that sending HTML email (the most popular format for emails) is not easily done using native PHP functions. I’ve provided below a somewhat foolproof function that will allow you to send HTML emails.

Simply pass in a to address, from address, from name (which is used as a nickname in email clients instead of displaying the sender’s email address), subject, and a properly formatted HTML email message.

If you are sending to multiple recipients, you can pass the $to_email parameter in as an array of multiple email addresses.

HTML Email Function

function send_email ($to_email, $from_email, $from_name, $subject, $msg) {
	//split up to email array, if given
	if (is_array($to_email)) {
		$to_email_string = implode(', ', $to_email);
	}
	else {
		$to_email_string = $to_email;
	}
 
	//Assemble headers
	$headers  = 'MIME-Version: 1.0' . "\r\n";
	$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
	$headers .= "From: $from_name <$from_email>" . "\r\n";
 
	//send via PHP's mail() function
	mail($to_email_string, $subject, $msg, $headers);
}

Usage

You call the function like this:

send_email("me@gmail.com", "roger@att.com", "Roger", "Hello There", 
  "<html>Hello There <strong>Bob</strong>! How are you doing</html>!");

Or, alternately, you call it like this when sending to multiple email addresses:

send_email(array("me@gmail.com", "sal@gmail.com"), "roger@att.com", "Roger", 
  "Hello There", "<html>Hello There <strong>Bob</strong>! How are you doing</html>!");

HTML Email Formatting

Remember that formatting HTML for email is different than for webpages. Do not use a CSS file and do not declare CSS in the head of your document. Instead, use either inline CSS or “Old School” HTML like font tags for formatting. Also, don’t use JavaScript, as major email clients don’t support it.

Though it may seem obvious, remember that images and links within your HTML email need to be full, absolute paths to their world wide web accessible location. No relative links!

Posted on September 9, 2008 in PHP by Elliott Brueggeman4 Comments »

Here’s another PHP function I cannot live without – I add this into my standard PHP functions include on all projects. Often when displaying text, I am forced to abbreviate the text to a certain number of characters. You might jump in a decide to use substring() on your text to achieve this abbreviation, but that can cause several problems. The most blatant is that you will often split the text right in the middle of a word. In addition, if there are any HTML tags in the text, they could get cut in the middle too, or have the closing tag left off completely, potentially breaking the display or exposing the remaining part of the tag.

As a solution to these problems, I have written a function that only trims on the last space before the number of characters you specify, so it will never cut words in half. Also, it strips out HTML tags before doing the character trim, preventing possible display issues. And, as a convenience it adds ellipses (the …) to all trimmed text, as a visual cue to the reader that the text has been abbreviated.

<?php
/**
 * trims text to a space then adds ellipses if desired
 * @param string $input text to trim
 * @param int $length in characters to trim to
 * @param bool $ellipses if ellipses (...) are to be added
 * @param bool $strip_html if html tags are to be stripped
 * @return string 
 */
function trim_text($input, $length, $ellipses = true, $strip_html = true) {
	//strip tags, if desired
	if ($strip_html) {
		$input = strip_tags($input);
	}
 
	//no need to trim, already shorter than trim length
	if (strlen($input) <= $length) {
		return $input;
	}
 
	//find last space within length
	$last_space = strrpos(substr($input, 0, $length), ' ');
	$trimmed_text = substr($input, 0, $last_space);
 
	//add ellipses (...)
	if ($ellipses) {
		$trimmed_text .= '...';
	}
 
	return $trimmed_text;
}
?>
Posted on August 24, 2008 in PHP by Elliott Brueggeman3 Comments »

Having a secure area to a PHP site is a common website requirement. Implementing the secure area, on the other hand, can be difficult and confusing. I’ve put together a basic security framework that you can use for your PHP based website.

What this framework is:

  • Simply coded & easy to understand
  • Secure enough for most sites, blogs, and internally accessed (intranet) sites.

What this framework is NOT:

  • Secure enough for sites involving e-commerce transactions and sensitive personal information.

Note the “NOT” clause above – this implementation is not for securing sensitive data. Most people implementing this framework will be doing it on unsecure sites (sites NOT using the HTTPS secure socket layer), causing user passwords to be sent from script to script in plaintext, which is vulneable to intrusion.

How the PHP security flow works

This framework works as follows:

  • User submits login form containing name and passsword to login processor script
  • Login processor form compares name and password to stored value
  • If name and password do not match expected value, send user back to login form
  • If name and password match expected value, set a session variable containing a unique hash value, and forward user to secure page

When a user tries to access a secure page, this happens:

  • Security code checks session variable with user hash and compares to expected value.
  • If the hash values match, continue displaying page.
  • If the hash values do not match, send user to login form.

Seems simple right? It is! To implement the above workflow you’re going to need to use the code I have included below.

Login Form

Below is the login form code. Note that you must set the destination of the form to match the name of your check login script (login processor.)

<?php
/*
* FILE: login.php
*/
?>
<html>
<head>
  <title>Login</title>
</head>
<body>
  <form name="login-form" method="post" action="check_login.php">
    <p>User: <input type="textfield" id="user" name="user"/></p>
    <p>Password: <input type="password" id="pass" name="pass"/></p>
    <p><input type="submit" name="Submit" value="Submit"></p>
</form>
</body>
</html>

Login Processor

The login processor has the main chunk of your security code. This is the script that decides whether you have a correct username and password, and what to do after logging in. Note that this code uses an include of login functions to accompish its purpose. These login functions are shown later in this article.

<?php
/*
* FILE: check_login.php
*/
 
session_start();
 
//include our login functions.
require('login_functions.php');
 
//retrieve post data
$user = trim($_POST['user']);
$pass = trim($_POST['pass']);
 
 
/*
* Basic Login Logic
*/
 
clear_login_state();
 
if (!empty($user) && !empty($pass)) {
 
  if (check_login_correct($user, $pass)) {
 
    //set appropiate session vars
    login_user($user);
 
    //redirect to secured page
    send_to_page('secure_page.php');
  }
  else {
    //wrong user or password supplied, send back to login
    send_to_page('login.php');
  }
}
else {
  //no user or password supplied, send back to login
  send_to_page('login.php');
}
?>

Login Functions

The above Login Processor code uses some important functions to accomplish the secure login. These functions are enclosed in their own file and included by the above code.

<?php
/*
* FILE: login_functions.php
*/
 
function check_login_correct($user, $pass) {
  /**
  * This function is for you to fill in.
  * Typically, you would compare the user's password 
  * to the password stored in the database, and then return
  * either true or false, depending on the result.
  */
 
  if ($user == 'admin' && $pass == 'Chelsea') { return true; }
 
  return false;
}
 
function login_user($user) {
  session_regenerate_id();
 
  //set the user session variable, for later app use
  $_SESSION['user'] = $user;
 
  //set the hash session variable
  $_SESSION['hash'] = calculate_secure_hash($user);
}
 
//function sends the user to a page. Note this must be called 
//in the header, before any page output (echo's, html, print, etc) 
function send_to_page($page) {
  header("Location: $page");
  die("Redirect Failed");
}
 
//clears login state (logs you out) by unsetting login variables
//must be called in header, before any page output (echo's, html, print, etc) 
function clear_login_state() {
  session_unset();
}
 
function calculate_secure_hash($user) {
  //the security of your system is based on the hash seed below - change often
  $hash_seed = 'this_is_a_secret';	
  return md5($_SERVER['HTTP_USER_AGENT'] . $hash_seed . $user);
}
 
function check_logged_in() {
 
  //retrieve session vars
  $found_hash = $_SESSION['hash'];
  $user = $_SESSION['user'];
 
  //must not be empty
  if (!empty($found_hash) && !empty($user)) {
 
    //recalculate the hash
    $calculated_hash = calculate_secure_hash($user);
 
    //if recalculated hash matches, we have a logged in user
    if ($calculated_hash != $found_hash) {
      send_to_page('login.php');
    }
  }
  else {
    send_to_page('login.php');
  }
}
 
?>

Secure Page Code

Okay, so we have successfully logged a user in – now what? Well, for each secure page accessed you have to reverify the hash value. On each secure page, you’re going to need to setup the top of your page (PHP script) like this:

<?php
/*
* FILE: secure_page.php
*/
 
session_start();
 
//include our login functions.
require('login_functions.php');
 
//do security check
check_logged_in();
 
//now, display the page's content...
echo "You are viewing a secured page!";
 
?>

Download the Above Code

You can download this zip of the above code, and run it on your server to test how the authentication code works. Remember, you’re going to need to customize the check_login_correct() function to fit your particular password storage method.

Posted on May 14, 2008 in PHP by Elliott Brueggeman6 Comments »

Last November, I published a post on creating a simple PHP Captcha. Some readers noted that I actually used a more advanced captcha for my own site’s discussion pages, and asked for the source code. I’ve actually gone a step further and improved my own captcha by adding more background noise, decreasing the likelihood that a bot would be able to break it. Though harder for a bot to read, I changed the font and made it easier for a human to read.

As noted before, Captchas are images that are meant to tell the difference between a person and a computer, be presenting an image with text in it, and asking the user to enter the text and submit it with the form. Captchas are used to reduce spam on publicly accessible message boards and comment lists.

Below is the new and improved PHP captcha script and example implementation.

Requirements

To use this script, you will need PHP enabled web server with the Image (GD) extension enabled. If you are not sure, check with your hosting company. Most major hosting companies, like GoDaddy.com provide this by default.

Setup

On the page where your users are submitting content, like a post or a comment, you want to display the captcha and an input box for the user to enter the text displayed 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 “advanced_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="advanced_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 = 6; //NUMBER OF CHARS TO DISPLAY 
$large_letters = array('m','w');
$rand_string = ''; 
 
for ($i=0; $i<$string_length; $i++) { 
  //PICK A RANDOM LOWERCASE LETTER USING ASCII CODE 
  $rand_string .= chr(rand(97,122)); 
}
 
//IMAGE VARIABLES 
$width = 100; 
$height = 36; 
 
//INIT IMAGE 
$img = imagecreatetruecolor($width, $height); 
 
//ALLOCATE COLORS 
$black = imagecolorallocate($img, 0, 0, 0); 
$gray = imagecolorallocate($img, 110, 110, 110); 
$medgray = imagecolorallocate($img, 180, 180, 180); 
$lightgray = imagecolorallocate($img, 220, 220, 220); 
//FILL BACKGROUND
imagefilledrectangle($img, 0, 0, $width, $height, $lightgray); 
 
//ADD NOISE - DRAW background squares
$square_count = 6;
for ($i = 0; $i < 10; $i++) {
  $cx = (int)rand(0, $width/2);
  $cy = (int)rand(0, $height);
  $h  = $cy + (int)rand(0, $height/5);
  $w  = $cx + (int)rand($width/3, $width);
  imagefilledrectangle($img, $cx, $cy, $w, $h, $medgray); 
}
 
//ADD NOISE - DRAW ELLIPSES
$ellipse_count = 5;
for ($i = 0; $i < $ellipse_count; $i++) {
  $cx = (int)rand(-1*($width/2), $width + ($width/2));
  $cy = (int)rand(-1*($height/2), $height + ($height/2));
  $h  = (int)rand($height/2, 2*$height);
  $w  = (int)rand($width/2, 2*$width);
  imageellipse($img, $cx, $cy, $w, $h, $gray);
}
 
//REPLACE THIS WITH THE FONT YOU UPLOAD 
$font = 'Tuffy.ttf'; 
$font_size = 18; 
 
//CALC APPROX LOCATION - CUSTOMIZED FOR ABOVE FONT 
$y_value = ($height/2) + ($font_size/2); 
$x_value = 0;
 
//DRAW STRING USING TRUE TYPE FUNCTION 
 
for ($i = 0; $i < $string_length; $i++) {
  $chr = substr($rand_string, $i, 1);
  $x_value += 3 * ($font_size/5); 
  imagettftext($img, $font_size, 0, $x_value, $y_value, $black, $font, $chr); 
  //check to see if larger than normal letters, if so add more horiz space
  if (in_array($chr, $large_letters)) {
    $x_value += 4;
  }
}
 
$_SESSION['encoded_captcha'] = md5($rand_string . 'my_secret_key'); 
 
//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

We are using a font called “Tuffy.ttf” that is in the public domain in this script. You will need to download this font and upload to the same directory as the captcha script. You can download this font from the homepage of its creator or directly from my site.

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:

  1. Compare the user entry to the captcha text
  2. If they are the same, enter the user’s content into your database
  3. 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 concatenated with a secret key. 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, concatenate in the secret key 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 . 'my_secret_key')) { 
    //..THE USER IS NOT A BOT, STORE THEIR INPUT
  } 
  else { 
    //THE USER ENTERED THE WRONG CAPTCHA, 
    //DISPLAY AN ERROR MESSAGE AND 
    //DO NOT STORE THEIR INPUT
  } 
} 
?>
Posted on April 9, 2008 in AJAX, Javascript, PHP by Elliott Brueggeman14 Comments »

Background

Previously I posted my PHP AJAX Framework so I thought I would give an example of its use. In this case, you probably have seen this example before – using AJAX and PHP to check if a username is available during some kind of web-based user registration. The goal is to alert the user if a username is taken before they have submitted the form, allowing them to enter another username quickly. This feat can be easily accomplished with the PHP AJAX Framework.

Setup

You are going to need to copy the contents of the PHP AJAX Framework into a JavaScript file. In this example I have put the contents into the “php_ajax_framework.js” file. You are also going to need to write a PHP script that will be called in the AJAX sequence of events, notifying the user whether the username is available or not.

Below is an example PHP Script, which has the filename “username_exists.php” and will need to be in the same directory as the page that is triggering the AJAX.

PHP Username Available Script

This script is requested by our AJAX helper function and sent the text in our username input box. In the script is a call to a function usernameExists() which returns true or false, depending on whether the username exists. In a real web site or application, this would query our database to see if the username existed. In this example, for ease of understanding, we just check to see if the username is in a defined array of usernames.

<?php 
$username = trim($_GET['username']);
 
if (usernameExists($username)) {
  echo '<span style="color:red";>Username Taken</span>';
}
else {
  echo '<span style="color:green;">Username Available</span>';
}
 
function usernameExists($input) {
  // in production use we would look up the username in 
  // our database, but for this example, we'll just check
  // to see if its in an array of preset usernames.
  $name_array =  array ('steve', 'jon', 'george', 'admin');
 
  if (in_array($input, $name_array)) {
    return true;
  }
  else {
    return false;
  }
}
?>

Username Check Page

Our example username page is very basic – you should integrate this into your existing site. The important parts are the JavaScript functions and the input box, which uses the onKeyUp() JavaScript event to call a function which them triggers the AJAX chain of events. More information on setting up the PHP AJAX Framework can be found on its post page, but the basic idea is that you create an _init function that specifies which PHP script to execute and what variables to send it (in this case, the value of the user input box.) You also create a _results function which will be given the results of your PHP Script and then do something with them (in this case, display a notice to the user whether the name is available.) The _init and _results functions are given function names prepended to these terms which are the same (in the below case, we prepend “check_username” to both) and then they are triggered by calling our PHP AJAX Framework function ajaxHelper() with the name we prepended.

<html>
<head>
<script type="text/javascript" src="php_ajax_framework.js"></script>
<script type="text/javascript">
function check_username_init() {
  var user_field = document.getElementById('user');
  return 'username_exists.php?username=' + user_field.value;
}
function check_username_ajax(results) {
  var results_div = document.getElementById('results_div');
  results_div.innerHTML = results;
}
function check_username() {
  var user_field = document.getElementById('user');
  if (user_field.value.length > 0) {
    //call our AJAX function in the PHP AJAX Framework
    ajaxHelper('check_username');
  }
  else {
    //clear results field 
    var results_div = document.getElementById('results_div');
    results_div.innerHTML = '';
  }
}
</script>
</head>
<body>
Username: 
<input name="user" id="user" size="20" onKeyUp="check_username();">
<div id="results_div"></div>
</body>
</html>

Here is an live example of the above scripts all working together. Remember that we are just checking against an array of names. Try typing in one of the names in the array to see what happens when a particular username is taken (steve, jon, george, admin.)

Conclusion

Implementing AJAX is easy and just requires putting all the pieces together. Give AJAX and shot and implement the PHP AJAX Framework on your site for simple AJAX tasks.

Posted on March 20, 2008 in PHP by Elliott Brueggeman2 Comments »

Again?

Awhile ago I posted a PHP Execution class article for timing various PHP elements. Since then, a few developers have requested that I include the ability to start and start the timer, so you can be more precise with elements that you want to time and elements that you don’t. I decided to code this class in full PHP 5+ object-oriented structure. In addition to increased functionality, sticking to this style of programming supports PHP as an enterprise level language, and helps its standing among other more weathered and commercially used languages.

The Timer Script

This script returns the time in ms (milliseconds) rounded to the nearest ms when used in a php script or web page.

<?php
class Timer{
 
  private $start_time;
  private $end_time;
  private $accumulated_time;
 
  //Public constructor
  public function __construct() {
    $this->start_time = NULL;
    $this->end_time = NULL;
    $this->accumulated_time = 0;
  }
 
  //Public functions
  public function start() {
    if ($this->is_stopped()) {
      //add time so far to accumulated time
      //reset end time and set start time
      $this->accumulated_time += ($this->end_time - $this->start_time); 
      $this->start_time = $this->get_timestamp();
      $this->end_time = NULL;
    }
    else if (!$this->is_started()) {
      $this->start_time = $this->get_timestamp();
    }
  }
 
  public function stop() {
    if ($this->is_started()) {
      $this->end_time = $this->get_timestamp();
    }
  }
 
  public function reset() {
    $this->__construct(); 
  }
 
  public function retrieve() {
    $this->stop();
    return round($this->accumulated_time + ($this->end_time - $this->start_time));
  } 
 
  //Private functions
  private function is_started() {
    //if start is numeric but end is null, we are started
     if(is_numeric($this->start_time) && is_null($this->end_time)) {
      return true;
    }
    return false;
  }
 
  private function is_stopped() {
    //if end time is numeric, we have a stopped timer
    if(is_numeric($this->end_time)) {
      return true;
    }
    return false;
  }
 
  private function get_timestamp() {	
    //retrieve seconds and microseconds (one millionth of a second)
	//multiply by 1000 to get milliseconds
    $timeofday = gettimeofday();
    return 1000*($timeofday['sec'] + ($timeofday['usec'] / 1000000));
  } 
}
?>

Usage

Using this script is relatively easy as you can probably see from the function names. The 4 main functions in addition to the constructor are start(), stop(), retrieve(), and reset(). Here is an example of usage of this class:

<?php
//instantiate the timer object
$timer = new Timer();
 
//start the timer
$timer->start();
 
//... do something worth timing
 
for($i=0;$i<10000000;$i++){}
 
//stop the timer
$timer->stop();
 
//... do something NOT worth timing
 
//start the timer again
$timer->start();
 
//... do something worth timing
 
//stop the timer
$timer->stop();
 
//print the time accumulated
echo $timer->retrieve();
Posted on March 9, 2008 in PHP by Elliott BrueggemanNo Comments »

MY Common PHP Includes

When I start a new application or website, I always start with the same framework of files. I have a series of include files that I include as necessary on pages (scripts) on the site. Stuff like site navigation, database connection, and core functions are some of the includes I use.

My functions include has all the functions that I’m confident are going to be used frequently enough on the site to warrant their inclusion (and subsequent declaration) in every script in the site. While most of the functions vary from site, because they relate to a specific feature or concept that the site incorporates, there are two functions that I always include.

My Get and Post Functions

All my sites and applications are dynamic, which means they receive input from the user using either the GET or POST method. If you incorporate forms into your site, you’re probably familiar with GET and POST and the differences between the two. One thing I noticed after some time programming was that handling data through GET and POST was done frequently and could be easily compartmentalized in two simple helper functions.

Below is my implementation of these functions:

<?php
function getData($var, $maxLength=99999) {
  $value = NULL;
  if (isset($_GET[$var])) {
    $value = trim(htmlentities($_GET[$var], ENT_QUOTES));
    if (strlen($value) > $maxLength) {
      $value = substr($value, 0, $maxLength);
    }
  }
  return $value;
}
 
function postData($var, $maxLength=99999) {
  $value = NULL;
  if (isset($_POST[$var])) {
    $value = trim(htmlentities($_POST[$var], ENT_QUOTES));
    if (strlen($value)>$maxLength) {
      $value = substr($value, 0, $maxLength);
    }
  }
  return $value;
}
?>

These functions act as helper functions to retrieve the value that was sent to the script and available to PHP’s global $_GET and $_POST arrays. They also implement a few simple extra features. When calling either of these two functions, you can also supply a $maxLength parameter, which would be the maximum expected length of that variable. If anything is longer, then someone may be trying to take advantage of your website by sending data not in the way you intended. If the variable is longer than expected, the function still allows it, though it trims it to the length you are expecting. This can be helpful if you are inserting values into a database that has limits on the number of characters in a field. In addition, the function also puts the value through PHP’s htmlentities() function which will encode each character into their html equivalent, which I almost always need. This can also disarm any injected code that a malicious user may be sending to your script. Lastly, the function returns NULL when the expected variable has not been passed. This allows easy error handling when calling this function. Here is an example of doing error handling when retrieving a function:

<?php
//Attempt to retrieve the value
$username = getData('username');
 
if ($username == false) {
  //This value does not exist, do something to handle this situation
}
else {
  echo 'Welcome ' . $username . '!';
}
?>
Posted on February 22, 2008 in PHP by Elliott BrueggemanNo Comments »

Why Change Your php.ini file?

Both PHP for Windows and Linux ship with pre-configured .ini files with settings common to most PHP setups. The Windows installer (which I recommend if you’re using Windows for a development machine, or even have your live site on Windows) goes a step further and also will add lines to your php.ini file through a simple GUI that enable both your web server and desired PHP extensions.

Most people will leave these the rest of the .ini file unchanged, but there are some changes that can make life much easier. Below are my recommendations for changes to the default php.ini file. The line number is next to each changed line, and is accurate for Windows PHP 5.25 distributions.

Short Tags

Short tags are PHP tags like this <? ?> and were very common a few years ago and taught to me in my Web Technologies class at NYU. You should generally allow these, especially if you are working with inherited code. This setting was the cause of over an hour of frustration when I moved an application to a new server and it suddenly wouldn’t load.

131 Orig: short_open_tag = Off
131 Mine: short_open_tag = On

Maximum Execution Time

For some reason this is only set to 30 seconds by default. Some heavy hitting scripts that write to disk, retrieve information from the web, or other things where waiting is involved, can run longer than 30 seconds. The cron.php script for a Drupal site that I work on customarily runs for over a minute.

303 Orig: max_execution_time = 30
303 Mine: max_execution_time = 240

Memory Limit

I’ve found that many high traffic sites will run out of memory when this is set to 128m. This setting is per script, so if 10 scripts are executing at once, you can easily max out your memory. If you’re using more than 64m for a certain script, you need to optimize your code, or split up functionality into more than one script.

306 Orig: memory_limit = 128M
306 Mine: memory_limit = 64M

Display Errors

I would recommend the following change only for development machines, not live severs. When set to “On”, PHP will output the error directly to the screen in addition to your error log (if enabled.) This can be very useful for debugging.

372 Orig: display_errors = Off
372 Mine: display_errors = On

Error Log

This is another setting I would only recommend doing on a development machine, not a live server. When uncommented and supplied with a valid filename, this will output all errors and warnings to an error log file in the base directory of your server root. Again, very helpful for debugging and development.

428 Orig: ;error_log = filename
428 Mine: error_log = errors.txt

Upload Filesize

On the chance that you are uploading files in your scripts, this is a handy change to make. I’ve found that 4M is a much friendlier setting, especially with digital picture uploads, which are regularly more than 2M.

597 Orig: upload_max_filesize = 2M
597 Mine: upload_max_filesize = 4M

Session Name

When using sessions, PHP will create cookies to store information and the below setting will be the name of the cookie. When in doubt, give a malicious user as little information as possible, and this setting exposes the fact that you are using PHP sessions. Pick a more general name.

1010 Orig: session.name = PHPSESSID
1010 Mine: session.name = XYZ

Don’t forget to restart your web server after making any of the above changes.

Posted on February 13, 2008 in PHP by Elliott Brueggeman1 Comment »

Debugging Can Be Difficult

Debugging a PHP script can be a difficult task, especially when code is located over many files. Trying to debug a complicated CMS like Drupal, where function calls are not always explicit and may be implemented as hooks, can be an outright nightmare.

Magic Constants

Luckily, PHP has a few not so well known magic constants that can greatly aid developers. I think the most useful of all is the __FUNCTION__ constant. This function will return the name of the function that it is called in. To use effectively add either of the following two statements to the first line of each function in the file(s) of code you are executing:

echo('Current Function: ' . __FUNCTION__);
error_log('Current Function: ' . __FUNCTION__);

After you execute your script or page, you will get a chronologically ordered function by function run-down of what has been executed. Note that you must choose either echo or error_log ouput, where appropriate. Echo will output directly to the screen, but may not work as expected in some circumstances where your output is buffered, or echo’s happen amid hidden page elements. The most reliable way is to use error_log() to output to your server’s PHP error log. Unfortunately, this log may not be viewable in some hosted site situations where you have limited access to PHP’s configuration.

Other magic constants are also available for debugging object oriented PHP code including __CLASS__ and __METHOD__. The constant __FUNCTION__ will return the same method information when a function is inside of a class, so you can just use __FUNCTION__ instead of __METHOD__.

The last two magic constants are __FILE__ and __LINE__ which do pretty much exactly what you think they would do. For more information on PHP’s magic constants, check out this PHP manual page.

Posted on February 6, 2008 in PHP, SEO, Search Engines by Elliott Brueggeman4 Comments »

Background

Displaying your email address on your site as text has always been risky. Why? Long ago, spammers created bots that searched the web for email address (by looking for something in the xxxx@yyyy.com format) and then spammed them to oblivion. As a result, web developers often use little tricks like writing out the @ symbol (xxxx at yyyy.com) or inserting a little image of an @ symbol between the username and the domain to prevent a spambot from reading the address. Another problem arises when a user wants to display their name on a website, but doesn’t want a search engine to be able to read the name and then associate it with the site in the engine’s search results. PHP allows a solution for both of these scenarios that is versatile and easy to implement.

Dynamically Generated Images

One of the many powers of PHP is its ability to generate images dynamically, meaning on the fly, when a page is requested. PHP uses the GD extension to create gifs, pngs, jpegs, etc and manipulate them with a small set of predefined functions. The idea here is to display a dynamically generated image of your name or email address that is invisible to search engines, because it is an image and not text.

Why not use Photoshop or another similar program to make an image of a name for one time use? Well you could do this, but what about a situation where data is displayed dynamically, like on a blogging site, where new users sign without the intervention of a web developer? You wouldn’t want to have to manually create an image each time this happened. Dynamically created images in PHP are the solution.

Inserting Dynamic Images Into Your Site

PHP scripts that generate images can only generate images. They cannot have html or other PHP elements echo’d out to the screen. In order to get them to work, you have to isolate the script that generates the image from the script (or page) that displays the image. Let’s say we want to display our email address on our page home.php, and we have a script that generates the image of our email address in email_address.php. To accomplish this, we would need to have an <img> tag on home.php that pointed to email_address.php. Here is what the tag on home.php could look like:

<img src="email_address.php" alt="" />

Note that we are substituting our image generating script into the spot where we would normally have the name of an image, but we keep the “.php” extension.

The Script

To use this script, copy the below code into a file and save it as disguise_text.php and upload it to your server. Then, follow the instructions in the “Implementing the Script” section.

<?php
//get name from passed arg
$text= base64_decode(urldecode($_GET[text]));
//width per char is based on experimentation - yours may be different
$width_per_char = 6.25;
//image height and width
$length = $width_per_char * strlen($text);
$height = 15;
//create image
$img = imagecreatetruecolor($length, $height);
//define used colors
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
//set the background to white
imagefilledrectangle($img, 0, 0, $length, $height, $white);
//write name in black
imagestring($img, 2, 2, 2, $text, $black);
//output header and generate image
header("Content-Type: image/png");
imagepng($img);
?>

Implementing the Script

After you have uploaded the above script to your server as disguise_text.php, insert the following image tag into the page you want to display the image (paste onto one line – it is separated due to column width):

<img src="http://www.ebrueggeman.com/blog/wp-admin/disguise_text.php?
text=<?php echo urlencode(base64_encode('jwaters@apple.com')); ?>" 
alt="email address" />

Here is what the above code actually generates: email address

Notes

Without getting overly complicated, the example we have uses size 2 of PHP’s default font to display the text. The auto image width feature of the script is based on the width of this particular font with this size. If you are going to change the font, make sure to change the $width_per_char and $height variables to accurately represent your font. Also, as shown above, the script only works for pages with white backgrounds. To display the image with a different color background, change the RGB values of the “$white = imagecolorallocate($img, 255, 255, 255);” code to match your background.

Conclusion

Generating images in PHP is easy if you know the basics, and hiding text from search engines can be a useful tool. Check out this related article on Image Optimization in PHP

Posted on January 16, 2008 in AJAX, Javascript, PHP by Elliott BrueggemanNo Comments »

Background

In the previous article, we examined the PHP AJAX Framework, which is an easy way of combining AJAX with PHP. In order to trigger our AJAX, we relied on user interaction. However, what happens when you want your AJAX call to execute at a certain time interval? The solution is relatively easy and involves the JavaScript function setInterval().

AJAX Timer Code

Below is a snippet of JavaScript code that will work with my PHP AJAX Framework to call the sales_calculate hook every 5 seconds:

<script language="JavaScript">
var time = 5; //time in seconds
var interval = time * 1000;
var timer = setInterval("ajaxHelper('sales_calculate')", interval);
</script>

The above code will execute our ajaxHelper() function with the sales_calculate hook that will in turn call sales_calculate_setup() and then sales_calculate_ajax() every 5 seconds.

Note that this code is meant to accompany my PHP Framework, and will not trigger an AJAX call unless properly configured. Please refer to the prior AJAX Framework article for more information.

Posted on January 9, 2008 in AJAX, Javascript, PHP by Elliott Brueggeman3 Comments »

Background

One of the most useful new web technologies is AJAX, or Asynchronous JavaScript and XML. In short, AJAX allows you to send and receive server requests without a user having to reload the page. This allows pages to be more dynamic without interrupting the user experience.

AJAX is fairly easy to implement and use effectively, but finding a comprehensive start to finish tutorial for integration with PHP is not quite as easy. To make the task easier, I have put together a simple PHP AJAX framework that is flexible and easy to implement.

AJAX Workflow

The inner workings of AJAX are a mystery for some so I will go over the basics of how our framework will work with PHP.

  1. Using JavaScript, a call to your AJAX function is triggered by clicking somewhere, entering something, etc.
  2. Your AJAX function creates an XMLHttpRequest object.
  3. When ready, the object requests information from your server in the form of a URL, possibly with arguments such as myscript.php?name=jon&year=2007, etc.
  4. The server executes the PHP script and sends the result by echo[ing] it out.
  5. Instead of printing it to the screen, that information is instead returned to you as a JavaScript variable.
  6. Using JavaScript, that information can now be dynamically inserted in the page by using the innerHTML property or by assigning the result to the value of a form element.
  7. Rinse and Repeat… The value of AJAX is that you can repeat this process infinitely without having the user have to navigate away from the page!

PHP AJAX Framework

The PHP AJAX Framework shown below is structured into three parts. The part that stays the same every time is the JavaScript ajaxHelper() function. This is the core of our AJAX functionality. We also need to create two additional JavaScript functions. The code of these functions is different depending on what you want to do. These functions or hooks will be called by the ajaxHelper() function and their names must end in “_init” and “_ajax” which will be explained below.

The ajaxHelper() function

function ajaxHelper(functionName, additionalArgs) {
  var xmlHttp;
  // Firefox, Opera 8.0+, Safari, SeaMonkey
  try {
    xmlHttp=new XMLHttpRequest();
  }
  catch (e) {
    // Internet Explorer
    try {
      xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      try {
        xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e) {
        alert("Sorry, your browser does not support AJAX.");
        return false;
      }
    }
  }
 
  xmlHttp.onreadystatechange=function() {
    //The request is complete == state 4
    if (xmlHttp.readyState==4) {
      var response=xmlHttp.responseText;
      //Send reponse to _ajax hook of passed function name
      eval(functionName + "_ajax" + '(\'' + response + '\')');
    }
  }
 
  //Get request string from _setup hook of passed function name
  if (additionalArgs !== undefined && additionalArgs.length > 0) {
    var requestString = eval(functionName+"_init" + '(' + additionalArgs + ')');
  }
  else {
    var requestString = eval(functionName+"_init" + '()');
  } 
 
  if (requestString) {
    xmlHttp.open("GET", requestString, true);
    xmlHttp.send(null);
  }
}

The _init and _ajax functions

As stated above, these are functions are hooks, meaning that they will be called dynamically by the ajaxHelper() function depending on the argument you pass it. For example, on a button click you execute the ajaxHelper(’chat_update’) function. The ajaxHelper will call chat_update_init() and then chat_update_ajax() automatically, so you must have them defined. By making them dynamic hooks, you can have many different AJAX calls on the same page but use the same ajaxHelper() function each time. You pass the ajaxHelper() function the first part of the name of your two additional functions (minus the _init and _ajax), which is “chat_update” in the above example.

The _init hook function specifies the name of the PHP file and any arguments to be passed to the ajaxHelper() function. An example _init hook is as follows:

function my_first_try_init() {
  //retrieve username from html input box with the id "name_box"
  var username = document.getElementById('name_box');
  var script = 'myscript.php';
  var queryString = "?username=" + username;
  return script + queryString;
}

The _ajax function is passed the results of the PHP script specified in the _init hook as a JavaScript variable. Using JavaScript trickery, we can update the page that the user is viewing. You can use the .innerHTML property and change the contents of a div or other element. Or, you could even change the text of input boxes by changing the .value property. This may sound confusing, but study the below examples for a better understanding.

function my_first_try_ajax(results) {
  var targetDiv = document.getElementById('firstDiv');
  var resultHTML='<h1>' + results + '</h1>';
  targetDiv.innerHTML = resultHTML;
}

The above code replaces the html within a div with the id “firstDiv” with whatever has been returned by myscript.php wrapped in h1 tags. You could have an empty div and only insert html into it on AJAX calls. The div would look like this:

<div id="firstDiv"></div>

While declaring an _ajax hook function is required, adding JavaScript code inside the function is optional. Why? Because often you do not want to change content on the user’s page, but instead just update values in the database on your call to the script specified in the _init hook. In that case, nothing would need to be updated on the page.

Your PHP Script

Creating your PHP script that will be called by the AJAX framework is easy if you know PHP. You can have your PHP script do pretty much anything. You probably want to either return some value or values, update a database, or both. The only thing to note is that to return a value, you need to “echo” it out. Values printed to the screen from your PHP callback script are returned to the the JavaScript _ajax() hook function as the results variable, as seen above.

How do you return multiple results? Well the implementation differs depending on what you want to return, but if you want to return an array you simply echo out a comma separated list in your PHP script and then you split the returned JavaScript variable by the commas and loop through the values in your _ajax() function and do whatever. Here is an example of a php script that connects to a database and returns the current sales totals for the year:

<?php
//connect to database
$link = mysql_connect('localhost', 'username', 'password')
  or die('Could not connect: ' . mysql_error());
mysql_select_db('sales_db') or die('Could not select database');
 
$currentYear = date('Y');
 
//execute query
$sql = "SELECT SUM(sale_total) as `total`
  FROM sales_table WHERE year = $currentYear";
$result = mysql_query($sql);
 
//retrieve results
while ($row = mysql_fetch_assoc($result)) {
  $total = $row["total"];
}
 
//return via echo to our JavaScript _ajax function
echo $total;
?>

Here is another example that returns an array of values:

<?php
//[not shown] do a database call and retrieve an array
$valueArray = array(23, 231, 'roger 123', 26, 'Las Veags,
  Nevada', 'Washington', 77);
 
//replace commas with their html value so they do not
//get in the way of separating out the array
// values with commas via the implode statement
echo implode(', ', str_replace(',', '&#44;', $valueArray));
?>

Activating AJAX

Finally, the only thing we are missing is how we trigger our AJAX call. There are many ways to do this. The most common method is when a user interacts with an element on the page, triggering the AJAX helper function, but this is not the only way. You can also use a JavaScript timer and call the AJAX at a set interval. This method will be covered in a future article. Let’s look at some common examples of triggering AJAX through user interaction:

Button Click

<input type="button" id="trig" value="ClickMe" onClick="ajaxHelper('my_first_ajax');" >

Mouse-Over a Div

<div id="TriggerDiv" onMouseOver="ajaxHelper('sales_calculate');" ></div>

Click in a Text Box

<input type="text" name="datefield" onClick="ajaxHelper('update_date');" >

Conclusion

The uses for AJAX are endless, especially coupled with PHP. Explore, experiment, and see what’s best for your website.

Update – September 15th, 2009

I added an optional second parameter to the ajaxHelper() function call – this allows you to pass additional variables to the PHP script via Javascript. Below is an example of passing an array of three values to the php script.

Example Usage

<a href="#" onclick="ajaxHelper('track_click', new Array(1303432, 26));">Click Here</a>

To utilize these values, add parameters to your _init hook function for each value passed. The below _init hook function takes each of the passed values and then puts them into a url friendly format to be passed to your PHP script.

function track_click_init(arg0, arg1) {
 
	var script = 'onclick.php';
	var queryString = "?id=" + arg0 + "&age=" + arg1;
 
	return script + queryString;
}

Posted on December 23, 2007 in PHP by Elliott Brueggeman2 Comments »

Background

PHP is not a strictly typed language, and many programmers often overlook problems that can be caused with not paying attention to numeric types. The problem is that PHP does not alert you when you have gone outside of the bounds of what an integer can hold. Instead, it silently converts your value to a float (floating point number.)

Why should you care? Mathematic expressions with floats are not always exact – sometimes they can be way off. PHP, like most programming languages, uses shortcuts to estimate the result of floating point mathematic expressions. The rule of thumb is that the larger the numbers you are working with, the greater amount of estimations involved in finding a result. If you were programming a PHP-based financial application, this could be a huge liability.

The best way to handle large numbers in PHP is to be aware of exactly what type of number you are dealing by knowing the PHP bounds of integers. PHP supplies a constant PHP_INT_MAX which will tell you what the maximum integer is for your instance of PHP. Not all computers/operating systems/versions of PHP are the same, so it is good to find the PHP_INT_MAX for each setup. Note that the PHP_INT_MAX also determines the smallest negative number – just multiply it by -1 to get the PHP integer minimum.

PHP Integer Testing Script

Below is a testing script to help you determine the PHP_INT_MAX:

<?php
$intMax = PHP_INT_MAX;
 
echo "$intMax<br />";
 
if (is_int($intMax)) {
	echo "$intMax is an Int<br />";
}
else {
	echo "$intMax is NOT an Int<br />";
}
 
if (is_int($intMax + 1)) {
	echo "$intMax+1 is an Int<br />";
}
else {
	echo "$intMax+1 is NOT an Int<br />";
}
 
if (is_int($intMax * (-1))) {
	echo "$intMax*(-1) is an Int<br />";
}
else {
	echo "$intMax*(-1) is NOT an Int<br />";
}
?>

The result of this script:

2147483647
2147483647 is an Int
2147483647+1 is NOT an Int
2147483647*(-1) is an Int

PHP Float Testing Script

Now that you know the bounds of integers, what do you do? Truth be told, there is not a whole lot you can do to guarantee the integrity of your floating point numbers. It may be more important to know which figures are the result of math involving floating point numbers, so you can disclose this to your audience, and act accordingly. See the simple example below that shows how poorly PHP can do math involving floating point numbers:

<?php
//TEST 1
$number = 216897510871;
$original_number = $number;
 
$number *= 11123.74;
$number /= 11123.74;
 
if ($original_number == $number) {
	echo "Test 1: Are Equal<br />";
}
else {
	echo "Test 1: Are NOT Equal<br />";
}
 
//TEST 2
$number = 216897510871;
$original_number = $number;
 
$number *= 11123.75;
$number /= 11123.75;
 
if ($original_number == $number) {
	echo "Test 2: Are Equal<br />";
}
else {
	echo "Test 2: Are NOT Equal<br />";
}
?>

The result of this script:

Test 1: Are Equal
Test 2: Are NOT Equal
Posted on December 16, 2007 in PHP by Elliott Brueggeman4 Comments »

Background

Previously we have seen how to make a native Excel spreadsheet through the use of the PEAR extension. This article is about generating comma (.csv.) and tab delimited spreadsheets that are readable in many popular programs, and useful in a multitude of websites and applications. You need no external packages or extensions to generate these files – PHP does this natively.

Differences

Comma separated value files known by their .csv extension are the most popular alternative to the native Excel .xls spreadsheet file. One problem is that .csv files are actually text files with column values separated with commas, and this can cause problems when your data also has commas in it. The additional code necessary to solve this problem is often not worth it, so many people generate tab delimited files with PHP instead. When creating tab delimited files, you can use both the native Excel .xls extension or the .tsv (tab separated values) extension. However, a user’s OS may not be setup to recognize the .tsv extension and may try to open it in a regular text editor. The better option is to use the Excel .xls extension for your tab delimited files to guarantee that the user will be able to open it successfully with a myriad of browser, OS, and software combinations – I have found that many other non Microsoft spreadsheet programs support the .xls extension. In the below script, I have opted below for an .xls tab delimited file, but I have also included the necessary changes in the comments to generate .csv files as well.

PHP Code

<?php
/* Data to be inserted into excel in an array of arrays
 * Each array is the avg monthly temp of a different city */
$data = array ( array ( "City" => "Seattle",
	"Jan" => 46, "Feb" => 50, "Mar" => 53, "Apr" => 58,
	"May" => 64, "Jun" => 70, "Jul" => 75, "Aug" => 76,
	"Sep" => 70, "Oct" => 60, "Nov" => 51, "Dec" => 46 ),
	array ( "City" => "New York",
	"Jan" => 39, "Feb" => 42, "Mar" => 50, "Apr" => 60,
	"May" => 71, "Jun" => 79, "Jul" => 85, "Aug" => 83,
	"Sep" => 76, "Oct" => 64, "Nov" => 54, "Dec" => 44 ),
	array ( "City" => "San Francisco",
	"Jan" => 56, "Feb" => 59, "Mar" => 61, "Apr" => 64,
	"May" => 67, "Jun" => 70, "Jul" => 71, "Aug" => 72,
	"Sep" => 73, "Oct" => 70, "Nov" => 62, "Dec" => 56 )
);
 
$csvTitle = "Monthly Average High Temperature By City";
 
/* We know the keys of each sub-array are the same, so
 * extract them from the first sub-array and set them
 * to be our column titles */
$titleArray = array_keys($data[0]);
 
/* Set your desired delimiter. You can make this a true
 * .csv and set $delimiter = ","; but I find that tabs
 * work better as commas can also be present in your data.
 * Note that you must use the .tsv or .xls file extension for Excel
 * to correctly interpret tabs. Otherwise if you are using commas
 * for your delimiter, use .csv for your file extension. */
$delimiter = "\t";
 
//Set target filename - see above comment on file extension.
$filename="Search_Export.xls";
 
//Send headers
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=$filename");
header("Pragma: no-cache");
header("Expires: 0");
 
//print the title to the first cell
print $csvTitle . "\r\n";
 
//Separate each column title name with the delimiter
$titleString = implode($delimiter, $titleArray);
print $titleString . "\r\n";
 
//Loop through each subarray, which are our data sets
foreach ($data as $subArrayKey => $subArray) {
	//Separate each datapoint in the row with the delimiter
	$dataRowString = implode($delimiter, $subArray);
	print $dataRowString . "\r\n";
}
?>
Posted on December 7, 2007 in PHP by Elliott Brueggeman11 Comments »

Background

Generating spreadsheets in PHP is a powerful tool. Natively, PHP can generate .csv spreadsheets with little fuss by sending a header to the browser to generate csv output. This article is not about .csv files, but rather generating Excel Spreadsheets with PHP.

Benefits of using actual Excel format (.xls) files:

  • Standard spreadsheet format for most offices
  • Rich formatting can be saved in the file
  • Less confusion for casual computer users

PEAR Setup

To generate Excel files we will be using the PEAR package Spreadsheet_Excel_Writer. PEAR stands for the PHP Extension and Application Repository and contains useful tools and functions that you can use in your PHP scripts. PEAR is closely tied to PHP development, and PHP can be configured to use PEAR easily. For installation instructions see: http://pear.php.net/manual/en/installation.php.

If you are like me and you have your site running on a shared host where you do not have the luxury to install and change whatever you want, you can still use PEAR in your site. There are instructions in the above installation page for installing it on a shared host.

For testing purposes, I have bundled the necessary Spreadsheet_Excel_Writer and OLE package PEAR files into a zip file so you can extract it to your web root and create Excel spreadsheets easily without the full installation of PEAR. I changed all include() paths so that they will work with a different directory structure than the default PEAR installation. Please note that this is not an official PEAR code release and should only be used for testing purposes. Download the testing package here.

Creating the Excel file with PHP

Using this package is relatively easy, once you understand the flow of how it works. The package provides many, many formatting functions. See the list of formatting releated functions in the package’s official documentation: http://pear.php.net/manual/en/package.fileformats.spreadsheet-excel-writer.php.

Below is a code example that generates a fairly simple spreadsheet. Click here to execute the code.

<?php
/*This require call will be different depending on how your PEAR
 *is installed. The below call works with the zipped test PEAR
 *files I have provided if your script is in the same folder as
 *the zipped PEAR folder.
 *Normally, If you have PEAR installed correctly, you would
 *use the call: require_once('Spreadsheet/Excel/Writer.php'); */
require_once('PEAR/Spreadsheet_Excel_Writer/Writer.php');
 
/* Data to be inserted into excel in an array of arrays
 * Each array is the avg monthly temp of a different city */
$data = array ( array ( "City" => "Seattle",
	"Jan" => 46, "Feb" => 50, "Mar" => 53, "Apr" => 58,
	"May" => 64, "Jun" => 70, "Jul" => 75, "Aug" => 76,
	"Sep" => 70, "Oct" => 60, "Nov" => 51, "Dec" => 46 ),
	array ( "City" => "New York",
	"Jan" => 39, "Feb" => 42, "Mar" => 50, "Apr" => 60,
	"May" => 71, "Jun" => 79, "Jul" => 85, "Aug" => 83,
	"Sep" => 76, "Oct" => 64, "Nov" => 54, "Dec" => 44 ),
	array ( "City" => "San Francisco",
	"Jan" => 56, "Feb" => 59, "Mar" => 61, "Apr" => 64,
	"May" => 67, "Jun" => 70, "Jul" => 71, "Aug" => 72,
	"Sep" => 73, "Oct" => 70, "Nov" => 62, "Dec" => 56 )
);
 
$sheetTitle = "Monthly Average High Temperature By City";
 
/*We know the keys of each sub-array are the same, so
 *extract them from the first sub-array and set them
 *to be our column titles */
$columnTitles = array_keys($data[0]);
$numColumns = count($columnTitles);
 
//Creating a workbook
$workbook = new Spreadsheet_Excel_Writer();
 
//Sending HTTP headers
$workbook->send('Search_Export.xls');
 
//Creating a worksheet
$worksheet=&$workbook->addWorksheet('Export');
$worksheet->setLandscape();
 
//set all columns same width
$columnWidth = 10;
$worksheet->setColumn (0, $numColumns, $columnWidth);
 
//Setup different styles
$sheetTitleFormat =& $workbook->addFormat(array('bold'=>1,
  'size'=>10));
$columnTitleFormat =& $workbook->addFormat(array('bold'=>1,
  'top'=>1,
  'bottom'=>1 ,
  'size'=>9));
$regularFormat =& $workbook->addFormat(array('size'=>9,
  'align'=>'left',
  'textWrap'=>1));
 
/*Speadsheet writer is in format y,x (row, column)
 *  column1  |  column2 |  column3
 *   (0,0)      (0,1)      (0,2) */
 
$column = 0;
$row    = 0;
 
//Write sheet title in upper left cell
$worksheet->write($row, $column, $sheetTitle, $sheetTitleFormat);
 
 
//Write column titles two rows beneath sheet title
$row += 2;
foreach ($columnTitles as $title) {
  $worksheet->write($row, $column, $title, $columnTitleFormat);
  $column++;
}
 
//Write each datapoint to the sheet starting one row beneath
$row++;
foreach ($data as $subArrayKey => $subArray) {
  //Loop through each row
  $column = 0;
  foreach ($subArray as $value) {
    //Loop through each row's columns
    $worksheet->write($row, $column, $value, $regularFormat);
    $column++;
  }
  $row++;
}
$workbook->close();
?>

Notes

There has not been any further development on this PEAR package since 2006, and there is a long user-submitted bug list on their site. Most of the bugs are related to the more complicated functionality possible with this package. To be careful, I would not make any generated spreadsheet too complicated in a production level application. I have also heard that very large spreadsheets (2mb+) can crash your script, so you may want to set a limit on the number of rows you are going to write.

Posted on December 2, 2007 in PHP by Elliott Brueggeman2 Comments »

If you’re a PHP programmer, but you’ve never used register_shutdown_function(), you are not alone. Buried in the Function Handling Functions section of the PHP manual, this function is seldom in PHP programming books or tutorials. However it is very useful in many situations where the integrity of your data is essential.

The function register_shutdown_function() takes the name of a user-defined function as an argument, and then calls that function when the script terminates. As long as you call register_shutdown_function() at the top of your script, your function will be executed even if there is a PHP error or the script times out. The function will also be called if the script executes normally, with no errors. 

Because of the guarantee that your shutdown function will be called, you can execute essential commands in your function and be certain of their result. Common uses include updating session variables or updating values in a database.

For example, say you have a script that loops through transactions, processing each one, and then updates a database with the total number of transactions processed. A good use of reigster_shutdown_function() would be to perform the database update of the number of transactions, because you can be assured that it will be executed. See example below:

<?php
register_shutdown_function('safe_update');
$done_processing=false;
$number_processed=0;
 
while($done_processing==false)
{
  //PROCESS A TRANSACTION...
  $number_processed++;
}
 
function safe_update()
{
  global $number_processed;
  //UPDATE DATABASE WITH $number_processed
}
?>
Posted on November 22, 2007 in PHP by Elliott Brueggeman8 Comments »

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:

  1. Compare the user entry to the captcha text
  2. If they are the same, enter the user’s content into your database
  3. 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.

Posted on November 8, 2007 in MySQL, PHP by Elliott Brueggeman3 Comments »

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.

Posted on November 5, 2007 in PHP by Elliott BrueggemanNo Comments »

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.

Posted on October 2, 2007 in MySQL, PHP by Elliott Brueggeman6 Comments »

Planning on storing IP addresses in MYSQL or any other similar database for your PHP application? If you are like most, you probably were thinking of storing the IP addresses as strings in a varchar(15) row. Well, there actually is a much faster and more efficient way of storing IP addresses. The secret lies in PHP’s ip2long() and long2ip() functions which convert a dotted IP address to and from it’s long integer representation. The IP address can then be stored in the database as an int(11) format. When you need to work with the IP address later, simply convert back to the dotted format using the long2ip() function.

The long format is much faster to query for in MYSQL because you are searching an integer index as opposed to a string index.  Make sure you don’t use “like” in your query or you could lose this speed increase, and make sure you include an index on this column.

Example code in PHP:

$ip_address="212.253.52.1";
$converted_address=ip2long($ip_address);
$sql="SELECT FROM ip_table WHERE ip = $converted_address";
$mysql_query($sql);

In addition to a query speed increase, storing IP addresses as int(11) also has a disk space savings. In my test with 50,000 unique IP addresses, storing them as int(11) used 40% less disk space for the combined data and index than the varchar(15) format. Take note!