PageRenderTime 83ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/captcha/classes/libraries/captcha/driver.php

http://github.com/enormego/EightPHP
PHP | 210 lines | 95 code | 32 blank | 83 comment | 10 complexity | 4afabd299c69dd625e898c25c7c88363 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Captcha driver class.
  4. *
  5. * @package Modules
  6. * @subpackage Captcha
  7. * @author EightPHP Development Team
  8. * @copyright (c) 2009-2010 EightPHP
  9. * @license http://license.eightphp.com
  10. */
  11. abstract class Captcha_Driver {
  12. // The correct Captcha challenge answer
  13. protected $response;
  14. // Image resource identifier and type ("png", "gif" or "jpeg")
  15. protected $image;
  16. protected $image_type = 'png';
  17. /**
  18. * Constructs a new challenge.
  19. *
  20. * @return void
  21. */
  22. public function __construct() {
  23. }
  24. public function update_challange() {
  25. $this->response = $this->generate_challenge();
  26. $this->update_response_session();
  27. }
  28. /**
  29. * Generate a new Captcha challenge.
  30. *
  31. * @return string the challenge answer
  32. */
  33. abstract public function generate_challenge();
  34. /**
  35. * Output the Captcha challenge.
  36. *
  37. * @param boolean html output
  38. * @return mixed the rendered Captcha (e.g. an image, riddle, etc.)
  39. */
  40. abstract public function render($html);
  41. /**
  42. * Stores the response for the current Captcha challenge in a session so it is available
  43. * on the next page load for Captcha::valid().
  44. *
  45. * @return void
  46. */
  47. public function update_response_session() {
  48. Session::instance()->set('captcha_response', sha1(strtoupper($this->response)));
  49. }
  50. /**
  51. * Validates a Captcha response from a user.
  52. *
  53. * @param string captcha response
  54. * @return boolean
  55. */
  56. public function valid($response) {
  57. return (sha1(strtoupper($response)) === Session::instance()->get('captcha_response'));
  58. }
  59. /**
  60. * Returns the image type.
  61. *
  62. * @param string filename
  63. * @return string|NO image type ("png", "gif" or "jpeg")
  64. */
  65. public function image_type($filename) {
  66. switch (strtolower(substr(strrchr($filename, '.'), 1))) {
  67. case 'png':
  68. return 'png';
  69. case 'gif':
  70. return 'gif';
  71. case 'jpg':
  72. case 'jpeg':
  73. // Return "jpeg" and not "jpg" because of the GD2 function names
  74. return 'jpeg';
  75. default:
  76. return NO;
  77. }
  78. }
  79. /**
  80. * Creates an image resource with the dimensions specified in config.
  81. * If a background image is supplied, the image dimensions are used.
  82. *
  83. * @throws Eight_Exception if no GD2 support
  84. * @param string path to the background image file
  85. * @return void
  86. */
  87. public function image_create($background = nil) {
  88. // Check for GD2 support
  89. if(!function_exists('imagegd2'))
  90. throw new Eight_Exception('captcha.requires_GD2');
  91. // Create a new image (black)
  92. $this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']);
  93. // Use a background image
  94. if(!empty($background)) {
  95. // Create the image using the right function for the filetype
  96. $function = 'imagecreatefrom'.$this->image_type($background);
  97. $this->background_image = $function($background);
  98. // Resize the image if needed
  99. if(imagesx($this->background_image) !== Captcha::$config['width']
  100. OR imagesy($this->background_image) !== Captcha::$config['height']) {
  101. imagecopyresampled
  102. (
  103. $this->image, $this->background_image, 0, 0, 0, 0,
  104. Captcha::$config['width'], Captcha::$config['height'],
  105. imagesx($this->background_image), imagesy($this->background_image)
  106. );
  107. }
  108. // Free up resources
  109. imagedestroy($this->background_image);
  110. }
  111. }
  112. /**
  113. * Fills the background with a gradient.
  114. *
  115. * @param resource gd image color identifier for start color
  116. * @param resource gd image color identifier for end color
  117. * @param string direction: 'horizontal' or 'vertical', 'random' by default
  118. * @return void
  119. */
  120. public function image_gradient($color1, $color2, $direction = nil) {
  121. $directions = array('horizontal', 'vertical');
  122. // Pick a random direction if needed
  123. if(!in_array($direction, $directions)) {
  124. $direction = $directions[array_rand($directions)];
  125. // Switch colors
  126. if(mt_rand(0, 1) === 1) {
  127. $temp = $color1;
  128. $color1 = $color2;
  129. $color2 = $temp;
  130. }
  131. }
  132. // Extract RGB values
  133. $color1 = imagecolorsforindex($this->image, $color1);
  134. $color2 = imagecolorsforindex($this->image, $color2);
  135. // Preparations for the gradient loop
  136. $steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height'];
  137. $r1 = ($color1['red'] - $color2['red']) / $steps;
  138. $g1 = ($color1['green'] - $color2['green']) / $steps;
  139. $b1 = ($color1['blue'] - $color2['blue']) / $steps;
  140. if($direction === 'horizontal') {
  141. $x1 =& $i;
  142. $y1 = 0;
  143. $x2 =& $i;
  144. $y2 = Captcha::$config['height'];
  145. } else {
  146. $x1 = 0;
  147. $y1 =& $i;
  148. $x2 = Captcha::$config['width'];
  149. $y2 =& $i;
  150. }
  151. // Execute the gradient loop
  152. for($i = 0; $i <= $steps; $i++) {
  153. $r2 = $color1['red'] - floor($i * $r1);
  154. $g2 = $color1['green'] - floor($i * $g1);
  155. $b2 = $color1['blue'] - floor($i * $b1);
  156. $color = imagecolorallocate($this->image, $r2, $g2, $b2);
  157. imageline($this->image, $x1, $y1, $x2, $y2, $color);
  158. }
  159. }
  160. /**
  161. * Returns the img html element or outputs the image to the browser.
  162. *
  163. * @param boolean html output
  164. * @return mixed html string or void
  165. */
  166. public function image_render($html) {
  167. // Output html element
  168. if($html)
  169. return '<img alt="Captcha" src="'.url::site('captcha/'.Captcha::$config['group']).'" width="'.Captcha::$config['width'].'" height="'.Captcha::$config['height'].'" />';
  170. // Send the correct HTTP header
  171. header('Content-Type: image/'.$this->image_type);
  172. // Pick the correct output function
  173. $function = 'image'.$this->image_type;
  174. $function($this->image);
  175. // Free up resources
  176. imagedestroy($this->image);
  177. }
  178. } // End Captcha Driver