Captcha Error

Hi.

I am using a captcha installed by an extension in my site.

The issue is that when enabled, the page goes blank with this error:


Fatal error: Call to a member function display() on a non-object in /homepages/13/d480589583/htdocs/html/components/com_captcha/views/property/view.html.php on line 103

If I deactivate it, there is no problem, but I need the captcha.

The code (with the 103 line in bolds):


    protected function displayCaptcha()
    {
        $plugin = JFactory::getConfig()->get('captcha');
        if ($plugin == '0') {
            $plugin = 'recaptcha';
        }
        $captcha = JCaptcha::getInstance($plugin);
[B]        return $captcha->display('captcha', 'jea-captcha');[/B]
    }

}

And the code in the default contact form php file:


      <?php if ($this->params->get('use_captcha')):?> 
      <dd><?php echo $this->displayCaptcha() ?></dd>
      <?php endif ?>

And the recaptcha plugin:


	public function onInit($id)
	{
		$document = JFactory::getDocument();
		$app      = JFactory::getApplication();

		$lang   = $this->_getLanguage();
		$pubkey = $this->params->get('public_key', '');
		$theme  = $this->params->get('theme', 'clean');

		if ($pubkey == null || $pubkey == '')
		{
			throw new Exception(JText::_('PLG_RECAPTCHA_ERROR_NO_PUBLIC_KEY'));
		}

		$server = self::RECAPTCHA_API_SERVER;

		if ($app->isSSLConnection())
		{
			$server = self::RECAPTCHA_API_SECURE_SERVER;
		}

		JHtml::_('script', $server . '/js/recaptcha_ajax.js');
		$document->addScriptDeclaration('window.addEvent(\\'domready\\', function()
		{
			Recaptcha.create("' . $pubkey . '", "dynamic_recaptcha_1", {theme: "' . $theme . '",' . $lang . 'tabindex: 0});});'
		);

		return true;
	}

	/**
	 * Gets the challenge HTML
	 *
	 * @param   string  $name   The name of the field.
	 * @param   string  $id     The id of the field.
	 * @param   string  $class  The class of the field.
	 *
	 * @return  string  The HTML to be embedded in the form.
	 *
	 * @since  2.5
	 */
	public function onDisplay($name, $id, $class)
	{
		return '<div id="dynamic_recaptcha_1"></div>';
	}

	/**
	  * Calls an HTTP POST function to verify if the user's guess was correct
	  *
	  * @return  True if the answer is correct, false otherwise
	  *
	  * @since  2.5
	  */
	public function onCheckAnswer($code)
	{
		$input      = JFactory::getApplication()->input;
		$privatekey = $this->params->get('private_key');
		$remoteip   = $input->server->get('REMOTE_ADDR', '', 'string');
		$challenge  = $input->get('recaptcha_challenge_field', '', 'string');
		$response   = $input->get('recaptcha_response_field', '', 'string');

		// Check for Private Key
		if (empty($privatekey))
		{
			$this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_NO_PRIVATE_KEY'));

			return false;
		}

		// Check for IP
		if (empty($remoteip))
		{
			$this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_NO_IP'));

			return false;
		}

		// Discard spam submissions
		if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0)
		{
			$this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_EMPTY_SOLUTION'));

			return false;
		}

		$response = $this->_recaptcha_http_post(
			self::RECAPTCHA_VERIFY_SERVER, "/verify",
			array(
				'privatekey' => $privatekey,
				'remoteip'   => $remoteip,
				'challenge'  => $challenge,
				'response'   => $response
			)
	);

		$answers = explode("\
", $response[1]);

		if (trim($answers[0]) == 'true')
			{
				return true;
		}
		else
		{
			// @todo use exceptions here
			$this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_' . strtoupper(str_replace('-', '_', $answers[1]))));

			return false;
		}
	}

	/**
	 * Encodes the given data into a query string format.
	 *
	 * @param   string  $data  Array of string elements to be encoded
	 *
	 * @return  string  Encoded request
	 *
	 * @since  2.5
	 */
	private function _recaptcha_qsencode($data)
	{
		$req = "";

		foreach ($data as $key => $value)
		{
			$req .= $key . '=' . urlencode(stripslashes($value)) . '&';
		}

		// Cut the last '&'
		$req = rtrim($req, '&');

		return $req;
	}

	/**
	 * Submits an HTTP POST to a reCAPTCHA server.
	 *
	 * @param   string  $host
	 * @param   string  $path
	 * @param   array   $data
	 * @param   int     $port
	 *
	 * @return  array   Response
	 *
	 * @since  2.5
	 */
	private function _recaptcha_http_post($host, $path, $data, $port = 80)
	{
		$req = $this->_recaptcha_qsencode($data);

		$http_request  = "POST $path HTTP/1.0\\r\
";
		$http_request .= "Host: $host\\r\
";
		$http_request .= "Content-Type: application/x-www-form-urlencoded;\\r\
";
		$http_request .= "Content-Length: " . strlen($req) . "\\r\
";
		$http_request .= "User-Agent: reCAPTCHA/PHP\\r\
";
		$http_request .= "\\r\
";
		$http_request .= $req;

		$response = '';

		if (($fs = @fsockopen($host, $port, $errno, $errstr, 10)) == false )
		{
			die('Could not open socket');
		}

		fwrite($fs, $http_request);

		while (!feof($fs))
		{
			// One TCP-IP packet
			$response .= fgets($fs, 1160);
		}

		fclose($fs);
		$response = explode("\\r\
\\r\
", $response, 2);

		return $response;
	}

	/**
	 * Get the language tag or a custom translation
	 *
	 * @return  string
	 *
	 * @since  2.5
	 */
	private function _getLanguage()
	{
		$language = JFactory::getLanguage();

		$tag = explode('-', $language->getTag());
		$tag = $tag[0];
		$available = array('en', 'pt', 'fr', 'de', 'nl', 'ru', 'es', 'tr');

		if (in_array($tag, $available))
		{
			return "lang : '" . $tag . "',";
		}

		// If the default language is not available, let's search for a custom translation
		if ($language->hasKey('PLG_RECAPTCHA_CUSTOM_LANG'))
		{
			$custom[] = 'custom_translations : {';
			$custom[] = "\	" . 'instructions_visual : "' . JText::_('PLG_RECAPTCHA_INSTRUCTIONS_VISUAL') . '",';
			$custom[] = "\	" . 'instructions_audio : "' . JText::_('PLG_RECAPTCHA_INSTRUCTIONS_AUDIO') . '",';
			$custom[] = "\	" . 'play_again : "' . JText::_('PLG_RECAPTCHA_PLAY_AGAIN') . '",';
			$custom[] = "\	" . 'cant_hear_this : "' . JText::_('PLG_RECAPTCHA_CANT_HEAR_THIS') . '",';
			$custom[] = "\	" . 'visual_challenge : "' . JText::_('PLG_RECAPTCHA_VISUAL_CHALLENGE') . '",';
			$custom[] = "\	" . 'audio_challenge : "' . JText::_('PLG_RECAPTCHA_AUDIO_CHALLENGE') . '",';
			$custom[] = "\	" . 'refresh_btn : "' . JText::_('PLG_RECAPTCHA_REFRESH_BTN') . '",';
			$custom[] = "\	" . 'help_btn : "' . JText::_('PLG_RECAPTCHA_HELP_BTN') . '",';
			$custom[] = "\	" . 'incorrect_try_again : "' . JText::_('PLG_RECAPTCHA_INCORRECT_TRY_AGAIN') . '",';
			$custom[] = '},';
			$custom[] = "lang : '" . $tag . "',";

			return implode("\
", $custom);
		}

		// If nothing helps fall back to english
		return '';
	}
}

I have no idea where the problem is?

Many thanks for any answer.

Check the name of the function you are calling.

display() function doesn’t exist in the code you have given but onDisplay() does, is that the function you meant to call?

You have been missing the “$this” in recaptcha plugin file.

Yes. But if I replace display() with onDisplay(), the error remains.

The recaptcha plugin file is ok. I have tested it with a native form.

The problem is in


    protected function displayCaptcha()
    {
        $plugin = JFactory::getConfig()->get('captcha');
        if ($plugin == '0') {
            $plugin = 'recaptcha';
        }
        $captcha = JCaptcha::getInstance($plugin);
        return $captcha->display('captcha', 'jea-captcha');
    }

}

Which is part of a form that I have included in the site.

Off Topic:

Captcha sucks, anyway, so perhaps this is a good prompt to use something better, like a simple honeypot, that catches the bots without forcing your sincere and legitimate visitors to jump through demeaning and frustrating hoops. :slight_smile:

Yes, you are right. But while waiting for someone to bring the honey, I need to fix the problem not to have my box full of rubbish.

How is $this defined in the scope of the contact form? That… shouldnt be in the context of a class definition…

The captcha in the contact form is defined by:


      <?php if ($this->params->get('use_captcha')):?> 
      <dd><?php echo $this->displayCaptcha() ?></dd>
      <?php endif ?>
      <dd>

If we are talking about the same thing.

(I am lost now)

<?php if ($this->params->get(‘use_captcha’)):?>

Where do you define $this ? is it an object you’ve created? $this->params is not a definition. $this = new GoofyBall(); is a definition. $this = “Strings are neat” is a definition. $this inside a class {} structure is a definition (referring to the instance of the class object).

Show us the rest of your contact form.

Hi StarLion.

It is an extension with a catalog. Clicking on a link, a page with a complete description of the product is displayed. At the very bottom of the page, there is a form for the user to ask for more information about the item.

A very usual coding.

If you enable the captcha to be displayed with the form, the system fails showing the above-mentioned error.

I have created nothing. It is an extension with some problem with my php version or the rest of my coding.

The form without the captcha:


form action="<?php echo JRoute::_('index.php?option=com_jea&task=default.sendContactForm') ?>" method="post" id="jea-contact-form" enctype="application/x-www-form-urlencoded">
  <fieldset>
    <legend><?php echo JText::_('COM_JEA_CONTACT_FORM_LEGEND') ?></legend>
    <dl>
      <dt><label for="name"><?php echo JText::_('COM_JEA_NAME') ?> :</label></dt>
      <dd><input type="text" name="name" id="name" size="30" value="<?php echo $this->escape($this->state->get('contact.name')) ?>" /></dd>


      <dt><label for="email"><?php echo JText::_('COM_JEA_EMAIL') ?> :</label></dt>
      <dd><input type="text" name="email" id="email" size="30" value="<?php echo $this->escape($this->state->get('contact.email')) ?>" /></dd>

      <dt><label for="telephone"><?php echo JText::_('COM_JEA_TELEPHONE') ?> :</label></dt>
      <dd><input type="text" name="telephone" id="telephone" size="30" value="<?php echo $this->escape($this->state->get('contact.telephone')) ?>" /></dd>

      <dt><label for="subject"><?php echo JText::_('COM_JEA_SUBJECT') ?> :</label></dt>
      <dd><input type="text" name="subject" id="subject" value="<?php echo JText::_('COM_JEA_REF') ?> : <?php echo $this->escape($this->row->ref) ?>" size="30" /></dd>

      <dt><label for="e_message"><?php echo JText::_('COM_JEA_MESSAGE') ?> :</label></dt>
      <dd><textarea name="message" id="e_message" rows="10" cols="40"><?php echo $this->escape($this->state->get('contact.message')) ?></textarea></dd>

[B]      <?php if ($this->params->get('use_captcha')):?> 
      <dd><?php echo $this->displayCaptcha() ?></dd>
      <?php endif ?[/B]>
      <dd>
        <input type="hidden" name="id" value="<?php echo $this->row->id ?>" />
        <?php echo JHTML::_( 'form.token' ) ?>
        <input type="hidden" name="propertyURL" value="<?php echo base64_encode($uri->toString())?>" />
        <input type="submit" value="<?php echo JText::_('COM_JEA_SEND') ?>" />
      </dd>
    </dl>
  </fieldset>
</form>


This code is just a part of the whole, which includes an image gallery, a Google Map and a series of other elements in other php files.

That… really doesnt look right to me still, because you’re invoking $this for an apparant non-object, but… i’ll focus on the specific error for the moment…
In here:

    protected function displayCaptcha()
    {
        $plugin = JFactory::getConfig()->get('captcha');
        if ($plugin == '0') {
            $plugin = 'recaptcha';
        }
        $captcha = JCaptcha::getInstance($plugin);
        return $captcha->display('captcha', 'jea-captcha');
    }

Right before the return line, insert


var_dump($captcha);

What does PHP think this variable holds?

The error remains:

This time

NULL
Fatal error: Call to a member function display() on a non-object in /homepages/13/d480589583/htdocs/html/components/com_jea/views/property/view.html.php on line 104

So it returned NULL, which tells me that this:
$captcha = JCaptcha::getInstance($plugin);

Is not working correctly, because it should have returned an object… Try var_dumping $plugin to see if that has a value other than 0. (It will either be ‘recaptcha’ or 1, i’m guessing).

You can also try var_dumping JCaptcha::_errors to see if the object is barking any error messages.