Skip to content

Instantly share code, notes, and snippets.

@Shaz3e
Created February 12, 2014 19:37
Show Gist options
  • Save Shaz3e/8962955 to your computer and use it in GitHub Desktop.
Save Shaz3e/8962955 to your computer and use it in GitHub Desktop.
Image Less CAPTCHA with PHP
<?php
session_start();
if (isset($_POST['submit'])){
$number = floatval($_POST['number']);
if ($number != $_SESSION['correctNumber']) {
$message = "<br /><span class='errors'>The number you entered for the spam filter is incorrect.</span><br />";
}else{
$message = "<br /><span class='success'>CAPTCHA Verified!!!</span><br />";
}
}else{
$message = '';
}
// include the class
include "imagelessCaptcha.php";
// implement imageless
$imgLess = new imagelessCaptcha();
$CaptchaPhrase = $imgLess->formPhrase();
$correctNumber = $imgLess->getInt();
$_SESSION['correctNumber'] = $correctNumber;
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Image less CAPTCHA</title>
<link href="style.css" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<div class="container"><?php echo $message; ?><br />
<form action="index.php" method="post">
<label class="highlight"><span><?php echo $CaptchaPhrase; ?></span></label><br />
<input type="number" name="number" step="0.1" class="inputbox" />
<input type="submit" value="Send" name="submit" class="button" />
</form>
</div>
</body>
</html>
<?php
/*
IMAGELESS CAPTCHA
*/
class imagelessCaptcha {
// set preferences
private $prefs = array(
'num_digits' => 3, // 1 - 4
'use_decimal' => true, // adds a decimal to the number
'decimal_chance' => true // makes whether a decimal is added random
);
// word arrays for phrase construction
private $ones = array('', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
private $teens = array('ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
private $tens = array('', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety');
private $phraseBeginning = array('How is ', 'What is ');
// create a number based on prefs
public $number;
function __construct() {
$min = pow(10, $this->prefs['num_digits'] - 1);
$max = pow(10, $this->prefs['num_digits']) -1;
$this->number = mt_rand($min, $max);
}
// form word phrase for tens digits
private function formTens($num, $and = false) {
$num = intval($num);
if ($num < 10) {
if ($num == 0) $and = false;
$phrase = $this->ones[$num];
}
else if ($num < 20) {
$phrase = $this->teens[$num-10];
}
else {
$digitTens = substr($num, 0, 1);
$digitOnes = substr($num, 1, 1);
if ($digitOnes != 0) {
$phrase = $this->tens[$digitTens].'-'.$this->ones[$digitOnes];
} else {
$phrase = $this->tens[$digitTens];
}
}
if ($and) $phrase = ' and '.$phrase;
return $phrase;
}
// create the number phrase
public function formPhrase() {
if ($this->number < 100) {
$phrase = $this->formTens($this->number);
}
else if ($this->number < 1000) {
$phrase = $this->ones[substr($this->number, 0, 1)].'-hundred ';
$phrase .= $this->formTens(substr($this->number, 1, 2), true);
}
else if ($number < 10000) {
$phrase = $this->ones[substr($this->number, 0, 1)].'-thousand ';
$hundreds = substr($this->number, 1, 1);
if ($hundreds > 0) $phrase .= $this->ones[$hundreds].'-hundred ';
$phrase .= $this->formTens(substr($this->number, 2, 2), true);
}
// decimal
if ($this->prefs['use_decimal'] == true) {
if ($this->prefs['decimal_chance'] == true) {
$useDecimal = mt_rand(0, 1);
if ($useDecimal) {
$dec = mt_rand(1, 9);
$this->number = $this->number + ($dec *.1);
$phrase .= ' point '.$this->ones[$dec];
}
} else {
$dec = mt_rand(1, 9);
$this->number = $this->number + ($dec *.1);
$phrase .= ' point '.$this->ones[$dec];
}
}
// randomize beginning of phrase, throw off parsers
$start = mt_rand(0, count($this->phraseBeginning)-1);
// final phrase
return $this->phraseBeginning[$start].$phrase.' written as a number?';
}
// return the int
public function getInt() {
return $this->number;
}
}
.inputbox{
display: inline-block;
width: 50%;
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.428571429;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
.inputbox:focus{
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
}
.button{
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: normal;
line-height: 1.428571429;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
border-color: #ccc;
}
.button:hover,.button:focus{
color: #333;
text-decoration: none;
background-color: #e0e0e0;
background-position: 0 -15px;
}
.button:focus{
outline: thin dotted;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.button:active{
background-image: none;
outline: 0;
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
background-image: none;
background-color: #e0e0e0;
border-color: #dbdbdb;
}
.container{
margin-left:auto;
margin-right:auto;
width:625px;
}
.highlight {
background:rgba(255,240,0,.2);
padding:0.5em;
}
.errors {
padding:20px 20px 20px 40px;
background: rgba(255, 0, 0, .2);
-webkit-border-radius:6px;
-moz-border-radius:6px;
border-radius:6px;
}
.success {
padding:20px;
background: rgba(0, 255, 0, .2);
-webkit-border-radius:6px;
-moz-border-radius:6px;
border-radius:6px;
list-style-type:none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment