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);