Gentics Portal.Node PHP API
 All Classes Namespaces Functions Variables Pages
Public Member Functions | Static Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
Securimage Class Reference

Public Member Functions

 __construct ($options=array())
 show ($background_image= '')
 check ($code)
 outputAudioFile ()
 getCode ($array=false)
 getRandomNoiseFile ()
 frand ()
 errorHandler ($errno, $errstr, $errfile= '', $errline=0, $errcontext=array())

Static Public Member Functions

static getPath ()
static getCaptchaId ($new=true, array $options=array())
static checkByCaptchaId ($id, $value)

Public Attributes

const SI_IMAGE_JPEG = 1
const SI_IMAGE_PNG = 2
const SI_IMAGE_GIF = 3
const SI_CAPTCHA_STRING = 0
const SI_CAPTCHA_MATHEMATIC = 1
 $image_width = 215
 $image_height = 80
 $image_type = self::SI_IMAGE_PNG
 $image_bg_color = '#ffffff'
 $text_color = '#707070'
 $line_color = '#707070'
 $noise_color = '#707070'
 $text_transparency_percentage = 50
 $use_transparent_text = false
 $code_length = 6
 $case_sensitive = false
 $charset = 'ABCDEFGHKLMNPRSTUVWYZabcdefghklmnprstuvwyz23456789'
 $expiry_time = 900
 $session_name = null
 $use_wordlist = false
 $perturbation = 0.75
 $num_lines = 8
 $noise_level = 0
 $image_signature = ''
 $signature_color = '#707070'
 $signature_font
 $use_sqlite_db = false
 $captcha_type = self::SI_CAPTCHA_STRING
 $namespace
 $ttf_file
 $wordlist_file
 $background_directory
 $sqlite_database
 $audio_path
 $audio_noise_path
 $audio_use_noise
 $audio_mix_normalization = 0.6
 $degrade_audio
 $audio_gap_min = 0
 $audio_gap_max = 600

Protected Member Functions

 doImage ()
 allocateColors ()
 setBackground ()
 getBackgroundFromDirectory ()
 createCode ()
 drawWord ()
 distortedCopy ()
 drawLines ()
 drawNoise ()
 addSignature ()
 output ()
 getAudibleCode ()
 readCodeFromFile ()
 generateCode ()
 validate ()
 saveData ()
 saveCodeToDatabase ()
 openDatabase ()
 getCodeFromDatabase ()
 clearCodeFromDatabase ()
 purgeOldCodesFromDatabase ()
 isCodeExpired ($creation_time)
 generateWAV ($letters)
 audioError ()
 canSendHeaders ()
 initColor ($color, $default)

Protected Attributes

 $im
 $tmpimg
 $bgimg
 $iscale = 5
 $securimage_path = null
 $code
 $code_display
 $display_value
 $captcha_code
 $no_exit
 $no_session
 $send_headers
 $sqlite_handle
 $gdbgcolor
 $gdtextcolor
 $gdlinecolor
 $gdsignaturecolor

Static Protected Attributes

static $_captchaId = null

Detailed Description

Definition at line 150 of file securimage.php.

Constructor & Destructor Documentation

Securimage::__construct (   $options = array())

Create a new securimage object, pass options to set in the constructor.
This can be used to display a captcha, play an audible captcha, or validate an entry

Parameters
array$options $options = array( 'text_color' => new Securimage_Color('#013020'), 'code_length' => 5, 'num_lines' => 5, 'noise_level' => 3, 'font_file' => Securimage::getPath() . '/custom.ttf' );

$img = new Securimage($options);

Definition at line 507 of file securimage.php.

References initColor().

{
$this->securimage_path = dirname(__FILE__);
if (is_array($options) && sizeof($options) > 0) {
foreach($options as $prop => $val) {
if ($prop == 'captchaId') {
Securimage::$_captchaId = $val;
$this->use_sqlite_db = true;
} else {
$this->$prop = $val;
}
}
}
$this->image_bg_color = $this->initColor($this->image_bg_color, '#ffffff');
$this->text_color = $this->initColor($this->text_color, '#616161');
$this->line_color = $this->initColor($this->line_color, '#616161');
$this->noise_color = $this->initColor($this->noise_color, '#616161');
$this->signature_color = $this->initColor($this->signature_color, '#616161');
if (is_null($this->ttf_file)) {
$this->ttf_file = $this->securimage_path . '/AHGBold.ttf';
}
$this->signature_font = $this->ttf_file;
if (is_null($this->wordlist_file)) {
$this->wordlist_file = $this->securimage_path . '/words/words.txt';
}
if (is_null($this->sqlite_database)) {
$this->sqlite_database = $this->securimage_path . '/database/securimage.sqlite';
}
if (is_null($this->audio_path)) {
$this->audio_path = $this->securimage_path . '/audio/';
}
if (is_null($this->audio_noise_path)) {
$this->audio_noise_path = $this->audio_path . '/noise/';
}
if (is_null($this->audio_use_noise)) {
$this->audio_use_noise = true;
}
if (is_null($this->degrade_audio)) {
$this->degrade_audio = true;
}
if (is_null($this->code_length) || (int)$this->code_length < 1) {
$this->code_length = 6;
}
if (is_null($this->perturbation) || !is_numeric($this->perturbation)) {
$this->perturbation = 0.75;
}
if (is_null($this->namespace) || !is_string($this->namespace)) {
$this->namespace = 'default';
}
if (is_null($this->no_exit)) {
$this->no_exit = false;
}
if (is_null($this->no_session)) {
$this->no_session = false;
}
#$this->no_session = true;
if (is_null($this->send_headers)) {
$this->send_headers = true;
}
if ($this->no_session != true) {
// Initialize session or attach to existing
if ( session_id() == '' ) { // no session has been started yet, which is needed for validation
if (!is_null($this->session_name) && trim($this->session_name) != '') {
session_name(trim($this->session_name)); // set session name if provided
}
session_start();
}
}
}

Member Function Documentation

Securimage::addSignature ( )
protected

Print signature text on image

Definition at line 1203 of file securimage.php.

Referenced by doImage().

{
$bbox = imagettfbbox(10, 0, $this->signature_font, $this->image_signature);
$textlen = $bbox[2] - $bbox[0];
$x = $this->image_width - $textlen - 5;
$y = $this->image_height - 3;
imagettftext($this->im, 10, 0, $x, $y, $this->gdsignaturecolor, $this->signature_font, $this->image_signature);
}
Securimage::allocateColors ( )
protected

Allocate the colors to be used for the image

Definition at line 871 of file securimage.php.

Referenced by doImage().

{
// allocate bg color first for imagecreate
$this->gdbgcolor = imagecolorallocate($this->im,
$this->image_bg_color->r,
$this->image_bg_color->g,
$this->image_bg_color->b);
$alpha = intval($this->text_transparency_percentage / 100 * 127);
if ($this->use_transparent_text == true) {
$this->gdtextcolor = imagecolorallocatealpha($this->im,
$this->text_color->r,
$this->text_color->g,
$this->text_color->b,
$alpha);
$this->gdlinecolor = imagecolorallocatealpha($this->im,
$this->line_color->r,
$this->line_color->g,
$this->line_color->b,
$alpha);
$this->gdnoisecolor = imagecolorallocatealpha($this->im,
$this->noise_color->r,
$this->noise_color->g,
$this->noise_color->b,
$alpha);
} else {
$this->gdtextcolor = imagecolorallocate($this->im,
$this->text_color->r,
$this->text_color->g,
$this->text_color->b);
$this->gdlinecolor = imagecolorallocate($this->im,
$this->line_color->r,
$this->line_color->g,
$this->line_color->b);
$this->gdnoisecolor = imagecolorallocate($this->im,
$this->noise_color->r,
$this->noise_color->g,
$this->noise_color->b);
}
$this->gdsignaturecolor = imagecolorallocate($this->im,
$this->signature_color->r,
$this->signature_color->g,
$this->signature_color->b);
}
Securimage::audioError ( )
protected

Return a wav file saying there was an error generating file

Returns
string The binary audio contents

Definition at line 1678 of file securimage.php.

Referenced by outputAudioFile().

{
return @file_get_contents(dirname(__FILE__) . '/audio/error.wav');
}
Securimage::canSendHeaders ( )
protected

Checks to see if headers can be sent and if any error has been output to the browser

Returns
bool true if headers haven't been sent and no output/errors will break audio/images, false if unsafe

Definition at line 1688 of file securimage.php.

Referenced by output(), and outputAudioFile().

{
if (headers_sent()) {
// output has been flushed and headers have already been sent
return false;
} else if (strlen((string)ob_get_contents()) > 0) {
// headers haven't been sent, but there is data in the buffer that will break image and audio data
return false;
}
return true;
}
Securimage::check (   $code)

Check a submitted code against the stored value

Parameters
string$codeThe captcha code to check $code = $_POST['code']; $img = new Securimage(); if ($img->check($code) == true) { $captcha_valid = true; } else { $captcha_valid = false; }

Definition at line 698 of file securimage.php.

References validate().

{
$this->code_entered = $code;
$this->validate();
return $this->correct_code;
}
static Securimage::checkByCaptchaId (   $id,
  $value 
)
static

Validate a captcha code input against a captcha ID

Parameters
string$idThe captcha ID to check
string$valueThe captcha value supplied by the user
Returns
bool true if the code was valid for the given captcha ID, false if not or if database failed to open

Definition at line 636 of file securimage.php.

{
$si = new self(array('captchaId' => $id,
'no_session' => true,
'use_sqlite_db' => true));
if ($si->openDatabase()) {
$code = $si->getCodeFromDatabase();
if (is_array($code)) {
$si->code = $code['code'];
$si->code_display = $code['code_disp'];
}
if ($si->check($value)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
Securimage::clearCodeFromDatabase ( )
protected

Remove an entered code from the database

Definition at line 1521 of file securimage.php.

Referenced by validate().

{
if (is_resource($this->sqlite_handle)) {
$ip = $_SERVER['REMOTE_ADDR'];
$ns = sqlite_escape_string($this->namespace);
sqlite_query($this->sqlite_handle, "DELETE FROM codes WHERE ip = '$ip' AND namespace = '$ns'");
}
}
Securimage::createCode ( )
protected

Generates the code or math problem and saves the value to the session

Definition at line 992 of file securimage.php.

References generateCode(), readCodeFromFile(), and saveData().

Referenced by doImage(), and getAudibleCode().

{
$this->code = false;
switch($this->captcha_type) {
case self::SI_CAPTCHA_MATHEMATIC:
{
do {
$signs = array('+', '-', 'x');
$left = rand(1, 10);
$right = rand(1, 5);
$sign = $signs[rand(0, 2)];
switch($sign) {
case 'x': $c = $left * $right; break;
case '-': $c = $left - $right; break;
default: $c = $left + $right; break;
}
} while ($c <= 0); // no negative #'s or 0
$this->code = $c;
$this->code_display = "$left $sign $right";
break;
}
default:
{
if ($this->use_wordlist && is_readable($this->wordlist_file)) {
$this->code = $this->readCodeFromFile();
}
if ($this->code == false) {
$this->code = $this->generateCode($this->code_length);
}
$this->code_display = $this->code;
$this->code = ($this->case_sensitive) ? $this->code : strtolower($this->code);
} // default
}
$this->saveData();
}
Securimage::distortedCopy ( )
protected

Copies the captcha image to the final image with distortion applied

Definition at line 1076 of file securimage.php.

References frand().

Referenced by doImage().

{
$numpoles = 3; // distortion factor
// make array of poles AKA attractor points
for ($i = 0; $i < $numpoles; ++ $i) {
$px[$i] = rand($this->image_width * 0.2, $this->image_width * 0.8);
$py[$i] = rand($this->image_height * 0.2, $this->image_height * 0.8);
$rad[$i] = rand($this->image_height * 0.2, $this->image_height * 0.8);
$tmp = ((- $this->frand()) * 0.15) - .15;
$amp[$i] = $this->perturbation * $tmp;
}
$bgCol = imagecolorat($this->tmpimg, 0, 0);
$width2 = $this->iscale * $this->image_width;
$height2 = $this->iscale * $this->image_height;
imagepalettecopy($this->im, $this->tmpimg); // copy palette to final image so text colors come across
// loop over $img pixels, take pixels from $tmpimg with distortion field
for ($ix = 0; $ix < $this->image_width; ++ $ix) {
for ($iy = 0; $iy < $this->image_height; ++ $iy) {
$x = $ix;
$y = $iy;
for ($i = 0; $i < $numpoles; ++ $i) {
$dx = $ix - $px[$i];
$dy = $iy - $py[$i];
if ($dx == 0 && $dy == 0) {
continue;
}
$r = sqrt($dx * $dx + $dy * $dy);
if ($r > $rad[$i]) {
continue;
}
$rscale = $amp[$i] * sin(3.14 * $r / $rad[$i]);
$x += $dx * $rscale;
$y += $dy * $rscale;
}
$c = $bgCol;
$x *= $this->iscale;
$y *= $this->iscale;
if ($x >= 0 && $x < $width2 && $y >= 0 && $y < $height2) {
$c = imagecolorat($this->tmpimg, $x, $y);
}
if ($c != $bgCol) { // only copy pixels of letters to preserve any background image
imagesetpixel($this->im, $ix, $iy, $c);
}
}
}
}
Securimage::doImage ( )
protected

The main image drawing routing, responsible for constructing the entire image and serving it

Definition at line 800 of file securimage.php.

References addSignature(), allocateColors(), createCode(), distortedCopy(), drawLines(), drawNoise(), drawWord(), getCaptchaId(), getCodeFromDatabase(), openDatabase(), output(), and setBackground().

Referenced by show().

{
if( ($this->use_transparent_text == true || $this->bgimg != '') && function_exists('imagecreatetruecolor')) {
$imagecreate = 'imagecreatetruecolor';
} else {
$imagecreate = 'imagecreate';
}
$this->im = $imagecreate($this->image_width, $this->image_height);
$this->tmpimg = $imagecreate($this->image_width * $this->iscale, $this->image_height * $this->iscale);
$this->allocateColors();
imagepalettecopy($this->tmpimg, $this->im);
$this->setBackground();
$code = '';
if ($this->getCaptchaId(false) !== null) {
// a captcha Id was supplied
// check to see if a display_value for the captcha image was set
if (is_string($this->display_value) && strlen($this->display_value) > 0) {
$this->code_display = $this->display_value;
$this->code = ($this->case_sensitive) ?
$this->display_value :
strtolower($this->display_value);
$code = $this->code;
} else if ($this->openDatabase()) {
// no display_value, check the database for existing captchaId
$code = $this->getCodeFromDatabase();
// got back a result from the database with a valid code for captchaId
if (is_array($code)) {
$this->code = $code['code'];
$this->code_display = $code['code_disp'];
$code = $code['code'];
}
}
}
if ($code == '') {
// if the code was not set using display_value or was not found in
// the database, create a new code
$this->createCode();
}
if ($this->noise_level > 0) {
$this->drawNoise();
}
$this->drawWord();
if ($this->perturbation > 0 && is_readable($this->ttf_file)) {
$this->distortedCopy();
}
if ($this->num_lines > 0) {
$this->drawLines();
}
if (trim($this->image_signature) != '') {
$this->addSignature();
}
$this->output();
}
Securimage::drawLines ( )
protected

Draws distorted lines on the image

Definition at line 1127 of file securimage.php.

References frand().

Referenced by doImage().

{
for ($line = 0; $line < $this->num_lines; ++ $line) {
$x = $this->image_width * (1 + $line) / ($this->num_lines + 1);
$x += (0.5 - $this->frand()) * $this->image_width / $this->num_lines;
$y = rand($this->image_height * 0.1, $this->image_height * 0.9);
$theta = ($this->frand() - 0.5) * M_PI * 0.7;
$w = $this->image_width;
$len = rand($w * 0.4, $w * 0.7);
$lwid = rand(0, 2);
$k = $this->frand() * 0.6 + 0.2;
$k = $k * $k * 0.5;
$phi = $this->frand() * 6.28;
$step = 0.5;
$dx = $step * cos($theta);
$dy = $step * sin($theta);
$n = $len / $step;
$amp = 1.5 * $this->frand() / ($k + 5.0 / $len);
$x0 = $x - 0.5 * $len * cos($theta);
$y0 = $y - 0.5 * $len * sin($theta);
$ldx = round(- $dy * $lwid);
$ldy = round($dx * $lwid);
for ($i = 0; $i < $n; ++ $i) {
$x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
$y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
imagefilledrectangle($this->im, $x, $y, $x + $lwid, $y + $lwid, $this->gdlinecolor);
}
}
}
Securimage::drawNoise ( )
protected

Draws random noise on the image

Definition at line 1164 of file securimage.php.

Referenced by doImage().

{
if ($this->noise_level > 10) {
$noise_level = 10;
} else {
$noise_level = $this->noise_level;
}
$t0 = microtime(true);
$noise_level *= 125; // an arbitrary number that works well on a 1-10 scale
$points = $this->image_width * $this->image_height * $this->iscale;
$height = $this->image_height * $this->iscale;
$width = $this->image_width * $this->iscale;
for ($i = 0; $i < $noise_level; ++$i) {
$x = rand(10, $width);
$y = rand(10, $height);
$size = rand(7, 10);
if ($x - $size <= 0 && $y - $size <= 0) continue; // dont cover 0,0 since it is used by imagedistortedcopy
imagefilledarc($this->tmpimg, $x, $y, $size, $size, 0, 360, $this->gdnoisecolor, IMG_ARC_PIE);
}
$t1 = microtime(true);
$t = $t1 - $t0;
/*
// DEBUG
imagestring($this->tmpimg, 5, 25, 30, "$t", $this->gdnoisecolor);
header('content-type: image/png');
imagepng($this->tmpimg);
exit;
*/
}
Securimage::drawWord ( )
protected

Draws the captcha code on the image

Definition at line 1038 of file securimage.php.

Referenced by doImage().

{
$width2 = $this->image_width * $this->iscale;
$height2 = $this->image_height * $this->iscale;
if (!is_readable($this->ttf_file)) {
imagestring($this->im, 4, 10, ($this->image_height / 2) - 5, 'Failed to load TTF font file!', $this->gdtextcolor);
} else {
if ($this->perturbation > 0) {
$font_size = $height2 * .4;
$bb = imageftbbox($font_size, 0, $this->ttf_file, $this->code_display);
$tx = $bb[4] - $bb[0];
$ty = $bb[5] - $bb[1];
$x = floor($width2 / 2 - $tx / 2 - $bb[0]);
$y = round($height2 / 2 - $ty / 2 - $bb[1]);
imagettftext($this->tmpimg, $font_size, 0, $x, $y, $this->gdtextcolor, $this->ttf_file, $this->code_display);
} else {
$font_size = $this->image_height * .4;
$bb = imageftbbox($font_size, 0, $this->ttf_file, $this->code_display);
$tx = $bb[4] - $bb[0];
$ty = $bb[5] - $bb[1];
$x = floor($this->image_width / 2 - $tx / 2 - $bb[0]);
$y = round($this->image_height / 2 - $ty / 2 - $bb[1]);
imagettftext($this->im, $font_size, 0, $x, $y, $this->gdtextcolor, $this->ttf_file, $this->code_display);
}
}
// DEBUG
//$this->im = $this->tmpimg;
//$this->output();
}
Securimage::errorHandler (   $errno,
  $errstr,
  $errfile = '',
  $errline = 0,
  $errcontext = array() 
)

Error handler used when outputting captcha image or audio. This error handler helps determine if any errors raised would prevent captcha image or audio from displaying. If they have no effect on the output buffer or headers, true is returned so the script can continue processing. See https://github.com/dapphp/securimage/issues/15

Parameters
int$errno
string$errstr
string$errfile
int$errline
array$errcontext
Returns
boolean true if handled, false if PHP should handle

Definition at line 1748 of file securimage.php.

{
// get the current error reporting level
$level = error_reporting();
// if error was supressed or $errno not set in current error level
if ($level == 0 || ($level & $errno) == 0) {
return true;
}
return false;
}
Securimage::frand ( )

Return a random float between 0 and 0.9999

Returns
float Random float between 0 and 0.9999

Definition at line 1706 of file securimage.php.

Referenced by distortedCopy(), and drawLines().

{
return 0.0001 * rand(0,9999);
}
Securimage::generateCode ( )
protected

Generates a random captcha code from the set character set

Definition at line 1330 of file securimage.php.

Referenced by createCode().

{
$code = '';
for($i = 1, $cslen = strlen($this->charset); $i <= $this->code_length; ++$i) {
$code .= $this->charset{rand(0, $cslen - 1)};
}
//return 'testing'; // debug, set the code to given string
return $code;
}
Securimage::generateWAV (   $letters)
protected

Generate a wav file given the $letters in the code

Todo:
Add ability to merge 2 sound files together to have random background sounds
Parameters
array$letters
Returns
string The binary contents of the wav file

Definition at line 1567 of file securimage.php.

Referenced by getAudibleCode().

{
$wavCaptcha = new WavFile();
$first = true; // reading first wav file
foreach ($letters as $letter) {
$letter = strtoupper($letter);
try {
$l = new WavFile($this->audio_path . '/' . $letter . '.wav');
if ($first) {
// set sample rate, bits/sample, and # of channels for file based on first letter
$wavCaptcha->setSampleRate($l->getSampleRate())
->setBitsPerSample($l->getBitsPerSample())
->setNumChannels($l->getNumChannels());
$first = false;
}
// append letter to the captcha audio
$wavCaptcha->appendWav($l);
// random length of silence between $audio_gap_min and $audio_gap_max
if ($this->audio_gap_max > 0 && $this->audio_gap_max > $this->audio_gap_min) {
$wavCaptcha->insertSilence( mt_rand($this->audio_gap_min, $this->audio_gap_max) / 1000.0 );
}
} catch (Exception $ex) {
// failed to open file, or the wav file is broken or not supported
// 2 wav files were not compatible, different # channels, bits/sample, or sample rate
throw $ex;
}
}
/********* Set up audio filters *****************************/
$filters = array();
if ($this->audio_use_noise == true) {
// use background audio - find random file
$noiseFile = $this->getRandomNoiseFile();
if ($noiseFile !== false && is_readable($noiseFile)) {
try {
$wavNoise = new WavFile($noiseFile, false);
} catch(Exception $ex) {
throw $ex;
}
// start at a random offset from the beginning of the wavfile
// in order to add more randomness
$randOffset = 0;
if ($wavNoise->getNumBlocks() > 2 * $wavCaptcha->getNumBlocks()) {
$randBlock = rand(0, $wavNoise->getNumBlocks() - $wavCaptcha->getNumBlocks());
$wavNoise->readWavData($randBlock * $wavNoise->getBlockAlign(), $wavCaptcha->getNumBlocks() * $wavNoise->getBlockAlign());
} else {
$wavNoise->readWavData();
$randOffset = rand(0, $wavNoise->getNumBlocks() - 1);
}
$mixOpts = array('wav' => $wavNoise,
'loop' => true,
'blockOffset' => $randOffset);
$filters[WavFile::FILTER_MIX] = $mixOpts;
$filters[WavFile::FILTER_NORMALIZE] = $this->audio_mix_normalization;
}
}
if ($this->degrade_audio == true) {
// add random noise.
// any noise level below 95% is intensely distorted and not pleasant to the ear
$filters[WavFile::FILTER_DEGRADE] = rand(95, 98) / 100.0;
}
if (!empty($filters)) {
$wavCaptcha->filter($filters); // apply filters to captcha audio
}
return $wavCaptcha->__toString();
}
Securimage::getAudibleCode ( )
protected

Gets the code and returns the binary audio file for the stored captcha code

Returns
The audio representation of the captcha in Wav format

Definition at line 1263 of file securimage.php.

References createCode(), generateWAV(), and getCode().

Referenced by outputAudioFile().

{
$letters = array();
$code = $this->getCode(true);
if ($code['code'] == '') {
$this->createCode();
$code = $this->getCode(true);
}
if (preg_match('/(\d+) (\+|-|x) (\d+)/i', $code['display'], $eq)) {
$math = true;
$left = $eq[1];
$sign = str_replace(array('+', '-', 'x'), array('plus', 'minus', 'times'), $eq[2]);
$right = $eq[3];
$letters = array($left, $sign, $right);
} else {
$math = false;
$length = strlen($code['display']);
for($i = 0; $i < $length; ++$i) {
$letter = $code['display']{$i};
$letters[] = $letter;
}
}
try {
return $this->generateWAV($letters);
} catch(Exception $ex) {
throw $ex;
}
}
Securimage::getBackgroundFromDirectory ( )
protected

Scan the directory for a background image to use

Definition at line 970 of file securimage.php.

Referenced by setBackground().

{
$images = array();
if ( ($dh = opendir($this->background_directory)) !== false) {
while (($file = readdir($dh)) !== false) {
if (preg_match('/(jpg|gif|png)$/i', $file)) $images[] = $file;
}
closedir($dh);
if (sizeof($images) > 0) {
return rtrim($this->background_directory, '/') . '/' . $images[rand(0, sizeof($images)-1)];
}
}
return false;
}
static Securimage::getCaptchaId (   $new = true,
array  $options = array() 
)
static

Generate a new captcha ID or retrieve the current ID

Parameters
$newbool If true, generates a new challenge and returns and ID
$optionsarray Additional options to be passed to Securimage
Returns
null|string Returns null if no captcha id set and new was false, or string captcha ID

Definition at line 612 of file securimage.php.

Referenced by doImage(), and saveCodeToDatabase().

{
if ((bool)$new == true) {
$id = sha1(uniqid($_SERVER['REMOTE_ADDR'], true));
$opts = array('no_session' => true,
'use_sqlite_db' => true);
if (sizeof($options) > 0) $opts = array_merge($opts, $options);
$si = new self($opts);
Securimage::$_captchaId = $id;
$si->createCode();
return $id;
} else {
return Securimage::$_captchaId;
}
}
Securimage::getCode (   $array = false)

Return the code from the session or sqlite database if used. If none exists yet, an empty string is returned

Parameters
$arraybool True to receive an array containing the code and properties
Returns
array|string Array if $array = true, otherwise a string containing the code

Definition at line 766 of file securimage.php.

References getCodeFromDatabase(), isCodeExpired(), and openDatabase().

Referenced by getAudibleCode(), and validate().

{
$code = '';
$time = 0;
$disp = 'error';
if ($this->no_session != true) {
if (isset($_SESSION['securimage_code_value'][$this->namespace]) &&
trim($_SESSION['securimage_code_value'][$this->namespace]) != '') {
if ($this->isCodeExpired(
$_SESSION['securimage_code_ctime'][$this->namespace]) == false) {
$code = $_SESSION['securimage_code_value'][$this->namespace];
$time = $_SESSION['securimage_code_ctime'][$this->namespace];
$disp = $_SESSION['securimage_code_disp'] [$this->namespace];
}
}
}
if ($this->use_sqlite_db == true && function_exists('sqlite_open')) {
// no code in session - may mean user has cookies turned off
$this->openDatabase();
$code = $this->getCodeFromDatabase();
} else { /* no code stored in session or sqlite database, validation will fail */ }
if ($array == true) {
return array('code' => $code, 'ctime' => $time, 'display' => $disp);
} else {
return $code;
}
}
Securimage::getCodeFromDatabase ( )
protected

Get a code from the sqlite database for ip address/captchaId.

Returns
string|array Empty string if no code was found or has expired, otherwise returns the stored captcha code. If a captchaId is set, this returns an array with indices "code" and "code_disp"

Definition at line 1486 of file securimage.php.

References isCodeExpired().

Referenced by doImage(), and getCode().

{
$code = '';
if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
if (Securimage::$_captchaId !== null) {
$query = "SELECT * FROM codes WHERE id = '" . sqlite_escape_string(Securimage::$_captchaId) . "'";
} else {
$ip = $_SERVER['REMOTE_ADDR'];
$ns = sqlite_escape_string($this->namespace);
$query = "SELECT * FROM codes WHERE ip = '$ip' AND namespace = '$ns'";
}
$res = sqlite_query($this->sqlite_handle, $query);
if ($res && sqlite_num_rows($res) > 0) {
$res = sqlite_fetch_array($res);
if ($this->isCodeExpired($res['created']) == false) {
if (Securimage::$_captchaId !== null) {
// return an array when using captchaId
$code = array('code' => $res['code'],
'code_disp' => $res['code_display']);
} else {
// return only the code if no captchaId specified
$code = $res['code'];
}
}
}
}
return $code;
}
static Securimage::getPath ( )
static

Return the absolute path to the Securimage directory

Returns
string The path to the securimage base directory

Definition at line 599 of file securimage.php.

{
return dirname(__FILE__);
}
Securimage::initColor (   $color,
  $default 
)
protected

Convert an html color code to a Securimage_Color

Parameters
string$color
Securimage_Color$defaultThe defalt color to use if $color is invalid

Definition at line 1716 of file securimage.php.

Referenced by __construct().

{
if ($color == null) {
return new Securimage_Color($default);
} else if (is_string($color)) {
try {
return new Securimage_Color($color);
} catch(Exception $e) {
return new Securimage_Color($default);
}
} else if (is_array($color) && sizeof($color) == 3) {
return new Securimage_Color($color[0], $color[1], $color[2]);
} else {
return new Securimage_Color($default);
}
}
Securimage::isCodeExpired (   $creation_time)
protected

Checks to see if the captcha code has expired and cannot be used

Parameters
unknown_type$creation_time

Definition at line 1548 of file securimage.php.

Referenced by getCode(), and getCodeFromDatabase().

{
$expired = true;
if (!is_numeric($this->expiry_time) || $this->expiry_time < 1) {
$expired = false;
} else if (time() - $creation_time < $this->expiry_time) {
$expired = false;
}
return $expired;
}
Securimage::openDatabase ( )
protected

Open sqlite database

Definition at line 1434 of file securimage.php.

References purgeOldCodesFromDatabase().

Referenced by doImage(), getCode(), and saveCodeToDatabase().

{
$this->sqlite_handle = false;
if ($this->use_sqlite_db == true && !function_exists('sqlite_open')) {
trigger_error('Securimage use_sqlite_db option is enable, but SQLIte is not supported by this PHP installation', E_USER_WARNING);
}
if ($this->use_sqlite_db && function_exists('sqlite_open')) {
if (!file_exists($this->sqlite_database)) {
$fp = fopen($this->sqlite_database, 'w+');
if (!$fp) {
trigger_error('Securimage failed to open sqlite database "' . $this->sqlite_database, E_USER_WARNING);
return false;
}
fclose($fp);
chmod($this->sqlite_database, 0666);
}
$this->sqlite_handle = sqlite_open($this->sqlite_database, 0666, $error);
if ($this->sqlite_handle !== false) {
$res = sqlite_query($this->sqlite_handle, "PRAGMA table_info(codes)");
if (sqlite_num_rows($res) == 0) {
$res = sqlite_query(
$this->sqlite_handle,
"CREATE TABLE codes (id VARCHAR(40) PRIMARY KEY, ip VARCHAR(32),
code VARCHAR(32) NOT NULL, code_display VARCHAR(32) NOT NULL,
namespace VARCHAR(32) NOT NULL, created INTEGER)"
);
}
if (mt_rand(0, 100) / 100.0 == 1.0) {
// randomly purge old codes
}
}
return $this->sqlite_handle != false;
}
return $this->sqlite_handle;
}
Securimage::output ( )
protected

Sends the appropriate image and cache headers and outputs image to the browser

Definition at line 1216 of file securimage.php.

References canSendHeaders().

Referenced by doImage().

{
if ($this->canSendHeaders() || $this->send_headers == false) {
if ($this->send_headers) {
// only send the content-type headers if no headers have been output
// this will ease debugging on misconfigured servers where warnings
// may have been output which break the image and prevent easily viewing
// source to see the error.
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
}
switch ($this->image_type) {
case self::SI_IMAGE_JPEG:
if ($this->send_headers) header("Content-Type: image/jpeg");
imagejpeg($this->im, null, 90);
break;
case self::SI_IMAGE_GIF:
if ($this->send_headers) header("Content-Type: image/gif");
imagegif($this->im);
break;
default:
if ($this->send_headers) header("Content-Type: image/png");
imagepng($this->im);
break;
}
} else {
echo '<hr /><strong>'
.'Failed to generate captcha image, content has already been '
.'output.<br />This is most likely due to misconfiguration or '
.'a PHP error was sent to the browser.</strong>';
}
imagedestroy($this->im);
restore_error_handler();
if (!$this->no_exit) exit;
}
Securimage::outputAudioFile ( )

Output a wav file of the captcha code to the browser

$img = new Securimage(); $img->outputAudioFile(); // outputs a wav file to the browser exit;

Definition at line 714 of file securimage.php.

References audioError(), canSendHeaders(), and getAudibleCode().

{
set_error_handler(array(&$this, 'errorHandler'));
require_once dirname(__FILE__) . '/WavFile.php';
try {
$audio = $this->getAudibleCode();
} catch (Exception $ex) {
if (($fp = @fopen(dirname(__FILE__) . '/si.error_log', 'a+')) !== false) {
fwrite($fp, date('Y-m-d H:i:s') . ': Securimage audio error "' . $ex->getMessage() . '"' . "\n");
fclose($fp);
}
$audio = $this->audioError();
}
if ($this->canSendHeaders() || $this->send_headers == false) {
if ($this->send_headers) {
$uniq = md5(uniqid(microtime()));
header("Content-Disposition: attachment; filename=\"securimage_audio-{$uniq}.wav\"");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Expires: Sun, 1 Jan 2000 12:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
header('Content-type: audio/x-wav');
if (extension_loaded('zlib')) {
ini_set('zlib.output_compression', true); // compress output if supported by browser
} else {
header('Content-Length: ' . strlen($audio));
}
}
echo $audio;
} else {
echo '<hr /><strong>'
.'Failed to generate audio file, content has already been '
.'output.<br />This is most likely due to misconfiguration or '
.'a PHP error was sent to the browser.</strong>';
}
restore_error_handler();
if (!$this->no_exit) exit;
}
Securimage::purgeOldCodesFromDatabase ( )
protected

Deletes old codes from sqlite database

Definition at line 1534 of file securimage.php.

Referenced by openDatabase().

{
if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
$now = time();
$limit = (!is_numeric($this->expiry_time) || $this->expiry_time < 1) ? 86400 : $this->expiry_time;
sqlite_query($this->sqlite_handle, "DELETE FROM codes WHERE $now - created > $limit");
}
}
Securimage::readCodeFromFile ( )
protected

Gets a captcha code from a wordlist

Definition at line 1302 of file securimage.php.

Referenced by createCode().

{
$fp = @fopen($this->wordlist_file, 'rb');
if (!$fp) return false;
$fsize = filesize($this->wordlist_file);
if ($fsize < 128) return false; // too small of a list to be effective
fseek($fp, rand(0, $fsize - 64), SEEK_SET); // seek to a random position of file from 0 to filesize-64
$data = fread($fp, 64); // read a chunk from our random position
fclose($fp);
$data = preg_replace("/\r?\n/", "\n", $data);
$start = @strpos($data, "\n", rand(0, 56)) + 1; // random start position
$end = @strpos($data, "\n", $start); // find end of word
if ($start === false) {
return false;
} else if ($end === false) {
$end = strlen($data);
}
return strtolower(substr($data, $start, $end - $start)); // return a line of the file
}
Securimage::saveCodeToDatabase ( )
protected

Saves the code to the sqlite database

Definition at line 1403 of file securimage.php.

References getCaptchaId(), and openDatabase().

Referenced by saveData().

{
$success = false;
$this->openDatabase();
if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
$id = $this->getCaptchaId(false);
$ip = $_SERVER['REMOTE_ADDR'];
if (empty($id)) {
$id = $ip;
}
$time = time();
$code = $this->code;
$code_disp = $this->code_display;
$query = "INSERT OR REPLACE INTO codes(id, ip, code, code_display,"
."namespace, created) VALUES('$id', '$ip', '$code', "
."'$code_disp', '{$this->namespace}', $time)";
$success = sqlite_query($this->sqlite_handle, $query);
}
return $success !== false;
}
Securimage::saveData ( )
protected

Save data to session namespace and database if used

Definition at line 1383 of file securimage.php.

References saveCodeToDatabase().

Referenced by createCode().

{
if ($this->no_session != true) {
if (isset($_SESSION['securimage_code_value']) && is_scalar($_SESSION['securimage_code_value'])) {
// fix for migration from v2 - v3
unset($_SESSION['securimage_code_value']);
unset($_SESSION['securimage_code_ctime']);
}
$_SESSION['securimage_code_disp'] [$this->namespace] = $this->code_display;
$_SESSION['securimage_code_value'][$this->namespace] = $this->code;
$_SESSION['securimage_code_ctime'][$this->namespace] = time();
}
}
Securimage::setBackground ( )
protected

The the background color, or background image to be used

Definition at line 922 of file securimage.php.

References getBackgroundFromDirectory().

Referenced by doImage().

{
// set background color of image by drawing a rectangle since imagecreatetruecolor doesn't set a bg color
imagefilledrectangle($this->im, 0, 0,
$this->image_width, $this->image_height,
$this->gdbgcolor);
imagefilledrectangle($this->tmpimg, 0, 0,
$this->image_width * $this->iscale, $this->image_height * $this->iscale,
$this->gdbgcolor);
if ($this->bgimg == '') {
if ($this->background_directory != null &&
is_dir($this->background_directory) &&
is_readable($this->background_directory))
{
$img = $this->getBackgroundFromDirectory();
if ($img != false) {
$this->bgimg = $img;
}
}
}
if ($this->bgimg == '') {
return;
}
$dat = @getimagesize($this->bgimg);
if($dat == false) {
return;
}
switch($dat[2]) {
case 1: $newim = @imagecreatefromgif($this->bgimg); break;
case 2: $newim = @imagecreatefromjpeg($this->bgimg); break;
case 3: $newim = @imagecreatefrompng($this->bgimg); break;
default: return;
}
if(!$newim) return;
imagecopyresized($this->im, $newim, 0, 0, 0, 0,
$this->image_width, $this->image_height,
imagesx($newim), imagesy($newim));
}
Securimage::show (   $background_image = '')

Used to serve a captcha image to the browser

Parameters
string$background_imageThe path to the background image to use $img = new Securimage(); $img->code_length = 6; $img->num_lines = 5; $img->noise_level = 5;

$img->show(); // sends the image to browser exit;

Definition at line 674 of file securimage.php.

References doImage().

{
set_error_handler(array(&$this, 'errorHandler'));
if($background_image != '' && is_readable($background_image)) {
$this->bgimg = $background_image;
}
$this->doImage();
}
Securimage::validate ( )
protected

Checks the entered code against the value stored in the session or sqlite database, handles case sensitivity Also clears the stored codes if the code was entered correctly to prevent re-use

Definition at line 1347 of file securimage.php.

References clearCodeFromDatabase(), and getCode().

Referenced by check().

{
if (!is_string($this->code) || strlen($this->code) == 0) {
$code = $this->getCode();
// returns stored code, or an empty string if no stored code was found
// checks the session and sqlite database if enabled
} else {
$code = $this->code;
}
if ($this->case_sensitive == false && preg_match('/[A-Z]/', $code)) {
// case sensitive was set from securimage_show.php but not in class
// the code saved in the session has capitals so set case sensitive to true
$this->case_sensitive = true;
}
$code_entered = trim( (($this->case_sensitive) ? $this->code_entered
: strtolower($this->code_entered))
);
$this->correct_code = false;
if ($code != '') {
if ($code == $code_entered) {
$this->correct_code = true;
if ($this->no_session != true) {
$_SESSION['securimage_code_value'][$this->namespace] = '';
$_SESSION['securimage_code_ctime'][$this->namespace] = '';
}
}
}
}

The documentation for this class was generated from the following file: