Changeset 3047

Show
Ignore:
Timestamp:
07/11/2008 07:14:01 AM (5 months ago)
Author:
Geert
Message:

Captcha updates:

  • Bug fix: made sure the captcha_response session cannot be overwritten too soon. The problem was that Captcha::valid() would break if you created a new Captcha instance before it. Another good example of the power of Kohana events.
  • Added a static instance() method so Captcha::valid() can access non-static methods, e.g. the counters.
  • Shortened method names a bit: from "valid_response" to "valid", same for counters.
  • Added a reset_count() method.
  • Updated the example.
Location:
trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/application/controllers/examples.php

    r3043 r3047  
    178178                new Profiler; 
    179179 
    180                 // Ban bots after 10 invalid responses 
     180                // Load Captcha library 
     181                $captcha = new Captcha; 
     182 
     183                // Ban bots (that accept session cookies) after 50 invalid responses 
    181184                // Be careful not to ban real people though! Set the threshold high enough. 
    182                 if (Captcha::invalid_response_count() > 9) 
     185                if ($captcha->invalid_count() > 49) 
    183186                        exit('Bye! Stupid bot.'); 
    184187 
     
    187190                { 
    188191                        // User has not given three valid responses yet 
    189                         if (Captcha::valid_response_count() < 3) 
     192                        if ($captcha->valid_count() < 3) 
    190193                        { 
    191                                 // Valid response has been submitted 
    192                                 if (Captcha::valid_response($this->input->post('captcha_response'))) 
     194                                // Captcha::valid() is a static method that can be used as a Validation rule also 
     195                                if (Captcha::valid($this->input->post('captcha_response'))) 
    193196                                { 
    194197                                        echo '<p style="color:green">Good answer!</p>'; 
     
    208211 
    209212                // Don't show Captcha anymore after three or more valid responses 
    210                 if (Captcha::valid_response_count() < 3) 
     213                if ($captcha->valid_count() < 3) 
    211214                { 
    212215                        echo '<p>'; 
    213                         echo Captcha::factory()->render(); // Shows the Captcha challenge (image/riddle/etc) 
     216                        echo $captcha->render(); // Shows the Captcha challenge (image/riddle/etc) 
    214217                        echo '</p>'; 
    215218                        echo form::input('captcha_response'); 
  • trunk/system/libraries/Captcha.php

    r3046 r3047  
    1212class Captcha_Core { 
    1313 
     14        // Captcha singleton 
     15        protected static $instance; 
     16 
    1417        // Style-dependent Captcha driver 
    1518        protected $driver; 
     
    3033 
    3134        /** 
     35         * Singleton instance of Captcha. 
     36         * 
     37         * @return  object 
     38         */ 
     39        public static function instance() 
     40        { 
     41                // Create the instance if it does not exist 
     42                if (empty(self::$instance)) 
     43                { 
     44                        self::$instance = new Captcha; 
     45                } 
     46 
     47                return self::$instance; 
     48        } 
     49 
     50        /** 
    3251         * Constructs and returns a new Captcha object. 
    3352         * 
     
    5170                static $gd2_check; 
    5271 
    53                 // We need GD2 exclusively 
     72                // Check once for GD2 support 
    5473                if ($gd2_check === NULL AND ($gd2_check = function_exists('imagegd2')) === FALSE) 
    5574                        throw new Kohana_Exception('captcha.requires_GD2'); 
     
    128147                self::$response = (string) $this->driver->generate_challenge(); 
    129148 
    130                 // Store the answer in a session 
     149                // Store the Captcha response in a session 
     150                Event::add('system.post_controller', array($this, 'update_response_session')); 
     151 
     152                Log::add('debug', 'Captcha Library initialized'); 
     153        } 
     154 
     155        /** 
     156         * Stores the response for the current Captcha challenge in a session so it is available 
     157         * on the next page load for Captcha::valid(). This method is called after controller 
     158         * execution (system.post_controller event) in order not to overwrite itself too soon. 
     159         * 
     160         * @return  void 
     161         */ 
     162        public function update_response_session() 
     163        { 
    131164                Session::instance()->set('captcha_response', sha1(strtoupper(self::$response))); 
    132  
    133                 Log::add('debug', 'Captcha Library initialized'); 
    134165        } 
    135166 
     
    140171         * @return  boolean 
    141172         */ 
    142         public static function valid_response($response) 
     173        public static function valid($response) 
    143174        { 
    144175                // Maximum one count per page load 
     
    149180 
    150181                // Increment response counter 
    151                 if ($counted === NULL) 
     182                if ($counted !== TRUE) 
    152183                { 
    153184                        $counted = TRUE; 
     
    156187                        if ($result === TRUE) 
    157188                        { 
    158                                 self::valid_response_count(Session::instance()->get('captcha_valid_response_count') + 1); 
     189                                self::instance()->valid_count(Session::instance()->get('captcha_valid_count') + 1); 
    159190                        } 
    160191                        // Invalid response 
    161192                        else 
    162193                        { 
    163                                 self::invalid_response_count(Session::instance()->get('captcha_invalid_response_count') + 1); 
     194                                self::instance()->invalid_count(Session::instance()->get('captcha_invalid_count') + 1); 
    164195                        } 
    165196                } 
     
    175206         * @return  integer  counter value 
    176207         */ 
    177         public static function valid_response_count($new_count = NULL, $invalid = FALSE) 
     208        public function valid_count($new_count = NULL, $invalid = FALSE) 
    178209        { 
    179210                // Pick the right session to use 
    180                 $session = ($invalid === TRUE) ? 'captcha_invalid_response_count' : 'captcha_valid_response_count'; 
     211                $session = ($invalid === TRUE) ? 'captcha_invalid_count' : 'captcha_valid_count'; 
    181212 
    182213                // Update counter 
     
    185216                        $new_count = (int) $new_count; 
    186217 
    187                         // Reset counter 
     218                        // Reset counter = delete session 
    188219                        if ($new_count < 1) 
    189220                        { 
     
    210241         * @return  integer  counter value 
    211242         */ 
    212         public static function invalid_response_count($new_count = NULL) 
    213         { 
    214                 return self::valid_response_count($new_count, TRUE); 
     243        public function invalid_count($new_count = NULL) 
     244        { 
     245                return $this->valid_count($new_count, TRUE); 
     246        } 
     247 
     248        /** 
     249         * Resets the Captcha response counters and removes the count sessions. 
     250         * 
     251         * @return  void 
     252         */ 
     253        public function reset_count() 
     254        { 
     255                $this->valid_count(0); 
     256                $this->valid_count(0, TRUE); 
    215257        } 
    216258