Completed
Push — fix/instant-search-non-ascii ( b82854...f54339 )
by
unknown
18:41 queued 10:23
created

modules/comments/comments.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
require dirname( __FILE__ ) . '/base.php';
4
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
5
6
/**
7
 * Main Comments class
8
 *
9
 * @package JetpackComments
10
 * @version 1.4
11
 * @since   1.4
12
 */
13
class Jetpack_Comments extends Highlander_Comments_Base {
14
15
	/** Variables *************************************************************/
16
17
	/**
18
	 * Possible comment form sources
19
	 * @var array
20
	 */
21
	public $id_sources = array();
22
23
	/**
24
	 * URL
25
	 * @var string
26
	 */
27
	public $signed_url = '';
28
29
	/**
30
	 * The default comment form color scheme
31
	 * @var string
32
	 * @see ::set_default_color_theme_based_on_theme_settings()
33
	 */
34
	public $default_color_scheme = 'light';
35
36
	/** Methods ***************************************************************/
37
38
	public static function init() {
39
		static $instance = false;
40
41
		if ( ! $instance ) {
42
			$instance = new Jetpack_Comments;
43
		}
44
45
		return $instance;
46
	}
47
48
	/**
49
	 * Main constructor for Comments
50
	 *
51
	 * @since JetpackComments (1.4)
52
	 */
53
	public function __construct() {
54
		parent::__construct();
55
56
		// Comments is loaded
57
58
		/**
59
		 * Fires after the Jetpack_Comments object has been instantiated
60
		 *
61
		 * @module comments
62
		 *
63
		 * @since  1.4.0
64
		 *
65
		 * @param array $jetpack_comments_loaded First element in array of type Jetpack_Comments
66
		 **/
67
		do_action_ref_array( 'jetpack_comments_loaded', array( $this ) );
68
		add_action( 'after_setup_theme', array( $this, 'set_default_color_theme_based_on_theme_settings' ), 100 );
69
	}
70
71
	public function set_default_color_theme_based_on_theme_settings() {
72
		if ( function_exists( 'twentyeleven_get_theme_options' ) ) {
73
			$theme_options      = twentyeleven_get_theme_options();
74
			$theme_color_scheme = isset( $theme_options['color_scheme'] ) ? $theme_options['color_scheme'] : 'transparent';
75
		} else {
76
			$theme_color_scheme = get_theme_mod( 'color_scheme', 'transparent' );
77
		}
78
		// Default for $theme_color_scheme is 'transparent' just so it doesn't match 'light' or 'dark'
79
		// The default for Jetpack's color scheme is still defined above as 'light'
80
81
		if ( false !== stripos( $theme_color_scheme, 'light' ) ) {
82
			$this->default_color_scheme = 'light';
83
		} elseif ( false !== stripos( $theme_color_scheme, 'dark' ) ) {
84
			$this->default_color_scheme = 'dark';
85
		}
86
	}
87
88
	/** Private Methods *******************************************************/
89
90
	/**
91
	 * Set any global variables or class variables
92
	 * @since JetpackComments (1.4)
93
	 */
94
	protected function setup_globals() {
95
		parent::setup_globals();
96
97
		// Sources
98
		$this->id_sources = array(
99
			'guest',
100
			'jetpack',
101
			'wordpress',
102
			'twitter',
103
			'facebook',
104
		);
105
	}
106
107
	/**
108
	 * Setup actions for methods in this class
109
	 * @since JetpackComments (1.4)
110
	 */
111
	protected function setup_actions() {
112
		parent::setup_actions();
113
114
		// Selfishly remove everything from the existing comment form
115
		remove_all_actions( 'comment_form_before' );
116
117
		// Selfishly add only our actions back to the comment form
118
		add_action( 'comment_form_before', array( $this, 'comment_form_before' ) );
119
		add_action( 'comment_form_after', array( $this, 'comment_form_after' ), 1 ); // Set very early since we remove everything outputed before our action.
120
121
		// Before a comment is posted
122
		add_action( 'pre_comment_on_post', array( $this, 'pre_comment_on_post' ), 1 );
123
124
		// After a comment is posted
125
		add_action( 'comment_post', array( $this, 'add_comment_meta' ) );
126
	}
127
128
	/**
129
	 * Setup filters for methods in this class
130
	 * @since 1.6.2
131
	 */
132
	protected function setup_filters() {
133
		parent::setup_filters();
134
135
		add_filter( 'comment_post_redirect', array( $this, 'capture_comment_post_redirect_to_reload_parent_frame' ), 100 );
136
		add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 4 );
137
	}
138
139
	/**
140
	 * Get the comment avatar from Gravatar, Twitter, or Facebook
141
	 *
142
	 * @since JetpackComments (1.4)
143
	 *
144
	 * @param string $avatar  Current avatar URL
145
	 * @param string $comment Comment for the avatar
146
	 * @param int    $size    Size of the avatar
147
	 * @param string $default Not used
148
	 *
149
	 * @return string New avatar
150
	 */
151
	public function get_avatar( $avatar, $comment, $size, $default ) {
152
		if ( ! isset( $comment->comment_post_ID ) || ! isset( $comment->comment_ID ) ) {
153
			// it's not a comment - bail
154
			return $avatar;
155
		}
156
157
		// Detect whether it's a Facebook or Twitter avatar
158
		$foreign_avatar          = get_comment_meta( $comment->comment_ID, 'hc_avatar', true );
159
		$foreign_avatar_hostname = wp_parse_url( $foreign_avatar, PHP_URL_HOST );
160
		if ( ! $foreign_avatar_hostname ||
0 ignored issues
show
Bug Best Practice introduced by
The expression $foreign_avatar_hostname of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
161
			! preg_match( '/\.?(graph\.facebook\.com|twimg\.com)$/', $foreign_avatar_hostname ) ) {
162
			return $avatar;
163
		}
164
165
		// Return the FB or Twitter avatar
166
		return preg_replace( '#src=([\'"])[^\'"]+\\1#', 'src=\\1' . esc_url( set_url_scheme( $this->photon_avatar( $foreign_avatar, $size ), 'https' ) ) . '\\1', $avatar );
167
	}
168
169
	/** Output Methods ********************************************************/
170
171
	/**
172
	 * Start capturing the core comment_form() output
173
	 * @since JetpackComments (1.4)
174
	 */
175
	public function comment_form_before() {
176
		/**
177
		 * Filters the setting that determines if Jetpack comments should be enabled for
178
		 * the current post type.
179
		 *
180
		 * @module comments
181
		 *
182
		 * @since  3.8.1
183
		 *
184
		 * @param boolean $return Should comments be enabled?
185
		 */
186
		if ( ! apply_filters( 'jetpack_comment_form_enabled_for_' . get_post_type(), true ) ) {
187
			return;
188
		}
189
190
		// Add some JS to the footer
191
		add_action( 'wp_footer', array( $this, 'watch_comment_parent' ), 100 );
192
193
		ob_start();
194
	}
195
196
	/**
197
	 * Noop the default comment form output, get some options, and output our
198
	 * tricked out totally radical comment form.
199
	 *
200
	 * @since JetpackComments (1.4)
201
	 */
202
	public function comment_form_after() {
203
		/** This filter is documented in modules/comments/comments.php */
204
		if ( ! apply_filters( 'jetpack_comment_form_enabled_for_' . get_post_type(), true ) ) {
205
			return;
206
		}
207
208
		// Throw it all out and drop in our replacement
209
		ob_end_clean();
210
211
		// If users are required to be logged in, and they're not, then we don't need to do anything else
212
		if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
213
			/**
214
			 * Changes the log in to comment prompt.
215
			 *
216
			 * @module comments
217
			 *
218
			 * @since  1.4.0
219
			 *
220
			 * @param string $var Default is "You must log in to post a comment."
221
			 */
222
			echo '<p class="must-log-in">' . sprintf( apply_filters( 'jetpack_must_log_in_to_comment', __( 'You must <a href="%s">log in</a> to post a comment.', 'jetpack' ) ), wp_login_url( get_permalink() . '#respond' ) ) . '</p>';
223
224
			return;
225
		}
226
227
		if ( in_array( 'subscriptions', Jetpack::get_active_modules() ) ) {
228
			$stb_enabled = get_option( 'stb_enabled', 1 );
229
			$stb_enabled = empty( $stb_enabled ) ? 0 : 1;
230
231
			$stc_enabled = get_option( 'stc_enabled', 1 );
232
			$stc_enabled = empty( $stc_enabled ) ? 0 : 1;
233
		} else {
234
			$stb_enabled = 0;
235
			$stc_enabled = 0;
236
		}
237
238
		$params = array(
239
			'blogid'               => Jetpack_Options::get_option( 'id' ),
240
			'postid'               => get_the_ID(),
241
			'comment_registration' => ( get_option( 'comment_registration' ) ? '1' : '0' ), // Need to explicitly send a '1' or a '0' for these
242
			'require_name_email'   => ( get_option( 'require_name_email' ) ? '1' : '0' ),
243
			'stc_enabled'          => $stc_enabled,
244
			'stb_enabled'          => $stb_enabled,
245
			'show_avatars'         => ( get_option( 'show_avatars' ) ? '1' : '0' ),
246
			'avatar_default'       => get_option( 'avatar_default' ),
247
			'greeting'             => get_option( 'highlander_comment_form_prompt', __( 'Leave a Reply', 'jetpack' ) ),
248
			/**
249
			 * Changes the comment form prompt.
250
			 *
251
			 * @module comments
252
			 *
253
			 * @since  2.3.0
254
			 *
255
			 * @param string $var Default is "Leave a Reply to %s."
256
			 */
257
			'greeting_reply'       => apply_filters( 'jetpack_comment_form_prompt_reply', __( 'Leave a Reply to %s', 'jetpack' ) ),
258
			'color_scheme'         => get_option( 'jetpack_comment_form_color_scheme', $this->default_color_scheme ),
259
			'lang'                 => get_locale(),
260
			'jetpack_version'      => JETPACK__VERSION,
261
		);
262
263
		// Extra parameters for logged in user
264
		if ( is_user_logged_in() ) {
265
			$current_user           = wp_get_current_user();
266
			$params['hc_post_as']   = 'jetpack';
267
			$params['hc_userid']    = $current_user->ID;
268
			$params['hc_username']  = $current_user->display_name;
269
			$params['hc_userurl']   = $current_user->user_url;
270
			$params['hc_useremail'] = md5( strtolower( trim( $current_user->user_email ) ) );
271
			if ( current_user_can( 'unfiltered_html' ) ) {
272
				$params['_wp_unfiltered_html_comment'] = wp_create_nonce( 'unfiltered-html-comment_' . get_the_ID() );
273
			}
274
		} else {
275
			$commenter                     = wp_get_current_commenter();
276
			$params['show_cookie_consent'] = (int) has_action( 'set_comment_cookies', 'wp_set_comment_cookies' );
277
			$params['has_cookie_consent']  = (int) ! empty( $commenter['comment_author_email'] );
278
		}
279
280
		$blog_token = Jetpack_Data::get_access_token();
281
		list( $token_key ) = explode( '.', $blog_token->secret, 2 );
282
		// Prophylactic check: anything else should never happen.
283
		if ( $token_key && $token_key !== $blog_token->secret ) {
284
			// Is the token a Special Token (@see class.jetpack-data.php)?
285
			if ( preg_match( '/^;.\d+;\d+;$/', $token_key, $matches ) ) {
286
				// The token key for a Special Token is public.
287
				$params['token_key'] = $token_key;
288
			} else {
289
				/*
290
				 * The token key for a Normal Token is public but
291
				 * looks like sensitive data. Since there can only be
292
				 * one Normal Token per site, avoid concern by
293
				 * sending the magic "use the Normal Token" token key.
294
				 */
295
				$params['token_key'] = Connection_Manager::MAGIC_NORMAL_TOKEN_KEY;
296
			}
297
		}
298
299
		$signature = Jetpack_Comments::sign_remote_comment_parameters( $params, $blog_token->secret );
300
		if ( is_wp_error( $signature ) ) {
301
			$signature = 'error';
302
		}
303
304
		$params['sig']    = $signature;
305
		$url_origin       = 'https://jetpack.wordpress.com';
306
		$url              = "{$url_origin}/jetpack-comment/?" . http_build_query( $params );
307
		$url              = "{$url}#parent=" . urlencode( set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) );
308
		$this->signed_url = $url;
309
		$height           = $params['comment_registration'] || is_user_logged_in() ? '315' : '430'; // Iframe can be shorter if we're not allowing guest commenting
310
		$transparent      = ( $params['color_scheme'] == 'transparent' ) ? 'true' : 'false';
311
312
		if ( isset( $_GET['replytocom'] ) ) {
313
			$url .= '&replytocom=' . (int) $_GET['replytocom'];
314
		}
315
316
		/**
317
		 * Filter whether the comment title can be displayed.
318
		 *
319
		 * @module comments
320
		 *
321
		 * @since  4.7.0
322
		 *
323
		 * @param bool $show Can the comment be displayed? Default to true.
324
		 */
325
		$show_greeting = apply_filters( 'jetpack_comment_form_display_greeting', true );
326
327
		// The actual iframe (loads comment form from Jetpack server)
328
329
		$is_amp = Jetpack_AMP_Support::is_amp_request();
330
		?>
331
332
		<div id="respond" class="comment-respond">
333
			<?php if ( true === $show_greeting ) : ?>
334
				<h3 id="reply-title" class="comment-reply-title"><?php comment_form_title( esc_html( $params['greeting'] ), esc_html( $params['greeting_reply'] ) ); ?>
335
					<small><?php cancel_comment_reply_link( esc_html__( 'Cancel reply', 'jetpack' ) ); ?></small>
336
				</h3>
337
			<?php endif; ?>
338
			<form id="commentform" class="comment-form">
339
				<iframe
340
					title="<?php esc_attr_e( 'Comment Form', 'jetpack' ); ?>"
341
					src="<?php echo esc_url( $url ); ?>"
342
					<?php if ( $is_amp ) : ?>
343
						resizable
344
						layout="fixed-height"
345
						height="<?php echo esc_attr( $height ); ?>"
346
					<?php else : ?>
347
						name="jetpack_remote_comment"
348
						style="width:100%; height: <?php echo esc_attr( $height ); ?>px; border:0;"
349
					<?php endif; ?>
350
					class="jetpack_remote_comment"
351
					id="jetpack_remote_comment"
352
					sandbox="allow-same-origin allow-top-navigation allow-scripts allow-forms allow-popups"
353
				>
354
					<?php if ( $is_amp ) : ?>
355
						<button overflow><?php esc_html_e( 'Show more', 'jetpack' ); ?></button>
356
					<?php endif; ?>
357
				</iframe>
358
				<?php if ( ! $is_amp ) : ?>
359
					<!--[if !IE]><!-->
360
					<script>
361
						document.addEventListener('DOMContentLoaded', function () {
362
							var commentForms = document.getElementsByClassName('jetpack_remote_comment');
363
							for (var i = 0; i < commentForms.length; i++) {
364
								commentForms[i].allowTransparency = <?php echo $transparent; ?>;
365
								commentForms[i].scrolling = 'no';
366
							}
367
						});
368
					</script>
369
					<!--<![endif]-->
370
				<?php endif; ?>
371
			</form>
372
		</div>
373
374
		<?php // Below is required for comment reply JS to work ?>
375
376
		<input type="hidden" name="comment_parent" id="comment_parent" value="" />
377
378
		<?php
379
	}
380
381
	/**
382
	 * Add some JS to wp_footer to watch for hierarchical reply parent change
383
	 *
384
	 * @since JetpackComments (1.4)
385
	 */
386
	public function watch_comment_parent() {
387
		if ( Jetpack_AMP_Support::is_amp_request() ) {
388
			// @todo Implement AMP support.
389
			return;
390
		}
391
392
		$url_origin = 'https://jetpack.wordpress.com';
393
		?>
394
395
		<!--[if IE]>
396
		<script type="text/javascript">
397
			if ( 0 === window.location.hash.indexOf( '#comment-' ) ) {
398
				// window.location.reload() doesn't respect the Hash in IE
399
				window.location.hash = window.location.hash;
400
			}
401
		</script>
402
		<![endif]-->
403
		<script type="text/javascript">
404
			(function () {
405
				var comm_par_el = document.getElementById( 'comment_parent' ),
406
					comm_par = ( comm_par_el && comm_par_el.value ) ? comm_par_el.value : '',
407
					frame = document.getElementById( 'jetpack_remote_comment' ),
408
					tellFrameNewParent;
409
410
				tellFrameNewParent = function () {
411
					if ( comm_par ) {
412
						frame.src = "<?php echo esc_url_raw( $this->signed_url ); ?>" + '&replytocom=' + parseInt( comm_par, 10 ).toString();
413
					} else {
414
						frame.src = "<?php echo esc_url_raw( $this->signed_url ); ?>";
415
					}
416
				};
417
418
				<?php if ( get_option( 'thread_comments' ) && get_option( 'thread_comments_depth' ) ) : ?>
419
420
				if ( 'undefined' !== typeof addComment ) {
421
					addComment._Jetpack_moveForm = addComment.moveForm;
422
423
					addComment.moveForm = function ( commId, parentId, respondId, postId ) {
424
						var returnValue = addComment._Jetpack_moveForm( commId, parentId, respondId, postId ),
425
							cancelClick, cancel;
426
427
						if ( false === returnValue ) {
428
							cancel = document.getElementById( 'cancel-comment-reply-link' );
429
							cancelClick = cancel.onclick;
430
							cancel.onclick = function () {
431
								var cancelReturn = cancelClick.call( this );
432
								if ( false !== cancelReturn ) {
433
									return cancelReturn;
434
								}
435
436
								if ( ! comm_par ) {
437
									return cancelReturn;
438
								}
439
440
								comm_par = 0;
441
442
								tellFrameNewParent();
443
444
								return cancelReturn;
445
							};
446
						}
447
448
						if ( comm_par == parentId ) {
449
							return returnValue;
450
						}
451
452
						comm_par = parentId;
453
454
						tellFrameNewParent();
455
456
						return returnValue;
457
					};
458
				}
459
460
				<?php endif; ?>
461
462
				// Do the post message bit after the dom has loaded.
463
				document.addEventListener( 'DOMContentLoaded', function () {
464
					var iframe_url = <?php echo json_encode( esc_url_raw( $url_origin ) ); ?>;
465
					if ( window.postMessage ) {
466
						if ( document.addEventListener ) {
467
							window.addEventListener( 'message', function ( event ) {
468
								var origin = event.origin.replace( /^http:\/\//i, 'https://' );
469
								if ( iframe_url.replace( /^http:\/\//i, 'https://' ) !== origin ) {
470
									return;
471
								}
472
								jQuery( frame ).height( event.data );
473
							});
474
						} else if ( document.attachEvent ) {
475
							window.attachEvent( 'message', function ( event ) {
476
								var origin = event.origin.replace( /^http:\/\//i, 'https://' );
477
								if ( iframe_url.replace( /^http:\/\//i, 'https://' ) !== origin ) {
478
									return;
479
								}
480
								jQuery( frame ).height( event.data );
481
							});
482
						}
483
					}
484
				})
485
486
			})();
487
		</script>
488
489
		<?php
490
	}
491
492
	/**
493
	 * Verify the hash included in remote comments.
494
	 *
495
	 * @since JetpackComments (1.4)
496
	 *
497
	 * @param type $comment Not used
498
	 */
499
	public function pre_comment_on_post( $comment ) {
500
		$post_array = stripslashes_deep( $_POST );
501
502
		// Bail if missing the Jetpack token
503
		if ( ! isset( $post_array['sig'] ) || ! isset( $post_array['token_key'] ) ) {
504
			unset( $_POST['hc_post_as'] );
505
506
			return;
507
		}
508
509
		if ( false !== strpos( $post_array['hc_avatar'], '.gravatar.com' ) ) {
510
			$post_array['hc_avatar'] = htmlentities( $post_array['hc_avatar'] );
511
		}
512
513
		$blog_token = Jetpack_Data::get_access_token( false, $post_array['token_key'] );
514
		if ( ! $blog_token ) {
515
			wp_die( __( 'Unknown security token.', 'jetpack' ), 400 );
516
		}
517
		$check = Jetpack_Comments::sign_remote_comment_parameters( $post_array, $blog_token->secret );
518
		if ( is_wp_error( $check ) ) {
519
			wp_die( $check );
520
		}
521
522
		// Bail if token is expired or not valid
523
		if ( ! hash_equals( $check, $post_array['sig'] ) ) {
524
			wp_die( __( 'Invalid security token.', 'jetpack' ), 400 );
525
		}
526
527
		/** This filter is documented in modules/comments/comments.php */
528
		if ( ! apply_filters( 'jetpack_comment_form_enabled_for_' . get_post_type( $post_array['comment_post_ID'] ), true ) ) {
529
			// In case the comment POST is legit, but the comments are
530
			// now disabled, we don't allow the comment
531
532
			wp_die( __( 'Comments are not allowed.', 'jetpack' ), 403 );
533
		}
534
	}
535
536
	/** Capabilities **********************************************************/
537
538
	/**
539
	 * Add some additional comment meta after comment is saved about what
540
	 * service the comment is from, the avatar, user_id, etc...
541
	 *
542
	 * @since JetpackComments (1.4)
543
	 *
544
	 * @param type $comment_id
545
	 */
546
	public function add_comment_meta( $comment_id ) {
547
		$comment_meta = array();
548
549
		switch ( $this->is_highlander_comment_post() ) {
550 View Code Duplication
			case 'facebook':
551
				$comment_meta['hc_post_as']         = 'facebook';
552
				$comment_meta['hc_avatar']          = stripslashes( $_POST['hc_avatar'] );
553
				$comment_meta['hc_foreign_user_id'] = stripslashes( $_POST['hc_userid'] );
554
				break;
555
556 View Code Duplication
			case 'twitter':
557
				$comment_meta['hc_post_as']         = 'twitter';
558
				$comment_meta['hc_avatar']          = stripslashes( $_POST['hc_avatar'] );
559
				$comment_meta['hc_foreign_user_id'] = stripslashes( $_POST['hc_userid'] );
560
				break;
561
562
			// phpcs:ignore WordPress.WP.CapitalPDangit
563
			case 'wordpress':
564
				// phpcs:ignore WordPress.WP.CapitalPDangit
565
				$comment_meta['hc_post_as']         = 'wordpress';
566
				$comment_meta['hc_avatar']          = stripslashes( $_POST['hc_avatar'] );
567
				$comment_meta['hc_foreign_user_id'] = stripslashes( $_POST['hc_userid'] );
568
				$comment_meta['hc_wpcom_id_sig']    = stripslashes( $_POST['hc_wpcom_id_sig'] ); //since 1.9
569
				break;
570
571 View Code Duplication
			case 'jetpack':
572
				$comment_meta['hc_post_as']         = 'jetpack';
573
				$comment_meta['hc_avatar']          = stripslashes( $_POST['hc_avatar'] );
574
				$comment_meta['hc_foreign_user_id'] = stripslashes( $_POST['hc_userid'] );
575
				break;
576
577
		}
578
579
		// Bail if no extra comment meta
580
		if ( empty( $comment_meta ) ) {
581
			return;
582
		}
583
584
		// Loop through extra meta and add values
585
		foreach ( $comment_meta as $key => $value ) {
586
			add_comment_meta( $comment_id, $key, $value, true );
587
		}
588
	}
589
590
	function capture_comment_post_redirect_to_reload_parent_frame( $url ) {
591
		if ( ! isset( $_GET['for'] ) || 'jetpack' != $_GET['for'] ) {
592
			return $url;
593
		}
594
		?>
595
		<!DOCTYPE html>
596
		<html <?php language_attributes(); ?>>
597
		<!--<![endif]-->
598
		<head>
599
			<meta charset="<?php bloginfo( 'charset' ); ?>" />
600
			<title><?php printf( __( 'Submitting Comment%s', 'jetpack' ), '&hellip;' ); ?></title>
601
			<style type="text/css">
602
				body {
603
					display: table;
604
					width: 100%;
605
					height: 60%;
606
					position: absolute;
607
					top: 0;
608
					left: 0;
609
					overflow: hidden;
610
					color: #333;
611
				}
612
613
				h1 {
614
					text-align: center;
615
					margin: 0;
616
					padding: 0;
617
					display: table-cell;
618
					vertical-align: middle;
619
					font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif;
620
					font-weight: normal;
621
				}
622
623
				.hidden {
624
					opacity: 0;
625
				}
626
627
				h1 span {
628
					-moz-transition-property: opacity;
629
					-moz-transition-duration: 1s;
630
					-moz-transition-timing-function: ease-in-out;
631
632
					-webkit-transition-property: opacity;
633
					-webkit-transition-duration: 1s;
634
					-webbit-transition-timing-function: ease-in-out;
635
636
					-o-transition-property: opacity;
637
					-o-transition-duration: 1s;
638
					-o-transition-timing-function: ease-in-out;
639
640
					-ms-transition-property: opacity;
641
					-ms-transition-duration: 1s;
642
					-ms-transition-timing-function: ease-in-out;
643
644
					transition-property: opacity;
645
					transition-duration: 1s;
646
					transition-timing-function: ease-in-out;
647
				}
648
			</style>
649
		</head>
650
		<body>
651
		<h1><?php printf( __( 'Submitting Comment%s', 'jetpack' ), '<span id="ellipsis" class="hidden">&hellip;</span>' ); ?></h1>
652
		<script type="text/javascript">
653
			try {
654
				window.parent.location = <?php echo json_encode( $url ); ?>;
655
				window.parent.location.reload(true);
656
			} catch (e) {
657
				window.location = <?php echo json_encode( $url ); ?>;
658
				window.location.reload(true);
659
			}
660
			ellipsis = document.getElementById('ellipsis');
661
662
			function toggleEllipsis() {
663
				ellipsis.className = ellipsis.className ? '' : 'hidden';
664
			}
665
666
			setInterval(toggleEllipsis, 1200);
667
		</script>
668
		</body>
669
		</html>
670
		<?php
671
		exit;
672
	}
673
}
674
675
Jetpack_Comments::init();
676