diff --git a/src/Controller/CaptchaHandlerController.php b/src/Controller/CaptchaHandlerController.php index b4dc224..0c671a0 100644 --- a/src/Controller/CaptchaHandlerController.php +++ b/src/Controller/CaptchaHandlerController.php @@ -17,20 +17,20 @@ public function initialize() { if ($this->isGetResourceContentsRequest()) { // validate filename - $filename = $this->request->query('get'); + $filename = $this->request->getQuery('get'); if (!preg_match('/^[a-z-]+\.(css|gif|js)$/', $filename)) { $this->badRequest('Invalid file name.'); } } else { // validate captcha id and load CaptchaComponent - $captchaId = $this->request->query('c'); + $captchaId = $this->request->getQuery('c'); if (is_null($captchaId) || !preg_match('/^(\w+)$/ui', $captchaId)) { $this->badRequest('Invalid captcha id.'); } - $captchaInstanceId = $this->request->query('t'); + $captchaInstanceId = $this->request->getQuery('t'); if (is_null($captchaInstanceId) || !(32 == strlen($captchaInstanceId) && - (1 === preg_match("/^([a-f0-9]+)$/u", $captchaInstanceId)))) { + (1 === preg_match("/^([a-f0-9]+)$/u", $captchaInstanceId)))) { $this->badRequest('Invalid instance id.'); } @@ -38,7 +38,6 @@ public function initialize() 'captchaConfig' => $captchaId, 'captchaInstanceId' => $captchaInstanceId ]); - } } @@ -70,7 +69,7 @@ public function index() \BDC_HttpHelper::BadRequest('captcha'); } - $commandString = $this->request->query('get'); + $commandString = $this->request->getQuery('get'); if (!\BDC_StringHelper::HasValue($commandString)) { \BDC_HttpHelper::BadRequest('command'); } @@ -100,7 +99,8 @@ public function index() // disallow audio file search engine indexing header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet'); - echo $responseBody; exit; + echo $responseBody; + exit; } } @@ -111,7 +111,7 @@ public function index() */ public function getResourceContents() { - $filename = $this->request->query('get'); + $filename = $this->request->getQuery('get'); $resourcePath = realpath(Path::getPublicDirPathInLibrary() . $filename); @@ -128,7 +128,8 @@ public function getResourceContents() header("Content-Type: {$mimeType}"); header("Content-Length: {$fileLength}"); - echo (file_get_contents($resourcePath)); exit; + echo (file_get_contents($resourcePath)); + exit; } /** @@ -247,7 +248,8 @@ public function getSound() } - public function getSoundData($p_Captcha, $p_InstanceId) { + public function getSoundData($p_Captcha, $p_InstanceId) + { $shouldCache = ( ($p_Captcha->SoundRegenerationMode == \SoundRegenerationMode::None) || // no sound regeneration allowed, so we must cache the first and only generated sound $this->detectIosRangeRequest() // keep the same Captcha sound across all chunked iOS requests @@ -269,42 +271,51 @@ public function getSoundData($p_Captcha, $p_InstanceId) { return $soundBytes; } - private function generateSoundData($p_Captcha, $p_InstanceId) { + private function generateSoundData($p_Captcha, $p_InstanceId) + { $rawSound = $p_Captcha->CaptchaBase->GetSound($p_InstanceId); $p_Captcha->CaptchaBase->SaveCodeCollection(); // always record sound generation count return $rawSound; } - private function saveSoundData($p_InstanceId, $p_SoundBytes) { + private function saveSoundData($p_InstanceId, $p_SoundBytes) + { CAKE_Session_Save("BDC_Cached_SoundData_" . $p_InstanceId, $p_SoundBytes); } - private function loadSoundData($p_InstanceId) { + private function loadSoundData($p_InstanceId) + { return CAKE_Session_Load("BDC_Cached_SoundData_" . $p_InstanceId); } - private function clearSoundData($p_InstanceId) { + private function clearSoundData($p_InstanceId) + { CAKE_Session_Clear("BDC_Cached_SoundData_" . $p_InstanceId); } // Instead of relying on unreliable user agent checks, we detect the iOS sound // requests by the Http headers they will always contain - private function detectIosRangeRequest() { + private function detectIosRangeRequest() + { - if(array_key_exists('HTTP_RANGE', $_SERVER) && - \BDC_StringHelper::HasValue($_SERVER['HTTP_RANGE'])) { + if ( + array_key_exists('HTTP_RANGE', $_SERVER) && + \BDC_StringHelper::HasValue($_SERVER['HTTP_RANGE']) + ) { // Safari on MacOS and all browsers on <= iOS 10.x - if(array_key_exists('HTTP_X_PLAYBACK_SESSION_ID', $_SERVER) && - \BDC_StringHelper::HasValue($_SERVER['HTTP_X_PLAYBACK_SESSION_ID'])) { + if ( + array_key_exists('HTTP_X_PLAYBACK_SESSION_ID', $_SERVER) && + \BDC_StringHelper::HasValue($_SERVER['HTTP_X_PLAYBACK_SESSION_ID']) + ) { return true; } $userAgent = array_key_exists('HTTP_USER_AGENT', $_SERVER) ? $_SERVER['HTTP_USER_AGENT'] : null; // all browsers on iOS 11.x and later - if(\BDC_StringHelper::HasValue($userAgent)) { + if (\BDC_StringHelper::HasValue($userAgent)) { $userAgentLC = \BDC_StringHelper::Lowercase($userAgent); if (\BDC_StringHelper::Contains($userAgentLC, "like mac os") || \BDC_StringHelper::Contains($userAgentLC, "like macos")) { return true; @@ -314,7 +325,8 @@ private function detectIosRangeRequest() { return false; } - private function getSoundByteRange() { + private function getSoundByteRange() + { // chunked requests must include the desired byte range $rangeStr = $_SERVER['HTTP_RANGE']; if (!\BDC_StringHelper::HasValue($rangeStr)) { @@ -329,12 +341,15 @@ private function getSoundByteRange() { ); } - private function detectFakeRangeRequest() { + private function detectFakeRangeRequest() + { $detected = false; if (array_key_exists('HTTP_RANGE', $_SERVER)) { $rangeStr = $_SERVER['HTTP_RANGE']; - if (\BDC_StringHelper::HasValue($rangeStr) && - preg_match('/bytes=0-$/', $rangeStr)) { + if ( + \BDC_StringHelper::HasValue($rangeStr) && + preg_match('/bytes=0-$/', $rangeStr) + ) { $detected = true; } } @@ -375,7 +390,8 @@ public function getValidationResult() return $resultJson; } - public function getScriptInclude() { + public function getScriptInclude() + { // saved data for the specified Captcha object in the application if (is_null($this->Captcha)) { \BDC_HttpHelper::BadRequest('captcha'); @@ -417,8 +433,9 @@ public function getScriptInclude() { */ private function getInstanceId() { - $instanceId = $this->request->query('t'); - if (!\BDC_StringHelper::HasValue($instanceId) || + $instanceId = $this->request->getQuery('t'); + if ( + !\BDC_StringHelper::HasValue($instanceId) || !\BDC_CaptchaBase::IsValidInstanceId($instanceId) ) { return; @@ -434,13 +451,13 @@ private function getInstanceId() private function getUserInput() { // BotDetect built-in Ajax Captcha validation - $input = $this->request->query('i'); + $input = $this->request->getQuery('i'); if (is_null($input)) { // jQuery validation support, the input key may be just about anything, // so we have to loop through fields and take the first unrecognized one $recognized = array('get', 'c', 't', 'd'); - foreach ($this->request->query as $key => $value) { + foreach ($this->request->getQuery() as $key => $value) { if (!in_array($key, $recognized)) { $input = $value; break; @@ -458,7 +475,7 @@ private function getUserInput() */ private function getJsonValidationResult($result) { - $resultStr = ($result ? 'true': 'false'); + $resultStr = ($result ? 'true' : 'false'); return $resultStr; } @@ -467,7 +484,7 @@ private function getJsonValidationResult($result) */ private function isGetResourceContentsRequest() { - $http_get_data = $this->request->query; + $http_get_data = $this->request->getQuery(); return array_key_exists('get', $http_get_data) && !array_key_exists('c', $http_get_data); } @@ -479,14 +496,17 @@ private function isGetResourceContentsRequest() */ private function badRequest($message) { - while (ob_get_contents()) { ob_end_clean(); } + while (ob_get_contents()) { + ob_end_clean(); + } header('HTTP/1.1 400 Bad Request'); header('Content-Type: text/plain'); echo $message; exit; } - public function getP() { + public function getP() + { if (is_null($this->Captcha)) { \BDC_HttpHelper::BadRequest('captcha'); } @@ -503,7 +523,7 @@ public function getP() { // response data $response = "{\"sp\":\"{$p->GetSP()}\",\"hs\":\"{$p->GetHs()}\"}"; - + // response MIME type & headers header('Content-Type: application/json'); diff --git a/src/Controller/Component/CaptchaComponent.php b/src/Controller/Component/CaptchaComponent.php index 23028c4..a411b20 100644 --- a/src/Controller/Component/CaptchaComponent.php +++ b/src/Controller/Component/CaptchaComponent.php @@ -14,7 +14,7 @@ class CaptchaComponent extends Component * @var object */ private $captcha; - + /** * BotDetect CakePHP CAPTCHA plugin information. * @@ -34,9 +34,9 @@ class CaptchaComponent extends Component */ public function initialize(array $params) { - self::$instance =& $this; + self::$instance = &$this; - $session = $this->request->session(); + $session = $this->request->getSession(); // load botdetect captcha library LibraryLoader::load($session); @@ -45,10 +45,7 @@ public function initialize(array $params) // this will avoid user being able to pass in a lowercase option (e.g. captchaconfig) $params = array_change_key_case($params, CASE_LOWER); - if (empty($params) || - !array_key_exists('captchaconfig', $params) || - empty($params['captchaconfig']) - ) { + if (empty($params) || !array_key_exists('captchaconfig', $params) || empty($params['captchaconfig'])) { $errorMessage = 'The BotDetect Captcha component requires you to declare "captchaConfig" option and assigns a captcha configuration key defined in config/captcha.php file.
'; $errorMessage .= 'For example: $this->loadComponent(\'CakeCaptcha.Captcha\', [\'captchaConfig\' => \'ContactCaptcha\']);'; throw new InvalidArgumentException($errorMessage); @@ -57,9 +54,8 @@ public function initialize(array $params) $captchaId = $params['captchaconfig']; $captchaInstanceId = null; - if(isset($params['captchainstanceid'])) { + if (isset($params['captchainstanceid'])) { $captchaInstanceId = $params['captchainstanceid']; - } // get captcha config @@ -75,7 +71,7 @@ public function initialize(array $params) // save user's captcha configuration options UserCaptchaConfiguration::save($config); - + // init botdetect captcha instance $this->initCaptcha($config, $captchaInstanceId); } @@ -128,56 +124,56 @@ public function __call($method, $args = array()) */ public function __get($name) { - if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'get_'.$name))) { + if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'get_' . $name))) { return $this->captcha->get_CaptchaBase()->$method(); } - if (method_exists($this->captcha, ($method = 'get_'.$name))) { + if (method_exists($this->captcha, ($method = 'get_' . $name))) { return $this->captcha->$method(); } - if (method_exists($this, ($method = 'get_'.$name))) { + if (method_exists($this, ($method = 'get_' . $name))) { return $this->$method(); } } public function __isset($name) { - if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'isset_'.$name))) { + if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'isset_' . $name))) { return $this->captcha->get_CaptchaBase()->$method(); } - if (method_exists($this->captcha, ($method = 'isset_'.$name))) { + if (method_exists($this->captcha, ($method = 'isset_' . $name))) { return $this->captcha->$method(); } - if (method_exists($this, ($method = 'isset_'.$name))) { + if (method_exists($this, ($method = 'isset_' . $name))) { return $this->$method(); } } public function __set($name, $value) { - if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'set_'.$name))) { + if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'set_' . $name))) { return $this->captcha->get_CaptchaBase()->$method($value); } - if (method_exists($this->captcha, ($method = 'set_'.$name))) { + if (method_exists($this->captcha, ($method = 'set_' . $name))) { $this->captcha->$method($value); - } else if (method_exists($this, ($method = 'set_'.$name))) { + } else if (method_exists($this, ($method = 'set_' . $name))) { $this->$method($value); } } public function __unset($name) { - if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'unset_'.$name))) { + if (method_exists($this->captcha->get_CaptchaBase(), ($method = 'unset_' . $name))) { return $this->captcha->get_CaptchaBase()->$method(); } - if (method_exists($this->captcha, ($method = 'unset_'.$name))) { + if (method_exists($this->captcha, ($method = 'unset_' . $name))) { $this->captcha->$method(); - } else if (method_exists($this, ($method = 'unset_'.$name))) { + } else if (method_exists($this, ($method = 'unset_' . $name))) { $this->$method(); } } @@ -195,6 +191,6 @@ public static function getProductInfo() // static field initialization CaptchaComponent::$productInfo = [ - 'name' => 'BotDetect 4 PHP Captcha generator integration for the CakePHP framework', + 'name' => 'BotDetect 4 PHP Captcha generator integration for the CakePHP framework', 'version' => '4.2.9' ]; diff --git a/src/Controller/SimpleCaptchaHandlerController.php b/src/Controller/SimpleCaptchaHandlerController.php index 576e5c7..dd303c3 100644 --- a/src/Controller/SimpleCaptchaHandlerController.php +++ b/src/Controller/SimpleCaptchaHandlerController.php @@ -20,12 +20,12 @@ public function initialize() SimpleLibraryLoader::load(); // validate captcha style name and load SimpleCaptchaComponent - $captchaStyleName = $this->request->query('c'); + $captchaStyleName = $this->request->getQuery('c'); if (is_null($captchaStyleName) || !preg_match('/^(\w+)$/ui', $captchaStyleName)) { return; } - $captchaId = $this->request->query('t'); + $captchaId = $this->request->getQuery('t'); if ($captchaId !== null) { $captchaId = \BDC_StringHelper::Normalize($captchaId); if (1 !== preg_match(\BDC_SimpleCaptchaBase::VALID_CAPTCHA_ID, $captchaId)) { @@ -60,7 +60,7 @@ public function index() // getting captcha image, sound, validation result - $commandString = $this->request->query('get'); + $commandString = $this->request->getQuery('get'); if (!\BDC_StringHelper::HasValue($commandString)) { \BDC_HttpHelper::BadRequest('command'); } @@ -84,8 +84,8 @@ public function index() case \BDC_SimpleCaptchaHttpCommand::GetHtml: $responseBody = $this->getHtml(); break; - - // Sound icon + + // Sound icon case \BDC_SimpleCaptchaHttpCommand::GetSoundIcon: $responseBody = $this->getSoundIcon(); break; @@ -98,8 +98,8 @@ public function index() case \BDC_SimpleCaptchaHttpCommand::GetSoundSmallDisabledIcon: $responseBody = $this->getSmallDisabledSoundIcon(); break; - - // Reload icon + + // Reload icon case \BDC_SimpleCaptchaHttpCommand::GetReloadIcon: $responseBody = $this->getReloadIcon(); break; @@ -113,7 +113,7 @@ public function index() $responseBody = $this->getSmallDisabledReloadIcon(); break; - // css, js + // css, js case \BDC_SimpleCaptchaHttpCommand::GetScriptInclude: $responseBody = $this->getScriptInclude(); break; @@ -131,7 +131,8 @@ public function index() // disallow audio file search engine indexing header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet'); - echo $responseBody; exit; + echo $responseBody; + exit; } /** @@ -182,13 +183,13 @@ public function getImage() public function getBase64ImageString() { header("Access-Control-Allow-Origin: *"); - + // authenticate client-side request $corsAuth = new \CorsAuth(); if (!$corsAuth->IsClientAllowed()) { \BDC_HttpHelper::BadRequest($corsAuth->GetFrontEnd() . " is not an allowed front-end"); } - + // MIME type $imageType = \ImageFormat::GetName($this->SimpleCaptcha->ImageFormat); $imageType = strtolower($imageType[0]); @@ -203,30 +204,30 @@ private function getImageData($p_Captcha) // identifier of the particular Captcha object instance $captchaId = $this->getCaptchaId(); if (is_null($captchaId)) { - \BDC_HttpHelper::BadRequest('Captcha Id doesn\'t exist'); + \BDC_HttpHelper::BadRequest('Captcha Id doesn\'t exist'); } - + if ($this->isObviousBotRequest($p_Captcha)) { - return; + return; } - + // image generation invalidates sound cache, if any $this->clearSoundData($p_Captcha, $captchaId); - + // response headers \BDC_HttpHelper::DisallowCache(); - + // we don't support content chunking, since image files // are regenerated randomly on each request header('Accept-Ranges: none'); - + // disallow audio file search engine indexing header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet'); - + // image generation $rawImage = $p_Captcha->CaptchaBase->GetImage($captchaId); $p_Captcha->SaveCode($captchaId, $p_Captcha->CaptchaBase->Code); // record generated Captcha code for validation - + return $rawImage; } @@ -237,7 +238,7 @@ private function getImageData($p_Captcha) public function getSound() { header("Access-Control-Allow-Origin: *"); - + // authenticate client-side request $corsAuth = new \CorsAuth(); if (!$corsAuth->IsClientAllowed()) { @@ -356,21 +357,26 @@ private function clearSoundData($p_Captcha, $p_CaptchaId) // Instead of relying on unreliable user agent checks, we detect the iOS sound // requests by the Http headers they will always contain - private function detectIosRangeRequest() { + private function detectIosRangeRequest() + { - if(array_key_exists('HTTP_RANGE', $_SERVER) && - \BDC_StringHelper::HasValue($_SERVER['HTTP_RANGE'])) { + if ( + array_key_exists('HTTP_RANGE', $_SERVER) && + \BDC_StringHelper::HasValue($_SERVER['HTTP_RANGE']) + ) { // Safari on MacOS and all browsers on <= iOS 10.x - if(array_key_exists('HTTP_X_PLAYBACK_SESSION_ID', $_SERVER) && - \BDC_StringHelper::HasValue($_SERVER['HTTP_X_PLAYBACK_SESSION_ID'])) { + if ( + array_key_exists('HTTP_X_PLAYBACK_SESSION_ID', $_SERVER) && + \BDC_StringHelper::HasValue($_SERVER['HTTP_X_PLAYBACK_SESSION_ID']) + ) { return true; } $userAgent = array_key_exists('HTTP_USER_AGENT', $_SERVER) ? $_SERVER['HTTP_USER_AGENT'] : null; // all browsers on iOS 11.x and later - if(\BDC_StringHelper::HasValue($userAgent)) { + if (\BDC_StringHelper::HasValue($userAgent)) { $userAgentLC = \BDC_StringHelper::Lowercase($userAgent); if (\BDC_StringHelper::Contains($userAgentLC, "like mac os") || \BDC_StringHelper::Contains($userAgentLC, "like macos")) { return true; @@ -380,7 +386,8 @@ private function detectIosRangeRequest() { return false; } - private function getSoundByteRange() { + private function getSoundByteRange() + { // chunked requests must include the desired byte range $rangeStr = $_SERVER['HTTP_RANGE']; if (!\BDC_StringHelper::HasValue($rangeStr)) { @@ -395,12 +402,15 @@ private function getSoundByteRange() { ); } - private function detectFakeRangeRequest() { + private function detectFakeRangeRequest() + { $detected = false; if (array_key_exists('HTTP_RANGE', $_SERVER)) { $rangeStr = $_SERVER['HTTP_RANGE']; - if (\BDC_StringHelper::HasValue($rangeStr) && - preg_match('/bytes=0-$/', $rangeStr)) { + if ( + \BDC_StringHelper::HasValue($rangeStr) && + preg_match('/bytes=0-$/', $rangeStr) + ) { $detected = true; } } @@ -549,7 +559,7 @@ public function getScriptInclude() private function getClientSideFramework() { - $clientSide = $this->request->query('cs'); + $clientSide = $this->request->getQuery('cs'); if (\BDC_StringHelper::HasValue($clientSide)) { $clientSide = \BDC_StringHelper::Normalize($clientSide); return $clientSide; @@ -563,22 +573,22 @@ private function getWebResource($p_Resource, $p_MimeType, $hasEtag = true) if ($hasEtag) { \BDC_HttpHelper::AllowEtagCache($p_Resource); } - + return file_get_contents($p_Resource); } private function isObviousBotRequest($p_Captcha) { $captchaRequestValidator = new \SimpleCaptchaRequestValidator($p_Captcha->Configuration); - - + + // some basic request checks $captchaRequestValidator->RecordRequest(); - + if ($captchaRequestValidator->IsObviousBotAttempt()) { - \BDC_HttpHelper::TooManyRequests('IsObviousBotAttempt'); + \BDC_HttpHelper::TooManyRequests('IsObviousBotAttempt'); } - + return false; } @@ -587,8 +597,9 @@ private function isObviousBotRequest($p_Captcha) */ private function getCaptchaId() { - $captchaId = $this->request->query('t'); - if (!\BDC_StringHelper::HasValue($captchaId) || + $captchaId = $this->request->getQuery('t'); + if ( + !\BDC_StringHelper::HasValue($captchaId) || !\BDC_CaptchaBase::IsValidInstanceId($captchaId) ) { return; @@ -604,13 +615,13 @@ private function getCaptchaId() private function getUserInput() { // BotDetect built-in Ajax Captcha validation - $input = $this->request->query('i'); + $input = $this->request->getQuery('i'); if (is_null($input)) { // jQuery validation support, the input key may be just about anything, // so we have to loop through fields and take the first unrecognized one $recognized = array('get', 'c', 't', 'd'); - foreach ($this->request->query as $key => $value) { + foreach ($this->request->getQuery as $key => $value) { if (!in_array($key, $recognized)) { $input = $value; break; @@ -628,7 +639,7 @@ private function getUserInput() */ private function getJsonValidationResult($result) { - $resultStr = ($result ? 'true': 'false'); + $resultStr = ($result ? 'true' : 'false'); return $resultStr; } @@ -637,7 +648,7 @@ private function getJsonValidationResult($result) */ private function isGetResourceContentsRequest() { - $http_get_data = $this->request->query; + $http_get_data = $this->request->getQuery; return array_key_exists('get', $http_get_data) && !array_key_exists('c', $http_get_data); } @@ -649,7 +660,9 @@ private function isGetResourceContentsRequest() */ private function badRequest($message) { - while (ob_get_contents()) { ob_end_clean(); } + while (ob_get_contents()) { + ob_end_clean(); + } header('HTTP/1.1 400 Bad Request'); header('Content-Type: text/plain'); echo $message; @@ -682,7 +695,7 @@ public function getP() // response data $response = "{\"sp\":\"{$p->GetSP()}\",\"hs\":\"{$p->GetHs()}\"}"; - + // response MIME type & headers header('Content-Type: application/json');