ZF-5728: Set session will be overwritten.


We have setSession() function where we can save the session into the $this->_session, but the generate() function simply overwrites what we kept here: $this->_session. There must be another way to handle this issue. If you protect the $this->_session, then don't provide public setSession().

 * Zend_Captcha_Word

public function setSession(Zend_Session_Namespace $session)
    $this->_session = $session;
    return $this;

public function generate()
    $this->_session = null;
    $id             = $this->_generateRandomId();
    $word           = $this->_generateWord();
    return $id;


I ran into this bug today and it took me 3 hours of thinking I was doing it wrong before I located the problem in zend. I fixed it by commenting out $this->_session = null;

The problem here is that when we use generate(), a captcha with new ID is generated and new session object is created, named by this ID. However, in many cases isValid() is called before generate() - such as when old captcha failed and we need to generate a new one. In this case, however, if we keep old session object, then the data will not be written into this object but to the object for the old ID which was created before that, and then when captcha comes back in the next request, it would not be able to find this new object, since only thing it has is the ID, and you didn't write the data into the session with that ID - you wrote it to some other place, with old ID. setSession() is useful when doing isValid(), but for generate it should create a new session, so you better use _sessionClass if change is needed.

I could however try to fix your use case, but for that I would need some short script demonstrating it, so I could check that both default usage and your scenario works well.

Here's an example of how I am using it (non-working unless commented out as per above). I believe the reason I used a separate session for the captcha is because of ZF-5806.

Controller: $figlet = array( 'name' => 'captcha', 'wordLen' => 6, 'timeout' => 300, 'outputWidth' => 600, 'font' => '/lib/figlet/univers.flf' ); $captcha = new Zend_Captcha_Figlet($figlet); $captcha->setSession(new Zend_Session_Namespace('captcha'));

if ($this->_request->isPost()) { if ($captcha->isValid($_POST)) { echo 'captcha passed'; } }

$this->view->captcha_id = $captcha->generate(); $this->view->assign('captcha', $captcha->render(new Zend_View()));

View: <?=$this->captcha?>

OK, this should be working in trunk now. Please check if it does what you wanted.

Oh great that this got fixed now, my report was flaged as no issue, whyever.