/berry/lib/captcha/kcaptcha.php

http://goodgirl.googlecode.com/ · PHP · 257 lines · 172 code · 49 blank · 36 comment · 52 complexity · 81a7f44c321b6bb4dc3248cd82bf5bfa MD5 · raw file

  1. <?
  2. # KCAPTCHA PROJECT VERSION 1.2.6
  3. # Automatic test to tell computers and humans apart
  4. # Copyright by Kruglov Sergei, 2006, 2007, 2008
  5. # www.captcha.ru, www.kruglov.ru
  6. # System requirements: PHP 4.0.6+ w/ GD
  7. # KCAPTCHA is a free software. You can freely use it for building own site or software.
  8. # If you use this software as a part of own sofware, you must leave copyright notices intact or add KCAPTCHA copyright notices to own.
  9. # As a default configuration, KCAPTCHA has a small credits text at bottom of CAPTCHA image.
  10. # You can remove it, but I would be pleased if you left it. ;)
  11. # See kcaptcha_config.php for customization
  12. // http://dle-news.ru
  13. class kcaptcha {
  14. // ?????????? ????????? ??????? ---------
  15. var $alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"; // ?? ?????????, ???? ?? ?? ???????? ???? ???????!
  16. // ?????????????????? ???? ?????? ?????????!
  17. // ????? ? ????????
  18. var $fontsdir = 'fonts';
  19. // ?????? ??????????? CAPTCHA (??????????? ?????????)
  20. var $width = 100;
  21. var $height = 50;
  22. // ????????? ???????????? ?????????? ????????, ???????? ?? 2
  23. var $fluctuation_amplitude = 2;
  24. // ??? ?????????? ???????????? ????? ?????? ??????? ????? ?????????
  25. var $no_spaces = true;
  26. // ???????? JPEG-??????????? CAPTCHA (??? ??????, ??? ???? ????????)
  27. var $jpeg_quality = 80; // ????????????, ????? ????????? 70-80
  28. var $keystring = ''; // ???????? ???????????? ??????
  29. // ???????, ???????????? ??? ????????? ???????????????? ??????????? CAPTCHA
  30. var $allowed_symbols = "23456789abcdeghkmnpqsuvxyz"; // ??????? ??? ??????? ???????? (o=0, 1=l, i=j, t=f)
  31. // ---------- ---------- ---------- ---------- ----------
  32. // ????????? ?????? ---------- ---------- -------
  33. function genstring($length = 4) {
  34. // ????? ?????? (?????????? ????????) CAPTCHA
  35. // ????????? ????? ? ???????? ?? $length_min ?? $length_max ????????????
  36. //$length = mt_rand( $this->length_min, $this->length_max );
  37. $this->length = $length;
  38. while (true) { // ??????????? ????, ???? ?? ?????????? ??????? ?????? =)
  39. $this->keystring = '';
  40. for ($i = 0; $i < $length ; $i++) {
  41. // ? ????? ????????? ? ?????? ?? 1 ?????????? ???????
  42. $this->keystring .= $this->allowed_symbols{ mt_rand( 0, strlen( $this->allowed_symbols ) -1 ) };
  43. }
  44. if (!preg_match( '/cp|cb|ck|c6|c9|rn|rm|co|do/', $this->keystring )) break;
  45. }
  46. }
  47. // ---------- ---------- ---------- ---------- ----------
  48. // ????????? ???????????
  49. function genimage() {
  50. // ????? ??????????? CAPTCHA (RGB, 0-255)
  51. $foreground_color = array( mt_rand( 0, 100 ), mt_rand( 0, 100 ), mt_rand( 0, 100 ) );
  52. $background_color = array( mt_rand( 200, 255 ), mt_rand( 200, 255 ), mt_rand( 200, 255 ) ); // ??? ?????? ???????
  53. $fonts = array();
  54. $fontsdir_absolute = dirname( __FILE__ ).'/'.$this->fontsdir; // ???? ? ????? ? ????????
  55. if ($handle = opendir( $fontsdir_absolute )) { // ??????? ?????? ? ??????? ?????? ? ???????????? ? ????????
  56. while (false !== ($file = readdir( $handle ))) {
  57. if (preg_match( '/\.png$/i', $file )) {
  58. $fonts[] = $fontsdir_absolute.'/'.$file;
  59. }
  60. }
  61. closedir( $handle );
  62. }
  63. $alphabet_length = strlen( $this->alphabet );
  64. while (true) {
  65. $font_file = $fonts[mt_rand( 0, count( $fonts ) - 1 )]; // ???????? ????????? ???? ??????
  66. $font = imagecreatefrompng( $font_file );
  67. $black = imagecolorallocate( $font, 0, 0, 0 );
  68. $fontfile_width = imagesx( $font );
  69. $fontfile_height = imagesy( $font ) - 1;
  70. $font_metrics = array();
  71. $symbol = 0;
  72. $reading_symbol = false;
  73. // loading font
  74. for ($i = 0; $i < $fontfile_width && $symbol < $alphabet_length; $i++) {
  75. $transparent = (imagecolorat( $font, $i, 0 ) >> 24) == 127;
  76. if (!$reading_symbol && !$transparent) {
  77. $font_metrics[$this->alphabet{$symbol}] = array( 'start' => $i );
  78. $reading_symbol = true;
  79. continue;
  80. }
  81. if ($reading_symbol && $transparent) {
  82. $font_metrics[$this->alphabet{$symbol}]['end'] = $i;
  83. $reading_symbol = false;
  84. $symbol++;
  85. continue;
  86. }
  87. }
  88. $img = imagecreatetruecolor( $this->width, $this->height );
  89. $white = imagecolorallocate( $img, 255, 255, 255 );
  90. $black = imagecolorallocate( $img, 0, 0, 0 );
  91. imagefilledrectangle( $img, 0, 0, $this->width - 1, $this->height - 1, $white );
  92. // draw text
  93. $x = 1;
  94. $shift = 0;
  95. for ($i = 0; $i < $this->length; $i++) {
  96. $m = $font_metrics[$this->keystring{$i}];
  97. $y = mt_rand( -$this->fluctuation_amplitude, $this->fluctuation_amplitude ) + ($this->height - $fontfile_height) / 2 + 2;
  98. if ($this->no_spaces) {
  99. $shift = 0;
  100. if ($i > 0) {
  101. $shift = 1000;
  102. for ($sy = 1; $sy < $fontfile_height - 15; $sy += 2) {
  103. for ($sx = $m['start'] - 1; $sx < $m['end']; $sx++) {
  104. $rgb = imagecolorat( $font, $sx, $sy );
  105. $opacity = $rgb >> 24;
  106. if ($opacity < 127) {
  107. $left = $sx - $m['start'] + $x;
  108. $py = $sy + $y;
  109. for ($px = min( $left, $this->width - 1 ); $px > $left - 15 && $px >= 0; $px--) {
  110. $color = imagecolorat( $img, $px, $py ) & 0xff;
  111. if ($color + $opacity < 190) {
  112. if ($shift > $left-$px) {
  113. $shift = $left - $px;
  114. }
  115. break;
  116. }
  117. }
  118. break;
  119. }
  120. }
  121. }
  122. }
  123. } else {
  124. $shift = 1;
  125. }
  126. imagecopy( $img, $font, $x - $shift, $y, $m['start'], 1, $m['end'] - $m['start'], $fontfile_height );
  127. $x += $m['end'] - $m['start'] - $shift;
  128. }
  129. if ($x < $this->width - 10) break; // fit in canvas
  130. }
  131. $center = $x/2;
  132. $img2=imagecreatetruecolor($this->width, $this->height);
  133. $foreground=imagecolorallocate($img2, $foreground_color[0], $foreground_color[1], $foreground_color[2]);
  134. $background=imagecolorallocate($img2, $background_color[0], $background_color[1], $background_color[2]);
  135. imagefilledrectangle($img2, 0, $this->height, $this->width, $this->height+12, $foreground);
  136. // periods
  137. $rand1 = mt_rand( 750000, 1200000 ) / 10000000;
  138. $rand2 = mt_rand( 750000, 1200000 ) / 10000000;
  139. $rand3 = mt_rand( 750000, 1200000 ) / 10000000;
  140. $rand4 = mt_rand( 750000, 1200000 ) / 10000000;
  141. // phases
  142. $rand5 = mt_rand( 0, 3141592 ) / 500000;
  143. $rand6 = mt_rand( 0, 3141592 ) / 500000;
  144. $rand7 = mt_rand( 0, 3141592 ) / 500000;
  145. $rand8 = mt_rand( 0, 3141592 ) / 500000;
  146. // amplitudes
  147. $rand9 = mt_rand( 330, 420 ) / 110;
  148. $rand10 = mt_rand(330, 450 ) / 110;
  149. //wave distortion
  150. for ($x = 0; $x < $this->width; $x++) {
  151. for ($y = 0; $y < $this->height; $y++) {
  152. $sx = $x + (sin( $x * $rand1 + $rand5 ) + sin( $y * $rand3 + $rand6 )) * $rand9 - $this->width / 2 + $center + 1;
  153. $sy = $y + (sin( $x * $rand2 + $rand7 ) + sin( $y * $rand4 + $rand8 )) * $rand10;
  154. if ($sx < 0 || $sy < 0 || $sx >= $this->width - 1 || $sy >= $this->height - 1) {
  155. $color = 255;
  156. $color_x = 255;
  157. $color_y = 255;
  158. $color_xy = 255;
  159. } else {
  160. $color = imagecolorat( $img, $sx, $sy ) & 0xFF;
  161. $color_x = imagecolorat( $img, $sx + 1, $sy ) & 0xFF;
  162. $color_y = imagecolorat( $img, $sx, $sy + 1 ) & 0xFF;
  163. $color_xy = imagecolorat( $img, $sx + 1, $sy + 1 ) & 0xFF;
  164. }
  165. if ($color == 0 && $color_x == 0 && $color_y == 0 && $color_xy == 0) {
  166. $newred = $foreground_color[0];
  167. $newgreen = $foreground_color[1];
  168. $newblue = $foreground_color[2];
  169. } else if ($color == 255 && $color_x == 255 && $color_y == 255 && $color_xy == 255) {
  170. $newred = $background_color[0];
  171. $newgreen = $background_color[1];
  172. $newblue = $background_color[2];
  173. } else {
  174. $frsx = $sx - floor( $sx );
  175. $frsy = $sy - floor( $sy );
  176. $frsx1 = 1 - $frsx;
  177. $frsy1 = 1 - $frsy;
  178. $newcolor = (
  179. $color * $frsx1 * $frsy1 +
  180. $color_x * $frsx * $frsy1 +
  181. $color_y * $frsx1 * $frsy +
  182. $color_xy * $frsx * $frsy);
  183. if ($newcolor > 255) $newcolor = 255;
  184. $newcolor = $newcolor / 255;
  185. $newcolor0 = 1 - $newcolor;
  186. $newred = $newcolor0 * $foreground_color[0] + $newcolor * $background_color[0];
  187. $newgreen = $newcolor0 * $foreground_color[1] + $newcolor * $background_color[1];
  188. $newblue = $newcolor0 * $foreground_color[2] + $newcolor * $background_color[2];
  189. }
  190. imagesetpixel( $img2, $x, $y, imagecolorallocate( $img2, $newred, $newgreen, $newblue ) );
  191. }
  192. }
  193. # ?????
  194. imageline( $img2, 0, 0, $this->width, 0, $foreground );
  195. imageline( $img2, 0, 0, 0, $this->height, $foreground );
  196. imageline( $img2, 0, $this->height-1, $this->width, $this->height-1, $foreground );
  197. imageline( $img2, $this->width-1, 0, $this->width-1, $this->height, $foreground);
  198. header( "Expires: Tue, 11 Jun 1985 05:00:00 GMT" );
  199. header( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . " GMT" );
  200. header( "Cache-Control: no-store, no-cache, must-revalidate" );
  201. header( "Cache-Control: post-check=0, pre-check=0", false );
  202. header( "Pragma: no-cache" );
  203. header( "Content-Type: image/jpeg" );
  204. imagejpeg($img2, null, $this->jpeg_quality);
  205. }
  206. // ---------- ---------- ---------- ---------- ----------
  207. }
  208. ?>