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 } elseif ($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) {
739 $opts = array(
'no_session' =>
true,
740 'use_database' =>
true);
742 $opts = array_merge(
$options, $opts);
744 $si =
new self($opts);
767 $opts = array(
'captchaId' =>
$id,
768 'no_session' =>
true,
769 'use_database' =>
true);
772 $opts = array_merge(
$options, $opts);
775 $si =
new self($opts);
777 if (
$si->openDatabase()) {
780 if (is_array(
$code)) {
782 $si->code_display =
$code[
'code_disp'];
785 if (
$si->check($value)) {
786 $si->clearCodeFromDatabase();
811 public function show($background_image =
'')
813 set_error_handler(array(&$this,
'errorHandler'));
815 if ($background_image !=
'' && is_readable($background_image)) {
816 $this->bgimg = $background_image;
837 $this->code_entered =
$code;
839 return $this->correct_code;
853 set_error_handler(array(&$this,
'errorHandler'));
855 require_once dirname(__FILE__) .
'/WavFile.php';
860 if (($fp = @
fopen(dirname(__FILE__) .
'/si.error_log',
'a+')) !==
false) {
861 fwrite($fp, date(
'Y-m-d H:i:s') .
': Securimage audio error "' . $ex->getMessage() .
'"' .
"\n");
869 if ($this->send_headers) {
870 $uniq = md5(uniqid(microtime()));
871 header(
"Content-Disposition: attachment; filename=\"securimage_audio-{$uniq}.wav\"");
872 header(
'Cache-Control: no-store, no-cache, must-revalidate');
873 header(
'Expires: Sun, 1 Jan 2000 12:00:00 GMT');
874 header(
'Last-Modified: ' . gmdate(
'D, d M Y H:i:s') .
'GMT');
875 header(
'Content-type: audio/x-wav');
877 if (extension_loaded(
'zlib')) {
878 ini_set(
'zlib.output_compression',
true);
880 header(
'Content-Length: ' . strlen($audio));
886 echo '<hr /><strong>' 887 .
'Failed to generate audio file, content has already been ' 888 .
'output.<br />This is most likely due to misconfiguration or ' 889 .
'a PHP error was sent to the browser.</strong>';
892 restore_error_handler();
894 if (!$this->no_exit) {
905 public function getCode($array =
false, $returnExisting =
false)
911 if ($returnExisting && strlen($this->code) > 0) {
913 return array(
'code' => $this->code,
914 'display' => $this->code_display,
915 'code_display' => $this->code_display,
922 if ($this->no_session !=
true) {
923 if (isset(
$_SESSION[
'securimage_code_value'][$this->
namespace]) &&
924 trim(
$_SESSION[
'securimage_code_value'][$this->
namespace]) !=
'') {
926 $_SESSION[
'securimage_code_ctime'][$this->
namespace]
935 if (empty(
$code) && $this->use_database) {
942 if ($array ==
true) {
943 return array(
'code' =>
$code,
'ctime' =>
$time,
'display' => $disp);
954 if (($this->use_transparent_text ==
true || $this->bgimg !=
'') && function_exists(
'imagecreatetruecolor')) {
955 $imagecreate =
'imagecreatetruecolor';
957 $imagecreate =
'imagecreate';
960 $this->im = $imagecreate($this->image_width, $this->image_height);
961 $this->tmpimg = $imagecreate($this->image_width * $this->iscale, $this->image_height * $this->iscale);
964 imagepalettecopy($this->tmpimg, $this->im);
974 if (is_string($this->display_value) && strlen($this->display_value) > 0) {
977 $this->display_value :
978 strtolower($this->display_value);
985 if (is_array(
$code)) {
986 $this->code =
$code[
'code'];
987 $this->code_display =
$code[
'code_disp'];
999 if ($this->noise_level > 0) {
1005 if ($this->perturbation > 0 && is_readable($this->ttf_file)) {
1009 if ($this->num_lines > 0) {
1013 if (trim($this->image_signature) !=
'') {
1026 $this->gdbgcolor = imagecolorallocate(
1028 $this->image_bg_color->r,
1029 $this->image_bg_color->g,
1030 $this->image_bg_color->b
1033 $alpha = intval($this->text_transparency_percentage / 100 * 127);
1035 if ($this->use_transparent_text ==
true) {
1036 $this->gdtextcolor = imagecolorallocatealpha(
1038 $this->text_color->r,
1039 $this->text_color->g,
1040 $this->text_color->b,
1043 $this->gdlinecolor = imagecolorallocatealpha(
1045 $this->line_color->r,
1046 $this->line_color->g,
1047 $this->line_color->b,
1050 $this->gdnoisecolor = imagecolorallocatealpha(
1052 $this->noise_color->r,
1053 $this->noise_color->g,
1054 $this->noise_color->b,
1058 $this->gdtextcolor = imagecolorallocate(
1060 $this->text_color->r,
1061 $this->text_color->g,
1062 $this->text_color->b
1064 $this->gdlinecolor = imagecolorallocate(
1066 $this->line_color->r,
1067 $this->line_color->g,
1068 $this->line_color->b
1070 $this->gdnoisecolor = imagecolorallocate(
1072 $this->noise_color->r,
1073 $this->noise_color->g,
1074 $this->noise_color->b
1078 $this->gdsignaturecolor = imagecolorallocate(
1080 $this->signature_color->r,
1081 $this->signature_color->g,
1082 $this->signature_color->b
1092 imagefilledrectangle(
1097 $this->image_height,
1100 imagefilledrectangle(
1104 $this->image_width * $this->iscale,
1105 $this->image_height * $this->iscale,
1109 if ($this->bgimg ==
'') {
1110 if ($this->background_directory != null &&
1111 is_dir($this->background_directory) &&
1112 is_readable($this->background_directory)) {
1114 if (
$img !=
false) {
1115 $this->bgimg =
$img;
1120 if ($this->bgimg ==
'') {
1124 $dat = @getimagesize($this->bgimg);
1125 if ($dat ==
false) {
1130 case 1: $newim = @imagecreatefromgif($this->bgimg);
break;
1131 case 2: $newim = @imagecreatefromjpeg($this->bgimg);
break;
1132 case 3: $newim = @imagecreatefrompng($this->bgimg);
break;
1148 $this->image_height,
1161 if (($dh = opendir($this->background_directory)) !==
false) {
1162 while (($file = readdir($dh)) !==
false) {
1163 if (preg_match(
'/(jpg|gif|png)$/i', $file)) {
1170 if (
sizeof($images) > 0) {
1171 return rtrim($this->background_directory,
'/') .
'/' . $images[mt_rand(0,
sizeof($images) - 1)];
1183 $this->code =
false;
1185 switch ($this->captcha_type) {
1186 case self::SI_CAPTCHA_MATHEMATIC:
1189 $signs = array(
'+',
'-',
'x');
1190 $left = mt_rand(1, 10);
1191 $right = mt_rand(1, 5);
1192 $sign = $signs[mt_rand(0, 2)];
1195 case 'x':
$c = $left * $right;
break;
1196 case '-':
$c = $left - $right;
break;
1197 default:
$c = $left + $right;
break;
1202 $this->code_display =
"$left $sign $right";
1206 case self::SI_CAPTCHA_WORDS:
1208 $this->code = implode(
' ', $words);
1214 if ($this->use_wordlist && is_readable($this->wordlist_file)) {
1218 if ($this->code ==
false) {
1238 if (!is_readable($this->ttf_file)) {
1239 imagestring($this->im, 4, 10, ($this->image_height / 2) - 5,
'Failed to load TTF font file!', $this->gdtextcolor);
1241 if ($this->perturbation > 0) {
1242 $font_size = $height2 * .4;
1243 $bb = imageftbbox($font_size, 0, $this->ttf_file, $this->code_display);
1244 $tx = $bb[4] - $bb[0];
1245 $ty = $bb[5] - $bb[1];
1246 $x = floor($width2 / 2 - $tx / 2 - $bb[0]);
1247 $y = round($height2 / 2 - $ty / 2 - $bb[1]);
1249 imagettftext($this->tmpimg, $font_size, 0,
$x,
$y, $this->gdtextcolor, $this->ttf_file, $this->code_display);
1251 $font_size = $this->image_height * .4;
1252 $bb = imageftbbox($font_size, 0, $this->ttf_file, $this->code_display);
1253 $tx = $bb[4] - $bb[0];
1254 $ty = $bb[5] - $bb[1];
1255 $x = floor($this->image_width / 2 - $tx / 2 - $bb[0]);
1256 $y = round($this->image_height / 2 - $ty / 2 - $bb[1]);
1258 imagettftext($this->im, $font_size, 0,
$x,
$y, $this->gdtextcolor, $this->ttf_file, $this->code_display);
1274 for (
$i = 0;
$i < $numpoles; ++
$i) {
1275 $px[
$i] = mt_rand($this->image_width * 0.2, $this->image_width * 0.8);
1276 $py[
$i] = mt_rand($this->image_height * 0.2, $this->image_height * 0.8);
1277 $rad[
$i] = mt_rand($this->image_height * 0.2, $this->image_height * 0.8);
1278 $tmp = ((-$this->
frand()) * 0.15) - .15;
1279 $amp[
$i] = $this->perturbation * $tmp;
1282 $bgCol = imagecolorat($this->tmpimg, 0, 0);
1285 imagepalettecopy($this->im, $this->tmpimg);
1291 for (
$i = 0;
$i < $numpoles; ++
$i) {
1292 $dx = $ix -
$px[
$i];
1293 $dy = $iy -
$py[
$i];
1294 if ($dx == 0 && $dy == 0) {
1297 $r = sqrt($dx * $dx + $dy * $dy);
1298 if (
$r > $rad[
$i]) {
1301 $rscale = $amp[
$i] * sin(3.14 *
$r / $rad[$i]);
1302 $x += $dx * $rscale;
1303 $y += $dy * $rscale;
1308 if (
$x >= 0 && $x < $width2 && $y >= 0 &&
$y < $height2) {
1309 $c = imagecolorat($this->tmpimg,
$x,
$y);
1312 imagesetpixel($this->im, $ix, $iy,
$c);
1324 $x = $this->image_width * (1 + $line) / ($this->num_lines + 1);
1325 $x += (0.5 - $this->
frand()) * $this->image_width / $this->num_lines;
1326 $y = mt_rand($this->image_height * 0.1, $this->image_height * 0.9);
1328 $theta = ($this->
frand() - 0.5) * M_PI * 0.7;
1330 $len = mt_rand(
$w * 0.4,
$w * 0.7);
1331 $lwid = mt_rand(0, 2);
1333 $k = $this->
frand() * 0.6 + 0.2;
1335 $phi = $this->
frand() * 6.28;
1337 $dx =
$step * cos($theta);
1338 $dy =
$step * sin($theta);
1340 $amp = 1.5 * $this->
frand() / ($k + 5.0 / $len);
1341 $x0 =
$x - 0.5 * $len * cos($theta);
1342 $y0 =
$y - 0.5 * $len * sin($theta);
1344 $ldx = round(-$dy * $lwid);
1345 $ldy = round($dx * $lwid);
1348 $x = $x0 +
$i * $dx + $amp * $dy * sin($k *
$i *
$step + $phi);
1349 $y = $y0 +
$i * $dy - $amp * $dx * sin($k *
$i *
$step + $phi);
1350 imagefilledrectangle($this->im,
$x,
$y,
$x + $lwid,
$y + $lwid, $this->gdlinecolor);
1360 if ($this->noise_level > 10) {
1366 $t0 = microtime(
true);
1370 $points = $this->image_width * $this->image_height *
$this->iscale;
1374 $x = mt_rand(10, $width);
1375 $y = mt_rand(10, $height);
1376 $size = mt_rand(7, 10);
1380 imagefilledarc($this->tmpimg,
$x,
$y,
$size,
$size, 0, 360, $this->gdnoisecolor, IMG_ARC_PIE);
1383 $t1 = microtime(
true);
1401 $bbox = imagettfbbox(10, 0, $this->signature_font, $this->image_signature);
1402 $textlen = $bbox[2] - $bbox[0];
1403 $x = $this->image_width - $textlen - 5;
1404 $y = $this->image_height - 3;
1406 imagettftext($this->im, 10, 0,
$x,
$y, $this->gdsignaturecolor, $this->signature_font, $this->image_signature);
1415 if ($this->send_headers) {
1420 header(
"Expires: Mon, 26 Jul 1997 05:00:00 GMT");
1421 header(
"Last-Modified: " . gmdate(
"D, d M Y H:i:s") .
"GMT");
1422 header(
"Cache-Control: no-store, no-cache, must-revalidate");
1423 header(
"Cache-Control: post-check=0, pre-check=0",
false);
1424 header(
"Pragma: no-cache");
1427 switch ($this->image_type) {
1428 case self::SI_IMAGE_JPEG:
1429 if ($this->send_headers) {
1430 header(
"Content-Type: image/jpeg");
1432 imagejpeg($this->im, null, 90);
1434 case self::SI_IMAGE_GIF:
1435 if ($this->send_headers) {
1436 header(
"Content-Type: image/gif");
1438 imagegif($this->im);
1441 if ($this->send_headers) {
1442 header(
"Content-Type: image/png");
1444 imagepng($this->im);
1448 echo '<hr /><strong>' 1449 .
'Failed to generate captcha image, content has already been ' 1450 .
'output.<br />This is most likely due to misconfiguration or ' 1451 .
'a PHP error was sent to the browser.</strong>';
1454 imagedestroy($this->im);
1455 restore_error_handler();
1457 if (!$this->no_exit) {
1472 if (
$code[
'code'] ==
'') {
1473 if (strlen($this->display_value) > 0) {
1474 $code = array(
'code' => $this->display_value,
'display' => $this->display_value);
1481 if (preg_match(
'/(\d+) (\+|-|x) (\d+)/i',
$code[
'display'], $eq)) {
1485 $sign = str_replace(array(
'+',
'-',
'x'), array(
'plus',
'minus',
'times'), $eq[2]);
1488 $letters = array($left, $sign, $right);
1492 $length = strlen(
$code[
'display']);
1494 for (
$i = 0;
$i < $length; ++
$i) {
1495 $letter =
$code[
'display']{
$i};
1496 $letters[] = $letter;
1512 $fp =
fopen($this->wordlist_file,
'rb');
1517 $fsize = filesize($this->wordlist_file);
1522 if ((
int) $numWords < 1 || (
int) $numWords > 5) {
1529 fseek($fp, mt_rand(0, $fsize - 64), SEEK_SET);
1530 $data = fread($fp, 64);
1531 $data = preg_replace(
"/\r?\n/",
"\n",
$data);
1533 $start = @strpos(
$data,
"\n", mt_rand(0, 56)) + 1;
1539 } elseif (
$end ===
false) {
1545 }
while (++
$i < $numWords);
1549 if ($numWords < 2) {
1563 if (function_exists(
'mb_strlen')) {
1565 $code .= mb_substr($this->charset, mt_rand(0, $cslen - 1), 1,
'UTF-8');
1569 $code .= substr($this->charset, mt_rand(0, $cslen - 1), 1);
1582 if (!is_string($this->code) || strlen($this->code) == 0) {
1590 if ($this->case_sensitive ==
false && preg_match(
'/[A-Z]/',
$code)) {
1593 $this->case_sensitive =
true;
1596 $code_entered = trim(
1597 (($this->case_sensitive) ? $this->code_entered
1598 : strtolower($this->code_entered))
1600 $this->correct_code =
false;
1603 if (strpos(
$code,
' ') !==
false) {
1605 $code_entered = preg_replace(
'/\s+/',
' ', $code_entered);
1606 $code_entered = strtolower($code_entered);
1609 if (
$code == $code_entered) {
1610 $this->correct_code =
true;
1611 if ($this->no_session !=
true) {
1625 if ($this->no_session !=
true) {
1626 if (isset(
$_SESSION[
'securimage_code_value']) && is_scalar(
$_SESSION[
'securimage_code_value'])) {
1628 unset(
$_SESSION[
'securimage_code_value']);
1629 unset(
$_SESSION[
'securimage_code_ctime']);
1637 if ($this->use_database) {
1650 if ($this->use_database && $this->pdo_conn) {
1665 $query =
"INSERT INTO {$this->database_table} (" 1666 .
"id, code, code_display, namespace, created) " 1667 .
"VALUES(?, ?, ?, ?, ?)";
1673 $err =
$stmt->errorInfo();
1674 trigger_error(
"Failed to insert code into database. {$err[1]}: {$err[2]}", E_USER_WARNING);
1686 $this->pdo_conn =
false;
1688 if ($this->use_database) {
1689 $pdo_extension =
'PDO_' . strtoupper($this->database_driver);
1691 if (!extension_loaded($pdo_extension)) {
1692 trigger_error(
"Database support is turned on in Securimage, but the chosen extension $pdo_extension is not loaded in PHP.", E_USER_WARNING);
1697 if ($this->database_driver == self::SI_DRIVER_SQLITE3) {
1698 if (!file_exists($this->database_file)) {
1699 $fp =
fopen($this->database_file,
'w+');
1701 $err = error_get_last();
1702 trigger_error(
"Securimage failed to create SQLite3 database file '{$this->database_file}'. Reason: {$err['message']}", E_USER_WARNING);
1706 chmod($this->database_file, 0666);
1707 } elseif (!is_writeable($this->database_file)) {
1708 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);
1717 $this->pdo_conn =
new PDO(
$dsn, $this->database_user, $this->database_pass,
$options);
1719 trigger_error(
"Database connection failed: " . $pdoex->getMessage(), E_USER_WARNING);
1729 trigger_error($ex->getMessage(), E_USER_WARNING);
1730 $this->pdo_conn = null;
1734 if (mt_rand(0, 100) / 100.0 == 1.0) {
1743 $dsn = sprintf(
'%s:', $this->database_driver);
1745 switch ($this->database_driver) {
1746 case self::SI_DRIVER_SQLITE3:
1750 case self::SI_DRIVER_MYSQL:
1751 case self::SI_DRIVER_PGSQL:
1753 'host=%s;dbname=%s',
1754 $this->database_host,
1755 $this->database_name
1766 $table = $this->pdo_conn->quote($this->database_table);
1768 switch ($this->database_driver) {
1769 case self::SI_DRIVER_SQLITE3:
1772 $query =
"SELECT COUNT(id) FROM $table";
1775 case self::SI_DRIVER_MYSQL:
1776 $query =
"SHOW TABLES LIKE $table";
1779 case self::SI_DRIVER_PGSQL:
1780 $query =
"SELECT * FROM information_schema.columns WHERE table_name = $table;";
1787 $err = $this->pdo_conn->errorInfo();
1789 if ($this->database_driver == self::SI_DRIVER_SQLITE3 &&
1790 $err[1] === 1 && strpos($err[2],
'no such table') !==
false) {
1794 throw new Exception(
"Failed to check tables: {$err[0]} - {$err[1]}: {$err[2]}");
1795 } elseif ($this->database_driver == self::SI_DRIVER_SQLITE3) {
1798 } elseif (
$result->rowCount() == 0) {
1809 switch ($this->database_driver) {
1810 case self::SI_DRIVER_SQLITE3:
1811 $queries[] =
"CREATE TABLE \"{$this->database_table}\" ( 1813 namespace VARCHAR(32) NOT NULL, 1814 code VARCHAR(32) NOT NULL, 1815 code_display VARCHAR(32) NOT NULL, 1816 created INTEGER NOT NULL, 1817 PRIMARY KEY(id, namespace) 1820 $queries[] =
"CREATE INDEX ndx_created ON {$this->database_table} (created)";
1823 case self::SI_DRIVER_MYSQL:
1824 $queries[] =
"CREATE TABLE `{$this->database_table}` ( 1825 `id` VARCHAR(40) NOT NULL, 1826 `namespace` VARCHAR(32) NOT NULL, 1827 `code` VARCHAR(32) NOT NULL, 1828 `code_display` VARCHAR(32) NOT NULL, 1829 `created` INT NOT NULL, 1830 PRIMARY KEY(id, namespace), 1835 case self::SI_DRIVER_PGSQL:
1836 $queries[] =
"CREATE TABLE {$this->database_table} ( 1837 id character varying(40) NOT NULL, 1838 namespace character varying(32) NOT NULL, 1839 code character varying(32) NOT NULL, 1840 code_display character varying(32) NOT NULL, 1841 created integer NOT NULL, 1842 CONSTRAINT pkey_id_namespace PRIMARY KEY (id, namespace) 1845 $queries[] =
"CREATE INDEX ndx_created ON {$this->database_table} (created);";
1849 $this->pdo_conn->beginTransaction();
1851 foreach ($queries as
$query) {
1852 $result = $this->pdo_conn->query($query);
1855 $err = $this->pdo_conn->errorInfo();
1856 trigger_error(
"Failed to create table. {$err[1]}: {$err[2]}", E_USER_WARNING);
1857 $this->pdo_conn->rollBack();
1858 $this->pdo_conn =
false;
1863 $this->pdo_conn->commit();
1879 if ($this->use_database ==
true && $this->pdo_conn) {
1881 $query =
"SELECT * FROM {$this->database_table} WHERE id = ?";
1889 $query =
"SELECT * FROM {$this->database_table} WHERE id = ? AND namespace = ?";
1895 $err = $this->pdo_conn->errorInfo();
1896 trigger_error(
"Failed to select code from database. {$err[0]}: {$err[1]}", E_USER_WARNING);
1898 if ((
$row =
$stmt->fetch()) !==
false) {
1903 'code_disp' =>
$row[
'code_display']);
1920 if ($this->pdo_conn) {
1922 $ns = $this->pdo_conn->quote($this->
namespace);
1929 $id = $this->pdo_conn->quote(
$id);
1932 "DELETE FROM %s WHERE id = %s AND namespace = %s",
1933 $this->database_table,
1940 trigger_error(
"Failed to delete code from database.", E_USER_WARNING);
1950 if ($this->use_database && $this->pdo_conn) {
1952 $limit = (!is_numeric($this->expiry_time) || $this->expiry_time < 1) ? 86400 : $this->expiry_time;
1955 "DELETE FROM %s WHERE %s - created > %s",
1956 $this->database_table,
1957 $this->pdo_conn->quote($now, PDO::PARAM_INT),
1958 $this->pdo_conn->quote($limit, PDO::PARAM_INT)
1973 if (!is_numeric($this->expiry_time) || $this->expiry_time < 1) {
1975 } elseif (time() - $creation_time < $this->expiry_time) {
1993 foreach ($letters as $letter) {
1994 $letter = strtoupper($letter);
1997 $l =
new WavFile($this->audio_path .
'/' . $letter .
'.wav');
2001 $wavCaptcha->setSampleRate(
$l->getSampleRate())
2002 ->setBitsPerSample(
$l->getBitsPerSample())
2003 ->setNumChannels(
$l->getNumChannels());
2008 $wavCaptcha->appendWav(
$l);
2011 if ($this->audio_gap_max > 0 && $this->audio_gap_max > $this->audio_gap_min) {
2012 $wavCaptcha->insertSilence(mt_rand($this->audio_gap_min, $this->audio_gap_max) / 1000.0);
2024 if ($this->audio_use_noise ==
true) {
2028 if ($noiseFile !==
false && is_readable($noiseFile)) {
2030 $wavNoise =
new WavFile($noiseFile,
false);
2038 if ($wavNoise->getNumBlocks() > 2 * $wavCaptcha->getNumBlocks()) {
2039 $randBlock = mt_rand(0, $wavNoise->getNumBlocks() - $wavCaptcha->getNumBlocks());
2040 $wavNoise->readWavData($randBlock * $wavNoise->getBlockAlign(), $wavCaptcha->getNumBlocks() * $wavNoise->getBlockAlign());
2042 $wavNoise->readWavData();
2043 $randOffset = mt_rand(0, $wavNoise->getNumBlocks() - 1);
2047 $mixOpts = array(
'wav' => $wavNoise,
2049 'blockOffset' => $randOffset);
2056 if ($this->degrade_audio ==
true) {
2062 if (!empty($filters)) {
2063 $wavCaptcha->filter($filters);
2066 return $wavCaptcha->__toString();
2073 if (($dh = opendir($this->audio_noise_path)) !==
false) {
2076 while (($file = readdir($dh)) !==
false) {
2077 if ($file ==
'.' || $file ==
'..') {
2080 if (strtolower(substr($file, -4)) !=
'.wav') {
2089 if (
sizeof(
$list) > 0) {
2091 $return = $this->audio_noise_path . DIRECTORY_SEPARATOR . $file;
2105 return @file_get_contents(dirname(__FILE__) .
'/audio/en/error.wav');
2115 if (headers_sent()) {
2118 } elseif (strlen((
string) ob_get_contents()) > 0) {
2133 return 0.0001 * mt_rand(0, 9999);
2143 if ($color == null) {
2145 } elseif (is_string($color)) {
2151 } elseif (is_array($color) &&
sizeof($color) == 3) {
2173 public function errorHandler($errno, $errstr, $errfile =
'', $errline = 0, $errcontext = array())
2176 $level = error_reporting();
2179 if ($level == 0 || ($level & $errno) == 0) {
2216 $args = func_get_args();
2218 if (
sizeof($args) == 0) {
2222 } elseif (
sizeof($args) == 1) {
2224 if (substr($color, 0, 1) ==
'#') {
2225 $color = substr($color, 1);
2228 if (strlen($color) != 3 && strlen($color) != 6) {
2230 'Invalid HTML color code passed to Securimage_Color' 2234 $this->constructHTML($color);
2235 } elseif (
sizeof($args) == 3) {
2236 $this->constructRGB($args[0], $args[1], $args[2]);
2239 'Securimage_Color constructor expects 0, 1 or 3 arguments; ' .
sizeof($args) .
' given' 2282 if (strlen($color) == 3) {
2283 $red = str_repeat(substr($color, 0, 1), 2);
2284 $green = str_repeat(substr($color, 1, 1), 2);
2285 $blue = str_repeat(substr($color, 2, 1), 2);
2287 $red = substr($color, 0, 2);
2288 $green = substr($color, 2, 2);
2289 $blue = substr($color, 4, 2);
2292 $this->r = hexdec(
$red);
2293 $this->g = hexdec(
$green);
2294 $this->b = hexdec(
$blue);
drawWord()
Draws the captcha code on the image.
openDatabase()
Open sqlite database.
if(isset($_REQUEST['delete'])) $list
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
static getPath()
Return the absolute path to the Securimage directory.
audioError()
Return a wav file saying there was an error generating file.
drawNoise()
Draws random noise on the image.
static getCaptchaId($new=true, array $options=array())
Generate a new captcha ID or retrieve the current ID.
getAudibleCode()
Gets the code and returns the binary audio file for the stored captcha code.
saveData()
Save data to session namespace and database if used.
setBackground()
The the background color, or background image to be used.
Project: Securimage: A PHP class for creating and managing form CAPTCHA images File: securimage...
constructHTML($color)
Construct from an html hex color code.
frand()
Return a random float between 0 and 0.9999.
createCode()
Generates the code or math problem and saves the value to the session.
saveCodeToDatabase()
Saves the code to the sqlite database.
initColor($color, $default)
Convert an html color code to a Securimage_Color.
readCodeFromFile($numWords=1)
Gets a captcha code from a wordlist.
if(!array_key_exists('StateId', $_REQUEST)) $id
generateCode()
Generates a random captcha code from the set character set.
$text_transparency_percentage
show($background_image='')
Used to serve a captcha image to the browser.
getBackgroundFromDirectory()
Scan the directory for a background image to use.
foreach($paths as $path) $dsn
validate()
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.
getCode($array=false, $returnExisting=false)
Return the code from the session or sqlite database if used.
isCodeExpired($creation_time)
Checks to see if the captcha code has expired and cannot be used.
addSignature()
Print signature text on image.
const SI_CAPTCHA_MATHEMATIC
errorHandler($errno, $errstr, $errfile='', $errline=0, $errcontext=array())
Error handler used when outputting captcha image or audio.
clearCodeFromDatabase()
Remove an entered code from the database.
doImage()
The main image drawing routing, responsible for constructing the entire image and serving it...
foreach( $_REQUEST as $var) foreach(array('_POST'=> 'HTTP_POST_VARS', '_GET'=> 'HTTP_GET_VARS', '_COOKIE'=> 'HTTP_COOKIE_VARS', '_SERVER'=> 'HTTP_SERVER_VARS', '_ENV'=> 'HTTP_ENV_VARS', '_FILES'=> 'HTTP_POST_FILES') as $array=> $other) $step
getCodeFromDatabase()
Get a code from the sqlite database for ip address/captchaId.
purgeOldCodesFromDatabase()
Deletes old codes from sqlite database.
static checkByCaptchaId($id, $value, array $options=array())
Validate a captcha code input against a captcha ID.
outputAudioFile()
Output a wav file of the captcha code to the browser.
output()
Sends the appropriate image and cache headers and outputs image to the browser.
allocateColors()
Allocate the colors to be used for the image.
canSendHeaders()
Checks to see if headers can be sent and if any error has been output to the browser.
__construct($options=array())
Create a new securimage object, pass options to set in the constructor.
__construct($color='#ffffff')
Create a new Securimage_Color object.
constructRGB($red, $green, $blue)
Construct from an rgb triplet.
if(empty($password)) $table
check($code)
Check a submitted code against the stored value.
drawLines()
Draws distorted lines on the image.
generateWAV($letters)
Generate a wav file given the $letters in the code.
distortedCopy()
Copies the captcha image to the final image with distortion applied.