PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/torrent_site/download_captcha/captcha.php

http://it-manager.googlecode.com/
PHP | 509 lines | 206 code | 179 blank | 124 comment | 31 complexity | c55eff17fa8946d7804dbebe482f132b MD5 | raw file
  1. <?php
  2. /**
  3. * Script para la generaciĆ³n de CAPTCHAS
  4. *
  5. * @author Jose Rodriguez <jose.rodriguez@exec.cl>
  6. * @license GPLv3
  7. * @link http://code.google.com/p/cool-php-captcha
  8. * @package captcha
  9. * @version 0.3
  10. *
  11. */
  12. session_start();
  13. $captcha = new SimpleCaptcha();
  14. // OPTIONAL Change configuration...
  15. //$captcha->wordsFile = 'words/es.php';
  16. //$captcha->session_var = 'secretword';
  17. //$captcha->imageFormat = 'png';
  18. //$captcha->scale = 3; $captcha->blur = true;
  19. //$captcha->resourcesPath = "/var/cool-php-captcha/resources";
  20. // OPTIONAL Simple autodetect language example
  21. /*
  22. if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  23. $langs = array('en', 'es');
  24. $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
  25. if (in_array($lang, $langs)) {
  26. $captcha->wordsFile = "words/$lang.php";
  27. }
  28. }
  29. */
  30. // Image generation
  31. $captcha->CreateImage();
  32. /**
  33. * SimpleCaptcha class
  34. *
  35. */
  36. class SimpleCaptcha {
  37. /** Width of the image */
  38. public $width = 200;
  39. /** Height of the image */
  40. public $height = 70;
  41. /** Dictionary word file (empty for randnom text) */
  42. public $wordsFile = 'words/en.php';
  43. /**
  44. * Path for resource files (fonts, words, etc.)
  45. *
  46. * "resources" by default. For security reasons, is better move this
  47. * directory to another location outise the web server
  48. *
  49. */
  50. public $resourcesPath = 'resources';
  51. /** Min word length (for non-dictionary random text generation) */
  52. public $minWordLength = 5;
  53. /**
  54. * Max word length (for non-dictionary random text generation)
  55. *
  56. * Used for dictionary words indicating the word-length
  57. * for font-size modification purposes
  58. */
  59. public $maxWordLength = 8;
  60. /** Sessionname to store the original text */
  61. public $session_var = 'captcha';
  62. /** Background color in RGB-array */
  63. public $backgroundColor = array(255, 255, 255);
  64. /** Foreground colors in RGB-array */
  65. public $colors = array(
  66. array(27,78,181), // blue
  67. array(22,163,35), // green
  68. array(214,36,7), // red
  69. );
  70. /** Shadow color in RGB-array or null */
  71. public $shadowColor = null; //array(0, 0, 0);
  72. /**
  73. * Font configuration
  74. *
  75. * - font: TTF file
  76. * - spacing: relative pixel space between character
  77. * - minSize: min font size
  78. * - maxSize: max font size
  79. */
  80. public $fonts = array(
  81. 'Antykwa' => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'),
  82. 'Candice' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
  83. 'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
  84. 'Duality' => array('spacing' => -2, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
  85. 'Heineken' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
  86. 'Jura' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
  87. 'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
  88. 'Times' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
  89. 'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
  90. );
  91. /** Wave configuracion in X and Y axes */
  92. public $Yperiod = 12;
  93. public $Yamplitude = 14;
  94. public $Xperiod = 11;
  95. public $Xamplitude = 5;
  96. /** letter rotation clockwise */
  97. public $maxRotation = 8;
  98. /**
  99. * Internal image size factor (for better image quality)
  100. * 1: low, 2: medium, 3: high
  101. */
  102. public $scale = 2;
  103. /**
  104. * Blur effect for better image quality (but slower image processing).
  105. * Better image results with scale=3
  106. */
  107. public $blur = false;
  108. /** Debug? */
  109. public $debug = false;
  110. /** Image format: jpeg or png */
  111. public $imageFormat = 'jpeg';
  112. /** GD image */
  113. public $im;
  114. public function __construct($config = array()) {
  115. }
  116. public function CreateImage() {
  117. $ini = microtime(true);
  118. /** Initialization */
  119. $this->ImageAllocate();
  120. /** Text insertion */
  121. $text = $this->GetCaptchaText();
  122. $fontcfg = $this->fonts[array_rand($this->fonts)];
  123. $this->WriteText($text, $fontcfg);
  124. $_SESSION[$this->session_var] = $text;
  125. /** Transformations */
  126. $this->WaveImage();
  127. if ($this->blur && function_exists('imagefilter')) {
  128. imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
  129. }
  130. $this->ReduceImage();
  131. if ($this->debug) {
  132. imagestring($this->im, 1, 1, $this->height-8,
  133. "$text {$fontcfg['font']} ".round((microtime(true)-$ini)*1000)."ms",
  134. $this->GdFgColor
  135. );
  136. }
  137. /** Output */
  138. $this->WriteImage();
  139. $this->Cleanup();
  140. }
  141. /**
  142. * Creates the image resources
  143. */
  144. protected function ImageAllocate() {
  145. // Cleanup
  146. if (!empty($this->im)) {
  147. imagedestroy($this->im);
  148. }
  149. $this->im = imagecreatetruecolor($this->width*$this->scale, $this->height*$this->scale);
  150. // Background color
  151. $this->GdBgColor = imagecolorallocate($this->im,
  152. $this->backgroundColor[0],
  153. $this->backgroundColor[1],
  154. $this->backgroundColor[2]
  155. );
  156. imagefilledrectangle($this->im, 0, 0, $this->width*$this->scale, $this->height*$this->scale, $this->GdBgColor);
  157. // Foreground color
  158. $color = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
  159. $this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]);
  160. // Shadow color
  161. if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) {
  162. $this->GdShadowColor = imagecolorallocate($this->im,
  163. $this->shadowColor[0],
  164. $this->shadowColor[1],
  165. $this->shadowColor[2]
  166. );
  167. }
  168. }
  169. /**
  170. * Text generation
  171. *
  172. * @return string Text
  173. */
  174. protected function GetCaptchaText() {
  175. $text = $this->GetDictionaryCaptchaText();
  176. if (!$text) {
  177. $text = $this->GetRandomCaptchaText();
  178. }
  179. return $text;
  180. }
  181. /**
  182. * Random text generation
  183. *
  184. * @return string Text
  185. */
  186. protected function GetRandomCaptchaText($length = null) {
  187. if (empty($length)) {
  188. $length = rand($this->minWordLength, $this->maxWordLength);
  189. }
  190. $words = "abcdefghijlmnopqrstvwyz";
  191. $vocals = "aeiou";
  192. $text = "";
  193. $vocal = rand(0, 1);
  194. for ($i=0; $i<$length; $i++) {
  195. if ($vocal) {
  196. $text .= substr($vocals, mt_rand(0, 4), 1);
  197. } else {
  198. $text .= substr($words, mt_rand(0, 22), 1);
  199. }
  200. $vocal = !$vocal;
  201. }
  202. return $text;
  203. }
  204. /**
  205. * Random dictionary word generation
  206. *
  207. * @param boolean $extended Add extended "fake" words
  208. * @return string Word
  209. */
  210. function GetDictionaryCaptchaText($extended = false) {
  211. if (empty($this->wordsFile)) {
  212. return false;
  213. }
  214. // Full path of words file
  215. if (substr($this->wordsFile, 0, 1) == '/') {
  216. $wordsfile = $this->wordsFile;
  217. } else {
  218. $wordsfile = $this->resourcesPath.'/'.$this->wordsFile;
  219. }
  220. $fp = fopen($wordsfile, "r");
  221. $length = strlen(fgets($fp));
  222. if (!$length) {
  223. return false;
  224. }
  225. $line = rand(1, (filesize($wordsfile)/$length)-2);
  226. if (fseek($fp, $length*$line) == -1) {
  227. return false;
  228. }
  229. $text = trim(fgets($fp));
  230. fclose($fp);
  231. /** Change ramdom volcals */
  232. if ($extended) {
  233. $text = preg_split('//', $text, -1, PREG_SPLIT_NO_EMPTY);
  234. $vocals = array('a', 'e', 'i', 'o', 'u');
  235. foreach ($text as $i => $char) {
  236. if (mt_rand(0, 1) && in_array($char, $vocals)) {
  237. $text[$i] = $vocals[mt_rand(0, 4)];
  238. }
  239. }
  240. $text = implode('', $text);
  241. }
  242. return $text;
  243. }
  244. /**
  245. * Text insertion
  246. */
  247. protected function WriteText($text, $fontcfg = array()) {
  248. if (empty($fontcfg)) {
  249. // Select the font configuration
  250. $fontcfg = $this->fonts[array_rand($this->fonts)];
  251. }
  252. // Full path of font file
  253. $fontfile = $this->resourcesPath.'/fonts/'.$fontcfg['font'];
  254. /** Increase font-size for shortest words: 9% for each glyp missing */
  255. $lettersMissing = $this->maxWordLength-strlen($text);
  256. $fontSizefactor = 1+($lettersMissing*0.09);
  257. // Text generation (char by char)
  258. $x = 20*$this->scale;
  259. $y = round(($this->height*27/40)*$this->scale);
  260. $length = strlen($text);
  261. for ($i=0; $i<$length; $i++) {
  262. $degree = rand($this->maxRotation*-1, $this->maxRotation);
  263. $fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize'])*$this->scale*$fontSizefactor;
  264. $letter = substr($text, $i, 1);
  265. if ($this->shadowColor) {
  266. $coords = imagettftext($this->im, $fontsize, $degree,
  267. $x+$this->scale, $y+$this->scale,
  268. $this->GdShadowColor, $fontfile, $letter);
  269. }
  270. $coords = imagettftext($this->im, $fontsize, $degree,
  271. $x, $y,
  272. $this->GdFgColor, $fontfile, $letter);
  273. $x += ($coords[2]-$x) + ($fontcfg['spacing']*$this->scale);
  274. }
  275. }
  276. /**
  277. * Wave filter
  278. */
  279. protected function WaveImage() {
  280. // X-axis wave generation
  281. $xp = $this->scale*$this->Xperiod*rand(1,3);
  282. $k = rand(0, 100);
  283. for ($i = 0; $i < ($this->width*$this->scale); $i++) {
  284. imagecopy($this->im, $this->im,
  285. $i-1, sin($k+$i/$xp) * ($this->scale*$this->Xamplitude),
  286. $i, 0, 1, $this->height*$this->scale);
  287. }
  288. // Y-axis wave generation
  289. $k = rand(0, 100);
  290. $yp = $this->scale*$this->Yperiod*rand(1,2);
  291. for ($i = 0; $i < ($this->height*$this->scale); $i++) {
  292. imagecopy($this->im, $this->im,
  293. sin($k+$i/$yp) * ($this->scale*$this->Yamplitude), $i-1,
  294. 0, $i, $this->width*$this->scale, 1);
  295. }
  296. }
  297. /**
  298. * Reduce the image to the final size
  299. */
  300. protected function ReduceImage() {
  301. // Reduzco el tama?o de la imagen
  302. $imResampled = imagecreatetruecolor($this->width, $this->height);
  303. imagecopyresampled($imResampled, $this->im,
  304. 0, 0, 0, 0,
  305. $this->width, $this->height,
  306. $this->width*$this->scale, $this->height*$this->scale
  307. );
  308. imagedestroy($this->im);
  309. $this->im = $imResampled;
  310. }
  311. /**
  312. * File generation
  313. */
  314. protected function WriteImage() {
  315. if ($this->imageFormat == 'png' && function_exists('imagepng')) {
  316. header("Content-type: image/png");
  317. imagepng($this->im);
  318. } else {
  319. header("Content-type: image/jpeg");
  320. imagejpeg($this->im, null, 80);
  321. }
  322. }
  323. /**
  324. * Cleanup
  325. */
  326. protected function Cleanup() {
  327. imagedestroy($this->im);
  328. }
  329. }
  330. ?>