Changeset 3015
- Timestamp:
- 07/09/08 15:45:47 (7 weeks ago)
- Location:
- trunk/system
- Files:
-
- 4 modified
-
config/captcha.php (modified) (1 diff)
-
controllers/captcha.php (modified) (2 diffs)
-
libraries/Captcha.php (modified) (2 diffs)
-
libraries/Pagination.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/system/config/captcha.php
r2652 r3015 1 1 <?php defined('SYSPATH') or die('No direct access allowed.'); 2 2 /** 3 * @package C aptcha3 * @package Core 4 4 * 5 * Configure the Captcha 6 * Custom styles can be added by extending the Captcha class 5 * Captcha configuration is defined in groups which allows you to easily switch 6 * between different Captcha settings for different forms on your website. 7 * Note: all groups inherit and overwrite the default group. 8 * 9 * Group Options: 10 * style - Style driver 11 * width - Width of the Captcha image 12 * height - Height of the Captcha image 13 * complexity - Difficulty of the Captcha, concrete usage depends on chosen style 14 * background_path - Path to folder in which background image reside 15 * background_file - Image file name 16 * font_path - Path to folder in which fonts reside 17 * font_file - Font file name 7 18 */ 8 9 /** 10 * Width and height of the Captcha image. 11 * These settings are ignored if using a background image. 12 */ 13 $config['width'] = 150; 14 $config['height'] = 50; 15 16 /** 17 * Captcha style to use. Default is 'basic' and is only for testing as it 18 * does not require any truetype fonts installed. 19 * 'standard' is the recommended style. A font must be supplied. A background 20 * image is optional. 21 * 'alphasoup' is an alternative style. A font must be supplied. 22 * 'math' is a 'solve the question' style. 23 * A font must be supplied. A background image is optional. 24 * Custom styles can be added easily by extending the library. 25 */ 26 $config['style'] = 'standard'; 27 28 /** 29 * Number of characters to use for the Captcha (4 or 5 recommended). 30 * This setting is ignored if using style 'math'. 31 */ 32 $config['num_chars'] = 4; 33 34 /** 35 * Path to font files. Example: 'application/fonts/'. 36 * If using 'standard' style, you must supply a valid truetype font file. 37 */ 38 $config['font_path'] = SYSPATH.'fonts/'; 39 40 /** 41 * Name of the font, with the file extension. Case sensitive. 42 */ 43 $config['font_name'] = 'DejaVuSerif.ttf'; 44 45 /** 46 * Background image. Example: 'application/images/pattern.jpg'. 47 * The dimensions of this image will be used. 48 */ 49 $config['background_image'] = ''; 19 $config['default'] = array 20 ( 21 'style' => 'riddle', 22 'width' => 150, 23 'height' => 50, 24 'complexity' => 4, 25 'background_path' => '', 26 'background_file' => '', 27 'font_path' => SYSPATH.'fonts/', 28 'font_file' => 'DejaVuSerif.ttf', 29 ); -
trunk/system/controllers/captcha.php
r3010 r3015 1 1 <?php defined('SYSPATH') or die('No direct script access.'); 2 2 /** 3 * Allows a CAPTCHA image to be displayed dynamically. 4 * Captcha library is called to output the image. 5 * 6 * 7 * Usage: Call the captcha controller from a view. 8 * `echo html::image(url::site().'captcha');` 3 * Outputs the dynamic Captcha image. 4 * Usage: Call the Captcha controller from a view, e.g. 5 * <img src="<?php echo url::site('captcha') ?>" /> 9 6 * 10 7 * $Id$ 11 8 * 12 * @package C ore9 * @package Captcha 13 10 * @author Kohana Team 14 11 * @copyright (c) 2007-2008 Kohana Team … … 17 14 class Captcha_Controller extends Controller { 18 15 19 public $session;20 public $captcha;21 22 protected $captcha_code;23 24 16 public function index() 25 17 { 26 $this->session = Session::instance(); 27 $this->captcha = new Captcha; 28 29 // Create and store a random captcha string 30 $this->captcha_code = $this->create_code(); 31 $this->captcha->set_code($this->captcha_code); 32 $this->session->set('captcha_code', $this->captcha_code); 33 34 // Output the image 35 $this->captcha->render(); 36 } 37 38 private function create_code() 39 { 40 if (Config::item('captcha.style') === 'math') 41 { 42 $code = (string) mt_rand(101, 991); 43 } 44 else 45 { 46 $code = text::random('distinct', Config::item('captcha.num_chars')); 47 } 48 49 return $code; 18 // Output the Captcha challenge resource (no html) 19 $captcha = new Captcha; 20 $captcha->render(FALSE); 50 21 } 51 22 -
trunk/system/libraries/Captcha.php
r3010 r3015 12 12 class Captcha_Core { 13 13 14 // Config 15 protected $font_path = ''; 16 protected $font_name = ''; 17 protected $width = 150; 18 protected $height = 50; 19 protected $background_image = ''; 20 protected $style = 'basic'; 21 protected $num_chars = 4; 14 // Style-dependent Captcha driver 15 protected $driver; 22 16 23 // Class internal variables 24 protected $image; 25 protected $color_black; 26 protected $color_white; 27 protected $spacing; 28 protected $captcha_code; 29 protected $numerals = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'); 17 // Config values 18 public static $config = array 19 ( 20 'style' => 'basic', 21 'width' => 150, 22 'height' => 50, 23 'complexity' => 4, 24 'background' => '', 25 'font' => '', 26 ); 27 28 // The Captcha challenge answer, the text the user is supposed to enter 29 public static $answer; 30 30 31 31 /** 32 * C reates a new Captcha instance.32 * Constructs a new Captcha object. 33 33 * 34 34 * @throws Kohana_Exception 35 * @param array configuration35 * @param string configuration settings 36 36 * @return void 37 37 */ 38 38 public function __construct($config = array()) 39 39 { 40 static $ check;40 static $gd2_check; 41 41 42 // Check that a suitable GD2 library is available 43 ($check === NULL) and $check = function_exists('imagegd2'); 44 45 if ($check === FALSE) 42 // We need GD2 exclusively 43 if ($gd2_check === NULL AND ($gd2_check = function_exists('imagegd2')) === FALSE) 46 44 throw new Kohana_Exception('captcha.requires_GD2'); 47 45 48 // Load configuration 49 $config += Config::item('captcha', FALSE, FALSE); 50 51 $this->initialize($config); 52 53 // If using a background image, check if it exists. 54 if ($this->background_image) 46 // No custom config group name given 47 if ( ! isset($config['group'])) 55 48 { 56 if ( ! file_exists($this->background_image)) 57 throw new Kohana_Exception('captcha.file_not_found', $this->background_image); 49 $config['group'] = 'default'; 58 50 } 59 51 60 // If using a font, check if it exists. 61 if ($this->font_name) 52 // Load and validate config group 53 if ( ! is_array($group_config = Config::item('captcha.'.$config['group']))) 54 throw new Kohana_Exception('captcha.undefined_group', $config['group']); 55 56 // All captcha config groups inherit default config group 57 if ($config['group'] !== 'default') 62 58 { 63 if ( ! file_exists($this->font_path.$this->font_name)) 64 throw new Kohana_Exception('captcha.file_not_found', $this->font_path.$this->font_name); 59 // Load and validate default config group 60 if ( ! is_array($default_config = Config::item('captcha.default'))) 61 throw new Kohana_Exception('captcha.undefined_group', 'default'); 62 63 // Merge config group with default config group 64 $group_config += $default_config; 65 65 } 66 67 // Merge custom config items with config group 68 $config += $group_config; 69 70 // Assign config values to the object 71 foreach ($config as $key => $value) 72 { 73 if (array_key_exists($key, self::$config)) 74 { 75 self::$config[$key] = $value; 76 } 77 } 78 79 // If using a background image, check if it exists 80 if ( ! empty($config['background_file'])) 81 { 82 self::$config['background'] = str_replace('\\', '/', realpath($config['background_path'])).'/'.$config['background_file']; 83 84 if ( ! file_exists(self::$config['background'])) 85 throw new Kohana_Exception('captcha.file_not_found', self::$config['background']); 86 } 87 88 // If using a font, check if it exists 89 if ( ! empty($config['font_file'])) 90 { 91 self::$config['font'] = str_replace('\\', '/', realpath($config['font_path'])).'/'.$config['font_file']; 92 93 if ( ! file_exists(self::$config['font'])) 94 throw new Kohana_Exception('captcha.file_not_found', self::$config['font']); 95 } 96 97 // Set driver name 98 $driver = 'Captcha_'.ucfirst($config['style']).'_Driver'; 99 100 // Load the driver 101 if ( ! Kohana::auto_load($driver)) 102 throw new Kohana_Exception('core.driver_not_found', $config['style'], get_class($this)); 103 104 // Initialize the driver 105 $this->driver = new $driver(); 106 107 // Validate the driver 108 if ( ! ($this->driver instanceof Captcha_Driver)) 109 throw new Kohana_Exception('core.driver_implements', $type, get_class($this), 'Captcha_Driver'); 110 111 // Generate a new Captcha challenge 112 self::$answer = (string) $this->driver->generate_challenge(); 113 114 // Store the answer in a session 115 Session::instance()->set('captcha_answer', self::$answer); 66 116 67 117 Log::add('debug', 'Captcha Library initialized'); … … 69 119 70 120 /** 71 * Sets or overwrites config values.121 * Validates a Captcha answer. 72 122 * 73 * @param array configuration74 * @return void123 * @param string captcha answer 124 * @return boolean 75 125 */ 76 public function initialize($config)126 public static function valid($answer) 77 127 { 78 // Assign config values to the object 79 foreach ($config as $key => $value) 80 { 81 if (property_exists($this, $key)) 82 { 83 $this->$key = $value; 84 } 85 } 128 return (strtoupper($answer) === strtoupper(Session::instance()->get('captcha_answer'))); 86 129 } 87 130 88 131 /** 89 * Sets the Captcha code to use.132 * Output the Captcha challenge. 90 133 * 91 * @param string captcha code generated in captcha controller92 * @return void134 * @param boolean TRUE to output html, e.g. <img src="#" /> 135 * @return mixed 93 136 */ 94 public function set_code($str)137 public function render($html = TRUE) 95 138 { 96 $this->captcha_code = (string) $str;139 return $this->driver->render($html); 97 140 } 98 141 99 142 /** 100 * Generates the Captcha image.143 * Magically outputs the Captcha challenge. 101 144 * 102 * @return void145 * @return mixed 103 146 */ 104 public function render()147 public function __toString() 105 148 { 106 // If extending the class with a custom Captcha function, name it 'xyz_captcha'. 107 // Style 'xyz' must be added to config. Now call the method that implements the Captcha. 108 $this->{$this->style.'_captcha'}(); 109 110 // Tell browser what to expect 111 // TODO: make this automatic 112 // header('Content-Type: image/jpeg'); 113 header('Content-Type: image/png'); 114 115 // Output the captcha image 116 // imagejpeg($this->image); 117 imagepng($this->image); 118 119 // Free up resources 120 imagedestroy($this->image); 121 } 122 123 /** 124 * Validates the Captcha code against session Captcha code 125 * 126 * @param string captcha code text 127 * @return boolean 128 */ 129 public static function valid_captcha($str) 130 { 131 return (strtoupper($str) === strtoupper(Session::instance()->get('captcha_code'))); 132 } 133 134 /** 135 * Creates image resource and allocates some basic colors. 136 * If a background image is supplied, the image dimensions are used. 137 * 138 * @return void 139 */ 140 protected function img_create() 141 { 142 if ($this->background_image) 143 { 144 // TODO: create from any valid image 145 $this->image = imagecreatefromjpeg($this->background_image); 146 $this->color_white = imagecolorallocate($this->image, 255, 255, 255); 147 148 // Get the background image dimensions 149 $this->width = imagesx($this->image); 150 $this->height = imagesy($this->image); 151 } 152 else 153 { 154 $this->image = imagecreatetruecolor($this->width, $this->height); 155 $this->color_white = imagecolorallocate($this->image, 255, 255, 255); 156 157 // Fill the image with a colored gradient (use random colors, but try not to obscure text) 158 $left_color = array(mt_rand(100,255), 0, 255); 159 $right_color = array(100, 100, mt_rand(100,0)); 160 $this->img_color_gradient($this->image, 0, 0, $this->height, $this->width, $left_color, $right_color); 161 } 162 } 163 164 /** 165 * Allocates a background color to image. 166 * 167 * @param array GD image color identifier 168 * @return void 169 */ 170 protected function img_background($color) 171 { 172 imagefill($this->image, 0, 0, $color); 173 } 174 175 /** 176 * Draws a very basic Captcha image. 177 * Requires only GD. Useful for testing or if you can't use truetype fonts. 178 * 179 * @return void 180 */ 181 protected function basic_captcha() 182 { 183 $this->image = imagecreate($this->width, $this->height); 184 $this->color_white = imagecolorallocate($this->image, 255, 255, 255); 185 $this->color_black = imagecolorallocate($this->image, 0, 0, 0); 186 187 imagestring($this->image, 5, 50, 15, $this->captcha_code, $this->color_black); 188 } 189 190 /** 191 * Draws the standard Captcha image: 192 * Requires GD with freetype and available truetype compatible font files. 193 * 194 * @param none 195 * @return void 196 */ 197 protected function standard_captcha() 198 { 199 $this->img_create(); 200 201 $font = $this->font_path.$this->font_name; 202 $this->calculate_spacing(); 203 204 // Draw each Captcha character with varying attributes 205 for ($i = 0, $strlen = strlen($this->captcha_code); $i < $strlen; $i++) 206 { 207 // Allocate random color, size and rotation attributes to text 208 $text_color = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); 209 $angle = mt_rand(-40, 40); 210 211 // Make first char angle inward 212 if ($i === 0) 213 { 214 $angle = -abs($angle); 215 } 216 // Make last char angle inward 217 if ($i === ($this->num_chars - 1)) 218 { 219 $angle = abs($angle); 220 } 221 222 // Scale the character size on image height 223 $font_size = mt_rand($this->height - 20, $this->height - 12); 224 $char_details = imageftbbox($font_size, $angle, $font, $this->captcha_code[$i], array()); 225 226 // Calculate character starting coordinates 227 $iX = $this->spacing / 4 + $i * $this->spacing; 228 $char_height = $char_details[2] - $char_details[5]; 229 $iY = $this->height / 2 + $char_height / 4; 230 231 // Write text character to image 232 imagefttext($this->image, $font_size, $angle, $iX, $iY, $text_color, $font, $this->captcha_code[$i], array()); 233 } 234 } 235 236 /** 237 * Draws the alphasoup Captcha image: 238 * Requires GD with freetype and available truetype compatible font files. 239 * 240 * @param none 241 * @return void 242 */ 243 protected function alphasoup_captcha() 244 { 245 $this->img_create(); 246 $font = $this->font_path.$this->font_name; 247 $text_color = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); 248 $color_limit = mt_rand(96, 160); 249 $fill_color = imageColorAllocate($this->image, mt_rand($color_limit, 255), mt_rand($color_limit, 255), mt_rand($color_limit, 255)); 250 imageFilledRectangle($this->image, 0, 0, $this->width, $this->height, $fill_color); 251 $font_width = imageFontWidth(10); 252 $chars = 'ABCDEFGHIJKLMNO'; 253 254 for($loop = 0; $loop < 20; $loop++) 255 { 256 $text_color = imageColorAllocate($this->image, mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255)); 257 $char = substr($chars, mt_rand(0, 15), 1); 258 imageTTFtext($this->image, mt_rand(23, 27), mt_rand(160, 200), mt_rand(-10, $this->width + 10), mt_rand(-10, 60), $text_color, $font, $char); 259 } 260 261 $this->calculate_spacing(); 262 // Draw each Captcha character with varying attributes 263 for ($i = 0, $strlen = strlen($this->captcha_code); $i < $strlen; $i++) 264 { 265 // Allocate random color, size and rotation attributes to text 266 $text_color = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); 267 $angle = mt_rand(-40, 40); 268 269 // Make first char angle inward 270 if ($i === 0) 271 { 272 $angle = -abs($angle); 273 } 274 // Make last char angle inward 275 if ($i === ($this->num_chars - 1)) 276 { 277 $angle = abs($angle); 278 } 279 280 // Scale the character size on image height 281 $font_size = mt_rand($this->height - 20, $this->height - 12); 282 $char_details = imageftbbox($font_size, $angle, $font, $this->captcha_code[$i], array()); 283 284 // Calculate character starting coordinates 285 $iX = $this->spacing / 4 + $i * $this->spacing; 286 $char_height = $char_details[2] - $char_details[5]; 287 $iY = $this->height / 2 + $char_height / 4; 288 289 // Write text character to image 290 imagefttext($this->image, $font_size, $angle, $iX, $iY, $text_color, $font, $this->captcha_code[$i], array()); 291 } 292 293 } 294 295 /** 296 * Draws the math riddle Captcha image. 297 * Requires GD with freetype and available truetype compatible font files. 298 * 299 * @return void 300 */ 301 protected function math_captcha() 302 { 303 $answer = Session::instance()->get('captcha_code'); 304 305 // Convert to numeral 306 $numeral = $this->numerals[substr($answer, -1)]; 307 308 // Subtract last digit from answer 309 $number = substr($answer, 0, 2).'0'; 310 311 // $number plus $numeral equals $answer 312 $text = $number.' + '.$numeral.' = '; 313 $this->img_create(); 314 $font = $this->font_path.$this->font_name; 315 316 // Scale the font size to image height 317 $font_size = $this->height / 3; 318 $text_details = imageftbbox($font_size, 0, $font, $text, array()); 319 $iX = 5; 320 $iY = ($this->height / 2) + 5; 321 322 imagefttext($this->image, $font_size, 0, $iX, $iY, $this->color_white, $font, $text, array()); 323 } 324 325 /** 326 * Calculates letter spacing for truetype font characters. 327 * 328 * @return integer 329 */ 330 protected function calculate_spacing() 331 { 332 return $this->spacing = (int) $this->width / $this->num_chars; 333 } 334 335 /** 336 * Fills the image with a colored gradient. 337 * 338 * @param resource gd image resource identifier 339 * @param integer start X position 340 * @param integer start Y position 341 * @param integer height of fill in pixels 342 * @param integer width of fill in pixels 343 * @param resource gd image color identifier for left of image 344 * @param resource gd image color identifier for right of image 345 * @return void 346 */ 347 protected function img_color_gradient($image, $x1, $y1, $height, $width, $left_color, $right_color) 348 { 349 $color0 = ($left_color[0] - $right_color[0]) / $width; 350 $color1 = ($left_color[1] - $right_color[1]) / $width; 351 $color2 = ($left_color[2] - $right_color[2]) / $width; 352 353 for ($i = 0; $i <= $width; $i++) 354 { 355 $red = $left_color[0] - floor($i * $color0); 356 $green = $left_color[1] - floor($i * $color1); 357 $blue = $left_color[2] - floor($i * $color2); 358 $col = imagecolorallocate($this->image, $red, $green, $blue); 359 360 imageline($this->image, $x1 + $i, $y1, $x1 + $i, $y1 + $height, $col); 361 } 149 return $this->render(); 362 150 } 363 151 -
trunk/system/libraries/Pagination.php
r2935 r3015 47 47 48 48 /** 49 * Constructs thePagination object.49 * Constructs a new Pagination object. 50 50 * 51 51 * @param array configuration settings … … 69 69 * Sets config values. 70 70 * 71 * @throws Kohana_Exception 71 72 * @param array configuration settings 72 73 * @return void … … 198 199 199 200 /** 200 * Magically converts pagination object to string.201 * Magically converts Pagination object to string. 201 202 * 202 203 * @return string pagination html
