_imgAlt; } /** * @return string */ public function getStartImage () { return $this->_startImage; } /** * @return int */ public function getDotNoiseLevel () { return $this->_dotNoiseLevel; } /** * @return int */ public function getLineNoiseLevel () { return $this->_lineNoiseLevel; } /** * Get captcha expiration * * @return int */ public function getExpiration() { return $this->_expiration; } /** * Get garbage collection frequency * * @return int */ public function getGcFreq() { return $this->_gcFreq; } /** * Get font to use when generating captcha * * @return string */ public function getFont() { return $this->_font; } /** * Get font size * * @return int */ public function getFontSize() { return $this->_fsize; } /** * Get captcha image height * * @return int */ public function getHeight() { return $this->_height; } /** * Get captcha image directory * * @return string */ public function getImgDir() { return $this->_imgDir; } /** * Get captcha image base URL * * @return string */ public function getImgUrl() { return $this->_imgUrl; } /** * Get captcha image file suffix * * @return string */ public function getSuffix() { return $this->_suffix; } /** * Get captcha image width * * @return int */ public function getWidth() { return $this->_width; } /** * Set start image * * @param string $startImage * @return Zend_Captcha_Image */ public function setStartImage ($startImage) { $this->_startImage = $startImage; return $this; } /** * Set dot noise level * * @param int $dotNoiseLevel * @return Zend_Captcha_Image */ public function setDotNoiseLevel ($dotNoiseLevel) { $this->_dotNoiseLevel = $dotNoiseLevel; return $this; } /** * Set line noise level * * @param int $lineNoiseLevel * @return Zend_Captcha_Image */ public function setLineNoiseLevel ($lineNoiseLevel) { $this->_lineNoiseLevel = $lineNoiseLevel; return $this; } /** * Set captcha expiration * * @param int $expiration * @return Zend_Captcha_Image */ public function setExpiration($expiration) { $this->_expiration = $expiration; return $this; } /** * Set garbage collection frequency * * @param int $gcFreq * @return Zend_Captcha_Image */ public function setGcFreq($gcFreq) { $this->_gcFreq = $gcFreq; return $this; } /** * Set captcha font * * @param string $font * @return Zend_Captcha_Image */ public function setFont($font) { $this->_font = $font; return $this; } /** * Set captcha font size * * @param int $fsize * @return Zend_Captcha_Image */ public function setFontSize($fsize) { $this->_fsize = $fsize; return $this; } /** * Set captcha image height * * @param int $height * @return Zend_Captcha_Image */ public function setHeight($height) { $this->_height = $height; return $this; } /** * Set captcha image storage directory * * @param string $imgDir * @return Zend_Captcha_Image */ public function setImgDir($imgDir) { $this->_imgDir = rtrim($imgDir, "/\\") . '/'; return $this; } /** * Set captcha image base URL * * @param string $imgUrl * @return Zend_Captcha_Image */ public function setImgUrl($imgUrl) { $this->_imgUrl = rtrim($imgUrl, "/\\") . '/'; return $this; } /** * Set image alternative text * * @param string $imgAlt * @return Zend_Captcha_Image */ public function setImgAlt ($imgAlt) { $this->_imgAlt = $imgAlt; return $this; } /** * Set captch image filename suffix * * @param string $suffix * @return Zend_Captcha_Image */ public function setSuffix($suffix) { $this->_suffix = $suffix; return $this; } /** * Set captcha image width * * @param int $width * @return Zend_Captcha_Image */ public function setWidth($width) { $this->_width = $width; return $this; } /** * Generate random frequency * * @return float */ protected function _randomFreq() { return mt_rand(700000, 1000000) / 15000000; } /** * Generate random phase * * @return float */ protected function _randomPhase() { // random phase from 0 to pi return mt_rand(0, 3141592) / 1000000; } /** * Generate random character size * * @return int */ protected function _randomSize() { return mt_rand(300, 700) / 100; } /** * Generate captcha * * @return string captcha ID */ public function generate() { $id = parent::generate(); $tries = 5; // If there's already such file, try creating a new ID while($tries-- && file_exists($this->getImgDir() . $id . $this->getSuffix())) { $id = $this->_generateRandomId(); $this->_setId($id); } $this->_generateImage($id, $this->getWord()); if (mt_rand(1, $this->getGcFreq()) == 1) { $this->_gc(); } return $id; } /** * Generate image captcha * * Override this function if you want different image generator * Wave transform from http://www.captcha.ru/captchas/multiwave/ * * @param string $id Captcha ID * @param string $word Captcha word * @throws Zend_Captcha_Exception */ protected function _generateImage($id, $word) { if (!extension_loaded("gd")) { require_once 'Zend/Captcha/Exception.php'; throw new Zend_Captcha_Exception("Image CAPTCHA requires GD extension"); } if (!function_exists("imagepng")) { require_once 'Zend/Captcha/Exception.php'; throw new Zend_Captcha_Exception("Image CAPTCHA requires PNG support"); } if (!function_exists("imageftbbox")) { require_once 'Zend/Captcha/Exception.php'; throw new Zend_Captcha_Exception("Image CAPTCHA requires FT fonts support"); } $font = $this->getFont(); if (empty($font)) { require_once 'Zend/Captcha/Exception.php'; throw new Zend_Captcha_Exception("Image CAPTCHA requires font"); } $w = $this->getWidth(); $h = $this->getHeight(); $fsize = $this->getFontSize(); $img_file = $this->getImgDir() . $id . $this->getSuffix(); if(empty($this->_startImage)) { $img = imagecreatetruecolor($w, $h); } else { $img = imagecreatefrompng($this->_startImage); if(!$img) { require_once 'Zend/Captcha/Exception.php'; throw new Zend_Captcha_Exception("Can not load start image"); } $w = imagesx($img); $h = imagesy($img); } $text_color = imagecolorallocate($img, 0, 0, 0); $bg_color = imagecolorallocate($img, 255, 255, 255); imagefilledrectangle($img, 0, 0, $w-1, $h-1, $bg_color); $textbox = imageftbbox($fsize, 0, $font, $word); $x = ($w - ($textbox[2] - $textbox[0])) / 2; $y = ($h - ($textbox[7] - $textbox[1])) / 2; imagefttext($img, $fsize, 0, $x, $y, $text_color, $font, $word); // generate noise for ($i=0; $i<$this->_dotNoiseLevel; $i++) { imagefilledellipse($img, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color); } for($i=0; $i<$this->_lineNoiseLevel; $i++) { imageline($img, mt_rand(0,$w), mt_rand(0,$h), mt_rand(0,$w), mt_rand(0,$h), $text_color); } // transformed image $img2 = imagecreatetruecolor($w, $h); $bg_color = imagecolorallocate($img2, 255, 255, 255); imagefilledrectangle($img2, 0, 0, $w-1, $h-1, $bg_color); // apply wave transforms $freq1 = $this->_randomFreq(); $freq2 = $this->_randomFreq(); $freq3 = $this->_randomFreq(); $freq4 = $this->_randomFreq(); $ph1 = $this->_randomPhase(); $ph2 = $this->_randomPhase(); $ph3 = $this->_randomPhase(); $ph4 = $this->_randomPhase(); $szx = $this->_randomSize(); $szy = $this->_randomSize(); for ($x = 0; $x < $w; $x++) { for ($y = 0; $y < $h; $y++) { $sx = $x + (sin($x*$freq1 + $ph1) + sin($y*$freq3 + $ph3)) * $szx; $sy = $y + (sin($x*$freq2 + $ph2) + sin($y*$freq4 + $ph4)) * $szy; if ($sx < 0 || $sy < 0 || $sx >= $w - 1 || $sy >= $h - 1) { continue; } else { $color = (imagecolorat($img, $sx, $sy) >> 16) & 0xFF; $color_x = (imagecolorat($img, $sx + 1, $sy) >> 16) & 0xFF; $color_y = (imagecolorat($img, $sx, $sy + 1) >> 16) & 0xFF; $color_xy = (imagecolorat($img, $sx + 1, $sy + 1) >> 16) & 0xFF; } if ($color == 255 && $color_x == 255 && $color_y == 255 && $color_xy == 255) { // ignore background continue; } elseif ($color == 0 && $color_x == 0 && $color_y == 0 && $color_xy == 0) { // transfer inside of the image as-is $newcolor = 0; } else { // do antialiasing for border items $frac_x = $sx-floor($sx); $frac_y = $sy-floor($sy); $frac_x1 = 1-$frac_x; $frac_y1 = 1-$frac_y; $newcolor = $color * $frac_x1 * $frac_y1 + $color_x * $frac_x * $frac_y1 + $color_y * $frac_x1 * $frac_y + $color_xy * $frac_x * $frac_y; } imagesetpixel($img2, $x, $y, imagecolorallocate($img2, $newcolor, $newcolor, $newcolor)); } } // generate noise for ($i=0; $i<$this->_dotNoiseLevel; $i++) { imagefilledellipse($img2, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color); } for ($i=0; $i<$this->_lineNoiseLevel; $i++) { imageline($img2, mt_rand(0,$w), mt_rand(0,$h), mt_rand(0,$w), mt_rand(0,$h), $text_color); } imagepng($img2, $img_file); imagedestroy($img); imagedestroy($img2); } /** * Remove old files from image directory */ protected function _gc() { $expire = time() - $this->getExpiration(); $imgdir = $this->getImgDir(); if(!$imgdir || strlen($imgdir) < 2) { // safety guard return; } $suffixLength = strlen($this->_suffix); foreach (new DirectoryIterator($imgdir) as $file) { if (!$file->isDot() && !$file->isDir()) { if (file_exists($file->getPathname()) && $file->getMTime() < $expire) { // only deletes files ending with $this->_suffix if (substr($file->getFilename(), -($suffixLength)) == $this->_suffix) { unlink($file->getPathname()); } } } } } /** * Display the captcha * * @param Zend_View_Interface $view * @param mixed $element * @return string */ public function render(Zend_View_Interface $view = null, $element = null) { $endTag = ' />'; if (($view instanceof Zend_View_Abstract) && !$view->doctype()->isXhtml()) { $endTag = '>'; } return '