Passed
Push — master ( cc1f64...334a6a )
by Aimeos
02:45 queued 16s
created

Recaptcha::header()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 33
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 33
rs 10
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2024
6
 * @package Client
7
 * @subpackage Html
8
 */
9
10
11
namespace Aimeos\Client\Html\Cms\Page\Decorator;
12
13
14
/**
15
 * Recaptcha decorator for HTML clients
16
 *
17
 * @package Client
18
 * @subpackage Html
19
 */
20
class Recaptcha
21
	extends \Aimeos\Client\Html\Common\Decorator\Base
22
	implements \Aimeos\Client\Html\Common\Decorator\Iface
23
{
24
	/**
25
	 * Processes the input, e.g. store given values.
26
	 */
27
	public function init()
28
	{
29
		$view = $this->view();
30
        $context = $this->context();
31
		$key = $context->config()->get( 'resource/recaptcha/secretkey' );
32
33
		if( $key && $view->request()->getMethod() === 'POST' )
34
		{
35
			if( ( $token = $view->param( 'g-recaptcha-response' ) ) === null ) {
36
				throw new \Aimeos\Client\Html\Exception( $context->translate( 'client', 'reCAPTCHA token missing' ) );
37
			}
38
39
			$ip = $view->request()->getClientAddress();
40
			$url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $key . '&response=' . $token . '&remoteip=' . $ip;
41
42
			if( ( $result = file_get_contents( $url ) ) === false || ( $data = json_decode( $result ) ) === null ) {
43
				throw new \Aimeos\Client\Html\Exception( $context->translate( 'client', 'Invalid reCAPTCHA response' ) );
44
			}
45
46
			if( $data->success != true || $data->score < 0.5 ) {
47
				throw new \Aimeos\Client\Html\Exception( $context->translate( 'client', 'Your request is likely spam and was not executed' ) );
48
			}
49
		}
50
51
		$this->client()->init();
52
	}
53
54
55
	/**
56
	 * Returns the HTML string for insertion into the header.
57
	 *
58
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
59
	 * @return string|null String including HTML tags for the header on error
60
	 */
61
	public function header( string $uid = '' ) : ?string
62
	{
63
		$context = $this->context();
64
		$content = $this->client()->header( $uid );
65
66
		if( $key = $context->config()->get( 'resource/recaptcha/sitekey' ) )
67
		{
68
			$content .= '
69
				<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=' . $key . '"></script>
70
				<script type="text/javascript" nonce="' . $context->nonce() . '">
71
					document.addEventListener("DOMContentLoaded", () => {
72
						document.querySelectorAll(".aimeos.cms-page form").forEach(el => {
73
							el.addEventListener("submit", ev => {
74
								ev.preventDefault();
75
								grecaptcha.ready(() => {
76
									grecaptcha.execute("' . $key . '", { action: "cmspage" }).then(token => {
77
										const input = document.createElement("input");
78
										input.name = "g-recaptcha-response";
79
										input.type = "hidden";
80
										input.value = token;
81
82
										ev.target.appendChild(input);
83
										ev.target.submit();
84
									});
85
								});
86
							});
87
						});
88
					});
89
				</script>
90
			';
91
		}
92
93
		return $content;
94
	}
95
}
96