289 public $charset =
'ABCDEFGHKLMNPRSTUVWYZabcdefghklmnprstuvwyz23456789';
631 $this->securimage_path = dirname(__FILE__);
634 foreach(
$options as $prop => $val) {
635 if ($prop ==
'captchaId') {
637 $this->use_database =
true;
638 }
else if ($prop ==
'use_sqlite_db') {
639 trigger_error(
"The use_sqlite_db option is deprecated, use 'use_database' instead", E_USER_NOTICE);
646 $this->image_bg_color = $this->
initColor($this->image_bg_color,
'#ffffff');
647 $this->text_color = $this->
initColor($this->text_color,
'#616161');
648 $this->line_color = $this->
initColor($this->line_color,
'#616161');
649 $this->noise_color = $this->
initColor($this->noise_color,
'#616161');
650 $this->signature_color = $this->
initColor($this->signature_color,
'#616161');
652 if (is_null($this->ttf_file)) {
653 $this->ttf_file = $this->securimage_path .
'/AHGBold.ttf';
658 if (is_null($this->wordlist_file)) {
659 $this->wordlist_file = $this->securimage_path .
'/words/words.txt';
662 if (is_null($this->database_file)) {
663 $this->database_file = $this->securimage_path .
'/database/securimage.sq3';
666 if (is_null($this->audio_path)) {
667 $this->audio_path = $this->securimage_path .
'/audio/en/';
670 if (is_null($this->audio_noise_path)) {
671 $this->audio_noise_path = $this->securimage_path .
'/audio/noise/';
674 if (is_null($this->audio_use_noise)) {
675 $this->audio_use_noise =
true;
678 if (is_null($this->degrade_audio)) {
679 $this->degrade_audio =
true;
682 if (is_null($this->code_length) || (
int)$this->code_length < 1) {
683 $this->code_length = 6;
686 if (is_null($this->perturbation) || !is_numeric($this->perturbation)) {
687 $this->perturbation = 0.75;
690 if (is_null($this->
namespace) || !is_string($this->
namespace)) {
691 $this->
namespace = 'default';
694 if (is_null($this->no_exit)) {
695 $this->no_exit =
false;
698 if (is_null($this->no_session)) {
699 $this->no_session =
false;
702 if (is_null($this->send_headers)) {
703 $this->send_headers =
true;
706 if ($this->no_session !=
true) {
708 if ( session_id() ==
'' ) {
709 if (!is_null($this->session_name) && trim($this->session_name) !=
'') {
710 session_name(trim($this->session_name));
723 return dirname(__FILE__);
737 if (is_null($new) || (
bool)$new ==
true) {
738 $id = sha1(uniqid($_SERVER[
'REMOTE_ADDR'],
true));
739 $opts = array(
'no_session' =>
true,
740 'use_database' =>
true);
742 $si =
new self($opts);
765 $opts = array(
'captchaId' => $id,
766 'no_session' =>
true,
767 'use_database' =>
true);
771 $si =
new self($opts);
773 if (
$si->openDatabase()) {
776 if (is_array(
$code)) {
778 $si->code_display =
$code[
'code_disp'];
781 if (
$si->check($value)) {
782 $si->clearCodeFromDatabase();
807 public function show($background_image =
'')
809 set_error_handler(array(&$this,
'errorHandler'));
811 if($background_image !=
'' && is_readable($background_image)) {
812 $this->bgimg = $background_image;
833 $this->code_entered =
$code;
835 return $this->correct_code;
849 set_error_handler(array(&$this,
'errorHandler'));
851 require_once dirname(__FILE__) .
'/WavFile.php';
856 if (($fp = @fopen(dirname(__FILE__) .
'/si.error_log',
'a+')) !==
false) {
857 fwrite($fp, date(
'Y-m-d H:i:s') .
': Securimage audio error "' . $ex->getMessage() .
'"' .
"\n");
865 if ($this->send_headers) {
866 $uniq = md5(uniqid(microtime()));
867 header(
"Content-Disposition: attachment; filename=\"securimage_audio-{$uniq}.wav\"");
868 header(
'Cache-Control: no-store, no-cache, must-revalidate');
869 header(
'Expires: Sun, 1 Jan 2000 12:00:00 GMT');
870 header(
'Last-Modified: ' . gmdate(
'D, d M Y H:i:s') .
'GMT');
871 header(
'Content-type: audio/x-wav');
873 if (extension_loaded(
'zlib')) {
874 ini_set(
'zlib.output_compression',
true);
876 header(
'Content-Length: ' . strlen($audio));
882 echo
'<hr /><strong>'
883 .
'Failed to generate audio file, content has already been '
884 .
'output.<br />This is most likely due to misconfiguration or '
885 .
'a PHP error was sent to the browser.</strong>';
888 restore_error_handler();
890 if (!$this->no_exit)
exit;
899 public function getCode($array =
false, $returnExisting =
false)
905 if ($returnExisting && strlen($this->code) > 0) {
907 return array(
'code' => $this->code,
908 'display' => $this->code_display,
909 'code_display' => $this->code_display,
916 if ($this->no_session !=
true) {
917 if (isset(
$_SESSION[
'securimage_code_value'][$this->
namespace]) &&
918 trim(
$_SESSION[
'securimage_code_value'][$this->
namespace]) !=
'') {
920 $_SESSION[
'securimage_code_ctime'][$this->
namespace]) ==
false) {
928 if (empty(
$code) && $this->use_database) {
934 if ($array ==
true) {
935 return array(
'code' =>
$code,
'ctime' => $time,
'display' => $disp);
946 if( ($this->use_transparent_text ==
true || $this->bgimg !=
'') && function_exists(
'imagecreatetruecolor')) {
947 $imagecreate =
'imagecreatetruecolor';
949 $imagecreate =
'imagecreate';
952 $this->im = $imagecreate($this->image_width, $this->image_height);
953 $this->tmpimg = $imagecreate($this->image_width * $this->iscale, $this->image_height * $this->iscale);
956 imagepalettecopy($this->tmpimg, $this->im);
966 if (is_string($this->display_value) && strlen($this->display_value) > 0) {
969 $this->display_value :
970 strtolower($this->display_value);
977 if (is_array(
$code)) {
978 $this->code =
$code[
'code'];
979 $this->code_display =
$code[
'code_disp'];
991 if ($this->noise_level > 0) {
997 if ($this->perturbation > 0 && is_readable($this->ttf_file)) {
1001 if ($this->num_lines > 0) {
1005 if (trim($this->image_signature) !=
'') {
1018 $this->gdbgcolor = imagecolorallocate($this->im,
1019 $this->image_bg_color->r,
1020 $this->image_bg_color->g,
1021 $this->image_bg_color->b);
1023 $alpha = intval($this->text_transparency_percentage / 100 * 127);
1025 if ($this->use_transparent_text ==
true) {
1026 $this->gdtextcolor = imagecolorallocatealpha($this->im,
1027 $this->text_color->r,
1028 $this->text_color->g,
1029 $this->text_color->b,
1031 $this->gdlinecolor = imagecolorallocatealpha($this->im,
1032 $this->line_color->r,
1033 $this->line_color->g,
1034 $this->line_color->b,
1036 $this->gdnoisecolor = imagecolorallocatealpha($this->im,
1037 $this->noise_color->r,
1038 $this->noise_color->g,
1039 $this->noise_color->b,
1042 $this->gdtextcolor = imagecolorallocate($this->im,
1043 $this->text_color->r,
1044 $this->text_color->g,
1045 $this->text_color->b);
1046 $this->gdlinecolor = imagecolorallocate($this->im,
1047 $this->line_color->r,
1048 $this->line_color->g,
1049 $this->line_color->b);
1050 $this->gdnoisecolor = imagecolorallocate($this->im,
1051 $this->noise_color->r,
1052 $this->noise_color->g,
1053 $this->noise_color->b);
1056 $this->gdsignaturecolor = imagecolorallocate($this->im,
1057 $this->signature_color->r,
1058 $this->signature_color->g,
1059 $this->signature_color->b);
1069 imagefilledrectangle($this->im, 0, 0,
1070 $this->image_width, $this->image_height,
1072 imagefilledrectangle($this->tmpimg, 0, 0,
1073 $this->image_width * $this->iscale, $this->image_height * $this->iscale,
1076 if ($this->bgimg ==
'') {
1077 if ($this->background_directory != null &&
1078 is_dir($this->background_directory) &&
1079 is_readable($this->background_directory))
1082 if (
$img !=
false) {
1083 $this->bgimg =
$img;
1088 if ($this->bgimg ==
'') {
1092 $dat = @getimagesize($this->bgimg);
1098 case 1: $newim = @imagecreatefromgif($this->bgimg);
break;
1099 case 2: $newim = @imagecreatefromjpeg($this->bgimg);
break;
1100 case 3: $newim = @imagecreatefrompng($this->bgimg);
break;
1106 imagecopyresized($this->im, $newim, 0, 0, 0, 0,
1107 $this->image_width, $this->image_height,
1108 imagesx($newim), imagesy($newim));
1118 if ( ($dh = opendir($this->background_directory)) !==
false) {
1119 while ((
$file = readdir($dh)) !==
false) {
1120 if (preg_match(
'/(jpg|gif|png)$/i',
$file)) $images[] =
$file;
1125 if (
sizeof($images) > 0) {
1126 return rtrim($this->background_directory,
'/') .
'/' . $images[mt_rand(0,
sizeof($images)-1)];
1138 $this->code =
false;
1140 switch($this->captcha_type) {
1141 case self::SI_CAPTCHA_MATHEMATIC:
1144 $signs = array(
'+',
'-',
'x');
1145 $left = mt_rand(1, 10);
1146 $right = mt_rand(1, 5);
1147 $sign = $signs[mt_rand(0, 2)];
1150 case 'x': $c = $left * $right;
break;
1151 case '-': $c = $left - $right;
break;
1152 default: $c = $left + $right;
break;
1157 $this->code_display =
"$left $sign $right";
1161 case self::SI_CAPTCHA_WORDS:
1163 $this->code = implode(
' ', $words);
1169 if ($this->use_wordlist && is_readable($this->wordlist_file)) {
1173 if ($this->code ==
false) {
1193 if (!is_readable($this->ttf_file)) {
1194 imagestring($this->im, 4, 10, ($this->image_height / 2) - 5,
'Failed to load TTF font file!', $this->gdtextcolor);
1196 if ($this->perturbation > 0) {
1197 $font_size = $height2 * .4;
1198 $bb = imageftbbox($font_size, 0, $this->ttf_file, $this->code_display);
1199 $tx = $bb[4] - $bb[0];
1200 $ty = $bb[5] - $bb[1];
1201 $x = floor($width2 / 2 - $tx / 2 - $bb[0]);
1202 $y = round($height2 / 2 - $ty / 2 - $bb[1]);
1204 imagettftext($this->tmpimg, $font_size, 0, $x, $y, $this->gdtextcolor, $this->ttf_file, $this->code_display);
1206 $font_size = $this->image_height * .4;
1207 $bb = imageftbbox($font_size, 0, $this->ttf_file, $this->code_display);
1208 $tx = $bb[4] - $bb[0];
1209 $ty = $bb[5] - $bb[1];
1210 $x = floor($this->image_width / 2 - $tx / 2 - $bb[0]);
1211 $y = round($this->image_height / 2 - $ty / 2 - $bb[1]);
1213 imagettftext($this->im, $font_size, 0, $x, $y, $this->gdtextcolor, $this->ttf_file, $this->code_display);
1230 for ($i = 0; $i < $numpoles; ++ $i) {
1231 $px[$i] = mt_rand($this->image_width * 0.2, $this->image_width * 0.8);
1232 $py[$i] = mt_rand($this->image_height * 0.2, $this->image_height * 0.8);
1233 $rad[$i] = mt_rand($this->image_height * 0.2, $this->image_height * 0.8);
1234 $tmp = ((- $this->
frand()) * 0.15) - .15;
1235 $amp[$i] = $this->perturbation * $tmp;
1238 $bgCol = imagecolorat($this->tmpimg, 0, 0);
1241 imagepalettecopy($this->im, $this->tmpimg);
1247 for ($i = 0; $i < $numpoles; ++ $i) {
1248 $dx = $ix - $px[$i];
1249 $dy = $iy - $py[$i];
1250 if ($dx == 0 && $dy == 0) {
1253 $r = sqrt($dx * $dx + $dy * $dy);
1254 if ($r > $rad[$i]) {
1257 $rscale = $amp[$i] * sin(3.14 * $r / $rad[$i]);
1258 $x += $dx * $rscale;
1259 $y += $dy * $rscale;
1264 if ($x >= 0 && $x < $width2 && $y >= 0 && $y < $height2) {
1265 $c = imagecolorat($this->tmpimg, $x, $y);
1268 imagesetpixel($this->im, $ix, $iy, $c);
1280 $x = $this->image_width * (1 + $line) / ($this->num_lines + 1);
1281 $x += (0.5 - $this->
frand()) * $this->image_width / $this->num_lines;
1282 $y = mt_rand($this->image_height * 0.1, $this->image_height * 0.9);
1284 $theta = ($this->
frand() - 0.5) * M_PI * 0.7;
1286 $len = mt_rand($w * 0.4, $w * 0.7);
1287 $lwid = mt_rand(0, 2);
1289 $k = $this->
frand() * 0.6 + 0.2;
1291 $phi = $this->
frand() * 6.28;
1293 $dx = $step * cos($theta);
1294 $dy = $step * sin($theta);
1296 $amp = 1.5 * $this->
frand() / ($k + 5.0 / $len);
1297 $x0 = $x - 0.5 * $len * cos($theta);
1298 $y0 = $y - 0.5 * $len * sin($theta);
1300 $ldx = round(- $dy * $lwid);
1301 $ldy = round($dx * $lwid);
1303 for ($i = 0; $i <
$n; ++ $i) {
1304 $x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
1305 $y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
1306 imagefilledrectangle($this->im, $x, $y, $x + $lwid, $y + $lwid, $this->gdlinecolor);
1316 if ($this->noise_level > 10) {
1322 $t0 = microtime(
true);
1326 $points = $this->image_width * $this->image_height *
$this->iscale;
1330 $x = mt_rand(10, $width);
1331 $y = mt_rand(10, $height);
1332 $size = mt_rand(7, 10);
1333 if ($x -
$size <= 0 && $y -
$size <= 0)
continue;
1334 imagefilledarc($this->tmpimg, $x, $y,
$size,
$size, 0, 360, $this->gdnoisecolor, IMG_ARC_PIE);
1337 $t1 = microtime(
true);
1355 $bbox = imagettfbbox(10, 0, $this->signature_font, $this->image_signature);
1356 $textlen = $bbox[2] - $bbox[0];
1357 $x = $this->image_width - $textlen - 5;
1358 $y = $this->image_height - 3;
1360 imagettftext($this->im, 10, 0, $x, $y, $this->gdsignaturecolor, $this->signature_font, $this->image_signature);
1369 if ($this->send_headers) {
1374 header(
"Expires: Mon, 26 Jul 1997 05:00:00 GMT");
1375 header(
"Last-Modified: " . gmdate(
"D, d M Y H:i:s") .
"GMT");
1376 header(
"Cache-Control: no-store, no-cache, must-revalidate");
1377 header(
"Cache-Control: post-check=0, pre-check=0",
false);
1378 header(
"Pragma: no-cache");
1381 switch ($this->image_type) {
1382 case self::SI_IMAGE_JPEG:
1383 if ($this->send_headers) header(
"Content-Type: image/jpeg");
1384 imagejpeg($this->im, null, 90);
1386 case self::SI_IMAGE_GIF:
1387 if ($this->send_headers) header(
"Content-Type: image/gif");
1388 imagegif($this->im);
1391 if ($this->send_headers) header(
"Content-Type: image/png");
1392 imagepng($this->im);
1396 echo
'<hr /><strong>'
1397 .
'Failed to generate captcha image, content has already been '
1398 .
'output.<br />This is most likely due to misconfiguration or '
1399 .
'a PHP error was sent to the browser.</strong>';
1402 imagedestroy($this->im);
1403 restore_error_handler();
1405 if (!$this->no_exit)
exit;
1418 if (
$code[
'code'] ==
'') {
1419 if (strlen($this->display_value) > 0) {
1420 $code = array(
'code' => $this->display_value,
'display' => $this->display_value);
1427 if (preg_match(
'/(\d+) (\+|-|x) (\d+)/i',
$code[
'display'], $eq)) {
1431 $sign = str_replace(array(
'+',
'-',
'x'), array(
'plus',
'minus',
'times'), $eq[2]);
1434 $letters = array($left, $sign, $right);
1438 $length = strlen(
$code[
'display']);
1440 for($i = 0; $i < $length; ++$i) {
1441 $letter =
$code[
'display']{$i};
1442 $letters[] = $letter;
1458 $fp = fopen($this->wordlist_file,
'rb');
1459 if (!$fp)
return false;
1461 $fsize = filesize($this->wordlist_file);
1462 if ($fsize < 128)
return false;
1464 if ((
int)$numWords < 1 || (
int)$numWords > 5) $numWords = 1;
1469 fseek($fp, mt_rand(0, $fsize - 64), SEEK_SET);
1470 $data = fread($fp, 64);
1471 $data = preg_replace(
"/\r?\n/",
"\n", $data);
1473 $start = @strpos($data,
"\n", mt_rand(0, 56)) + 1;
1474 $end = @strpos($data,
"\n", $start);
1476 if ($start ===
false) {
1479 }
else if ($end ===
false) {
1480 $end = strlen($data);
1483 $word = strtolower(substr($data, $start, $end - $start));
1485 }
while (++$i < $numWords);
1489 if ($numWords < 2) {
1503 if (function_exists(
'mb_strlen')) {
1505 $code .= mb_substr($this->charset, mt_rand(0, $cslen - 1), 1,
'UTF-8');
1509 $code .= substr($this->charset, mt_rand(0, $cslen - 1), 1);
1522 if (!is_string($this->code) || strlen($this->code) == 0) {
1530 if ($this->case_sensitive ==
false && preg_match(
'/[A-Z]/',
$code)) {
1533 $this->case_sensitive =
true;
1536 $code_entered = trim( (($this->case_sensitive) ? $this->code_entered
1537 : strtolower($this->code_entered))
1539 $this->correct_code =
false;
1542 if (strpos(
$code,
' ') !==
false) {
1544 $code_entered = preg_replace(
'/\s+/',
' ', $code_entered);
1545 $code_entered = strtolower($code_entered);
1548 if (
$code == $code_entered) {
1549 $this->correct_code =
true;
1550 if ($this->no_session !=
true) {
1564 if ($this->no_session !=
true) {
1565 if (isset(
$_SESSION[
'securimage_code_value']) && is_scalar(
$_SESSION[
'securimage_code_value'])) {
1567 unset(
$_SESSION[
'securimage_code_value']);
1568 unset(
$_SESSION[
'securimage_code_ctime']);
1576 if ($this->use_database) {
1589 if ($this->use_database && $this->pdo_conn) {
1591 $ip = $_SERVER[
'REMOTE_ADDR'];
1604 $query =
"INSERT INTO {$this->database_table} ("
1605 .
"id, code, code_display, namespace, created) "
1606 .
"VALUES(?, ?, ?, ?, ?)";
1608 $stmt = $this->pdo_conn->prepare(
$query);
1609 $success = $stmt->execute(array($id,
$code, $code_disp, $this->
namespace, $time));
1612 $err = $stmt->errorInfo();
1613 trigger_error(
"Failed to insert code into database. {$err[1]}: {$err[2]}", E_USER_WARNING);
1625 $this->pdo_conn =
false;
1627 if ($this->use_database) {
1628 $pdo_extension =
'PDO_' . strtoupper($this->database_driver);
1630 if (!extension_loaded($pdo_extension)) {
1631 trigger_error(
"Database support is turned on in Securimage, but the chosen extension $pdo_extension is not loaded in PHP.", E_USER_WARNING);
1636 if ($this->database_driver == self::SI_DRIVER_SQLITE3) {
1637 if (!file_exists($this->database_file)) {
1638 $fp = fopen($this->database_file,
'w+');
1640 $err = error_get_last();
1641 trigger_error(
"Securimage failed to create SQLite3 database file '{$this->database_file}'. Reason: {$err['message']}", E_USER_WARNING);
1645 chmod($this->database_file, 0666);
1646 }
else if (!is_writeable($this->database_file)) {
1647 trigger_error(
"Securimage does not have read/write access to database file '{$this->database_file}. Make sure permissions are 0666 and writeable by user '" . get_current_user() .
"'", E_USER_WARNING);
1656 $this->pdo_conn =
new PDO($dsn, $this->database_user, $this->database_pass,
$options);
1657 }
catch (PDOException $pdoex) {
1658 trigger_error(
"Database connection failed: " . $pdoex->getMessage(), E_USER_WARNING);
1668 trigger_error($ex->getMessage(), E_USER_WARNING);
1669 $this->pdo_conn = null;
1673 if (mt_rand(0, 100) / 100.0 == 1.0) {
1682 $dsn = sprintf(
'%s:', $this->database_driver);
1684 switch($this->database_driver) {
1685 case self::SI_DRIVER_SQLITE3:
1689 case self::SI_DRIVER_MYSQL:
1690 case self::SI_DRIVER_PGSQL:
1691 $dsn .= sprintf(
'host=%s;dbname=%s',
1692 $this->database_host,
1693 $this->database_name);
1703 $table = $this->pdo_conn->quote($this->database_table);
1705 switch($this->database_driver) {
1706 case self::SI_DRIVER_SQLITE3:
1709 $query =
"SELECT COUNT(id) FROM $table";
1712 case self::SI_DRIVER_MYSQL:
1713 $query =
"SHOW TABLES LIKE $table";
1716 case self::SI_DRIVER_PGSQL:
1717 $query =
"SELECT * FROM information_schema.columns WHERE table_name = $table;";
1724 $err = $this->pdo_conn->errorInfo();
1726 if ($this->database_driver == self::SI_DRIVER_SQLITE3 &&
1727 $err[1] === 1 && strpos($err[2],
'no such table') !==
false)
1732 throw new Exception(
"Failed to check tables: {$err[0]} - {$err[1]}: {$err[2]}");
1733 }
else if ($this->database_driver == self::SI_DRIVER_SQLITE3) {
1736 }
else if (
$result->rowCount() == 0) {
1747 switch($this->database_driver) {
1748 case self::SI_DRIVER_SQLITE3:
1749 $queries[] =
"CREATE TABLE \"{$this->database_table}\" (
1751 namespace VARCHAR(32) NOT NULL,
1752 code VARCHAR(32) NOT NULL,
1753 code_display VARCHAR(32) NOT NULL,
1754 created INTEGER NOT NULL,
1755 PRIMARY KEY(id, namespace)
1758 $queries[] =
"CREATE INDEX ndx_created ON {$this->database_table} (created)";
1761 case self::SI_DRIVER_MYSQL:
1762 $queries[] =
"CREATE TABLE `{$this->database_table}` (
1763 `id` VARCHAR(40) NOT NULL,
1764 `namespace` VARCHAR(32) NOT NULL,
1765 `code` VARCHAR(32) NOT NULL,
1766 `code_display` VARCHAR(32) NOT NULL,
1767 `created` INT NOT NULL,
1768 PRIMARY KEY(id, namespace),
1773 case self::SI_DRIVER_PGSQL:
1774 $queries[] =
"CREATE TABLE {$this->database_table} (
1775 id character varying(40) NOT NULL,
1776 namespace character varying(32) NOT NULL,
1777 code character varying(32) NOT NULL,
1778 code_display character varying(32) NOT NULL,
1779 created integer NOT NULL,
1780 CONSTRAINT pkey_id_namespace PRIMARY KEY (id, namespace)
1783 $queries[] =
"CREATE INDEX ndx_created ON {$this->database_table} (created);";
1787 $this->pdo_conn->beginTransaction();
1789 foreach($queries as
$query) {
1790 $result = $this->pdo_conn->query($query);
1793 $err = $this->pdo_conn->errorInfo();
1794 trigger_error(
"Failed to create table. {$err[1]}: {$err[2]}", E_USER_WARNING);
1795 $this->pdo_conn->rollBack();
1796 $this->pdo_conn =
false;
1801 $this->pdo_conn->commit();
1817 if ($this->use_database ==
true && $this->pdo_conn) {
1819 $query =
"SELECT * FROM {$this->database_table} WHERE id = ?";
1820 $stmt = $this->pdo_conn->prepare(
$query);
1823 $ip = $_SERVER[
'REMOTE_ADDR'];
1827 $query =
"SELECT * FROM {$this->database_table} WHERE id = ? AND namespace = ?";
1828 $stmt = $this->pdo_conn->prepare(
$query);
1829 $result = $stmt->execute(array($ip, $ns));
1833 $err = $this->pdo_conn->errorInfo();
1834 trigger_error(
"Failed to select code from database. {$err[0]}: {$err[1]}", E_USER_WARNING);
1836 if ( (
$row = $stmt->fetch()) !==
false ) {
1841 'code_disp' =>
$row[
'code_display']);
1858 if ($this->pdo_conn) {
1859 $ip = $_SERVER[
'REMOTE_ADDR'];
1860 $ns = $this->pdo_conn->quote($this->
namespace);
1867 $id = $this->pdo_conn->quote($id);
1869 $query = sprintf(
"DELETE FROM %s WHERE id = %s AND namespace = %s",
1870 $this->database_table, $id, $ns);
1874 trigger_error(
"Failed to delete code from database.", E_USER_WARNING);
1884 if ($this->use_database && $this->pdo_conn) {
1886 $limit = (!is_numeric($this->expiry_time) || $this->expiry_time < 1) ? 86400 : $this->expiry_time;
1888 $query = sprintf(
"DELETE FROM %s WHERE %s - created > %s",
1889 $this->database_table,
1890 $this->pdo_conn->quote($now, PDO::PARAM_INT),
1891 $this->pdo_conn->quote($limit, PDO::PARAM_INT));
1905 if (!is_numeric($this->expiry_time) || $this->expiry_time < 1) {
1907 }
else if (time() - $creation_time < $this->expiry_time) {
1925 foreach ($letters as $letter) {
1926 $letter = strtoupper($letter);
1929 $l =
new WavFile($this->audio_path .
'/' . $letter .
'.wav');
1933 $wavCaptcha->setSampleRate($l->getSampleRate())
1934 ->setBitsPerSample($l->getBitsPerSample())
1935 ->setNumChannels($l->getNumChannels());
1940 $wavCaptcha->appendWav($l);
1943 if ($this->audio_gap_max > 0 && $this->audio_gap_max > $this->audio_gap_min) {
1944 $wavCaptcha->insertSilence( mt_rand($this->audio_gap_min, $this->audio_gap_max) / 1000.0 );
1956 if ($this->audio_use_noise ==
true) {
1960 if ($noiseFile !==
false && is_readable($noiseFile)) {
1962 $wavNoise =
new WavFile($noiseFile,
false);
1970 if ($wavNoise->getNumBlocks() > 2 * $wavCaptcha->getNumBlocks()) {
1971 $randBlock = mt_rand(0, $wavNoise->getNumBlocks() - $wavCaptcha->getNumBlocks());
1972 $wavNoise->readWavData($randBlock * $wavNoise->getBlockAlign(), $wavCaptcha->getNumBlocks() * $wavNoise->getBlockAlign());
1974 $wavNoise->readWavData();
1975 $randOffset = mt_rand(0, $wavNoise->getNumBlocks() - 1);
1979 $mixOpts = array(
'wav' => $wavNoise,
1981 'blockOffset' => $randOffset);
1988 if ($this->degrade_audio ==
true) {
1994 if (!empty($filters)) {
1995 $wavCaptcha->filter($filters);
1998 return $wavCaptcha->__toString();
2005 if ( ($dh = opendir($this->audio_noise_path)) !==
false ) {
2008 while ( (
$file = readdir($dh)) !==
false ) {
2010 if (strtolower(substr(
$file, -4)) !=
'.wav')
continue;
2017 if (
sizeof($list) > 0) {
2018 $file = $list[array_rand($list, 1)];
2019 $return = $this->audio_noise_path . DIRECTORY_SEPARATOR .
$file;
2033 return @file_get_contents(dirname(__FILE__) .
'/audio/en/error.wav');
2043 if (headers_sent()) {
2046 }
else if (strlen((
string)ob_get_contents()) > 0) {
2061 return 0.0001 * mt_rand(0,9999);
2071 if ($color == null) {
2073 }
else if (is_string($color)) {
2079 }
else if (is_array($color) &&
sizeof($color) == 3) {
2101 public function errorHandler($errno, $errstr, $errfile =
'', $errline = 0, $errcontext = array())
2104 $level = error_reporting();
2107 if ($level == 0 || ($level & $errno) == 0) {
2144 $args = func_get_args();
2146 if (
sizeof($args) == 0) {
2150 }
else if (
sizeof($args) == 1) {
2152 if (substr($color, 0, 1) ==
'#') {
2153 $color = substr($color, 1);
2156 if (strlen($color) != 3 && strlen($color) != 6) {
2157 throw new InvalidArgumentException(
2158 'Invalid HTML color code passed to Securimage_Color'
2163 }
else if (
sizeof($args) == 3) {
2166 throw new InvalidArgumentException(
2167 'Securimage_Color constructor expects 0, 1 or 3 arguments; ' .
sizeof($args) .
' given'
2180 if ($red < 0) $red = 0;
2181 if ($red > 255) $red = 255;
2182 if ($green < 0) $green = 0;
2183 if ($green > 255) $green = 255;
2184 if ($blue < 0) $blue = 0;
2185 if ($blue > 255) $blue = 255;
2198 if (strlen($color) == 3) {
2199 $red = str_repeat(substr($color, 0, 1), 2);
2200 $green = str_repeat(substr($color, 1, 1), 2);
2201 $blue = str_repeat(substr($color, 2, 1), 2);
2203 $red = substr($color, 0, 2);
2204 $green = substr($color, 2, 2);
2205 $blue = substr($color, 4, 2);
2208 $this->r = hexdec($red);
2209 $this->g = hexdec($green);
2210 $this->b = hexdec($blue);