PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 12.0.3
Jetpack – WP Security, Backup, Speed, & Growth v12.0.3
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 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / comments / comments.php
jetpack / modules / comments Last commit date
admin.php 3 years ago base.php 4 years ago comments.php 3 years ago
comments.php
773 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Module: Comments
4 *
5 * @package automattic/jetpack
6 */
7
8 require __DIR__ . '/base.php';
9 use Automattic\Jetpack\Connection\Tokens;
10
11 /**
12 * Main Comments class
13 *
14 * @package automattic/jetpack
15 * @version 1.4
16 * @since 1.4
17 */
18 class Jetpack_Comments extends Highlander_Comments_Base {
19
20 /** Variables *************************************************************/
21
22 /**
23 * Possible comment form sources - empty array as default
24 *
25 * @var array
26 */
27 public $id_sources = array();
28
29 /**
30 * Remote comment URL - empty string as default
31 *
32 * @var string
33 */
34 public $signed_url = '';
35
36 /**
37 * The default comment form color scheme - default is light
38 *
39 * @var string
40 * @see ::set_default_color_theme_based_on_theme_settings()
41 */
42 public $default_color_scheme = 'light';
43
44 /** Methods ***************************************************************/
45
46 /**
47 * Initialize class
48 */
49 public static function init() {
50 static $instance = false;
51
52 if ( ! $instance ) {
53 $instance = new Jetpack_Comments();
54 }
55
56 return $instance;
57 }
58
59 /**
60 * Main constructor for Comments
61 *
62 * @since JetpackComments (1.4)
63 */
64 public function __construct() {
65 parent::__construct();
66
67 // Comments is loaded.
68
69 /**
70 * Fires after the Jetpack_Comments object has been instantiated
71 *
72 * @module comments
73 *
74 * @since 1.4.0
75 *
76 * @param array $jetpack_comments_loaded First element in array of type Jetpack_Comments
77 */
78 do_action_ref_array( 'jetpack_comments_loaded', array( $this ) );
79 add_action( 'after_setup_theme', array( $this, 'set_default_color_theme_based_on_theme_settings' ), 100 );
80 }
81
82 /**
83 * Set the default comments color theme based on theme settings
84 */
85 public function set_default_color_theme_based_on_theme_settings() {
86 if ( function_exists( 'twentyeleven_get_theme_options' ) ) {
87 $theme_options = twentyeleven_get_theme_options();
88 $theme_color_scheme = isset( $theme_options['color_scheme'] ) ? $theme_options['color_scheme'] : 'transparent';
89 } else {
90 $theme_color_scheme = get_theme_mod( 'color_scheme', 'transparent' );
91 }
92 // Default for $theme_color_scheme is 'transparent' just so it doesn't match 'light' or 'dark'.
93 // The default for Jetpack's color scheme is still defined above as 'light'.
94
95 if ( false !== stripos( $theme_color_scheme, 'light' ) ) {
96 $this->default_color_scheme = 'light';
97 } elseif ( false !== stripos( $theme_color_scheme, 'dark' ) ) {
98 $this->default_color_scheme = 'dark';
99 }
100 }
101
102 /** Private Methods *******************************************************/
103
104 /**
105 * Set any global variables or class variables
106 *
107 * This is primarily defining the comment form sources.
108 *
109 * @since JetpackComments (1.4)
110 */
111 protected function setup_globals() {
112 parent::setup_globals();
113
114 // Sources.
115 $this->id_sources = array(
116 'guest',
117 'jetpack',
118 'wordpress',
119 'twitter',
120 'facebook',
121 );
122 }
123
124 /**
125 * Setup actions for methods in this class
126 *
127 * @since JetpackComments (1.4)
128 */
129 protected function setup_actions() {
130 parent::setup_actions();
131
132 // Selfishly remove everything from the existing comment form.
133 remove_all_actions( 'comment_form_before' );
134
135 // Selfishly add only our actions back to the comment form.
136 add_action( 'comment_form_before', array( $this, 'comment_form_before' ) );
137 add_action( 'comment_form_after', array( $this, 'comment_form_after' ), 1 ); // Set very early since we remove everything outputed before our action.
138
139 // Before a comment is posted.
140 add_action( 'pre_comment_on_post', array( $this, 'pre_comment_on_post' ), 1 );
141
142 // After a comment is posted.
143 add_action( 'comment_post', array( $this, 'add_comment_meta' ) );
144 }
145
146 /**
147 * Setup filters for methods in this class
148 *
149 * @since 1.6.2
150 */
151 protected function setup_filters() {
152 parent::setup_filters();
153
154 add_filter( 'comment_post_redirect', array( $this, 'capture_comment_post_redirect_to_reload_parent_frame' ), 100 );
155 add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 4 );
156 }
157
158 /**
159 * Get the comment avatar from Gravatar, Twitter, or Facebook
160 *
161 * @since JetpackComments (1.4)
162 *
163 * @param string $avatar Current avatar URL.
164 * @param string $comment Comment for the avatar.
165 * @param int $size Size of the avatar.
166 *
167 * @return string New avatar
168 */
169 public function get_avatar( $avatar, $comment, $size ) {
170 if ( ! isset( $comment->comment_post_ID ) || ! isset( $comment->comment_ID ) ) {
171 // it's not a comment - bail.
172 return $avatar;
173 }
174
175 // Detect whether it's a Facebook or Twitter avatar.
176 $foreign_avatar = get_comment_meta( $comment->comment_ID, 'hc_avatar', true );
177 $foreign_avatar_hostname = wp_parse_url( $foreign_avatar, PHP_URL_HOST );
178 if ( ! $foreign_avatar_hostname ||
179 ! preg_match( '/\.?(graph\.facebook\.com|twimg\.com)$/', $foreign_avatar_hostname ) ) {
180 return $avatar;
181 }
182
183 // Return the Facebook or Twitter avatar.
184 return preg_replace( '#src=([\'"])[^\'"]+\\1#', 'src=\\1' . esc_url( set_url_scheme( $this->photon_avatar( $foreign_avatar, $size ), 'https' ) ) . '\\1', $avatar );
185 }
186
187 /**
188 * Get the site's blog token.
189 * This can be used to bypass Comments entirely if Jetpack is not properly connected.
190 *
191 * @since 11.2
192 *
193 * @return bool|object False if not properly connected. Object with the blog token if connected.
194 */
195 private function get_blog_token() {
196 $blog_token = ( new Tokens() )->get_access_token();
197 // If we have no token, bail.
198 if ( ! $blog_token || is_wp_error( $blog_token ) ) {
199 return false;
200 }
201
202 return $blog_token;
203 }
204
205 /** Output Methods ********************************************************/
206
207 /**
208 * Start capturing the core comment_form() output
209 *
210 * Comment form output will only be captured if comments are enabled - we return otherwise.
211 *
212 * @since JetpackComments (1.4)
213 */
214 public function comment_form_before() {
215 /**
216 * Filters the setting that determines if Jetpack comments should be enabled for
217 * the current post type.
218 *
219 * @module comments
220 *
221 * @since 3.8.1
222 *
223 * @param boolean $return Should comments be enabled?
224 */
225 if ( ! apply_filters( 'jetpack_comment_form_enabled_for_' . get_post_type(), true ) ) {
226 return;
227 }
228
229 // If the Jetpack connection is not healthy, bail.
230 if ( ! $this->get_blog_token() ) {
231 return;
232 }
233
234 // Add some JS to the footer.
235 add_action( 'wp_footer', array( $this, 'watch_comment_parent' ), 100 );
236
237 ob_start();
238 }
239
240 /**
241 * Noop the default comment form output, get some options, and output our
242 * tricked out totally radical comment form.
243 *
244 * @since JetpackComments (1.4)
245 */
246 public function comment_form_after() {
247 /** This filter is documented in modules/comments/comments.php */
248 if ( ! apply_filters( 'jetpack_comment_form_enabled_for_' . get_post_type(), true ) ) {
249 return;
250 }
251
252 $blog_token = $this->get_blog_token();
253 // If the Jetpack connection is not healthy, bail.
254 if ( ! $blog_token ) {
255 return;
256 }
257
258 // Throw it all out and drop in our replacement.
259 ob_end_clean();
260
261 // If users are required to be logged in, and they're not, then we don't need to do anything else.
262 if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
263 /**
264 * Changes the log in to comment prompt.
265 *
266 * @module comments
267 *
268 * @since 1.4.0
269 *
270 * @param string $var Default is "You must log in to post a comment."
271 */
272 echo '<p class="must-log-in">' . wp_kses_post(
273 sprintf(
274 apply_filters(
275 'jetpack_must_log_in_to_comment',
276 /* translators: %s is the wp-login URL for the site */
277 __( 'You must <a href="%s">log in</a> to post a comment.', 'jetpack' )
278 ),
279 wp_login_url( get_permalink() . '#respond' )
280 )
281 ) . '</p>';
282 return;
283 }
284
285 if ( in_array( 'subscriptions', Jetpack::get_active_modules(), true ) ) {
286 $stb_enabled = get_option( 'stb_enabled', 1 );
287 $stb_enabled = empty( $stb_enabled ) ? 0 : 1;
288
289 $stc_enabled = get_option( 'stc_enabled', 1 );
290 $stc_enabled = empty( $stc_enabled ) ? 0 : 1;
291 } else {
292 $stb_enabled = 0;
293 $stc_enabled = 0;
294 }
295
296 $params = array(
297 'blogid' => Jetpack_Options::get_option( 'id' ),
298 'postid' => get_the_ID(),
299 'comment_registration' => ( get_option( 'comment_registration' ) ? '1' : '0' ), // Need to explicitly send a '1' or a '0' for these.
300 'require_name_email' => ( get_option( 'require_name_email' ) ? '1' : '0' ),
301 'stc_enabled' => $stc_enabled,
302 'stb_enabled' => $stb_enabled,
303 'show_avatars' => ( get_option( 'show_avatars' ) ? '1' : '0' ),
304 'avatar_default' => get_option( 'avatar_default' ),
305 'greeting' => get_option( 'highlander_comment_form_prompt', __( 'Leave a Reply', 'jetpack' ) ),
306 'jetpack_comments_nonce' => wp_create_nonce( 'jetpack_comments_nonce-' . get_the_ID() ),
307 /**
308 * Changes the comment form prompt.
309 *
310 * @module comments
311 *
312 * @since 2.3.0
313 *
314 * @param string $var Default is "Leave a Reply to %s."
315 */
316 'greeting_reply' => apply_filters(
317 'jetpack_comment_form_prompt_reply',
318 /* translators: %s is the displayed username of the post (or comment) author */
319 __( 'Leave a Reply to %s', 'jetpack' )
320 ),
321 'color_scheme' => get_option( 'jetpack_comment_form_color_scheme', $this->default_color_scheme ),
322 'lang' => get_locale(),
323 'jetpack_version' => JETPACK__VERSION,
324 );
325
326 // Extra parameters for logged in user.
327 if ( is_user_logged_in() ) {
328 $current_user = wp_get_current_user();
329 $params['hc_post_as'] = 'jetpack';
330 $params['hc_userid'] = $current_user->ID;
331 $params['hc_username'] = $current_user->display_name;
332 $params['hc_userurl'] = $current_user->user_url;
333 $params['hc_useremail'] = md5( strtolower( trim( $current_user->user_email ) ) );
334 if ( current_user_can( 'unfiltered_html' ) ) {
335 $params['_wp_unfiltered_html_comment'] = wp_create_nonce( 'unfiltered-html-comment_' . get_the_ID() );
336 }
337 } else {
338 $commenter = wp_get_current_commenter();
339 $params['show_cookie_consent'] = (int) has_action( 'set_comment_cookies', 'wp_set_comment_cookies' );
340 $params['has_cookie_consent'] = (int) ! empty( $commenter['comment_author_email'] );
341 }
342
343 list( $token_key ) = explode( '.', $blog_token->secret, 2 );
344 // Prophylactic check: anything else should never happen.
345 if ( $token_key && $token_key !== $blog_token->secret ) {
346 // Is the token a Special Token (@see class.tokens.php)?
347 if ( preg_match( '/^;.\d+;\d+;$/', $token_key, $matches ) ) {
348 // The token key for a Special Token is public.
349 $params['token_key'] = $token_key;
350 } else {
351 /*
352 * The token key for a Normal Token is public but
353 * looks like sensitive data. Since there can only be
354 * one Normal Token per site, avoid concern by
355 * sending the magic "use the Normal Token" token key.
356 */
357 $params['token_key'] = Tokens::MAGIC_NORMAL_TOKEN_KEY;
358 }
359 }
360
361 $signature = self::sign_remote_comment_parameters( $params, $blog_token->secret );
362 if ( is_wp_error( $signature ) ) {
363 $signature = 'error';
364 }
365
366 $params['sig'] = $signature;
367 $url_origin = 'https://jetpack.wordpress.com';
368 $url = "{$url_origin}/jetpack-comment/?" . http_build_query( $params );
369 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sniff misses the esc_url_raw.
370 $url = "{$url}#parent=" . rawurlencode( esc_url_raw( set_url_scheme( 'http://' . ( isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : '' ) . ( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '' ) ) ) );
371 $this->signed_url = $url;
372 $height = $params['comment_registration'] || is_user_logged_in() ? '315' : '430'; // Iframe can be shorter if we're not allowing guest commenting.
373 $transparent = ( 'transparent' === $params['color_scheme'] ) ? 'true' : 'false';
374
375 if ( isset( $_GET['replytocom'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
376 $url .= '&replytocom=' . (int) $_GET['replytocom']; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
377 }
378
379 /**
380 * Filter whether the comment title can be displayed.
381 *
382 * @module comments
383 *
384 * @since 4.7.0
385 *
386 * @param bool $show Can the comment be displayed? Default to true.
387 */
388 $show_greeting = apply_filters( 'jetpack_comment_form_display_greeting', true );
389
390 // The actual iframe (loads comment form from Jetpack server).
391
392 $is_amp = Jetpack_AMP_Support::is_amp_request();
393 ?>
394
395 <div id="respond" class="comment-respond">
396 <?php if ( true === $show_greeting ) : ?>
397 <h3 id="reply-title" class="comment-reply-title"><?php comment_form_title( esc_html( $params['greeting'] ), esc_html( $params['greeting_reply'] ) ); ?>
398 <small><?php cancel_comment_reply_link( esc_html__( 'Cancel reply', 'jetpack' ) ); ?></small>
399 </h3>
400 <?php endif; ?>
401 <form id="commentform" class="comment-form">
402 <iframe
403 title="<?php esc_attr_e( 'Comment Form', 'jetpack' ); ?>"
404 src="<?php echo esc_url( $url ); ?>"
405 <?php if ( $is_amp ) : ?>
406 resizable
407 layout="fixed-height"
408 height="<?php echo esc_attr( $height ); ?>"
409 <?php else : ?>
410 name="jetpack_remote_comment"
411 style="width:100%; height: <?php echo esc_attr( $height ); ?>px; border:0;"
412 <?php endif; ?>
413 class="jetpack_remote_comment"
414 id="jetpack_remote_comment"
415 sandbox="allow-same-origin allow-top-navigation allow-scripts allow-forms allow-popups"
416 >
417 <?php if ( $is_amp ) : ?>
418 <button overflow><?php esc_html_e( 'Show more', 'jetpack' ); ?></button>
419 <?php endif; ?>
420 </iframe>
421 <?php if ( ! $is_amp ) : ?>
422 <!--[if !IE]><!-->
423 <script>
424 document.addEventListener('DOMContentLoaded', function () {
425 var commentForms = document.getElementsByClassName('jetpack_remote_comment');
426 for (var i = 0; i < commentForms.length; i++) {
427 commentForms[i].allowTransparency = <?php echo esc_html( $transparent ); ?>;
428 commentForms[i].scrolling = 'no';
429 }
430 });
431 </script>
432 <!--<![endif]-->
433 <?php endif; ?>
434 </form>
435 </div>
436
437 <?php // Below is required for comment reply JS to work. ?>
438
439 <input type="hidden" name="comment_parent" id="comment_parent" value="" />
440
441 <?php
442 }
443
444 /**
445 * Add some JS to wp_footer to watch for hierarchical reply parent change
446 *
447 * If AMP is enabled, we don't make any changes.
448 *
449 * @since JetpackComments (1.4)
450 */
451 public function watch_comment_parent() {
452 if ( Jetpack_AMP_Support::is_amp_request() ) {
453 // @todo Implement AMP support.
454 return;
455 }
456
457 $url_origin = 'https://jetpack.wordpress.com';
458 ?>
459
460 <!--[if IE]>
461 <script type="text/javascript">
462 if ( 0 === window.location.hash.indexOf( '#comment-' ) ) {
463 // window.location.reload() doesn't respect the Hash in IE
464 window.location.hash = window.location.hash;
465 }
466 </script>
467 <![endif]-->
468 <script type="text/javascript">
469 (function () {
470 var comm_par_el = document.getElementById( 'comment_parent' ),
471 comm_par = ( comm_par_el && comm_par_el.value ) ? comm_par_el.value : '',
472 frame = document.getElementById( 'jetpack_remote_comment' ),
473 tellFrameNewParent;
474
475 tellFrameNewParent = function () {
476 if ( comm_par ) {
477 frame.src = "<?php echo esc_url_raw( $this->signed_url ); ?>" + '&replytocom=' + parseInt( comm_par, 10 ).toString();
478 } else {
479 frame.src = "<?php echo esc_url_raw( $this->signed_url ); ?>";
480 }
481 };
482
483 <?php if ( get_option( 'thread_comments' ) && get_option( 'thread_comments_depth' ) ) : ?>
484
485 if ( 'undefined' !== typeof addComment ) {
486 addComment._Jetpack_moveForm = addComment.moveForm;
487
488 addComment.moveForm = function ( commId, parentId, respondId, postId ) {
489 var returnValue = addComment._Jetpack_moveForm( commId, parentId, respondId, postId ),
490 cancelClick, cancel;
491
492 if ( false === returnValue ) {
493 cancel = document.getElementById( 'cancel-comment-reply-link' );
494 cancelClick = cancel.onclick;
495 cancel.onclick = function () {
496 var cancelReturn = cancelClick.call( this );
497 if ( false !== cancelReturn ) {
498 return cancelReturn;
499 }
500
501 if ( ! comm_par ) {
502 return cancelReturn;
503 }
504
505 comm_par = 0;
506
507 tellFrameNewParent();
508
509 return cancelReturn;
510 };
511 }
512
513 if ( comm_par == parentId ) {
514 return returnValue;
515 }
516
517 comm_par = parentId;
518
519 tellFrameNewParent();
520
521 return returnValue;
522 };
523 }
524
525 <?php endif; ?>
526
527 // Do the post message bit after the dom has loaded.
528 document.addEventListener( 'DOMContentLoaded', function () {
529 var iframe_url = <?php echo wp_json_encode( esc_url_raw( $url_origin ) ); ?>;
530 if ( window.postMessage ) {
531 if ( document.addEventListener ) {
532 window.addEventListener( 'message', function ( event ) {
533 var origin = event.origin.replace( /^http:\/\//i, 'https://' );
534 if ( iframe_url.replace( /^http:\/\//i, 'https://' ) !== origin ) {
535 return;
536 }
537 frame.style.height = event.data + 'px';
538 });
539 } else if ( document.attachEvent ) {
540 window.attachEvent( 'message', function ( event ) {
541 var origin = event.origin.replace( /^http:\/\//i, 'https://' );
542 if ( iframe_url.replace( /^http:\/\//i, 'https://' ) !== origin ) {
543 return;
544 }
545 frame.style.height = event.data + 'px';
546 });
547 }
548 }
549 })
550
551 })();
552 </script>
553
554 <?php
555 }
556
557 /**
558 * Verify the hash included in remote comments.
559 *
560 * If the Jetpack token is missing we return nothing,
561 * and if the token is unknown or invalid, or comments not allowed, an error is returned.
562 *
563 * @since JetpackComments (1.4)
564 */
565 public function pre_comment_on_post() {
566 $post_array = stripslashes_deep( $_POST );
567
568 // Bail if missing the Jetpack token.
569 if ( ! isset( $post_array['sig'] ) || ! isset( $post_array['token_key'] ) ) {
570 unset( $_POST['hc_post_as'] );
571
572 return;
573 }
574
575 if ( empty( $post_array['jetpack_comments_nonce'] ) || ! wp_verify_nonce( $post_array['jetpack_comments_nonce'], "jetpack_comments_nonce-{$post_array['comment_post_ID']}" ) ) {
576 wp_die( esc_html__( 'Nonce verification failed.', 'jetpack' ), 400 );
577 }
578
579 if ( false !== strpos( $post_array['hc_avatar'], '.gravatar.com' ) ) {
580 $post_array['hc_avatar'] = htmlentities( $post_array['hc_avatar'], ENT_COMPAT );
581 }
582
583 $blog_token = ( new Tokens() )->get_access_token( false, $post_array['token_key'] );
584 if ( ! $blog_token || is_wp_error( $blog_token ) ) {
585 wp_die( esc_html__( 'Unknown security token.', 'jetpack' ), 400 );
586 }
587 $check = self::sign_remote_comment_parameters( $post_array, $blog_token->secret );
588 if ( is_wp_error( $check ) ) {
589 wp_die( esc_html( $check ) );
590 }
591
592 // Bail if token is expired or not valid.
593 if ( ! hash_equals( $check, $post_array['sig'] ) ) {
594 wp_die( esc_html__( 'Invalid security token.', 'jetpack' ), 400 );
595 }
596
597 /** This filter is documented in modules/comments/comments.php */
598 if ( ! apply_filters( 'jetpack_comment_form_enabled_for_' . get_post_type( $post_array['comment_post_ID'] ), true ) ) {
599 // In case the comment POST is legit, but the comments are
600 // now disabled, we don't allow the comment.
601
602 wp_die( esc_html__( 'Comments are not allowed.', 'jetpack' ), 403 );
603 }
604 }
605
606 /** Capabilities **********************************************************/
607
608 /**
609 * Add some additional comment meta after comment is saved about what
610 * service the comment is from, the avatar, user_id, etc...
611 *
612 * @since JetpackComments (1.4)
613 *
614 * @param int $comment_id The comment ID.
615 */
616 public function add_comment_meta( $comment_id ) {
617 $comment_meta = array();
618
619 // phpcs:disable WordPress.Security.NonceVerification.Missing
620 switch ( $this->is_highlander_comment_post() ) {
621 case 'facebook':
622 $comment_meta['hc_post_as'] = 'facebook';
623 $comment_meta['hc_avatar'] = isset( $_POST['hc_avatar'] ) ? filter_var( wp_unslash( $_POST['hc_avatar'] ) ) : null;
624 $comment_meta['hc_foreign_user_id'] = isset( $_POST['hc_userid'] ) ? filter_var( wp_unslash( $_POST['hc_userid'] ) ) : null;
625 break;
626
627 case 'twitter':
628 $comment_meta['hc_post_as'] = 'twitter';
629 $comment_meta['hc_avatar'] = isset( $_POST['hc_avatar'] ) ? filter_var( wp_unslash( $_POST['hc_avatar'] ) ) : null;
630 $comment_meta['hc_foreign_user_id'] = isset( $_POST['hc_userid'] ) ? filter_var( wp_unslash( $_POST['hc_userid'] ) ) : null;
631 break;
632
633 // phpcs:ignore WordPress.WP.CapitalPDangit
634 case 'wordpress':
635 // phpcs:ignore WordPress.WP.CapitalPDangit
636 $comment_meta['hc_post_as'] = 'wordpress';
637 $comment_meta['hc_avatar'] = isset( $_POST['hc_avatar'] ) ? filter_var( wp_unslash( $_POST['hc_avatar'] ) ) : null;
638 $comment_meta['hc_foreign_user_id'] = isset( $_POST['hc_userid'] ) ? filter_var( wp_unslash( $_POST['hc_userid'] ) ) : null;
639 $comment_meta['hc_wpcom_id_sig'] = isset( $_POST['hc_wpcom_id_sig'] ) ? filter_var( wp_unslash( $_POST['hc_wpcom_id_sig'] ) ) : null; // since 1.9.
640 break;
641
642 case 'jetpack':
643 $comment_meta['hc_post_as'] = 'jetpack';
644 $comment_meta['hc_avatar'] = isset( $_POST['hc_avatar'] ) ? filter_var( wp_unslash( $_POST['hc_avatar'] ) ) : null;
645 $comment_meta['hc_foreign_user_id'] = isset( $_POST['hc_userid'] ) ? filter_var( wp_unslash( $_POST['hc_userid'] ) ) : null;
646 break;
647
648 }
649 // phpcs:enable WordPress.Security.NonceVerification.Missing
650
651 // Bail if no extra comment meta.
652 if ( empty( $comment_meta ) ) {
653 return;
654 }
655
656 // Loop through extra meta and add values.
657 foreach ( $comment_meta as $key => $value ) {
658 add_comment_meta( $comment_id, $key, $value, true );
659 }
660 }
661
662 /**
663 * POST the submitted comment to the iframe
664 *
665 * @param string $url The comment URL origin.
666 */
667 public function capture_comment_post_redirect_to_reload_parent_frame( $url ) {
668 if ( ! isset( $_GET['for'] ) || 'jetpack' !== $_GET['for'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
669 return $url;
670 }
671 ?>
672 <!DOCTYPE html>
673 <html <?php language_attributes(); ?>>
674 <!--<![endif]-->
675 <head>
676 <meta charset="<?php bloginfo( 'charset' ); ?>" />
677 <title>
678 <?php
679 wp_kses_post(
680 printf(
681 /* translators: %s is replaced by an ellipsis */
682 __( 'Submitting Comment%s', 'jetpack' ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
683 '&hellip;'
684 )
685 );
686 ?>
687 </title>
688 <style type="text/css">
689 body {
690 display: table;
691 width: 100%;
692 height: 60%;
693 position: absolute;
694 top: 0;
695 left: 0;
696 overflow: hidden;
697 color: #333;
698 }
699
700 h1 {
701 text-align: center;
702 margin: 0;
703 padding: 0;
704 display: table-cell;
705 vertical-align: middle;
706 font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif;
707 font-weight: normal;
708 }
709
710 .hidden {
711 opacity: 0;
712 }
713
714 h1 span {
715 -moz-transition-property: opacity;
716 -moz-transition-duration: 1s;
717 -moz-transition-timing-function: ease-in-out;
718
719 -webkit-transition-property: opacity;
720 -webkit-transition-duration: 1s;
721 -webbit-transition-timing-function: ease-in-out;
722
723 -o-transition-property: opacity;
724 -o-transition-duration: 1s;
725 -o-transition-timing-function: ease-in-out;
726
727 -ms-transition-property: opacity;
728 -ms-transition-duration: 1s;
729 -ms-transition-timing-function: ease-in-out;
730
731 transition-property: opacity;
732 transition-duration: 1s;
733 transition-timing-function: ease-in-out;
734 }
735 </style>
736 </head>
737 <body>
738 <h1>
739 <?php
740 wp_kses_post(
741 printf(
742 /* translators: %s is replaced by HTML markup to include an ellipsis */
743 __( 'Submitting Comment%s', 'jetpack' ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
744 '<span id="ellipsis" class="hidden">&hellip;</span>'
745 )
746 );
747 ?>
748 </h1>
749 <script type="text/javascript">
750 try {
751 window.parent.location = <?php echo wp_json_encode( $url ); ?>;
752 window.parent.location.reload(true);
753 } catch (e) {
754 window.location = <?php echo wp_json_encode( $url ); ?>;
755 window.location.reload(true);
756 }
757 ellipsis = document.getElementById('ellipsis');
758
759 function toggleEllipsis() {
760 ellipsis.className = ellipsis.className ? '' : 'hidden';
761 }
762
763 setInterval(toggleEllipsis, 1200);
764 </script>
765 </body>
766 </html>
767 <?php
768 exit;
769 }
770 }
771
772 Jetpack_Comments::init();
773