/lib/captcha/Captcha.class.php

https://github.com/opto/web2project · PHP · 267 lines · 189 code · 16 blank · 62 comment · 54 complexity · e89ae04755ece6ef1cad9ef740c7d5ee MD5 · raw file

  1. <?php
  2. /*
  3. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. ::
  5. :: Captcha Version 2.0 by László Zsidi, http://gifs.hu
  6. ::
  7. :: This class is a rewritten 'Captcha.class.php' version.
  8. ::
  9. :: Modification:
  10. :: - Simplified and easy code,
  11. :: - Stable working
  12. ::
  13. ::
  14. :: Created at 2007. 02. 01. '07.47.AM'
  15. ::
  16. */
  17. define ( "ANIM_FRAMES", 5 );
  18. define ( "ANIM_DELAYS", 10 );
  19. Class Captcha {
  20. var $image;
  21. function Captcha ( $text, $font, $color )
  22. {
  23. $C = HexDec ( $color );
  24. $R = floor ( $C / pow ( 256, 2 ) );
  25. $G = floor ( ( $C % pow ( 256, 2 ) ) / pow ( 256, 1 ) );
  26. $B = floor ( ( ( $C % pow ( 256, 2 ) ) % pow ( 256, 1 ) ) / pow ( 256, 0 ) );
  27. $fsize = 32;
  28. $bound = array ( );
  29. $bound = imageTTFBbox ( $fsize, 0, $font, $text );
  30. $this->image = imageCreateTrueColor ( $bound [ 4 ] + 5, abs($bound [ 5 ] ) + 15 );
  31. imageFill ( $this->image, 0, 0, ImageColorAllocate ( $this->image, 255, 255, 255 ) );
  32. imagettftext ( $this->image, $fsize, 0, 2, abs( $bound [ 5 ] ) + 5, ImageColorAllocate ( $this->image, $R, $G, $B ), $font, $text );
  33. }
  34. /*
  35. :::::::::::::::::::::::::::::::::::::::::::::::::::
  36. ::
  37. :: DoNoise...
  38. ::
  39. */
  40. function DoNoise ( $image, $G0, $C0 ) {
  41. $W = imageSX ( $image );
  42. $H = imageSY ( $image );
  43. for ( $i = 0; $i < 768; $i++ ) {
  44. $arrLUT [ $i ] = $i < 512 ? ( $i < 255 ? 0 : ( $i - 256 ) ) : 255;
  45. }
  46. $G1 = $G0 / 2;
  47. $C1 = $C0 / 2;
  48. for ( $y = 0; $y < $H; $y++ ) {
  49. for ( $x = 0; $x < $W; $x++ ) {
  50. $P = imageColorAt ( $image, $x, $y );
  51. $R = ( $P >> 16 ) & 0xFF;
  52. $G = ( $P >> 8 ) & 0xFF;
  53. $B = ( $P >> 0 ) & 0xFF;
  54. $N = rand ( 0, $G0 ) - $G1;
  55. $R += 255 + $N + mt_rand ( 0, $C0 ) - $C1;
  56. $G += 255 + $N + mt_rand ( 0, $C0 ) - $C1;
  57. $B += 255 + $N + mt_rand ( 0, $C0 ) - $C1;
  58. imageSetPixel ( $image, $x, $y, ( $arrLUT [ $R ] << 16 ) | ( $arrLUT [ $G ] << 8 ) | $arrLUT [ $B ] );
  59. }
  60. }
  61. }
  62. /*
  63. :::::::::::::::::::::::::::::::::::::::::::::::::::
  64. ::
  65. :: AnimatedOut...
  66. ::
  67. */
  68. function AnimatedOut ( ) {
  69. for ( $i = 0; $i < ANIM_FRAMES; $i++ ) {
  70. $image = imageCreateTrueColor ( imageSX ( $this->image ), imageSY ( $this->image ) );
  71. if ( imageCopy ( $image, $this->image, 0, 0, 0, 0, imageSX ( $this->image ), imageSY ( $this->image ) ) ) {
  72. Captcha::DoNoise ( $image, 200, 0 );
  73. Ob_Start ( );
  74. imageGif ( $image );
  75. imageDestroy ( $image );
  76. $f_arr [ ] = Ob_Get_Contents ( );
  77. $d_arr [ ] = ANIM_DELAYS;
  78. Ob_End_Clean ( );
  79. }
  80. }
  81. $GIF = new GIFEncoder ( $f_arr, $d_arr, 0, 2, -1, -1, -1, 'C_MEMORY' );
  82. return ( $GIF->GetAnimation ( ) );
  83. }
  84. }
  85. /*
  86. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  87. ::
  88. :: GIFEncoder Version 2.0 by László Zsidi, http://gifs.hu
  89. ::
  90. :: This class is a rewritten 'GifMerge.class.php' version.
  91. ::
  92. :: Modification:
  93. :: - Simplified and easy code,
  94. :: - Ultra fast encoding,
  95. :: - Built-in errors,
  96. :: - Stable working
  97. ::
  98. ::
  99. :: Created at 2007. 02. 01. '07.47.AM'
  100. ::
  101. */
  102. Class GIFEncoder extends Captcha {
  103. var $GIF = 'GIF89a'; /* GIF header 6 bytes */
  104. var $VER = 'GIFEncoder V2.0'; /* Encoder version */
  105. var $ERR = Array (
  106. "ERR00"=>"Does not supported function for only one image!",
  107. "ERR01"=>"Source is not a GIF image!",
  108. "ERR02"=>"Unintelligible flag ",
  109. "ERR03"=>"Missing image descriptor block!<br>First byte of this block "
  110. );
  111. function GIFEncoder (
  112. $GIF_src, $GIF_tim, $GIF_lop, $GIF_dis,
  113. $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod
  114. ) {
  115. /*
  116. :::::::::::::::::::::::::::::::::::::::::::::::::::
  117. ::
  118. :: Set-up conditions & pre-processing frames...
  119. ::
  120. */
  121. if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_tim ) ) {
  122. printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] );
  123. exit ( 0 );
  124. }
  125. if ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) {
  126. $transColor = $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 );
  127. }
  128. else {
  129. $transColor = -1;
  130. }
  131. if ( $GIF_mod == 'C_FILE' ) {
  132. for ( $i = 0; $i < count ( $GIF_src ); $i++ ) {
  133. $GIF_buf [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) );
  134. if ( substr ( $GIF_buf [ $i ], 0, 6 ) != 'GIF87a' && substr ( $GIF_buf [ $i ], 0, 6 ) != 'GIF89a' ) {
  135. printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] );
  136. exit ( 0 );
  137. }
  138. }
  139. }
  140. else if ( $GIF_mod == 'C_MEMORY' ) {
  141. for ( $i = 0; $i < count ( $GIF_src ); $i++ ) {
  142. $GIF_buf [ ] = $GIF_src [ $i ];
  143. if ( substr ( $GIF_buf [ $i ], 0, 6 ) != 'GIF87a' && substr ( $GIF_buf [ $i ], 0, 6 ) != 'GIF89a' ) {
  144. printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] );
  145. exit ( 0 );
  146. }
  147. }
  148. }
  149. else {
  150. printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod );
  151. exit ( 0 );
  152. }
  153. /*
  154. :::::::::::::::::::::::::::::::::::::::::::::::::::
  155. ::
  156. :: Build & post-processing animation...
  157. ::
  158. */
  159. for ( $i = 0; $i < count ( $GIF_buf ); $i++ ) {
  160. $tranid = false;
  161. $length = strlen ( $GIF_buf [ $i ] );
  162. $seek_p = 14 + ( 3 * ( 2 << ( ord ( $GIF_buf [ $i ] { 10 } ) & 0x07 ) ) );
  163. if ( strlen ( $this->GIF ) == 6 ) {
  164. $this->GIF .= substr ( $GIF_buf [ $i ], 6, $seek_p - 7 );
  165. $this->GIF .= "\x21\xFF\x0B" . "NETSCAPE" . "\x32\x2E\x30\x03\x01" . chr ( $GIF_lop & 0xFF ) . chr ( $GIF_lop >> 8 ) . "\x00";
  166. }
  167. if ( ord ( substr ( $GIF_buf [ $i ], $seek_p - 1, 1 ) ) != 0x21 ) {
  168. if ( $transColor > -1 ) {
  169. $rgb = substr ( $GIF_buf [ $i ], 14, 3 * ( 2 << ( ord ( $GIF_buf [ $i ] { 10 } ) & 0x07 ) ) );
  170. for ( $j = 0; $j < ( 2 << ( ord ( $GIF_buf [ $i ] { 10 } ) & 0x07 ) ); $j++ ) {
  171. if (
  172. ord ( $rgb { 3 * $j } ) == ( ( $transColor >> 16 ) & 0xFF ) &&
  173. ord ( $rgb { 3 * $j + 1 } ) == ( ( $transColor >> 8 ) & 0xFF ) &&
  174. ord ( $rgb { 3 * $j + 2 } ) == ( ( $transColor >> 0 ) & 0xFF )
  175. ) {
  176. $tranid = true;
  177. break;
  178. }
  179. }
  180. if ( $tranid && $j < 256 ) {
  181. $GIF_buf [ $i ] .= chr ( 0x21 );
  182. $GIF_buf [ $i ] .= chr ( 0xf9 );
  183. $GIF_buf [ $i ] .= chr ( 0x04 );
  184. $GIF_buf [ $i ] .= chr ( ( $GIF_dis << 2 ) + 1 );
  185. $GIF_buf [ $i ] .= chr ( $GIF_tim [ $i ] & 0xFF );
  186. $GIF_buf [ $i ] .= chr ( $GIF_tim [ $i ] >> 8 );
  187. $GIF_buf [ $i ] .= chr ( $j );
  188. $GIF_buf [ $i ] .= chr ( 0 );
  189. }
  190. else {
  191. $GIF_buf [ $i ] .= chr ( 0x21 );
  192. $GIF_buf [ $i ] .= chr ( 0xf9 );
  193. $GIF_buf [ $i ] .= chr ( 0x04 );
  194. $GIF_buf [ $i ] .= chr ( ( $GIF_dis << 2 ) + 0 );
  195. $GIF_buf [ $i ] .= chr ( $GIF_tim [ $i ] & 0xFF );
  196. $GIF_buf [ $i ] .= chr ( $GIF_tim [ $i ] >> 8 );
  197. $GIF_buf [ $i ] .= chr ( 0 );
  198. $GIF_buf [ $i ] .= chr ( 0 );
  199. }
  200. }
  201. if ( ord ( $GIF_buf [ $i ] { $seek_p - 1 } ) != 0x2c ) {
  202. printf ( "%s: %s ( 0x%x )", $this->VER, $this->ERR [ 'ERR03' ], ord ( substr ( $GIF_buf [ $i ], $seek_p - 1, 1 ) ) );
  203. exit ( 0 );
  204. }
  205. }
  206. else {
  207. if ( $transColor > -1 ) {
  208. $rgb = substr ( $GIF_buf [ $i ], 14, 3 * ( 2 << ( ord ( $GIF_buf [ $i ] { 10 } ) & 0x07 ) ) );
  209. for ( $j = 0; $j < ( 2 << ( ord ( $GIF_buf [ $i ] { 10 } ) & 0x07 ) ); $j++ ) {
  210. if (
  211. ord ( $rgb { 3 * $j } ) == ( ( $transColor >> 16 ) & 0xFF ) &&
  212. ord ( $rgb { 3 * $j + 1 } ) == ( ( $transColor >> 8 ) & 0xFF ) &&
  213. ord ( $rgb { 3 * $j + 2 } ) == ( ( $transColor >> 0 ) & 0xFF )
  214. ) {
  215. $tranid = true;
  216. break;
  217. }
  218. }
  219. if ( $tranid && $j < 256 ) {
  220. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 3 } = chr ( ( $GIF_dis << 2 ) + 1 );
  221. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 4 } = chr ( $GIF_tim [ $i ] & 0xFF );
  222. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 5 } = chr ( $GIF_tim [ $i ] >> 8 );
  223. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 6 } = chr ( $j );
  224. }
  225. else {
  226. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 3 } = chr ( ( $GIF_dis << 2 ) + 0 );
  227. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 4 } = chr ( $GIF_tim [ $i ] & 0xFF );
  228. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 5 } = chr ( $GIF_tim [ $i ] >> 8 );
  229. $GIF_buf [ $i ] { ( $seek_p - 1 ) + 6 } = chr ( 0 );
  230. }
  231. }
  232. if ( ord ( $GIF_buf [ $i ] { ( $seek_p - 1 ) + 8 } ) != 0x2c ) {
  233. printf ( "%s: %s ( 0x%x )", $this->VER, $this->ERR [ 'ERR03' ], ord ( substr ( $GIF_buf [ $i ], $seek_p - 1, 1 ) ) );
  234. exit ( 0 );
  235. }
  236. }
  237. $this->GIF .= substr ( $GIF_buf [ $i ], $seek_p - 1, $length - $seek_p );
  238. }
  239. $this->GIF .= ";";
  240. }
  241. /*
  242. :::::::::::::::::::::::::::::::::::::::::::::::::::
  243. ::
  244. :: GetAnimation...
  245. ::
  246. */
  247. function GetAnimation ( ) {
  248. return ( $this->GIF );
  249. }
  250. } /* __END_OF_CLASS__ */
  251. ?>