PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/captcha/engine_potpourri.php

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