PageRenderTime 488ms CodeModel.GetById 132ms app.highlight 146ms RepoModel.GetById 117ms app.codeStats 0ms

/Captcha/Word.php

https://bitbucket.org/goldie/zend-framework1
PHP | 418 lines | 180 code | 42 blank | 196 comment | 17 complexity | a29b8870e6ffbe5f83546d3a54f0daf1 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-2011 Zend Technologies USA Inc. (http://www.zend.com)
 19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 20 */
 21
 22/** @see Zend_Captcha_Base */
 23require_once 'Zend/Captcha/Base.php';
 24
 25/**
 26 * Word-based captcha adapter
 27 *
 28 * Generates random word which user should recognise
 29 *
 30 * @category   Zend
 31 * @package    Zend_Captcha
 32 * @subpackage Adapter
 33 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 34 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 35 * @version    $Id: Word.php 23775 2011-03-01 17:25:24Z ralph $
 36 */
 37abstract class Zend_Captcha_Word extends Zend_Captcha_Base
 38{
 39    /**#@+
 40     * @var array Character sets
 41     */
 42    static $V  = array("a", "e", "i", "o", "u", "y");
 43    static $VN = array("a", "e", "i", "o", "u", "y","2","3","4","5","6","7","8","9");
 44    static $C  = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z");
 45    static $CN = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z","2","3","4","5","6","7","8","9");
 46    /**#@-*/
 47
 48    /**
 49     * Random session ID
 50     *
 51     * @var string
 52     */
 53    protected $_id;
 54
 55    /**
 56     * Generated word
 57     *
 58     * @var string
 59     */
 60    protected $_word;
 61
 62    /**
 63     * Session
 64     *
 65     * @var Zend_Session_Namespace
 66     */
 67    protected $_session;
 68
 69    /**
 70     * Class name for sessions
 71     *
 72     * @var string
 73     */
 74    protected $_sessionClass = 'Zend_Session_Namespace';
 75
 76    /**
 77     * Should the numbers be used or only letters
 78     *
 79     * @var boolean
 80     */
 81    protected $_useNumbers = true;
 82
 83    /**
 84     * Should both cases be used or only lowercase
 85     *
 86     * @var boolean
 87     */
 88    // protected $_useCase = false;
 89
 90    /**
 91     * Session lifetime for the captcha data
 92     *
 93     * @var integer
 94     */
 95    protected $_timeout = 300;
 96
 97    /**
 98     * Should generate() keep session or create a new one?
 99     *
100     * @var boolean
101     */
102    protected $_keepSession = false;
103
104    /**#@+
105     * Error codes
106     */
107    const MISSING_VALUE = 'missingValue';
108    const MISSING_ID    = 'missingID';
109    const BAD_CAPTCHA   = 'badCaptcha';
110    /**#@-*/
111
112    /**
113     * Error messages
114     * @var array
115     */
116    protected $_messageTemplates = array(
117        self::MISSING_VALUE => 'Empty captcha value',
118        self::MISSING_ID    => 'Captcha ID field is missing',
119        self::BAD_CAPTCHA   => 'Captcha value is wrong',
120    );
121
122    /**
123     * Length of the word to generate
124     *
125     * @var integer
126     */
127    protected $_wordlen = 8;
128
129    /**
130     * Retrieve session class to utilize
131     *
132     * @return string
133     */
134    public function getSessionClass()
135    {
136        return $this->_sessionClass;
137    }
138
139    /**
140     * Set session class for persistence
141     *
142     * @param  string $_sessionClass
143     * @return Zend_Captcha_Word
144     */
145    public function setSessionClass($_sessionClass)
146    {
147        $this->_sessionClass = $_sessionClass;
148        return $this;
149    }
150
151    /**
152     * Retrieve word length to use when genrating captcha
153     *
154     * @return integer
155     */
156    public function getWordlen()
157    {
158        return $this->_wordlen;
159    }
160
161    /**
162     * Set word length of captcha
163     *
164     * @param integer $wordlen
165     * @return Zend_Captcha_Word
166     */
167    public function setWordlen($wordlen)
168    {
169        $this->_wordlen = $wordlen;
170        return $this;
171    }
172
173    /**
174     * Retrieve captcha ID
175     *
176     * @return string
177     */
178    public function getId ()
179    {
180        if (null === $this->_id) {
181            $this->_setId($this->_generateRandomId());
182        }
183        return $this->_id;
184    }
185
186    /**
187     * Set captcha identifier
188     *
189     * @param string $id
190     * return Zend_Captcha_Word
191     */
192    protected function _setId ($id)
193    {
194        $this->_id = $id;
195        return $this;
196    }
197
198    /**
199     * Set timeout for session token
200     *
201     * @param  int $ttl
202     * @return Zend_Captcha_Word
203     */
204    public function setTimeout($ttl)
205    {
206        $this->_timeout = (int) $ttl;
207        return $this;
208    }
209
210    /**
211     * Get session token timeout
212     *
213     * @return int
214     */
215    public function getTimeout()
216    {
217        return $this->_timeout;
218    }
219
220    /**
221     * Sets if session should be preserved on generate()
222     *
223     * @param bool $keepSession Should session be kept on generate()?
224     * @return Zend_Captcha_Word
225     */
226    public function setKeepSession($keepSession)
227    {
228        $this->_keepSession = $keepSession;
229        return $this;
230    }
231
232    /**
233     * Numbers should be included in the pattern?
234     *
235     * @return bool
236     */
237    public function getUseNumbers()
238    {
239        return $this->_useNumbers;
240    }
241
242    /**
243     * Set if numbers should be included in the pattern
244     *
245     * @param bool $_useNumbers numbers should be included in the pattern?
246     * @return Zend_Captcha_Word
247     */
248    public function setUseNumbers($_useNumbers)
249    {
250        $this->_useNumbers = $_useNumbers;
251        return $this;
252    }
253    
254    /**
255     * Get session object
256     *
257     * @return Zend_Session_Namespace
258     */
259    public function getSession()
260    {
261        if (!isset($this->_session) || (null === $this->_session)) {
262            $id = $this->getId();
263            if (!class_exists($this->_sessionClass)) {
264                require_once 'Zend/Loader.php';
265                Zend_Loader::loadClass($this->_sessionClass);
266            }
267            $this->_session = new $this->_sessionClass('Zend_Form_Captcha_' . $id);
268            $this->_session->setExpirationHops(1, null, true);
269            $this->_session->setExpirationSeconds($this->getTimeout());
270        }
271        return $this->_session;
272    }
273
274    /**
275     * Set session namespace object
276     *
277     * @param  Zend_Session_Namespace $session
278     * @return Zend_Captcha_Word
279     */
280    public function setSession(Zend_Session_Namespace $session)
281    {
282        $this->_session = $session;
283        if($session) {
284            $this->_keepSession = true;
285        }
286        return $this;
287    }
288
289    /**
290     * Get captcha word
291     *
292     * @return string
293     */
294    public function getWord()
295    {
296        if (empty($this->_word)) {
297            $session     = $this->getSession();
298            $this->_word = $session->word;
299        }
300        return $this->_word;
301    }
302
303    /**
304     * Set captcha word
305     *
306     * @param  string $word
307     * @return Zend_Captcha_Word
308     */
309    protected function _setWord($word)
310    {
311        $session       = $this->getSession();
312        $session->word = $word;
313        $this->_word   = $word;
314        return $this;
315    }
316
317    /**
318     * Generate new random word
319     *
320     * @return string
321     */
322    protected function _generateWord()
323    {
324        $word       = '';
325        $wordLen    = $this->getWordLen();
326        $vowels     = $this->_useNumbers ? self::$VN : self::$V;
327        $consonants = $this->_useNumbers ? self::$CN : self::$C;
328
329        for ($i=0; $i < $wordLen; $i = $i + 2) {
330            // generate word with mix of vowels and consonants
331            $consonant = $consonants[array_rand($consonants)];
332            $vowel     = $vowels[array_rand($vowels)];
333            $word     .= $consonant . $vowel;
334        }
335
336        if (strlen($word) > $wordLen) {
337            $word = substr($word, 0, $wordLen);
338        }
339
340        return $word;
341    }
342
343    /**
344     * Generate new session ID and new word
345     *
346     * @return string session ID
347     */
348    public function generate()
349    {
350        if(!$this->_keepSession) {
351            $this->_session = null;
352        }
353        $id = $this->_generateRandomId();
354        $this->_setId($id);
355        $word = $this->_generateWord();
356        $this->_setWord($word);
357        return $id;
358    }
359
360    protected function _generateRandomId()
361    {
362        return md5(mt_rand(0, 1000) . microtime(true));
363    }
364
365    /**
366     * Validate the word
367     *
368     * @see    Zend_Validate_Interface::isValid()
369     * @param  mixed $value
370     * @return boolean
371     */
372    public function isValid($value, $context = null)
373    {
374        if (!is_array($value) && !is_array($context)) {
375            $this->_error(self::MISSING_VALUE);
376            return false;
377        }
378        if (!is_array($value) && is_array($context)) {
379            $value = $context;
380        }
381
382        $name = $this->getName();
383
384        if (isset($value[$name])) {
385            $value = $value[$name];
386        }
387
388        if (!isset($value['input'])) {
389            $this->_error(self::MISSING_VALUE);
390            return false;
391        }
392        $input = strtolower($value['input']);
393        $this->_setValue($input);
394
395        if (!isset($value['id'])) {
396            $this->_error(self::MISSING_ID);
397            return false;
398        }
399
400        $this->_id = $value['id'];
401        if ($input !== $this->getWord()) {
402            $this->_error(self::BAD_CAPTCHA);
403            return false;
404        }
405
406        return true;
407    }
408
409    /**
410     * Get captcha decorator
411     *
412     * @return string
413     */
414    public function getDecorator()
415    {
416        return "Captcha_Word";
417    }
418}