Class Antz_IntelliForm

Uses of Antz_IntelliForm

Examples of Usage >>

Resubmit Messages

Users often use the back button to go back to a previous page. If they go back to a page that has submitted a form using the POST header, they encounter a warning to the effect:

"The page you are trying to view contains POSTDATA that has expired from cache. If you resend the data, any action the form carried out ( such as a search or online purchase ) will be repeated. To resend the data, click OK. Otherwise, click Cancel"

This is confusing to the user, and dangerous to the application because re-submitting data may result in multiple forum threads, or as the warning suggests, multiple purchases etc.

PHP has no inbuilt protection against these vulnerabilities, developers need to be cautious and defensive in their approach to programming. Antz_IntelliForm can be implemented to protect against resubmitted post data, preventing the warning altogether.

The data that has been submitted in the form is stored in a session variable. The user is then redirected to the same page using GET. When the page is reloaded, Antz_IntelliForm checks the session to see if any form data has been saved. If so, it puts the form data from the session into the $_POST array and removes the data from the session. This way the application can access the data from the $_POST array, but the page has been reached by GET rather than POST.

When the user hits their refresh button, the page is re-requested by GET, but because the data is no longer stored in the session, the application treats it as though the form has not been submitted.

All this is acheived by calling Antz_IntelliForm::antiRepost() AFTER session_start() but before the application begins to use the $_POST data.

Save Form Data

Sometimes a user may enter incorrect or insufficient information into a form. They may then navigate away from the form to check some of the information. When they return to the form, they would have to enter all the information again.

Antz_IntelliForm can save the data for a given period of time. By default it is set to 300 seconds ( 5 minutes ). It is easy to save the form data, all you do is Antz_IntelliForm::save('myForm', 600), where 'myForm' is any unique key and 600 is the number of seconds it should be saved for. If you leave the second parameter out, it will default to 300 seconds.

It is equally as easy to restore saved data: Antz_IntelliForm::restore('myForm'). The form data is stored in $_SESSION['intelliForm'][$key].

You can delete saved form data by calling Antz_IntelliForm::clear('myForm') . Also remember that saved form data gets deleted when it expires, but this only happens when Antz_IntelliForm::purge() is called, and only if the data has expired.

You should call Antz_IntelliForm::purge() on each page load, otherwise the data will never be deleted from the session and it will cause a data leak.

Unique Key

It is easy to make a form and submit it to a foreign server. It is then up to the server to determine if the form is a valid submission. To assist with this, Antz_IntelliForm puts a random number in a hidden field of the form, then checks the submitted form to make sure that it is a valid number.

To put the number in the form, use:

<form method="post">
  <?php echo Antz_IntelliForm::seed()?>
  <input type="submit">
</form>

To check if the form has been submitted:

if(Antz_IntelliForm::submitted()){
  // do some code to check and process
};

Example of usage

I will demonstrate 2 approaches to using Antz_IntelliForm, hopefully you can see how you would approach it in your programming.

Inline Programming

You will have many files in the public directory of your server, and the browser will request each file directly. You probably have an include or require command at the top of each file to take care of repetitive tasks, such as connecting to the database.

For the purpose of this example, I will call the file form.php, and the included file config.php.

    // file: form.php
    <?php include('config.php'?>
    
    <?php  
        
if(Antz_IntelliForm::submitted()){
            
// form has been submitted
            
Antz_IntelliForm::save('login');
            
$username mysql_real_escape_string(post('username'));
            
$pass post('pass');
            
$error '';
            
$res mysql_fetch_assoc(mysql_query("SELECT * FROM `users` WHERE `username` = '{$username}'"));
            if(
count($res)==0){
                
$error .= 'Invalid Username<br>';
            }elseif(
$res['password'] == md5($password)){
                
// successful login
                
Antz_IntelliForm::clear('login');
                include(
'login.php');
                
login($res);
                
header('location: nextpage.php');
            }else{
                
$error .= 'Invalid Password<br>';
            };
        }else{
            
// form has not been submitted
            
Antz_IntelliForm::restore('login');
        };
    
?>
    <h1>Login</h1>
    <?php
        
if($error != '')echo '<div class="error">'.$error.'</div>';
    
?>
    <form method="post">
      <?php echo Antz_IntelliForm::seed()?>
      <label>Username</label>
      <input type="text" name="username" value="<?php echo post('username')?>">
      <label>Password</label>
      <input type="password" name="password" value="<?php echo post('password')?>">
      <input type="submit" value="Login >>">
    </form>
    
    // file: config.php
    <?php 
      session_start
();
      include(
'Antz/IntelliForm.php' );
      
Antz_IntelliForm::antiRepost();
      
Antz_IntelliForm::purge();
      include(
'dbConnect.php');
      function 
post($key$alt)
      {
          return (isset(
$_POST[$key])) ? $_POST[$key] : $alt;
      }
    
?>

    

Of course, it would be noted that it is not good practice to echo the submitted password to the form, but I hope that this example is sufficient for demonstrating how to use the class.

MVC Programming

You will have a bootstrap file ( index.php ), a controller ( Users.php ), and a view ( login.tpl.php ).

    // file: index.php
     <?php 
      
// connect to the db
      
include('dbConnect.php');
      
// session.php contains the class that holds the user object and manages session data
      
include('session.php');
      global 
$session;
      
$session = new Session();
      include(
'Antz/IntelliForm.php'
      
Antz_IntelliForm::antiRepost();
      
Antz_IntelliForm::purge();       
      
// now we dispatch the controller and echo the page contents
      
include('controller.php');
      include(
'page.php');
      
$page = new Page();
      
$controller = new Controller();
      
$controller->dispatch();
      echo 
$page->render();
    
?>
    

    // file: Controllers/Users.php
    <?php 
    
class UsersController{
        function 
loginAction()
        {
            if(
Antz_IntelliForm::submitted()){
              
// form has been submitted
              
Antz_IntelliForm::save('login');
              
$username mysql_real_escape_string(post('username'));
              
$pass post('pass');
              
$error '';
              
$res mysql_fetch_assoc(mysql_query("SELECT * FROM `users` WHERE `username` = '{$username}'"));
              if(
count($res)==0){
                  
$error .= 'Invalid Username<br>';
              }elseif(
$res['password'] == md5($password)){
                  
// successful login
                  
Antz_IntelliForm::clear('login');
                  global 
$session;
                  
$session->login($res);
                  
header('location: nextpage.php');
              }else{
                  
$error .= 'Invalid Password<br>';
              };
          }else{
              
// form has not been submitted
              
Antz_IntelliForm::restore('login');
          };
          global 
$page;
          
$page->mainTemplate 'Users/login.tpl.php';
          
$page->setError($error);
        }
    }
// end class
    
?>

    

    // file: templates/Users/login.tpl.php
    <h1>Login</h1>
    
    <?php echo $this->getError(); ?>
    
    <form method="post">
      <?php echo Antz_IntelliForm::seed()?>
      <label>Username</label>
      <input type="text" name="username" value="<?php echo post('username')?>">
      <label>Password</label>
      <input type="password" name="password" value="<?php echo post('password')?>">
      <input type="submit" value="Login >>">
    </form>