Просмотр файла system/classes/captcha.php

Размер файла: 9.79Kb
  1. <?php
  2.  
  3. class KCAPTCHA {
  4. // generates keystring and image
  5. function KCAPTCHA() {
  6. ////////////////////////////////////////////////////////////
  7. // Настройки CAPTCHA //
  8. ////////////////////////////////////////////////////////////
  9. $alphabet = "abcdeghmzxwq0123456789";
  10. //$allowed_symbols = "abcdeghmzxwq0123456789";
  11. $allowed_symbols = "abcdeghmzxwq0123456789"; // Не ставить похожие символы (o=0, 1=l, i=j, t=f)
  12. $fontsdir = '/template/fonts/'; // папка с шрифтами
  13. $length = mt_rand(4, 5);
  14. $width = 100;
  15. $height = 50;
  16. $fluctuation_amplitude = 5;
  17. $no_spaces = true;
  18. $show_credits = false;
  19. $credits = '';
  20. $foreground_color = array (
  21. mt_rand(0, 100),
  22. mt_rand(0, 100),
  23. mt_rand(0, 100)
  24. );
  25. $background_color = array (
  26. mt_rand(200, 255),
  27. mt_rand(200, 255),
  28. mt_rand(200, 255)
  29. );
  30. $jpeg_quality = 90;
  31. ////////////////////////////////////////////////////////////
  32. $fonts = array ();
  33. $fontsdir_absolute = dirname(__FILE__) . '/' . $fontsdir;
  34. if ($handle = opendir($fontsdir_absolute)) {
  35. while (false !== ($file = readdir($handle))) {
  36. if (preg_match('/\.png$/i', $file)) {
  37. $fonts[] = $fontsdir_absolute . '/' . $file;
  38. }
  39. }
  40. closedir($handle);
  41. }
  42. $alphabet_length = strlen($alphabet);
  43. do {
  44. // generating random keystring
  45. while (true) {
  46. $this->keystring = '';
  47. for ($i = 0; $i < $length; $i++) {
  48. $this->keystring .= $allowed_symbols{mt_rand(0, strlen($allowed_symbols) - 1)};
  49. }
  50. if (!preg_match('/cp|cb|ck|c6|c9|rn|rm|mm|co|do|cl|db|qp|qb|dp|ww/', $this->keystring))
  51. break;
  52. }
  53. $font_file = $fonts[mt_rand(0, count($fonts) - 1)];
  54. $font = imagecreatefrompng($font_file);
  55. imagealphablending($font, true);
  56. $fontfile_width = imagesx($font);
  57. $fontfile_height = imagesy($font) - 1;
  58. $font_metrics = array ();
  59. $symbol = 0;
  60. $reading_symbol = false;
  61. // loading font
  62. for ($i = 0; $i < $fontfile_width && $symbol < $alphabet_length; $i++) {
  63. $transparent = (imagecolorat($font, $i, 0) >> 24) == 127;
  64. if (!$reading_symbol && !$transparent) {
  65. $font_metrics[$alphabet{$symbol}] = array ('start' => $i);
  66. $reading_symbol = true;
  67. continue;
  68. }
  69. if ($reading_symbol && $transparent) {
  70. $font_metrics[$alphabet{$symbol}]['end'] = $i;
  71. $reading_symbol = false;
  72. $symbol++;
  73. continue;
  74. }
  75. }
  76. $img = imagecreatetruecolor($width, $height);
  77. imagealphablending($img, true);
  78. $white = imagecolorallocate($img, 255, 255, 255);
  79. $black = imagecolorallocate($img, 0, 0, 0);
  80. imagefilledrectangle($img, 0, 0, $width - 1, $height - 1, $white);
  81. // draw text
  82. $x = 1;
  83. for ($i = 0; $i < $length; $i++) {
  84. $m = $font_metrics[$this->keystring{$i}];
  85. $y = mt_rand(-$fluctuation_amplitude, $fluctuation_amplitude) + ($height - $fontfile_height) / 2 + 2;
  86. if ($no_spaces) {
  87. $shift = 0;
  88. if ($i > 0) {
  89. $shift = 10000;
  90. for ($sy = 7; $sy < $fontfile_height - 20; $sy += 1) {
  91. for ($sx = $m['start'] - 1; $sx < $m['end']; $sx += 1) {
  92. $rgb = imagecolorat($font, $sx, $sy);
  93. $opacity = $rgb >> 24;
  94. if ($opacity < 127) {
  95. $left = $sx - $m['start'] + $x;
  96. $py = $sy + $y;
  97. if ($py > $height)
  98. break;
  99. for ($px = min($left, $width - 1); $px > $left - 12 && $px >= 0; $px -= 1) {
  100. $color = imagecolorat($img, $px, $py) & 0xff;
  101. if ($color + $opacity < 190) {
  102. if ($shift > $left - $px) {
  103. $shift = $left - $px;
  104. }
  105. break;
  106. }
  107. }
  108. break;
  109. }
  110. }
  111. }
  112. if ($shift == 10000) {
  113. $shift = mt_rand(4, 6);
  114. }
  115. }
  116. } else {
  117. $shift = 1;
  118. }
  119. imagecopy($img, $font, $x - $shift, $y, $m['start'], 1, $m['end'] - $m['start'], $fontfile_height);
  120. $x += $m['end'] - $m['start'] - $shift;
  121. }
  122. } while ($x >= $width - 10); // while not fit in canvas
  123. $center = $x / 2;
  124. // credits. To remove, see configuration file
  125. $img2 = imagecreatetruecolor($width, $height + ($show_credits ? 12 : 0));
  126. $foreground = imagecolorallocate($img2, $foreground_color[0], $foreground_color[1], $foreground_color[2]);
  127. $background = imagecolorallocate($img2, $background_color[0], $background_color[1], $background_color[2]);
  128. imagefilledrectangle($img2, 0, 0, $width - 1, $height - 1, $background);
  129. imagefilledrectangle($img2, 0, $height, $width - 1, $height + 12, $foreground);
  130. $credits = empty($credits) ? $_SERVER['HTTP_HOST'] : $credits;
  131. imagestring($img2, 2, $width / 2 - imagefontwidth(2) * strlen($credits) / 2, $height - 2, $credits, $background);
  132. // periods
  133. $rand1 = mt_rand(750000, 1200000) / 10000000;
  134. $rand2 = mt_rand(750000, 1200000) / 10000000;
  135. $rand3 = mt_rand(750000, 1200000) / 10000000;
  136. $rand4 = mt_rand(750000, 1200000) / 10000000;
  137. // phases
  138. $rand5 = mt_rand(0, 31415926) / 10000000;
  139. $rand6 = mt_rand(0, 31415926) / 10000000;
  140. $rand7 = mt_rand(0, 31415926) / 10000000;
  141. $rand8 = mt_rand(0, 31415926) / 10000000;
  142. // amplitudes
  143. $rand9 = mt_rand(330, 420) / 110;
  144. $rand10 = mt_rand(330, 450) / 110;
  145. //wave distortion
  146. for ($x = 0; $x < $width; $x++) {
  147. for ($y = 0; $y < $height; $y++) {
  148. $sx = $x + (sin($x * $rand1 + $rand5) + sin($y * $rand3 + $rand6)) * $rand9 - $width / 2 + $center + 1;
  149. $sy = $y + (sin($x * $rand2 + $rand7) + sin($y * $rand4 + $rand8)) * $rand10;
  150. if ($sx < 0 || $sy < 0 || $sx >= $width - 1 || $sy >= $height - 1) {
  151. continue;
  152. } else {
  153. $color = imagecolorat($img, $sx, $sy) & 0xFF;
  154. $color_x = imagecolorat($img, $sx + 1, $sy) & 0xFF;
  155. $color_y = imagecolorat($img, $sx, $sy + 1) & 0xFF;
  156. $color_xy = imagecolorat($img, $sx + 1, $sy + 1) & 0xFF;
  157. }
  158. if ($color == 255 && $color_x == 255 && $color_y == 255 && $color_xy == 255) {
  159. continue;
  160. } else if ($color == 0 && $color_x == 0 && $color_y == 0 && $color_xy == 0) {
  161. $newred = $foreground_color[0];
  162. $newgreen = $foreground_color[1];
  163. $newblue = $foreground_color[2];
  164. } else {
  165. $frsx = $sx - floor($sx);
  166. $frsy = $sy - floor($sy);
  167. $frsx1 = 1 - $frsx;
  168. $frsy1 = 1 - $frsy;
  169.  
  170. $newcolor = ($color * $frsx1 * $frsy1 + $color_x * $frsx * $frsy1 + $color_y * $frsx1 * $frsy + $color_xy * $frsx * $frsy);
  171. if ($newcolor > 255)
  172. $newcolor = 255;
  173. $newcolor = $newcolor / 255;
  174. $newcolor0 = 1 - $newcolor;
  175. $newred = $newcolor0 * $foreground_color[0] + $newcolor * $background_color[0];
  176. $newgreen = $newcolor0 * $foreground_color[1] + $newcolor * $background_color[1];
  177. $newblue = $newcolor0 * $foreground_color[2] + $newcolor * $background_color[2];
  178. }
  179. imagesetpixel($img2, $x, $y, imagecolorallocate($img2, $newred, $newgreen, $newblue));
  180. }
  181. }
  182. header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
  183. header('Cache-Control: no-store, no-cache, must-revalidate');
  184. header('Cache-Control: post-check=0, pre-check=0', FALSE);
  185. header('Pragma: no-cache');
  186. if (function_exists("imagejpeg")) {
  187. header("Content-Type: image/jpeg");
  188. imagejpeg($img2, null, $jpeg_quality);
  189. } else if (function_exists("imagegif")) {
  190. header("Content-Type: image/gif");
  191. imagegif($img2);
  192. } else if (function_exists("imagepng")) {
  193. header("Content-Type: image/x-png");
  194. imagepng($img2);
  195. }
  196. }
  197.  
  198. // returns keystring
  199. function getKeyString() { return $this->keystring; }
  200. }
  201.  
  202. // Обрабатываем запрос на картинку CAPTCHA
  203. session_name('PSID');
  204. session_start();
  205. $captcha = new KCAPTCHA();
  206. $_SESSION['captcha'] = $captcha->getKeyString();