includes/captcha/engine_potpourri.php
changeset 401 6ae6e387a0e3
child 411 d1a95497b68f
equal deleted inserted replaced
400:7eef739a5b81 401:6ae6e387a0e3
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
       
     5  * Version 1.1.1 (Caoineag alpha 1)
       
     6  * Copyright (C) 2006-2007 Dan Fuhry
       
     7  * captcha.php - visual confirmation system used during registration
       
     8  *
       
     9  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
    10  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    13  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
       
    14  */
       
    15 
       
    16 /**
       
    17  * A more complex captcha engine that relies on GD.
       
    18  * @package Enano
       
    19  * @subpackage User management
       
    20  * @copyright 2007-2008 Dan Fuhry
       
    21  * @copyright 2002-2008 phpBB Group
       
    22  */
       
    23  
       
    24 class captcha_engine_potpourri extends captcha_base
       
    25 {
       
    26   var $captcha_config;
       
    27   
       
    28   function __construct($sid, $r = false)
       
    29   {
       
    30     parent::__construct($sid, $r);
       
    31     
       
    32     $hex = Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
       
    33     $latticecolor = '#';
       
    34     for ( $i = 0; $i < 6; $i++ )
       
    35       $latticecolor .= $hex[mt_rand(0, 15)];
       
    36     
       
    37     $this->captcha_config = array (
       
    38       'width' => '350',
       
    39       'height' => '90',
       
    40       'background_color' => '#E5ECF9',
       
    41       'jpeg' => '0',
       
    42       'jpeg_quality' => '95',
       
    43       'pre_letters' => '1',
       
    44       'pre_letters_great' => '0',
       
    45       'font' => '1',
       
    46       'chess' => '2',
       
    47       'ellipses' => '2',
       
    48       'arcs' => '2',
       
    49       'lines' => '2',
       
    50       'image' => '0',
       
    51       'gammacorrect' => '0.8',
       
    52       'foreground_lattice_x' => (string)mt_rand(25, 30),
       
    53       'foreground_lattice_y' => (string)mt_rand(25, 30),
       
    54       'lattice_color' => $latticecolor,
       
    55     );
       
    56   }
       
    57   
       
    58   function make_image()
       
    59   {
       
    60     $code = $this->get_code();
       
    61     
       
    62     // Prefs
       
    63     $total_width = $this->captcha_config['width'];
       
    64     $total_height = $this->captcha_config['height'];
       
    65     
       
    66     $hex_bg_color = $this->get_rgb($this->captcha_config['background_color']);
       
    67     $bg_color = array();
       
    68     $bg_color = explode(",", $hex_bg_color);
       
    69     
       
    70     $jpeg = $this->captcha_config['jpeg'];
       
    71     $img_quality = $this->captcha_config['jpeg_quality'];
       
    72     // Max quality is 95
       
    73     
       
    74     $pre_letters = $this->captcha_config['pre_letters'];
       
    75     $pre_letter_great = $this->captcha_config['pre_letters_great'];
       
    76     $rnd_font = $this->captcha_config['font'];
       
    77     $chess = $this->captcha_config['chess'];
       
    78     $ellipses = $this->captcha_config['ellipses'];
       
    79     $arcs = $this->captcha_config['arcs'];
       
    80     $lines = $this->captcha_config['lines'];
       
    81     $image = $this->captcha_config['image'];
       
    82     
       
    83     $gammacorrect = $this->captcha_config['gammacorrect'];
       
    84     
       
    85     $foreground_lattice_y = $this->captcha_config['foreground_lattice_y'];
       
    86     $foreground_lattice_x = $this->captcha_config['foreground_lattice_x'];
       
    87     $hex_lattice_color = $this->get_rgb($this->captcha_config['lattice_color']);
       
    88     $rgb_lattice_color = array();
       
    89     $rgb_lattice_color = explode(",", $hex_lattice_color);
       
    90     
       
    91     $font_debug = false;
       
    92     
       
    93     // Fonts and images init
       
    94     if ($image)
       
    95     {
       
    96       $bg_imgs = array();
       
    97       if ($img_dir = opendir(ENANO_ROOT.'/includes/captcha/pics/'))
       
    98       {
       
    99         while (true == ($file = @readdir($img_dir))) 
       
   100         { 
       
   101           if ((substr(strtolower($file), -3) == 'jpg') || (substr(strtolower($file), -3) == 'gif'))    
       
   102           {         
       
   103             $bg_imgs[] = $file; 
       
   104           }     
       
   105         }
       
   106         closedir($img_dir);
       
   107       }
       
   108       // Grab a random Background Image or set FALSE if none was found
       
   109       $bg_img = ( count($bg_imgs) ) ? rand(0, (count($bg_imgs)-1)) : false;
       
   110     }
       
   111     
       
   112     $fonts = array();
       
   113     if ($fonts_dir = opendir(ENANO_ROOT . '/includes/captcha/fonts/'))
       
   114     {
       
   115       while (true == ($file = @readdir($fonts_dir))) 
       
   116       { 
       
   117         if ((substr(strtolower($file), strlen($file)-3, strlen($file)) == 'ttf'))
       
   118         {
       
   119           $fonts[] = $file; 
       
   120         }     
       
   121       }
       
   122       closedir($fonts_dir);
       
   123     } else {
       
   124       die('Error reading directory: '.ENANO_ROOT.'/includes/captcha/fonts/');
       
   125     }
       
   126     $font = mt_rand(0, (count($fonts)-1));
       
   127     
       
   128     // Generate
       
   129     $image = ($this->gdVersion() >= 2) ? imagecreatetruecolor($total_width, $total_height) : imagecreate($total_width, $total_height);
       
   130     $background_color = imagecolorallocate($image, $bg_color[0], $bg_color[1], $bg_color[2]);
       
   131     imagefill($image, 0, 0, $background_color);
       
   132     
       
   133     // Generate backgrund
       
   134     if ($chess == '1' || $chess == '2' && rand(0,1))
       
   135     {
       
   136       // Draw rectangles
       
   137       for($i = 0; $i <= 8; $i++)
       
   138       {
       
   139         $rectanglecolor = imagecolorallocate($image, rand(100,200),rand(100,200),rand(100,200));
       
   140         imagefilledrectangle($image, 0, 0, round($total_width-($total_width/8*$i)), round($total_height), $rectanglecolor);
       
   141         $rectanglecolor = imagecolorallocate($image, rand(100,200),rand(100,200),rand(100,200));
       
   142         imagefilledrectangle($image, 0, 0, round($total_width-($total_width/8*$i)), round($total_height/2), $rectanglecolor);
       
   143       }
       
   144     }
       
   145     if ($ellipses == '1' || $ellipses == '2' && rand(0,1))
       
   146     {
       
   147       // Draw random ellipses
       
   148       for ($i = 1; $i <= 60; $i++)
       
   149       {
       
   150         $ellipsecolor = imagecolorallocate($image, rand(100,250),rand(100,250),rand(100,250));
       
   151         imagefilledellipse($image, round(rand(0, $total_width)), round(rand(0, $total_height)), round(rand(0, $total_width/8)), round(rand(0, $total_height/4)), $ellipsecolor);	
       
   152       }
       
   153     }
       
   154     if ($arcs == '1' || $arcs == '2' && rand(0,1))
       
   155     {
       
   156       // Draw random partial ellipses
       
   157       for ($i = 0; $i <= 30; $i++)
       
   158       {
       
   159         $linecolor = imagecolorallocate($image, rand(120,255),rand(120,255),rand(120,255));
       
   160         $cx = round(rand(1, $total_width));
       
   161         $cy = round(rand(1, $total_height));
       
   162         $int_w = round(rand(1, $total_width/2));
       
   163         $int_h = round(rand(1, $total_height));
       
   164         imagearc($image, $cx, $cy, $int_w, $int_h, round(rand(0, 190)), round(rand(191, 360)), $linecolor);
       
   165         imagearc($image, $cx-1, $cy-1, $int_w, $int_h, round(rand(0, 190)), round(rand(191, 360)), $linecolor);
       
   166       }
       
   167     }
       
   168     if ($lines == '1' || $lines == '2' && rand(0,1))
       
   169     {
       
   170       // Draw random lines
       
   171       for ($i = 0; $i <= 50; $i++)
       
   172       {
       
   173         $linecolor = imagecolorallocate($image, rand(120,255),rand(120,255),rand(120,255));
       
   174         imageline($image, round(rand(1, $total_width*3)), round(rand(1, $total_height*5)), round(rand(1, $total_width/2)), round(rand(1, $total_height*2)), $linecolor);
       
   175       }
       
   176     }
       
   177     
       
   178     $text_color_array = array('255,51,0', '51,77,255', '204,51,102', '0,153,0', '255,166,2', '255,0,255', '255,0,0', '0,255,0', '0,0,255', '0,255,255');
       
   179     shuffle($text_color_array);
       
   180     $pre_text_color_array = array('255,71,20', '71,20,224', '224,71,122', '20,173,20', '255,186,22', '25,25,25');
       
   181     shuffle($pre_text_color_array);
       
   182     $white = imagecolorallocate($image, 255, 255, 255);
       
   183     $gray = imagecolorallocate($image, 100, 100, 100);
       
   184     $black = imagecolorallocate($image, 0, 0, 0);
       
   185     $lattice_color = imagecolorallocate($image, $rgb_lattice_color[0], $rgb_lattice_color[1], $rgb_lattice_color[2]);
       
   186     
       
   187     $x_char_position = (round(($total_width - 12) / strlen($code)) + mt_rand(-3, 5));
       
   188     
       
   189     for ($i = 0; $i < strlen($code); $i++)
       
   190     {
       
   191       mt_srand((double)microtime()*1000000);
       
   192     
       
   193       $char = $code{$i};
       
   194       $size = mt_rand(floor($total_height / 3.5), ceil($total_height / 2.8));
       
   195       $font = ($rnd_font) ? rand(0, (count($fonts)-1)) : $font;
       
   196       $angle = mt_rand(-30, 30);
       
   197     
       
   198       $char_pos = array();
       
   199       $char_pos = imagettfbbox($size, $angle, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   200       $letter_width = abs($char_pos[0]) + abs($char_pos[4]);
       
   201       $letter_height = abs($char_pos[1]) + abs($char_pos[5]);
       
   202     
       
   203       $x_pos = ($x_char_position / 4) + ($i * $x_char_position);
       
   204       ($i == strlen($code)-1 && $x_pos >= ($total_width - ($letter_width + 5))) ? $x_pos = ($total_width - ($letter_width + 5)) : '';
       
   205       $y_pos = mt_rand(($size * 1.4 ), $total_height - ($size * 0.4));
       
   206     
       
   207     //	Pre letters
       
   208       $size = ($pre_letter_great) ? $size + (2 * $pre_letters) : $size - (2 * $pre_letters);
       
   209       for ($count = 1; $count <= $pre_letters; $count++)
       
   210       {
       
   211         $pre_angle = $angle + mt_rand(-20, 20);
       
   212     
       
   213         $text_color = $pre_text_color_array[mt_rand(0,count($pre_text_color_array)-1)];
       
   214         $text_color = explode(",", $text_color);
       
   215         $textcolor = imagecolorallocate($image, $text_color[0], $text_color[1], $text_color[2]);
       
   216     
       
   217         imagettftext($image, $size, $pre_angle, $x_pos, $y_pos-2, $white, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   218         imagettftext($image, $size, $pre_angle, $x_pos+2, $y_pos, $black, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   219         imagettftext($image, $size, $pre_angle, $x_pos+1, $y_pos-1, $textcolor, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   220     
       
   221         $size = ($pre_letter_great) ? $size - 2 : $size + 2;
       
   222       }
       
   223     
       
   224     //	Final letters
       
   225       $text_color = $text_color_array[mt_rand(0,count($text_color_array)-1)];
       
   226       $text_color = explode(",", $text_color);
       
   227       $textcolor = imagecolorallocate($image, $text_color[0], $text_color[1], $text_color[2]);
       
   228     
       
   229       imagettftext($image, $size, $angle, $x_pos, $y_pos-2, $white, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   230       imagettftext($image, $size, $angle, $x_pos+2, $y_pos, $black, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   231       imagettftext($image, $size, $angle, $x_pos+1, $y_pos-1, $textcolor, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
       
   232     }
       
   233     
       
   234     
       
   235     ($gammacorrect) ? imagegammacorrect($image, 1.0, $gammacorrect) : '';
       
   236     
       
   237     // Generate a white lattice in foreground
       
   238     if ($foreground_lattice_y)
       
   239     {
       
   240       // x lines
       
   241       $ih = round($total_height / $foreground_lattice_y);
       
   242       for ($i = 0; $i <= $ih; $i++)
       
   243       {
       
   244         imageline($image, 0, $i*$foreground_lattice_y, $total_width, $i*$foreground_lattice_y, $lattice_color);
       
   245       }
       
   246     }
       
   247     if ($foreground_lattice_x)
       
   248     {
       
   249       // y lines
       
   250       $iw = round($total_width / $foreground_lattice_x);
       
   251       for ($i = 0; $i <= $iw; $i++)
       
   252       {
       
   253         imageline($image, $i*$foreground_lattice_x, 0, $i*$foreground_lattice_x, $total_height, $lattice_color);
       
   254       }
       
   255     }
       
   256     
       
   257     // Font debug
       
   258     if ($font_debug && !$rnd_font)
       
   259     {
       
   260       imagestring($image, 5, 2, 0, $fonts[$font], $white);
       
   261       imagestring($image, 5, 5, 0, $fonts[$font], $white);
       
   262       imagestring($image, 5, 4, 2, $fonts[$font], $gray);
       
   263       imagestring($image, 5, 3, 1, $fonts[$font], $black);
       
   264     }
       
   265     
       
   266     // Display
       
   267     header("Last-Modified: " . gmdate("D, d M Y H:i:s") ." GMT"); 
       
   268     header("Pragma: no-cache"); 
       
   269     header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");
       
   270     (!$jpeg) ? header("Content-Type: image/png") : header("Content-Type: image/jpeg");
       
   271     
       
   272     (!$jpeg) ? imagepng($image) : imagejpeg($image, '', $img_quality);
       
   273     imagedestroy($image);
       
   274   }
       
   275   
       
   276   // Function get_rgb by Frank Burian
       
   277   // http://www.phpfuncs.org/?content=show&id=46
       
   278   function get_rgb($hex) { 
       
   279     $hex_array = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
       
   280         'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 
       
   281         'F' => 15); 
       
   282     $hex = str_replace('#', '', strtoupper($hex)); 
       
   283     if (($length = strlen($hex)) == 3) { 
       
   284         $hex = $hex{0}.$hex{0}.$hex{1}.$hex{1}.$hex{2}.$hex{2}; 
       
   285         $length = 6; 
       
   286     } 
       
   287     if ($length != 6 or strlen(str_replace(array_keys($hex_array), '', $hex))) 
       
   288         return NULL; 
       
   289     $rgb['r'] = $hex_array[$hex{0}] * 16 + $hex_array[$hex{1}]; 
       
   290     $rgb['g'] = $hex_array[$hex{2}] * 16 + $hex_array[$hex{3}]; 
       
   291     $rgb['b']= $hex_array[$hex{4}] * 16 + $hex_array[$hex{5}]; 
       
   292     return $rgb['r'].','.$rgb['g'].','.$rgb['b']; 
       
   293   }
       
   294   
       
   295   // Function  gdVersion by Hagan Fox
       
   296   // http://de3.php.net/manual/en/function.gd-info.php#52481
       
   297   function gdVersion($user_ver = 0)
       
   298   {
       
   299      if (! extension_loaded('gd')) { return; }
       
   300      static $gd_ver = 0;
       
   301      // Just accept the specified setting if it's 1.
       
   302      if ($user_ver == 1) { $gd_ver = 1; return 1; }
       
   303      // Use the static variable if function was called previously.
       
   304      if ($user_ver !=2 && $gd_ver > 0 ) { return $gd_ver; }
       
   305      // Use the gd_info() function if possible.
       
   306      if (function_exists('gd_info')) {
       
   307          $ver_info = gd_info();
       
   308          preg_match('/\d/', $ver_info['GD Version'], $match);
       
   309          $gd_ver = $match[0];
       
   310          return $match[0];
       
   311      }
       
   312      // If phpinfo() is disabled use a specified / fail-safe choice...
       
   313      if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
       
   314          if ($user_ver == 2) {
       
   315              $gd_ver = 2;
       
   316              return 2;
       
   317          } else {
       
   318              $gd_ver = 1;
       
   319              return 1;
       
   320          }
       
   321      }
       
   322      // ...otherwise use phpinfo().
       
   323      ob_start();
       
   324      phpinfo(8);
       
   325      $info = ob_get_contents();
       
   326      ob_end_clean();
       
   327      $info = stristr($info, 'gd version');
       
   328      preg_match('/\d/', $info, $match);
       
   329      $gd_ver = $match[0];
       
   330      return $match[0];
       
   331   }
       
   332 }