PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 14.9
Jetpack – WP Security, Backup, Speed, & Growth v14.9
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / sharedaddy / recaptcha.php

recaptcha.php in Jetpack – WP Security, Backup, Speed, & Growth 14.9, at modules/sharedaddy/recaptcha.php

231 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Google reCAPTCHA utilities, for use in the sharing feature.
4 *
5 * @package automattic/jetpack
6 */
7
8 /**
9 * Class that handles reCAPTCHA.
10 *
11 * @deprecated 11.0
12 */
13 class Jetpack_ReCaptcha {
14
15 /**
16 * URL to which requests are POSTed.
17 *
18 * @const string
19 */
20 const VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
21
22 /**
23 * Site key to use in HTML code.
24 *
25 * @var string
26 */
27 private $site_key;
28
29 /**
30 * Shared secret for the site.
31 *
32 * @var string
33 */
34 private $secret_key;
35
36 /**
37 * Config for reCAPTCHA instance.
38 *
39 * @var array
40 */
41 private $config;
42
43 /**
44 * Error codes returned from reCAPTCHA API.
45 *
46 * @see https://developers.google.com/recaptcha/docs/verify
47 *
48 * @var array
49 */
50 private $error_codes;
51
52 /**
53 * Create a configured instance to use the reCAPTCHA service.
54 *
55 * @param string $site_key Site key to use in HTML code.
56 * @param string $secret_key Shared secret between site and reCAPTCHA server.
57 * @param array $config Config array to optionally configure reCAPTCHA instance.
58 */
59 public function __construct( $site_key, $secret_key, $config = array() ) {
60 $this->site_key = $site_key;
61 $this->secret_key = $secret_key;
62 $this->config = wp_parse_args( $config, $this->get_default_config() );
63
64 $this->error_codes = array(
65 'missing-input-secret' => __( 'The secret parameter is missing', 'jetpack' ),
66 'invalid-input-secret' => __( 'The secret parameter is invalid or malformed', 'jetpack' ),
67 'missing-input-response' => __( 'The response parameter is missing', 'jetpack' ),
68 'invalid-input-response' => __( 'The response parameter is invalid or malformed', 'jetpack' ),
69 'invalid-json' => __( 'Invalid JSON', 'jetpack' ),
70 'unexpected-response' => __( 'Unexpected response', 'jetpack' ),
71 'unexpected-hostname' => __( 'Unexpected hostname', 'jetpack' ),
72 );
73 }
74
75 /**
76 * Get default config for this reCAPTCHA instance.
77 *
78 * @return array Default config
79 */
80 public function get_default_config() {
81 return array(
82 'language' => get_locale(),
83 'script_async' => false,
84 'script_defer' => true,
85 'script_lazy' => false,
86 'tag_class' => 'g-recaptcha',
87 'tag_attributes' => array(
88 'theme' => 'light',
89 'type' => 'image',
90 'tabindex' => 0,
91 ),
92 );
93 }
94
95 /**
96 * Calls the reCAPTCHA siteverify API to verify whether the user passes
97 * CAPTCHA test.
98 *
99 * @param string $response The value of 'g-recaptcha-response' in the submitted
100 * form.
101 * @param string $remote_ip The end user's IP address.
102 *
103 * @return bool|WP_Error Returns true if verified. Otherwise WP_Error is returned.
104 */
105 public function verify( $response, $remote_ip ) {
106 // No need make a request if response is empty.
107 if ( empty( $response ) ) {
108 return new WP_Error( 'missing-input-response', $this->error_codes['missing-input-response'], 400 );
109 }
110
111 $resp = wp_remote_post( self::VERIFY_URL, $this->get_verify_request_params( $response, $remote_ip ) );
112 if ( is_wp_error( $resp ) ) {
113 return $resp;
114 }
115
116 $resp_decoded = json_decode( wp_remote_retrieve_body( $resp ), true );
117 if ( ! $resp_decoded ) {
118 return new WP_Error( 'invalid-json', $this->error_codes['invalid-json'], 400 );
119 }
120
121 // Default error code and message.
122 $error_code = 'unexpected-response';
123 $error_message = $this->error_codes['unexpected-response'];
124
125 // Use the first error code if exists.
126 if ( isset( $resp_decoded['error-codes'] ) && is_array( $resp_decoded['error-codes'] ) ) {
127 if ( isset( $resp_decoded['error-codes'][0] ) && isset( $this->error_codes[ $resp_decoded['error-codes'][0] ] ) ) {
128 $error_message = $this->error_codes[ $resp_decoded['error-codes'][0] ];
129 $error_code = $resp_decoded['error-codes'][0];
130 }
131 }
132
133 if ( ! isset( $resp_decoded['success'] ) ) {
134 return new WP_Error( $error_code, $error_message );
135 }
136
137 if ( true !== $resp_decoded['success'] ) {
138 return new WP_Error( $error_code, $error_message );
139 }
140 // Validate the hostname matches expected source
141 if ( isset( $resp_decoded['hostname'] ) ) {
142 $url = wp_parse_url( get_home_url() );
143
144 /**
145 * Allow other valid hostnames.
146 *
147 * This can be useful in cases where the token hostname is expected to be
148 * different from the get_home_url (ex. AMP recaptcha token contains a different hostname)
149 *
150 * @module sharedaddy
151 *
152 * @since 9.1.0
153 *
154 * @param array [ $url['host'] ] List of the valid hostnames to check against.
155 */
156 $valid_hostnames = apply_filters( 'jetpack_recaptcha_valid_hostnames', array( $url['host'] ) );
157
158 if ( ! in_array( $resp_decoded['hostname'], $valid_hostnames, true ) ) {
159 return new WP_Error( 'unexpected-host', $this->error_codes['unexpected-hostname'] );
160 }
161 }
162
163 return true;
164 }
165
166 /**
167 * Get siteverify request parameters.
168 *
169 * @param string $response The value of 'g-recaptcha-response' in the submitted
170 * form.
171 * @param string $remote_ip The end user's IP address.
172 *
173 * @return array
174 */
175 public function get_verify_request_params( $response, $remote_ip ) {
176 return array(
177 'body' => array(
178 'secret' => $this->secret_key,
179 'response' => $response,
180 'remoteip' => $remote_ip,
181 ),
182 'sslverify' => true,
183 );
184 }
185
186 /**
187 * Get reCAPTCHA HTML to render.
188 *
189 * @return string
190 */
191 public function get_recaptcha_html() {
192 $url = sprintf(
193 'https://www.google.com/recaptcha/api.js?hl=%s',
194 rawurlencode( $this->config['language'] )
195 );
196
197 $html = sprintf(
198 '
199 <div
200 class="%s"
201 data-sitekey="%s"
202 data-theme="%s"
203 data-type="%s"
204 data-tabindex="%s"
205 data-lazy="%s"
206 data-url="%s"></div>
207 ',
208 esc_attr( $this->config['tag_class'] ),
209 esc_attr( $this->site_key ),
210 esc_attr( $this->config['tag_attributes']['theme'] ),
211 esc_attr( $this->config['tag_attributes']['type'] ),
212 esc_attr( $this->config['tag_attributes']['tabindex'] ),
213 $this->config['script_lazy'] ? 'true' : 'false',
214 esc_attr( $url )
215 );
216
217 if ( ! $this->config['script_lazy'] ) {
218 $html = $html . sprintf(
219 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
220 '<script src="%s"%s%s></script>
221 ',
222 $url,
223 $this->config['script_async'] && ! $this->config['script_defer'] ? ' async' : '',
224 $this->config['script_defer'] ? ' defer' : ''
225 );
226 }
227
228 return $html;
229 }
230 }
231