web/Zend/Captcha/Word.php
changeset 0 4eba9c11703f
equal deleted inserted replaced
-1:000000000000 0:4eba9c11703f
       
     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-2010 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 */
       
    23 require_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-2010 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 21793 2010-04-08 00:51:31Z stas $
       
    36  */
       
    37 abstract 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 $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 $_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 }