Spade

Mini Shell

Directory:~$ /proc/self/root/home/lmsyaran/public_html/joomla5/plugins/fabrik_element/captcha/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ //proc/self/root/home/lmsyaran/public_html/joomla5/plugins/fabrik_element/captcha/captcha.php

<?php
/**
 * Plugin element to captcha
 *
 * @package     Joomla.Plugin
 * @subpackage  Fabrik.element.captcha
 * @copyright   Copyright (C) 2005-2020  Media A-Team, Inc. - All rights
reserved.
 * @license     GNU/GPL http://www.gnu.org/copyleft/gpl.html
 */

// No direct access
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Language\Text;
use Joomla\CMS\Environment\Browser;
use Joomla\CMS\Factory;
use Joomla\String\StringHelper;
use ReCaptcha\ReCaptcha;

require_once JPATH_ROOT .
'/plugins/fabrik_element/captcha/vendor/autoload.php';
/**
 * Plugin element to captcha
 *
 * @package     Joomla.Plugin
 * @subpackage  Fabrik.element.captcha
 * @since       3.0
 */
class PlgFabrik_ElementCaptcha extends PlgFabrik_Element
{
	protected $font = 'monofont.ttf';

	/**
	 * Generate captcha text
	 *
	 * @param   int $characters number of characters to generate
	 *
	 * @return  string captcha text
	 */
	protected function _generateCode($characters)
	{
		// List all possible characters, similar looking characters and vowels
have been removed
		$possible = '23456789bcdfghjkmnpqrstvwxyz';
		$code     = '';
		$i        = 0;

		while ($i < $characters)
		{
			$code .= StringHelper::substr($possible, mt_rand(0,
StringHelper::strlen($possible) - 1), 1);
			$i++;
		}

		return $code;
	}

	/**
	 * Get the element's HTML label
	 *
	 * @param   int    $repeatCounter group repeat counter
	 * @param   string $tmpl          form template
	 *
	 * @return  string  label
	 */
	public function getLabel($repeatCounter, $tmpl = '')
	{
		$params = $this->getParams();

		if ($this->user->id != 0)
		{
			if ($params->get('captcha-showloggedin', 0) == 0)
			{
				return '';
			}
		}

		if ($params->get('captcha-method') == 'invisible')
		{
			return '';
		}

		return parent::getLabel($repeatCounter, $tmpl);
	}

	/**
	 * Is the element hidden or not - if not set then return false
	 *
	 * @return  bool
	 */
	public function isHidden()
	{
		$params = $this->getParams();

		if ($this->user->get('id') != 0)
		{
			if ($params->get('captcha-showloggedin', 0) == 0)
			{
				return true;
			}
		}

		return parent::isHidden();
	}

	/**
	 * Check user can view the read only element OR view in list view
	 * $$$ rob 14/03/2012 always returns false now - cant see a need to show
it in the details / list view
	 *
	 * @param   string $view View list/form @since 3.0.7
	 *
	 * @return  bool  can view or not
	 */
	public function canView($view = 'form')
	{
		return false;
	}

	/**
	 * Check if the user can use the active element
	 *
	 * @param   string $location To trigger plugin on
	 * @param   string $event    To trigger plugin on
	 *
	 * @return  bool can use or not
	 */
	public function canUse($location = null, $event = null)
	{
		$params = $this->getParams();

		if ($this->user->get('id') != 0)
		{
			if ($params->get('captcha-showloggedin', 0) == 0)
			{
				return false;
			}
		}

		return parent::canUse();
	}

	/**
	 * Gets the challenge HTML (AJAX version).
	 * This is called from the browser, and the resulting reCAPTCHA HTML
widget
	 * is embedded within the HTML form it was called from.
	 *
	 * @param string  $id      the HTML id for the div
	 * @param string  $pubkey  A public key for reCAPTCHA
	 * @param string  $theme   Theme to use, default red
	 * @param string  $lang    Language to use, default en
	 * @param string  $error   The error given by reCAPTCHA (optional, default
is null)
	 * @param boolean $use_ssl Should the request be made over ssl? (optional,
default is false)
	 *
	 * @return string - The HTML to be embedded in the user's form.
	 */
	 /* reCaptcha v1 is not longer supported
	function fabrik_recaptcha_get_html($id, $pubkey, $theme = "red",
$lang = "en", $error = null, $use_ssl = false)
	{
		if ($pubkey == null || $pubkey == '')
		{
			die ("To use reCAPTCHA you must get an API key from <a
href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
		}

		if ($use_ssl)
		{
			$server = RECAPTCHA_API_SECURE_SERVER;
		}
		else
		{
			$server = RECAPTCHA_API_SERVER;
		}

		//$str = '<script type="text/javascript"
src="' . $server .
'/js/recaptcha_ajax.js"></script> ';
		$str      = '  <div id="' . $id .
'"></div> ';
		$document = Factory::getDocument();
		$document->addScript($server . '/js/recaptcha_ajax.js');
		FabrikHelperHTML::addScriptDeclaration(
			'window.addEvent("fabrik.loaded", function() {
			Recaptcha.create(
				"' . $pubkey . '",
	    		"' . $id . '",
	    		{
	    			theme: "' . $theme . '",
					lang : "' . $lang . '"
				}
			);
		});'
		);

		return $str;
	}
	*/

	/**
	 * Draws the html form element
	 *
	 * @param   array $data          to pre-populate element with
	 * @param   int   $repeatCounter repeat group counter
	 *
	 * @return  string    elements html
	 */
	public function render($data, $repeatCounter = 0)
	{
		$name    = $this->getHTMLName($repeatCounter);
		$id      = $this->getHTMLId($repeatCounter);
		$element = $this->getElement();
		$params  = $this->getParams();
		$value   = $this->getValue($data, $repeatCounter);

		if (!$this->isEditable())
		{
			if ($element->hidden == '1')
			{
				return '<!-- ' . stripslashes($value) . '
-->';
			}
			else
			{
				return stripslashes($value);
			}
		}

		// Old v1 reCaptcha not longer supported, handle like v2
reCaptcha(checkbox) - here called 'nocaptcha'
		if ($params->get('captcha-method') == 'nocaptcha'
|| $params->get('captcha-method') == 'recaptcha')
		{
			$layout                = $this->getLayout('nocaptcha');
			$displayData           = new stdClass;
			$displayData->id       = $id;
			$displayData->name     = $name;
			$displayData->site_key =
$params->get('recaptcha_publickey');
			$displayData->lang     =
FabrikWorker::replaceWithLanguageTags(StringHelper::strtolower($params->get('recaptcha_lang',
'en')));

			return $layout->render($displayData);
		}
		elseif ($params->get('captcha-method') ==
'invisible')
		{
			$layout                =
$this->getLayout('nocaptcha-invisible');
			$displayData           = new stdClass;
			$displayData->id       = $id;
			$displayData->name     = $name;
			$displayData->site_key =
$params->get('recaptcha_publickey');
			$displayData->lang     =
FabrikWorker::replaceWithLanguageTags(StringHelper::strtolower($params->get('recaptcha_lang',
'en')));

			return $layout->render($displayData);
		}
		else
		{
			if (!function_exists('imagettfbbox'))
			{
				throw new
RuntimeException(Text::_('PLG_FABRIK_ELEMENT_CAPTCHA_STANDARD_TTF_ERROR'));
			}

			$size       = $element->width;
			$fontSize   = $params->get('captcha-font-size', 22);
			$angle      = $params->get('captcha-angle', 0);
			$padding    = $params->get('captcha-padding', 10);
			$characters = $params->get('captcha-chars', 6);
			$code       = $this->_generateCode($characters);
			$this->session->set('com_' . $this->package .
'.element.captcha.security_code', $code);
			$type = $params->get('password') == '1' ?
'password' : 'text';

			if ($this->elementError != '')
			{
				$type .= ' elementErrorHighlight';
			}

			if ($element->hidden == '1')
			{
				$type = 'hidden';
			}

			$layout            = $this->getLayout('form');
			$displayData       = new stdClass;
			$displayData->id   = $id;
			$displayData->name = $name;

			$formId    = $this->getFormModel()->getId();
			$rowId     = $this->app->input->get('rowid',
'0');
			$elementId = $this->getId();

			$displayData->url  = COM_FABRIK_LIVESITE .
'index.php?option=com_' . $this->package
				.
'&task=plugin.pluginAjax&plugin=captcha&method=ajax_image&format=raw&element_id='
				. $elementId . '&formid=' . $formId .
'&rowid=' . $rowId . '&repeatcount=' .
$repeatCounter;

			$displayData->type = $type;
			$displayData->size = $size;

			return $layout->render($displayData);
		}
	}

	/**
	 * Internal element validation
	 *
	 * @param   array $data          form data
	 * @param   int   $repeatCounter repeat group counter
	 *
	 * @return bool
	 */
	public function validate($data, $repeatCounter = 0)
	{
	    if ($this->app->input->get('task', '')
=== 'form.ajax_validate')
        {
            return true;
        }

		$params = $this->getParams();
		$input  = $this->app->input;

		// if this is the submit from the confirmation plugin, we already
validated when rendering confirmation page
		if ($this->app->input->get('fabrik_confirmation',
'') === '2')
		{
			return true;
		}

		if (!$this->canUse())
		{
			return true;
		}

		$method = $params->get('captcha-method', '');

		if ($method === 'nocaptcha' || $method ===
'invisible' || $method === 'recaptcha')
		{
			if ($input->get('g-recaptcha-response'))
			{
				$privateKey = $params->get('recaptcha_privatekey');

				/*
				 * Some Windows boxes with CA cert bundle issues may fail using
CurlPost, because the ReCaptcha lib
				 * asserts verify_peer, so check to see if our global setting is turned
off, if so try using socket instead
				 */
				if ($this->config->get('verify_peer', '1')
=== '0')
				{
					$noCaptcha = new ReCaptcha($privateKey, new
\ReCaptcha\RequestMethod\SocketPost());
				}
				else
				{
					$noCaptcha = new ReCaptcha($privateKey, new
\ReCaptcha\RequestMethod\CurlPost());
				}

				$response   = $input->get('g-recaptcha-response');
				$server     = $input->server->get('REMOTE_ADDR');
				$resp       = $noCaptcha->verify($response, $server);

				if ($resp->isSuccess())
				{
					return true;
				}
				else
				{
					if (FabrikHelperHTML::isDebug())
					{
						$msg = "noCaptcha error: ";
						foreach ($resp->getErrorCodes() as $code) {
							$msg .= '<tt>' . $code . '</tt> ';
						}
						$this->app->enqueueMessage($msg);
					}
					return false;
				}
			}

			if (FabrikHelperHTML::isDebug())
			{
				$this->app->enqueueMessage("No g-recaptcha-response!");
			}

			return false;
		}
		else
		{
			$this->getParams();

			if ($this->session->get('com_' . $this->package .
'.element.captcha.security_code', null) != $data)
			{
				return false;
			}

			return true;
		}
	}

	/**
	 * Get validation error - run through Text
	 *
	 * @return  string
	 */
	public function getValidationErr()
	{
		$params = $this->getParams();
		$method = $params->get('captcha-method',
'standard');
		return Text::_('PLG_ELEMENT_CAPTCHA_' . strtoupper($method) .
'_FAILED');
	}

	/**
	 * Determine if the element should run its validation plugins on form
submission
	 *
	 * @return  bool    default true
	 */

	public function mustValidate()
	{
		if (!$this->canUse() && !$this->canView())
		{
			return false;
		}

		return parent::mustValidate();
	}

	/**
	 * Returns javascript which creates an instance of the class defined in
formJavascriptClass()
	 *
	 * @param   int $repeatCounter Repeat group counter
	 *
	 * @return  array
	 */
	public function elementJavascript($repeatCounter)
	{
		$params = $this->getParams();

		if ($params->get('captcha-showloggedin', 0) == 1 ||
$this->user->get('id') == 0)
		{
			$params       = $this->getParams();
			$id           = $this->getHTMLId($repeatCounter);
			$opts         = $this->getElementJSOptions($repeatCounter);
			$opts->method = $params->get('captcha-method');
			$opts->siteKey = $params->get('recaptcha_publickey');

			return array('FbCaptcha', $id, $opts);
		}

		return array();
	}

	/**
	 * Used to format the data when shown in the form's email
	 *
	 * @param   mixed $value         element's data
	 * @param   array $data          form records data
	 * @param   int   $repeatCounter repeat group counter
	 *
	 * @return  string    formatted value
	 */
	public function getEmailValue($value, $data = array(), $repeatCounter = 0)
	{
		return "";
	}

	/**
	 * $$$ e-kinst Convert a hex colour to RGB
	 *
	 * @param   string $hexColor 3- or 6-digits hex color with optional
leading '#'
	 * @param   string $default  default hex color if first param invalid
	 *
	 * @return  string    as 'R+G+B' where R,G,B are decimal
	 */
	private function _getRGBcolor($hexColor, $default = 'FF0000')
	{
		$regex =
'/^#?(([\da-f])([\da-f])([\da-f])|([\da-f]{2})([\da-f]{2})([\da-f]{2}))$/i';
		$rgb   = array();

		if (!preg_match($regex, $hexColor, $rgb))
		{
			if (!preg_match($regex, $default, $rgb))
			{
				// In case where $default invalid also (call error)
				$rgb = array('FF0000', 'FF0000', 'FF',
'00', '00');
			}
		}

		array_shift($rgb);
		array_shift($rgb);

		if (count($rgb) > 3)
		{
			$rgb = array_slice($rgb, 3, 3);
		}

		for ($i = 0; $i < 3; $i++)
		{
			if (StringHelper::strlen($rgb[$i]) == 1)
			{
				$rgb[$i] .= $rgb[$i];
			}

			$rgb[$i] = intval($rgb[$i], 16);
		}

		return $rgb;
	}

	public function onAjax_image() {
		$package = $this->app->getUserState('com_fabrik.package',
'fabrik');
		$this->setId($this->app->input->getInt('element_id'));
		$this->loadMeForAjax();
		$this->getElement();
		$params = $this->getParams();

		$code = $this->session->get('com_' . $package .
'.element.captcha.security_code', false);

		if (empty($code))
		{
			exit;
		}

		$fontSize   = $params->get('captcha-font-size', 22);
		$angle      = $params->get('captcha-angle', 0);
		$padding    = $params->get('captcha-padding', 10);
		$nc = $params->get('captcha-noise-color',
'0000FF');
		$nc = $this->_getRGBcolor($nc, '0000FF');
		$tc  = $params->get('captcha-text-color',
'0000FF');
		$tc  = $this->_getRGBcolor($tc, '0000FF');
		$bc    = $params->get('captcha-bg', 'FFFFFF');
		$bc    = $this->_getRGBcolor($bc, 'FFFFFF');

		// Create textbox and add text
		$fontPath = JPATH_SITE . '/plugins/fabrik_element/captcha/' .
$this->font;

		if (function_exists('imagettfbbox'))
		{
			$the_box = $this->calculateTextBox($code, $fontPath, $fontSize,
$angle);
		}
		else
		{
			$the_box = array('width' => 150, 'height' =>
50, 'top' => 0, 'left' => 0);
		}


		$imgWidth = $the_box["width"] + $padding;
		$imgHeight = $the_box["height"] + $padding;

		$image = imagecreate($imgWidth, $imgHeight);

		$background_color = imagecolorallocate($image, $bc[0], $bc[1], $bc[2]);
		$text_color = imagecolorallocate($image, $tc[0], $tc[1], $tc[2]);
		$noise_color = imagecolorallocate($image, $nc[0], $nc[1], $nc[2]);

		// Generate random dots in background
		for ($i = 0; $i < ($imgWidth * $imgHeight) / 3; $i++)
		{
			imagefilledellipse($image, mt_rand(0, $imgWidth), mt_rand(0,
$imgHeight), 1, 1, $noise_color);
		}

		// Generate random lines in background
		for ($i = 0; $i < ($imgWidth * $imgHeight) / 150; $i++)
		{
			imageline($image, mt_rand(0, $imgWidth), mt_rand(0, $imgHeight),
mt_rand(0, $imgWidth), mt_rand(0, $imgHeight), $noise_color);
		}

		$left = $the_box["left"] + ($imgWidth / 2) -
($the_box["width"] / 2);
		$top = $the_box["top"] + ($imgHeight / 2) -
($the_box["height"] / 2);

		if (function_exists('imagettfbbox'))
		{
			imagettftext(
				$image,
				$fontSize,
				$angle,
				$left,
				$top,
				$text_color,
				$fontPath,
				$code
			);
		}
		else
		{
			imagestring($image, 6, $left, $top, $code, $text_color);
		}

		// ... set no-cache (and friends) headers ...
		// Some time in the past
		header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
		header("Last-Modified: " . gmdate("D, d M Y H:i:s") .
" GMT");
		header("Cache-Control: no-store, no-cache, must-revalidate");
		header("Cache-Control: post-check=0, pre-check=0", false);
		header("Pragma: no-cache");
		header('Accept-Ranges: bytes');

		header('Content-Type: image/jpeg');

		ob_start();
		imagejpeg($image);
		$img = ob_get_contents();

		/**
		Felixkat - Clean has been replaced with flush due to a image truncating
issue
		Haven't been able to pinpoint the exact issue yet, possibly PHP
version related
		http://fabrikar.com/forums/showthread.php?p=147606#post147606
		 */
		// Not this: ob_end_clean();
		ob_end_flush();

		// For some weird reason if we do this in 5.2.x the image gets truncated
		// http://fabrikar.com/forums/showthread.php?t=26941&page=5
		if (version_compare(PHP_VERSION, '5.3.0') < 0)
		{
			header('Content-Length: ' . StringHelper::strlen($img));
		}

		imagedestroy($image);
		echo $img;

		// ... and we're done.
		exit();

	}

	/**
	 *  Simple function that calculates the *exact* bounding box (single pixel
precision).
	 *  The function returns an associative array with these keys:
	 *  left, top:  coordinates you will pass to imagettftext
	 *  width, height: dimension of the image you have to create
	 *
	 * @param   string  $code      Code
	 * @param   string  $fontPath  Font path
	 * @param   int     $fontsize  Font size
	 * @param   int     $angle     Text angle
	 *
	 * @return  array
	 */
	private function calculateTextBox($code, $fontPath, $fontsize, $angle)
	{
		$rect = imagettfbbox($fontsize, $angle, $fontPath, $code);
		$minX = min(array($rect[0], $rect[2], $rect[4], $rect[6]));
		$maxX = max(array($rect[0], $rect[2], $rect[4], $rect[6]));
		$minY = min(array($rect[1], $rect[3], $rect[5], $rect[7]));
		$maxY = max(array($rect[1], $rect[3], $rect[5], $rect[7]));

		return array
		(
			"left"   => abs($minX) - 1,
			"top"    => abs($minY) - 1,
			"width"  => $maxX - $minX,
			"height" => $maxY - $minY,
			"box"    => $rect
		);
	}
}