OxyScripts.com
Menu spacer Home Tutorials Articles Code Forums irc.freenode.net #oxyscripts
Main (PHP)
Home Forums PHP News PHP Tutorials Articles PHP Code Snippets Contact Us Sysadmin Resources Books Template Shop
3rd Party Streams
SlashDot PHPDeveloper.org PHP.Net
Resources
PHP Manual MySQL Manual Smarty Manual PEAR Manual PHP-GTK Manual Symfony Manual
Code Snippets
Authentication Database Graphics HTTP Miscellaneous Time/Date
Affiliates
Scripts TutorialMan TutorialGuide CodingForums.com PHP Scripts Cheap Web Hosting Affordable Web Hosting

Search This Site :     PHP Function Reference :
 

Image CAPTCHA Doesn't Work, Use Text

By admin (2007-03-04. 3033 views.)
There has been significant development using readily available tools to overcome image CAPTCHA methods very reliably (90%+). This tutorial shows how to use simple text instead.

In the phpBB world, the standard registration form allows for image verification. If any of you have used this you know you will still get pounded daily with spam programs that overcome the image verification quite easily.

TextConfirmation developed by http://bbantispam.com/tc/ is an phpBB add-in that uses a random text response question that overcomes autmomated bots.

This code provides a standardized set of routines to provide text confirmation on any PHP form.

First the MYSQL database, we have 2 tables (see Listing 1):
1) ov_question - contains the questions to ask
2) ov_answer - the possible answers to each question

Listing 1. ov.sql


CREATE TABLE ov_question (
question_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
question VARCHAR(100) NOT NULL,
PRIMARY KEY(question_id)
);

CREATE TABLE ov_answer (
answer_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
question_id INTEGER UNSIGNED NOT NULL,
answer VARCHAR(100) NOT NULL,
PRIMARY KEY(answer_id),
INDEX Index_2(question_id)
);

-- sample questions and answers
INSERT INTO ov_question (question) VALUES('Enter the name of a day of the week');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'sunday');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'monday');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'tuesday');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'wednesday');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'thursday');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'friday');
INSERT INTO ov_answer (question_id, answer) VALUES(1, 'saturday');

INSERT INTO ov_question (question) VALUES('Enter a number greater than 5 and less than 8');
INSERT INTO ov_answer (question_id, answer) VALUES(2, '6');
INSERT INTO ov_answer (question_id, answer) VALUES(2, '7');

INSERT INTO ov_question (question) VALUES('How much is 2 plus 2?');
INSERT INTO ov_answer (question_id, answer) VALUES(3, '4');


So, we need a couple of access points:
1) get a question to ask, should be random amongst the set
2) see if the answer provided was valid
3) for management of the set, get and replace the entirety

These functions are provided in Listing 2 (ov.php):

<?php

// ==================================================================
//  Author: Dan Toomey(info@oxyscripts.com)
//    Web:     http://oxyscripts.com
//    Name:     oxyscripts_verify
//     Desc:     Class to test whether a human is filling out a form
//
//  Please send me a mail telling me what you think of oxyscripts_verify
//  and what your using it for or post on the forum
//
// ==================================================================

// ==================================================================
//    oxscripts_verify Constants
define("OV_VERSION","1.00");
define("OV""http://www.oxyscripts.com/item-1159.html");

// ==================================================================
//    The Main Class

class oxyscripts_verify {

    var 
$number_of_questions 0;            //how many questions are in the system
    
var $question_id 0;                    //question asked
    
var $debug 0;                            //echo arguments
    
var $errors 0;                        //show error messages
    
var $last_error "";                    //last error message
    
var $dbh;                                //database handle/link
    
    /**
    *    constructor
    *
    *    @access    public
    *    @param    $dbuser        string    database username
    *            $dbpassword    string    database password
    *            $dbname        string    database name
    *            $dbhost        string    database server
    */
    
function oxyscripts_verify($dbuser$dbpassword$dbname$dbhost) {
        if (
$this->debug) {
            echo 
"username = " $dbuser "<br/>" .
                
"psw = " $dbpassword "<br/>" .
                
"name = " $dbname "<br/>" .
                
"host = " $dbhost "<br/>";
        }        
        
$this->dbh = @mysql_connect($dbhost,$dbuser,$dbpassword);        
        if ( ! 
$this->dbh )
            
$this->print_error(0,"<ol><b>Error establishing a database connection!</b><li>Are you sure you have the correct user/password?<li>Are you sure that you have typed the correct hostname?<li>Are you sure that the database server is running?</ol>");            
        if ( !@
mysql_select_db($dbname,$this->dbh)) 
            
$this->print_error(0,"<ol><b>Error selecting database $dbname!</b><li>Are you sure it exists?<li>Are you sure there is a valid database connection?</ol>");
    }

    
    function 
__destruct(){
        if (
$this->dbh) {
            
//free database @mysql_close();
        
}
    }

    
    function 
print_error($query=0$error=0) {
        if (
$this->errors) {
            if (
$query)
                echo 
$query;
            if (
$this->dbh)
                echo @
mysql_error($dbh);
            if (
$error)
                echo 
$error;
        }
        
$this->last_error $error;
        die;
    }

    
    
/**
    *    pick a question for your form
    *
    *    @access    public
    *    @return                string    question to ask user on form
    */
    
function pick() {
        
//determine how many questions are in system
        
if ($this->number_of_questions==0) {
            
$query "SELECT COUNT(*) 
                        FROM ov_question"
;
            
$this->result = @mysql_query($query,$this->dbh);
            if (! 
$this->result)
                
$this->print_error($query,0);
            
$row = @mysql_fetch_row($this->result);
            
$this->number_of_questions $row[0];
            @
mysql_free_result($this->result);
            if (
$this->debug)
                echo 
"number of questions=" $this->number_of_questions "<br/>";
            if (
$this->number_of_questions==0)
                
$this->print_error($query,"No questions found?");
        }
        
        
//pick one
        
srand((double)microtime()*1000000);  
        
$this->question_id rand(1,$this->number_of_questions);
        if (
$this->debug)
            echo 
"picked question # = $this->question_id<br/>";
        
        
//grab it
        
$query "SELECT question 
                    FROM ov_question 
                    WHERE question_id = $this->question_id"
;
        
$this->result = @mysql_query($query,$this->dbh);
        if (! 
$this->result)
            
$this->print_error($query,0);        
        
$row = @mysql_fetch_row($this->result);
        
$question $row[0];
        @
mysql_free_result($this->result);
        
        return 
$question;
    }

    
    
/**
    *    validate a response to a question
    *
    *    @access    public
    *    @param    $question_id    int
    *            $response        string    the answer the user typed in
    *    @return                boolean    true if answer is valid
    */    
    
function validate($response) {
        
$query "SELECT COUNT(*) 
                    FROM ov_answer
                    WHERE question_id = $this->question_id
                    AND answer = '" 
$response "'";
        
$this->result = @mysql_query($query,$this->dbh);
        if (! 
$this->result)
            
$this->print_error($query,0);        
        
$row = @mysql_fetch_row($this->result);
        @
mysql_free_result($this->result);
        return 
$row[0];
    }
    
    
    
/**
    *    update the entire database set
    *
    *    @access    public
    *    @param    $questions        complex array    each element contains array with:
    *                                    'question'
    *                                    'answers' array
    */
    
function put($questions) {
        
//reset tables
        
$query "TRUNCATE TABLE ov_question";
        
$this->result = @mysql_query($query,$this->dbh);
        
        
$query "TRUNCATE TABLE ov_answer";
        
$this->result = @mysql_query($query,$this->dbh);
        if (! 
$this->result)
            
$this->print_error($query,0);        

        
//for each question
        
$this->number_of_questions 0;
        foreach(
$questions as $question_info) {
        
            
//add the question
            
$question $question_info['question'];
            
$query "INSERT INTO ov_question (question) VALUES('" $question "')";
            
$this->result = @mysql_query($query,$this->dbh);
            if (! 
$this->result)
                
$this->print_error($query,0);            
            
$question_id = @mysql_insert_id($this->dbh);
        
            
//add the answers
            
$answers $question_info['answers'];
            foreach(
$answers as $answer) {
                
$query "INSERT INTO ov_answer (question_id, answer) VALUES($question_id, '" $answer "')";
                
$this->result = @mysql_query($query,$this->dbh);
                if (! 
$this->result)
                    
$this->print_error($query,0);                            
            }
            
            
$this->number_of_questions++;
        }
    }
    
    
    
/**
    *    retrieve the entire database set
    *
    *    @access    public
    *    @return    $questions        complex array    each element contains array with:
    *                                    'question'
    *                                    'answers' array    
    */
    
function get() {
        
//get the whole thing at once
        
$query "SELECT ov_question.question_id, question, answer
                    FROM ov_question, ov_answer
                    WHERE ov_question.question_id = ov_answer.question_id
                    ORDER BY ov_question.question_id, answer"
;
        
$this->result = @mysql_query($query,$this->dbh);
        if (! 
$this->result)
            
$this->print_error($query,0);        
        
        
//setup variables so they exist out of loop scope
        
$questions = array();
        
$last_question_id 0;
        
$answers = array();
        
$question_info = array();
        
        
//walk through every row
        
while($row = @mysql_fetch_assoc($this->result)) {
            
//break out columns
            
$question_id $row['question_id'];
            
$question $row['question'];
            
$answer $row['answer'];
            
            
//start a new question
            
if ($question_id != $last_question_id) {
                
//save last set off
                
if ($last_question_id!=0) {
                    
$question_info['answers'] = $answers;
                    
$questions[] = $question_info;
                }
                
                
//start a new one
                
$question_info = array();
                
$question_info['question_id'] = $question_id;
                
$question_info['question'] = $question;
                
$answers = array();
                
                
//rem where we are
                
$last_question_id $question_id;
            }
            
            
//add in this answer
            
$answers[] = $answer;    
        }
        
//save off last one
        
$question_info['answers'] = $answers;
        
$questions[] = $question_info;
        
        @
mysql_free_result($this->result);
        
        return 
$questions;
    }
}

?>


This is all wrapped in an object, oxscripts_verify. The constructor needs the database credentials to access the database.

The pick() function selects a random question and returns the question to ask. A public member, $ov->question_id, contains the id of the question. The idea is you would either store question_id in a hidden form variable or in a session variable for later confirmation.

Example using pick:

<?php

$ov 
= new oxyscripts_verify(OV_DB_USEROV_DB_PASSWORDOV_DB_NAMEOV_DB_HOST);
$q $ov->pick();

?>


The validate() function tests whether the response provided matches any of the possible answers to the question being asked, returns 0 or 1=correct. Example:

<?php

$ov 
= new oxyscripts_verify(OV_DB_USEROV_DB_PASSWORDOV_DB_NAMEOV_DB_HOST);
$ov->question_id $question_id//probably from a hidden form field
$test $ov->validate('ok');
//do something with the result

?>


The get() function returns a complex array where every element looks like:
- question_id
- question
- answers[]

The put function takes the same array and updates the database with the question set.

The get and put functions would be used by a maintenance program to update the questions used in the system. A later tutorial will provide a smarty version of this maintenance.
 

 
   Print this page

Top Sponsor
Symantec\'s Norton SystemWorks 2006
Sponsors
CA
Sponsors
AdWords Dominator 125*125
Advertisting


Affiliates
VertexTemplates PHPFreaks CodeWalkers StarGeek DevScripts CGI & PHP Scripts PHP CMS Free Templates

Shopping Rebates   Sell It 4 You   Flash Page Counters   Get Insured
GPS Tracking Service   Charity Donate Info   Web Site Hosting   VOIP Service

Privacy Policy | Links | Site Map | Advertising

All content on OxyScripts.com is (©)2002-2007

 
Powered by Adrastea - Version 1.0.0. Copyright © Rune Solutions, 2004-2005