在国外网站上看到的一个很好用的验证码封装类,跟大家分享一下。
还有部分文件没有放上去。
1 <?php 2 /** 3 * Script para la generaci 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 13 session_start(); 14 15 $captcha = new SimpleCaptcha(); 16 17 // OPTIONAL Change configuration... 18 //$captcha->wordsFile = 'words/es.php'; 19 //$captcha->session_var = 'secretword'; 20 //$captcha->imageFormat = 'png'; 21 //$captcha->lineWidth = 3; 22 //$captcha->scale = 3; $captcha->blur = true; 23 //$captcha->resourcesPath = "/var/cool-php-captcha/resources"; 24 25 // OPTIONAL Simple autodetect language example 26 /* 27 if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { 28 $langs = array('en', 'es'); 29 $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); 30 if (in_array($lang, $langs)) { 31 $captcha->wordsFile = "words/$lang.php"; 32 } 33 } 34 */ 35 36 // Image generation 37 $captcha->CreateImage(); 38 39 40 /** 41 * SimpleCaptcha class 42 * 43 */ 44 class SimpleCaptcha { 45 46 /** Width of the image */ 47 public $width = 200; 48 49 /** Height of the image */ 50 public $height = 70; 51 52 /** Dictionary word file (empty for random text) */ 53 public $wordsFile = 'words/en.php'; 54 55 /** 56 * Path for resource files (fonts, words, etc.) 57 * 58 * "resources" by default. For security reasons, is better move this 59 * directory to another location outise the web server 60 * 61 */ 62 public $resourcesPath = 'resources'; 63 64 /** Min word length (for non-dictionary random text generation) */ 65 public $minWordLength = 5; 66 67 /** 68 * Max word length (for non-dictionary random text generation) 69 * 70 * Used for dictionary words indicating the word-length 71 * for font-size modification purposes 72 */ 73 public $maxWordLength = 8; 74 75 /** Sessionname to store the original text */ 76 public $session_var = 'captcha'; 77 78 /** Background color in RGB-array */ 79 public $backgroundColor = array(255, 255, 255); 80 81 /** Foreground colors in RGB-array */ 82 public $colors = array( 83 array(27,78,181), // blue 84 array(22,163,35), // green 85 array(214,36,7), // red 86 ); 87 88 /** Shadow color in RGB-array or null */ 89 public $shadowColor = null; //array(0, 0, 0); 90 91 /** Horizontal line through the text */ 92 public $lineWidth = 0; 93 94 /** 95 * Font configuration 96 * 97 * - font: TTF file 98 * - spacing: relative pixel space between character 99 * - minSize: min font size 100 * - maxSize: max font size 101 */ 102 public $fonts = array( 103 'Antykwa' => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'), 104 'Candice' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'), 105 'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'), 106 'Duality' => array('spacing' => -2, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'), 107 'Heineken' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'), 108 'Jura' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'), 109 'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'), 110 'Times' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'), 111 'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'), 112 ); 113 114 /** Wave configuracion in X and Y axes */ 115 public $Yperiod = 12; 116 public $Yamplitude = 14; 117 public $Xperiod = 11; 118 public $Xamplitude = 5; 119 120 /** letter rotation clockwise */ 121 public $maxRotation = 8; 122 123 /** 124 * Internal image size factor (for better image quality) 125 * 1: low, 2: medium, 3: high 126 */ 127 public $scale = 2; 128 129 /** 130 * Blur effect for better image quality (but slower image processing). 131 * Better image results with scale=3 132 */ 133 public $blur = false; 134 135 /** Debug? */ 136 public $debug = false; 137 138 /** Image format: jpeg or png */ 139 public $imageFormat = 'jpeg'; 140 141 142 /** GD image */ 143 public $im; 144 145 public function __construct($config = array()) { 146 } 147 148 public function CreateImage() { 149 $ini = microtime(true); 150 151 /** Initialization */ 152 $this->ImageAllocate(); 153 154 /** Text insertion */ 155 $text = $this->GetCaptchaText(); 156 $fontcfg = $this->fonts[array_rand($this->fonts)]; 157 $this->WriteText($text, $fontcfg); 158 159 $_SESSION[$this->session_var] = $text; 160 161 /** Transformations */ 162 if (!empty($this->lineWidth)) { 163 $this->WriteLine(); 164 } 165 $this->WaveImage(); 166 if ($this->blur && function_exists('imagefilter')) { 167 imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR); 168 } 169 $this->ReduceImage(); 170 171 172 if ($this->debug) { 173 imagestring($this->im, 1, 1, $this->height-8, 174 "$text {$fontcfg['font']} ".round((microtime(true)-$ini)*1000)."ms", 175 $this->GdFgColor 176 ); 177 } 178 179 180 /** Output */ 181 $this->WriteImage(); 182 $this->Cleanup(); 183 } 184 185 186 /** 187 * Creates the image resources 188 */ 189 protected function ImageAllocate() { 190 // Cleanup 191 if (!empty($this->im)) { 192 imagedestroy($this->im); 193 } 194 195 $this->im = imagecreatetruecolor($this->width*$this->scale, $this->height*$this->scale); 196 197 // Background color 198 $this->GdBgColor = imagecolorallocate($this->im, 199 $this->backgroundColor[0], 200 $this->backgroundColor[1], 201 $this->backgroundColor[2] 202 ); 203 imagefilledrectangle($this->im, 0, 0, $this->width*$this->scale, $this->height*$this->scale, $this->GdBgColor); 204 205 // Foreground color 206 $color = $this->colors[mt_rand(0, sizeof($this->colors)-1)]; 207 $this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]); 208 209 // Shadow color 210 if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) { 211 $this->GdShadowColor = imagecolorallocate($this->im, 212 $this->shadowColor[0], 213 $this->shadowColor[1], 214 $this->shadowColor[2] 215 ); 216 } 217 } 218 219 220 /** 221 * Text generation 222 * 223 * @return string Text 224 */ 225 protected function GetCaptchaText() { 226 $text = $this->GetDictionaryCaptchaText(); 227 if (!$text) { 228 $text = $this->GetRandomCaptchaText(); 229 } 230 return $text; 231 } 232 233 234 /** 235 * Random text generation 236 * 237 * @return string Text 238 */ 239 protected function GetRandomCaptchaText($length = null) { 240 if (empty($length)) { 241 $length = rand($this->minWordLength, $this->maxWordLength); 242 } 243 244 $words = "abcdefghijlmnopqrstvwyz"; 245 $vocals = "aeiou"; 246 247 $text = ""; 248 $vocal = rand(0, 1); 249 for ($i=0; $i<$length; $i++) { 250 if ($vocal) { 251 $text .= substr($vocals, mt_rand(0, 4), 1); 252 } else { 253 $text .= substr($words, mt_rand(0, 22), 1); 254 } 255 $vocal = !$vocal; 256 } 257 return $text; 258 } 259 260 261 /** 262 * Random dictionary word generation 263 * 264 * @param boolean $extended Add extended "fake" words 265 * @return string Word 266 */ 267 function GetDictionaryCaptchaText($extended = false) { 268 if (empty($this->wordsFile)) { 269 return false; 270 } 271 272 // Full path of words file 273 if (substr($this->wordsFile, 0, 1) == '/') { 274 $wordsfile = $this->wordsFile; 275 } else { 276 $wordsfile = $this->resourcesPath.'/'.$this->wordsFile; 277 } 278 279 if (!file_exists($wordsfile)) { 280 return false; 281 } 282 283 $fp = fopen($wordsfile, "r"); 284 $length = strlen(fgets($fp)); 285 if (!$length) { 286 return false; 287 } 288 $line = rand(1, (filesize($wordsfile)/$length)-2); 289 if (fseek($fp, $length*$line) == -1) { 290 return false; 291 } 292 $text = trim(fgets($fp)); 293 fclose($fp); 294 295 296 /** Change ramdom volcals */ 297 if ($extended) { 298 $text = preg_split('//', $text, -1, PREG_SPLIT_NO_EMPTY); 299 $vocals = array('a', 'e', 'i', 'o', 'u'); 300 foreach ($text as $i => $char) { 301 if (mt_rand(0, 1) && in_array($char, $vocals)) { 302 $text[$i] = $vocals[mt_rand(0, 4)]; 303 } 304 } 305 $text = implode('', $text); 306 } 307 308 return $text; 309 } 310 311 312 /** 313 * Horizontal line insertion 314 */ 315 protected function WriteLine() { 316 317 $x1 = $this->width*$this->scale*.15; 318 $x2 = $this->textFinalX; 319 $y1 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65); 320 $y2 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65); 321 $width = $this->lineWidth/2*$this->scale; 322 323 for ($i = $width*-1; $i <= $width; $i++) { 324 imageline($this->im, $x1, $y1+$i, $x2, $y2+$i, $this->GdFgColor); 325 } 326 } 327 328 /** 329 * Text insertion 330 */ 331 protected function WriteText($text, $fontcfg = array()) { 332 if (empty($fontcfg)) { 333 // Select the font configuration 334 $fontcfg = $this->fonts[array_rand($this->fonts)]; 335 } 336 337 // Full path of font file 338 $fontfile = $this->resourcesPath.'/fonts/'.$fontcfg['font']; 339 340 341 /** Increase font-size for shortest words: 9% for each glyp missing */ 342 $lettersMissing = $this->maxWordLength-strlen($text); 343 $fontSizefactor = 1+($lettersMissing*0.09); 344 345 // Text generation (char by char) 346 $x = 20*$this->scale; 347 $y = round(($this->height*27/40)*$this->scale); 348 $length = strlen($text); 349 for ($i=0; $i<$length; $i++) { 350 $degree = rand($this->maxRotation*-1, $this->maxRotation); 351 $fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize'])*$this->scale*$fontSizefactor; 352 $letter = substr($text, $i, 1); 353 354 if ($this->shadowColor) { 355 $coords = imagettftext($this->im, $fontsize, $degree, 356 $x+$this->scale, $y+$this->scale, 357 $this->GdShadowColor, $fontfile, $letter); 358 } 359 $coords = imagettftext($this->im, $fontsize, $degree, 360 $x, $y, 361 $this->GdFgColor, $fontfile, $letter); 362 $x += ($coords[2]-$x) + ($fontcfg['spacing']*$this->scale); 363 } 364 365 $this->textFinalX = $x; 366 } 367 368 /** 369 * Wave filter 370 */ 371 protected function WaveImage() { 372 // X-axis wave generation 373 $xp = $this->scale*$this->Xperiod*rand(1,3); 374 $k = rand(0, 100); 375 for ($i = 0; $i < ($this->width*$this->scale); $i++) { 376 imagecopy($this->im, $this->im, 377 $i-1, sin($k+$i/$xp) * ($this->scale*$this->Xamplitude), 378 $i, 0, 1, $this->height*$this->scale); 379 } 380 381 // Y-axis wave generation 382 $k = rand(0, 100); 383 $yp = $this->scale*$this->Yperiod*rand(1,2); 384 for ($i = 0; $i < ($this->height*$this->scale); $i++) { 385 imagecopy($this->im, $this->im, 386 sin($k+$i/$yp) * ($this->scale*$this->Yamplitude), $i-1, 387 0, $i, $this->width*$this->scale, 1); 388 } 389 } 390 391 /** 392 * Reduce the image to the final size 393 */ 394 protected function ReduceImage() { 395 396 $imResampled = imagecreatetruecolor($this->width, $this->height); 397 imagecopyresampled($imResampled, $this->im, 398 0, 0, 0, 0, 399 $this->width, $this->height, 400 $this->width*$this->scale, $this->height*$this->scale 401 ); 402 imagedestroy($this->im); 403 $this->im = $imResampled; 404 } 405 406 407 /** 408 * File generation 409 */ 410 protected function WriteImage() { 411 if ($this->imageFormat == 'png' && function_exists('imagepng')) { 412 header("Content-type: image/png"); 413 imagepng($this->im); 414 } else { 415 header("Content-type: image/jpeg"); 416 imagejpeg($this->im, null, 80); 417 } 418 } 419 420 /** 421 * Cleanup 422 */ 423 protected function Cleanup() { 424 imagedestroy($this->im); 425 } 426 } 427 428 ?>