PageRenderTime 131ms CodeModel.GetById 117ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Captcha/Image.php

https://bitbucket.org/baruffaldi/webapp-urltube
PHP | 495 lines | 220 code | 51 blank | 224 comment | 36 complexity | d50171855eab50ba1fd0bdbe573e9c57 MD5 | raw file
  1<?php
  2/**
  3 * Zend Framework
  4 *
  5 * LICENSE
  6 *
  7 * This source file is subject to the new BSD license that is bundled
  8 * with this package in the file LICENSE.txt.
  9 * It is also available through the world-wide-web at this URL:
 10 * http://framework.zend.com/license/new-bsd
 11 * If you did not receive a copy of the license and are unable to
 12 * obtain it through the world-wide-web, please send an email
 13 * to license@zend.com so we can send you a copy immediately.
 14 *
 15 * @category   Zend
 16 * @package    Zend_Captcha
 17 * @subpackage Adapter
 18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 20 */
 21
 22/** Zend_Captcha_Word */
 23require_once 'Zend/Captcha/Word.php';
 24
 25/**
 26 * Image-based captcha element 
 27 * 
 28 * Generates image displaying random word
 29 * 
 30 * @category   Zend
 31 * @package    Zend_Captcha
 32 * @subpackage Adapter
 33 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 34 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 35 * @version    $Id: $
 36 */
 37class Zend_Captcha_Image extends Zend_Captcha_Word
 38{
 39    /**
 40     * Directory for generated images
 41     *
 42     * @var string
 43     */
 44    protected $_imgDir = "./images/captcha/";
 45
 46    /**
 47     * URL for accessing images
 48     *
 49     * @var string
 50     */
 51    protected $_imgUrl = "/images/captcha/";
 52
 53    /**
 54     * Image suffix (including dot)
 55     *
 56     * @var string
 57     */
 58    protected $_suffix = ".png";
 59
 60    /**
 61     * Image width
 62     *
 63     * @var int
 64     */
 65    protected $_width = 200;
 66
 67    /**
 68     * Image height
 69     *
 70     * @var int
 71     */
 72    protected $_height = 50;
 73
 74    /**
 75     * Font size
 76     *
 77     * @var int
 78     */
 79    protected $_fsize = 24;
 80
 81    /**
 82     * Image font file
 83     *
 84     * @var string
 85     */
 86    protected $_font;
 87	
 88    /**
 89     * How frequently to execute garbage collection
 90     *
 91     * @var int
 92     */
 93    protected $_gcFreq = 10;
 94	
 95    /**
 96     * How long to keep generated images
 97     *
 98     * @var int
 99     */
100    protected $_expiration = 600;
101
102	/**
103     * Get captcha expiration
104     *
105	 * @return int
106	 */
107    public function getExpiration() 
108    {
109		return $this->_expiration;
110	}
111	
112	/**
113     * Get garbage collection frequency
114     *
115	 * @return int
116	 */
117    public function getGcFreq() 
118    {
119		return $this->_gcFreq;
120	}
121	
122	/**
123     * Set captcha expiration
124     *
125	 * @param int $expiration
126     * @return Zend_Captcha_Image
127	 */
128    public function setExpiration($expiration)
129    {
130		$this->_expiration = $expiration;
131		return $this;
132	}
133	
134	/**
135     * Set garbage collection frequency
136     *
137	 * @param int $gcFreq
138     * @return Zend_Captcha_Image
139	 */
140    public function setGcFreq($gcFreq) 
141    {
142		$this->_gcFreq = $gcFreq;
143		return $this;
144	}
145
146    /**
147     * Get font to use when generating captcha
148     *
149	 * @return string
150	 */
151    public function getFont() 
152    {
153		return $this->_font;
154	}
155	
156	/**
157     * Get font size
158     *
159	 * @return int
160	 */
161    public function getFontSize() 
162    {
163		return $this->_fsize;
164	}
165	
166	/**
167     * Get captcha image height
168     *
169	 * @return int
170	 */
171    public function getHeight() 
172    {
173		return $this->_height;
174	}
175	
176	/**
177     * Get captcha image directory
178     *
179	 * @return string
180	 */
181    public function getImgDir() 
182    {
183		return $this->_imgDir;
184	}
185	
186	/**
187     * Get captcha image base URL
188     *
189	 * @return string
190	 */
191    public function getImgUrl() 
192    {
193		return $this->_imgUrl;
194	}
195	
196	/**
197     * Get captcha image file suffix
198     *
199	 * @return string
200	 */
201    public function getSuffix() 
202    {
203		return $this->_suffix;
204	}
205	
206	/**
207     * Get captcha image width
208     *
209	 * @return int
210	 */
211    public function getWidth() 
212    {
213		return $this->_width;
214	}
215	
216	/**
217     * Set captcha font
218     *
219	 * @param  string $font
220	 * @return Zend_Captcha_Image
221	 */
222    public function setFont($font) 
223    {
224		$this->_font = $font;
225		return $this;
226	}
227	
228	/**
229     * Set captcha font size
230     *
231	 * @param  int $fsize
232	 * @return Zend_Captcha_Image
233	 */
234    public function setFontSize($fsize) 
235    {
236		$this->_fsize = $fsize;
237		return $this;
238	}
239	
240	/**
241     * Set captcha image height
242     *
243	 * @param  int $height
244	 * @return Zend_Captcha_Image
245	 */
246    public function setHeight($height) 
247    {
248		$this->_height = $height;
249		return $this;
250	}
251	
252	/**
253     * Set captcha image storage directory
254     *
255	 * @param  string $imgDir
256	 * @return Zend_Captcha_Image
257	 */
258    public function setImgDir($imgDir) 
259    {
260		$this->_imgDir = rtrim($imgDir, "/\\") . '/';
261		return $this;
262	}
263	
264	/**
265     * Set captcha image base URL
266     *
267	 * @param  string $imgUrl
268	 * @return Zend_Captcha_Image
269	 */
270    public function setImgUrl($imgUrl) 
271    {
272		$this->_imgUrl = rtrim($imgUrl, "/\\") . '/';
273		return $this;
274	}
275	
276	/**
277     * Set captch image filename suffix
278     *
279	 * @param  string $suffix
280	 * @return Zend_Captcha_Image
281	 */
282    public function setSuffix($suffix) 
283    {
284		$this->_suffix = $suffix;
285		return $this;
286	}
287	
288	/**
289     * Set captcha image width
290     *
291	 * @param  int $width
292	 * @return Zend_Captcha_Image
293	 */
294    public function setWidth($width) 
295    {
296		$this->_width = $width;
297		return $this;
298	}
299    
300    /**
301     * Generate random frequency
302     * 
303     * @return float
304     */
305    protected function _randomFreq() 
306    {
307	    return mt_rand(700000, 1000000) / 15000000;
308    }
309
310    /**
311     * Generate random phase
312     * 
313     * @return float
314     */
315    protected function _randomPhase() 
316    {
317        // random phase from 0 to pi
318	    return mt_rand(0, 3141592) / 1000000;
319    }
320
321    /**
322     * Generate random character size
323     * 
324     * @return int
325     */
326    protected function _randomSize() 
327    {
328	    return mt_rand(300, 700) / 100;
329    }
330    
331    /**
332     * Generate captcha
333     * 
334     * @return string captcha ID
335     */
336    public function generate()
337    {
338        $id = parent::generate();
339        $this->_generateImage($id, $this->getWord());
340        
341        if (mt_rand(0, $this->getGcFreq()) == 1) {
342            $this->_gc();
343        }
344        return $id;
345    }
346    
347    /**
348     * Generate image captcha
349     * 
350     * Override this function if you want different image generator
351     * Wave transform from http://www.captcha.ru/captchas/multiwave/
352     *
353     * @param string $id Captcha ID
354     * @param string $word Captcha word
355     */
356    protected function _generateImage($id, $word) 
357    { 
358        if (!extension_loaded("gd")) {
359            require_once 'Zend/Form/Exception.php';
360            throw new Zend_Form_Exception("Image CAPTCHA requires GD extension");
361        }
362
363        if (!function_exists("imagepng")) {
364            require_once 'Zend/Form/Exception.php';
365            throw new Zend_Form_Exception("Image CAPTCHA requires PNG support");
366        }
367
368        if (!function_exists("imageftbbox")) {
369            require_once 'Zend/Form/Exception.php';
370            throw new Zend_Form_Exception("Image CAPTCHA requires FT fonts support");
371        }
372
373        $font = $this->getFont();
374
375        if (empty($font)) {
376            require_once 'Zend/Form/Exception.php';
377            throw new Zend_Form_Exception("Image CAPTCHA requires font");
378        }
379        
380        $w     = $this->getWidth();
381        $h     = $this->getHeight();
382        $fsize = $this->getFontSize();
383        
384        $img_file   = $this->getImgDir() . $id . $this->getSuffix();
385        $img        = imagecreatetruecolor($w, $h);
386        $text_color = imagecolorallocate($img, 0, 0, 0);
387        $bg_color   = imagecolorallocate($img, 255, 255, 255);
388        imagefilledrectangle($img, 0, 0, $w-1, $h-1, $bg_color);
389        $textbox = imageftbbox($fsize, 0, $font, $word);
390        $x = ($w - ($textbox[2] - $textbox[0])) / 2;
391        $y = ($h - ($textbox[7] - $textbox[1])) / 2;
392        imagefttext($img, $fsize, 0, $x, $y, $text_color, $font, $word);
393        
394       // generate noise
395        for ($i=0; $i<100; $i++) {
396           imagefilledellipse($img, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color);
397        }
398        for($i=0; $i<5; $i++) {
399           imageline($img, mt_rand(0,$w), mt_rand(0,$h), mt_rand(0,$w), mt_rand(0,$h), $text_color);
400        }
401        
402        // transformed image
403        $img2     = imagecreatetruecolor($w, $h);
404        $bg_color = imagecolorallocate($img2, 255, 255, 255);
405        imagefilledrectangle($img2, 0, 0, $w-1, $h-1, $bg_color);
406        // apply wave transforms
407        $freq1 = $this->_randomFreq();
408        $freq2 = $this->_randomFreq();
409	    $freq3 = $this->_randomFreq();
410	    $freq4 = $this->_randomFreq();
411
412        $ph1 = $this->_randomPhase();
413        $ph2 = $this->_randomPhase();
414        $ph3 = $this->_randomPhase();
415        $ph4 = $this->_randomPhase();
416
417        $szx = $this->_randomSize();
418        $szy = $this->_randomSize();
419 
420        for ($x = 0; $x < $w; $x++) {
421            for ($y = 0; $y < $h; $y++) {
422                $sx = $x + (sin($x*$freq1 + $ph1) + sin($y*$freq3 + $ph3)) * $szx;
423                $sy = $y + (sin($x*$freq2 + $ph2) + sin($y*$freq4 + $ph4)) * $szy;
424    
425                if ($sx < 0 || $sy < 0 || $sx >= $w - 1 || $sy >= $h - 1) { 
426                    continue;
427                } else {
428                    $color    = (imagecolorat($img, $sx, $sy) >> 16)         & 0xFF;
429                    $color_x  = (imagecolorat($img, $sx + 1, $sy) >> 16)     & 0xFF;
430                    $color_y  = (imagecolorat($img, $sx, $sy + 1) >> 16)     & 0xFF;
431                    $color_xy = (imagecolorat($img, $sx + 1, $sy + 1) >> 16) & 0xFF;
432                }
433                if ($color == 255 && $color_x == 255 && $color_y == 255 && $color_xy == 255) {
434                    // ignore background
435                    continue;
436                } elseif ($color == 0 && $color_x == 0 && $color_y == 0 && $color_xy == 0) {
437                    // transfer inside of the image as-is
438                    $newcolor = 0;
439                } else {
440                    // do antialiasing for border items
441                    $frac_x  = $sx-floor($sx);
442                    $frac_y  = $sy-floor($sy);
443                    $frac_x1 = 1-$frac_x;
444                    $frac_y1 = 1-$frac_y;
445
446                    $newcolor = $color    * $frac_x1 * $frac_y1
447                              + $color_x  * $frac_x  * $frac_y1
448                              + $color_y  * $frac_x1 * $frac_y
449                              + $color_xy * $frac_x  * $frac_y;
450                }
451                imagesetpixel($img2, $x, $y, imagecolorallocate($img2, $newcolor, $newcolor, $newcolor));
452            }
453        }
454       
455        // generate noise
456        for ($i=0; $i<100; $i++) {
457            imagefilledellipse($img2, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color);
458        }
459        for ($i=0; $i<5; $i++) {
460           imageline($img2, mt_rand(0,$w), mt_rand(0,$h), mt_rand(0,$w), mt_rand(0,$h), $text_color);
461        }
462        
463        imagepng($img2, $img_file);
464        imagedestroy($img);
465        imagedestroy($img2);
466    }
467    
468    /**
469     * Remove old files from image directory
470     *
471     */
472    protected function _gc()
473    {
474        $expire = time() - $this->getExpiration();
475        foreach (new DirectoryIterator($this->getImgDir()) as $file) {
476            if (!$file->isDot() && !$file->isDir()) {
477                if ($file->getMTime() < $expire) {
478                    unlink($file->getPathname());
479                }
480            }
481        }
482    }
483    
484	/**
485	 * Display the captcha
486	 *
487	 * @param Zend_View $view
488	 * @param mixed $element
489	 * @return string
490	 */
491	public function render(Zend_View $view, $element = null)
492    {
493        return '<img src="' . $this->getImgUrl() . $this->getId() . $this->getSuffix() . '"/><br/>';
494    }
495}