PHP Guestbook with using math captcha
Today I will tell you how to create your own guestbook with spam protection system – math captcha. This will and easy for your members and also good new protection from bots. In our guestbook we will use mySQL to store records.
Step 1. SQL
Firstly – we should prepare SQL table to store records of our guestbook. Execute next SQL:
CREATE TABLE `s_guestbook` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(16) NOT NULL default '',
`name` varchar(32) NOT NULL default '',
`message` text NOT NULL,
`when` INT(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
We will be storing IP of sender, his name, message itself, and time of adding post (timestamp)
Step 2. CSS
Here are used CSS styles. Just few styles for our demo page:
css/main.css
body{background:#eee;font-family:Verdana, Helvetica, Arial, sans-serif;margin:0;padding:0}
.example{background:#FFF;width:625px;font-size:80%;border:1px #000 solid;margin:3.5em auto 2em;padding:1em 2em 2em}
.post {border:1px #DDD dashed;margin:5px;padding:5px;font-size:11px;width:95%}
.example form div{margin-bottom:5px;}
Step 3. PHP
Ok, here are all used PHP file:
index.php
<?php
// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
error_reporting(E_ALL & ~E_NOTICE);
require_once('inc/guestbook.inc.php');
$oGuestbook = new Guestbook();
$sRes = '<h2>You can add your post here</h2>';
if ($_POST['post'] != '' && $_POST['name'] != '' && $_POST['captcha'] != '') { // if something posted
$iCaptcha = (int)$_POST['captcha'];
$iCaptchaHash = md5($iCaptcha);
session_start();
$iOldCaptchaHash = $_SESSION['captcha_res'];
if ($iCaptchaHash == $iOldCaptchaHash) { // perform posting
$oGuestbook->addPost($_POST['name'], $_POST['post']);
$sRes = '<h2>Your post successfully posted</h2>';
} else {
$sRes = '<h2>Captcha incorrect</h2>';
}
}
list($sQuestion, $iRes) = $oGuestbook->getMathCaptcha();
$sPosts = $oGuestbook->getAllPosts();
// our page template
$sPageCode = <<<EOF
<link rel="stylesheet" href="css/main.css" type="text/css" />
<div class="example">
<h3><a href="#">PHP Guestbook with using math captcha</a></h3>
<div>
<div style="margin-bottom:10px;">
<h4>{result}</h4>
<form method="post" action="index.php">
<div>Your name:</div>
<div><input type="text" name="name" value="" /></div>
<div>Your guestbook post:</div>
<div><textarea name="post"></textarea></div>
<div>Captcha:</div>
<div>{captcha}</div>
<div>Verification (Type what you see):</div>
<div><input type="text" name="captcha" value="" /></div>
<div><input type="submit" name="submit" value="Submit" /></div>
</form>
</div>
<div>
<h4>Other Guestbook posts</h4>
{guestbook_posts}
</div>
</div>
</div>
EOF;
$aReplaces = array(
'{captcha}' => $sQuestion,
'{result}' => $sRes,
'{guestbook_posts}' => $sPosts,
);
echo strtr($sPageCode, $aReplaces);
?>
This file draw us posting form with math captcha, also it checking typed posted captcha value, and if all fine – then allow to add post. Also, as you noticed, I started using ‘strtr’ function in generation of result HTML code. Very easy to replace keys to values in template file via array of replaces.
inc/guestbook.inc.php
<?php
// guestbook class
class Guestbook {
// DB variables
var $sDbName;
var $sDbUser;
var $sDbPass;
// constructor
function Guestbook() {
$this->sDbName = 'DB_NAME';
$this->sDbUser = 'DB_USER';
$this->sDbPass = 'DB_PASS';
}
// adding to DB table posted record
function addPost($sNameUnsafe = '', $sPostUnsafe = '') {
if ($sPostUnsafe != '') {
$vLink = mysql_connect('localhost', $this->sDbUser, $this->sDbPass); // the host, name, and password for your mysql
mysql_select_db($this->sDbName); // select the database
$sName = mysql_real_escape_string(strip_tags($sNameUnsafe));
$sMessage = mysql_real_escape_string(strip_tags($sPostUnsafe));
$iVisitorIp = $this->getVisitorIp();
if ($sMessage != '' && $iVisitorIp)
mysql_query("INSERT INTO `s_guestbook` SET `ip`='{$iVisitorIp}', `name`='{$sName}', `message`='{$sMessage}', `when`=UNIX_TIMESTAMP()");
mysql_close($vLink);
}
}
function getAllPosts() {
$vLink = mysql_connect('localhost', $this->sDbUser, $this->sDbPass);
mysql_select_db($this->sDbName); // select the database
$vRes = mysql_query('SELECT * FROM `s_guestbook` ORDER BY `id` DESC LIMIT 15'); // returning the last 15 posts
$sMessages = '';
if ($vRes) {
while($aMessages = mysql_fetch_array($vRes)) {
$sWhen = date('H:i:s', $aMessages['when']);
$sMessages .= '<div class="post">' . $aMessages['name'] . ': ' . $aMessages['message'] . '<span> (' . $sWhen . ')</span></div>';
}
} else {
$sMessages = 'DB error, create SQL table before';
}
mysql_close($vLink);
return $sMessages;
}
function getMathCaptcha() {
$aOps = array('+', '-', '*'); // possible operators
$iVal1 = rand(1,10); // first variable
$iVal2 = rand(1,10); // second variable
$i = array_rand($aOps, 1); // random operator index
$sRandOp = $aOps[$i]; // random operator
$sQuestion = "{$iVal1} {$sRandOp} {$iVal2}"; // generation of question
$sQuestionEval = "\$iRes = {$iVal1} {$sRandOp} {$iVal2};";
eval($sQuestionEval);
session_start();
$sHashRes = md5($iRes);
$_SESSION['captcha_res'] = $sHashRes; // store md5 result in session param
return array($sQuestion, $iRes);
}
function getVisitorIp() {
$ip = '0.0.0.0';
if ((isset($_SERVER['HTTP_X_FORWARDED_FOR'])) && (! empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif ((isset($_SERVER['HTTP_CLIENT_IP'])) && (! empty($_SERVER['HTTP_CLIENT_IP']))) {
$ip = explode('.',$_SERVER['HTTP_CLIENT_IP']);
$ip = $ip[3].'.'.$ip[2].'.'.$ip[1].'.'.$ip[0];
} elseif ((! isset($_SERVER['HTTP_X_FORWARDED_FOR'])) || (empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
if ((! isset($_SERVER['HTTP_CLIENT_IP'])) && (empty($_SERVER['HTTP_CLIENT_IP']))) {
$ip = $_SERVER['REMOTE_ADDR'];
}
}
return $ip;
}
}
?>
This is library class for our Guestbook. It contain several necessary functions: addPost – for adding new posts, getAllPosts – return us last 15 records from database, getMathCaptcha – get math capthca, getVisitorIp – get visitor IP (which we will storing for records)
Conclusion
I hope that made interesting sample today, its contain two interesting ideas – creating Guestbook itself plus Math captcha to protect from bots. Good luck!