PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 6.4
Jetpack – WP Security, Backup, Speed, & Growth v6.4
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 All 500 releases
← All changes | modules/comments/base.php +102 -134 13.2.46.4 View file →
@@ -1,22 +1,11 @@
1 -<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 -/**
3 - * Jetpack comments base file - where the code shared between WP.com Highlander and Jetpack Highlander is defined
4 - *
5 - * @package automattic/jetpack
6 - */
1 +<?php
7 2
8 -use Automattic\Jetpack\Image_CDN\Image_CDN_Core;
9 -
10 3 /**
11 4 * All the code shared between WP.com Highlander and Jetpack Highlander
12 5 */
13 6 class Highlander_Comments_Base {
14 -
15 - /**
16 - * Constructor
17 - */
18 - public function __construct() {
7 + function __construct() {
19 8 $this->setup_globals();
20 9 $this->setup_actions();
21 10 $this->setup_filters();
22 11 }
@@ -22,76 +11,69 @@
22 11 }
23 12
24 13 /**
25 14 * Set any global variables or class variables
26 - *
27 - * @since 1.4
15 + * @since JetpackComments (1.4)
28 16 */
29 17 protected function setup_globals() {}
30 18
31 19 /**
32 20 * Setup actions for methods in this class
33 - *
34 - * @since 1.4
21 + * @since JetpackComments (1.4)
35 22 */
36 23 protected function setup_actions() {
37 - // Before a comment is posted.
24 + // Before a comment is posted
38 25 add_action( 'pre_comment_on_post', array( $this, 'allow_logged_out_user_to_comment_as_external' ) );
39 26
40 - // After a comment is posted.
27 + // After a comment is posted
41 28 add_action( 'comment_post', array( $this, 'set_comment_cookies' ) );
42 29 }
43 30
44 31 /**
45 32 * Setup filters for methods in this class
46 - *
47 - * @since 1.4
33 + * @since JetpackComments (1.4)
48 34 */
49 35 protected function setup_filters() {
50 - add_filter( 'comments_array', array( $this, 'comments_array' ) );
36 + add_filter( 'comments_array', array( $this, 'comments_array' ) );
51 37 add_filter( 'preprocess_comment', array( $this, 'allow_logged_in_user_to_comment_as_guest' ), 0 );
52 38 }
53 39
54 40 /**
55 41 * Is this a Highlander POST request?
56 - * Optionally restrict to one or more credentials slug (facebook, ...)
42 + * Optionally restrict to one or more credentials slug (facebook, twitter, ...)
57 43 *
58 - * @param mixed ...$args Comments credentials slugs.
44 + * @param string Comment credentials slug
45 + * @param ...
59 46 * @return false|string false if it's not a Highlander POST request. The matching credentials slug if it is.
60 47 */
61 - public function is_highlander_comment_post( ...$args ) {
62 -
63 - // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verification should happen in Jetpack_Comments::pre_comment_on_post(). Internal ref for details: p1645643468937519/1645189749.180299-slack-C02HQGKMFJ8
48 + function is_highlander_comment_post() {
64 49 if ( empty( $_POST['hc_post_as'] ) ) {
65 50 return false;
66 51 }
67 - $hc_post_as = wp_unslash( $_POST['hc_post_as'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized here by comparing against known values.
68 - // phpcs:enable WordPress.Security.NonceVerification.Missing
69 52
70 - if ( $args ) {
71 - foreach ( $args as $id_source ) {
72 - if ( $id_source === $hc_post_as ) {
53 + if ( func_num_args() ) {
54 + foreach ( func_get_args() as $id_source ) {
55 + if ( $id_source === $_POST['hc_post_as'] ) {
73 56 return $id_source;
74 57 }
75 58 }
76 59 return false;
77 60 }
78 - return is_string( $hc_post_as ) && in_array( $hc_post_as, $this->id_sources, true ) ? $hc_post_as : false;
61 +
62 + return is_string( $_POST['hc_post_as'] ) && in_array( $_POST['hc_post_as'], $this->id_sources ) ? $_POST['hc_post_as'] : false;
79 63 }
80 64
81 65 /**
82 66 * Signs an array of scalars with the self-hosted blog's Jetpack Token
83 67 *
84 - * If parameter values are not scalars a WP_Error is returned, otherwise a keyed hash value is returned using the HMAC method.
85 - *
86 - * @param array $parameters Comment parameters.
87 - * @param string $key Key used for generating the HMAC variant of the message digest.
68 + * @param array $parameters
69 + * @param string $key
88 70 * @return string HMAC
89 71 */
90 - public static function sign_remote_comment_parameters( $parameters, $key ) {
72 + static function sign_remote_comment_parameters( $parameters, $key ) {
91 73 unset(
92 - $parameters['sig'], // Don't sign the signature.
93 - $parameters['replytocom'] // This parameter is unsigned - it changes dynamically as the comment form moves from parent comment to parent comment.
74 + $parameters['sig'], // Don't sign the signature
75 + $parameters['replytocom'] // This parameter is unsigned - it changes dynamically as the comment form moves from parent comment to parent comment
94 76 );
95 77
96 78 ksort( $parameters );
97 79
@@ -96,10 +78,10 @@
96 78 ksort( $parameters );
97 79
98 80 $signing = array();
99 81 foreach ( $parameters as $k => $v ) {
100 - if ( ! is_scalar( $v ) ) {
101 - return new WP_Error( 'invalid_input', __( 'Invalid request', 'jetpack' ), array( 'status' => 400 ) );
82 + if ( !is_scalar( $v ) ) {
83 + return new WP_Error( 'invalid_input', __( 'Invalid request', 'jetpack' ) );
102 84 }
103 85
104 86 $signing[] = "{$k}={$v}";
105 87 }
@@ -106,44 +88,39 @@
106 88
107 89 return hash_hmac( 'sha1', implode( ':', $signing ), $key );
108 90 }
109 91
110 - /**
111 - * Adds comment author email and whether the comment is approved to the comments array
92 + /*
93 + * After commenting as a guest while logged in, the user needs to see both:
112 94 *
113 - * After commenting as a guest while logged in, the user needs to see both:
114 95 * ( user_id = blah AND comment_approved = 0 )
115 - * and ( comment_author_email = blah AND comment_approved = 0 )
116 - * Core only does the first since the user is logged in, so this adds the second to the comments array.
96 + * and
97 + * ( comment_author_email = blah AND comment_approved = 0 )
117 98 *
118 - * @param array $comments All comment data.
119 - * @return array A modified array of comment data.
120 - */
121 - public function comments_array( $comments ) {
99 + * Core only does the first since the user is logged in.
100 + *
101 + * Add the second to the comments array.
102 + */
103 + function comments_array( $comments ) {
122 104 global $wpdb, $post;
123 105
124 106 $commenter = $this->get_current_commenter();
125 107
126 - if ( ! $commenter['user_id'] ) {
108 + if ( !$commenter['user_id'] )
127 109 return $comments;
128 - }
129 110
130 - if ( ! $commenter['comment_author'] ) {
111 + if ( !$commenter['comment_author'] )
131 112 return $comments;
132 - }
133 113
134 - $in_moderation_comments = $wpdb->get_results(
135 - $wpdb->prepare(
136 - "SELECT * FROM `$wpdb->comments` WHERE `comment_post_ID` = %d AND `user_id` = 0 AND `comment_author` = %s AND `comment_author_email` = %s AND `comment_approved` = '0' ORDER BY `comment_date_gmt` /* Highlander_Comments_Base::comments_array() */",
137 - $post->ID,
138 - wp_specialchars_decode( $commenter['comment_author'], ENT_QUOTES ),
139 - $commenter['comment_author_email']
140 - )
141 - );
114 + $in_moderation_comments = $wpdb->get_results( $wpdb->prepare(
115 + "SELECT * FROM `$wpdb->comments` WHERE `comment_post_ID` = %d AND `user_id` = 0 AND `comment_author` = %s AND `comment_author_email` = %s AND `comment_approved` = '0' ORDER BY `comment_date_gmt` /* Highlander_Comments_Base::comments_array() */",
116 + $post->ID,
117 + wp_specialchars_decode( $commenter['comment_author'], ENT_QUOTES ),
118 + $commenter['comment_author_email']
119 + ) );
142 120
143 - if ( ! $in_moderation_comments ) {
121 + if ( !$in_moderation_comments )
144 122 return $comments;
145 - }
146 123
147 124 // @todo ZOMG this is a bad idea
148 125 $comments = array_merge( $comments, $in_moderation_comments );
149 126 usort( $comments, array( $this, 'sort_comments_by_comment_date_gmt' ) );
@@ -153,40 +130,44 @@
153 130
154 131 /**
155 132 * Comment sort comparator: comment_date_gmt
156 133 *
157 - * @since 1.4
158 - * @param object $a The first comment to compare dates with.
159 - * @param object $b The second comment to compare dates with.
134 + * @since JetpackComments (1.4)
135 + * @param object $a
136 + * @param object $b
160 137 * @return int
161 138 */
162 139 public function sort_comments_by_comment_date_gmt( $a, $b ) {
163 - return $a->comment_date_gmt <=> $b->comment_date_gmt;
140 + if ( $a->comment_date_gmt == $b->comment_date_gmt ) {
141 + return 0;
142 + }
143 +
144 + return $a->comment_date_gmt < $b->comment_date_gmt ? -1 : 1;
164 145 }
165 146
166 147 /**
167 148 * Get the current commenter's information from their cookie
168 149 *
169 - * @since 1.4
150 + * @since JetpackComments (1.4)
170 151 * @return array Commenters information from cookie
171 152 */
172 153 protected function get_current_commenter() {
173 - // Defaults.
154 + // Defaults
174 155 $user_id = 0;
175 156 $comment_author = '';
176 157 $comment_author_email = '';
177 158 $comment_author_url = '';
178 159
179 - if ( isset( $_COOKIE[ 'comment_author_' . COOKIEHASH ] ) ) {
180 - $comment_author = sanitize_text_field( wp_unslash( $_COOKIE[ 'comment_author_' . COOKIEHASH ] ) );
160 + if ( isset( $_COOKIE['comment_author_' . COOKIEHASH] ) ) {
161 + $comment_author = $_COOKIE['comment_author_' . COOKIEHASH];
181 162 }
182 163
183 - if ( isset( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] ) ) {
184 - $comment_author_email = sanitize_email( wp_unslash( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] ) );
164 + if ( isset( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) {
165 + $comment_author_email = $_COOKIE['comment_author_email_' . COOKIEHASH];
185 166 }
186 167
187 - if ( isset( $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] ) ) {
188 - $comment_author_url = esc_url_raw( wp_unslash( $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] ) );
168 + if ( isset( $_COOKIE['comment_author_url_' . COOKIEHASH] ) ) {
169 + $comment_author_url = $_COOKIE['comment_author_url_' . COOKIEHASH];
189 170 }
190 171
191 172 if ( is_user_logged_in() ) {
192 173 $user = wp_get_current_user();
@@ -196,87 +177,74 @@
196 177 return compact( 'comment_author', 'comment_author_email', 'comment_author_url', 'user_id' );
197 178 }
198 179
199 180 /**
200 - * Allows a logged out user to leave a comment as a facebook/wp.com credentialed user.
181 + * Allows a logged out user to leave a comment as a facebook or twitter credentialed user.
201 182 * Overrides WordPress' core comment_registration option to treat these commenters as "registered" (verified) users.
202 183 *
203 - * @since 1.4
184 + * @since JetpackComments (1.4)
185 + * @return If no
204 186 */
205 - public function allow_logged_out_user_to_comment_as_external() {
206 - // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText
207 - if ( ! $this->is_highlander_comment_post( 'facebook', 'wordpress' ) ) {
187 + function allow_logged_out_user_to_comment_as_external() {
188 + if ( !$this->is_highlander_comment_post( 'facebook', 'twitter', 'googleplus' ) ) {
208 189 return;
209 190 }
210 191
211 192 add_filter( 'pre_option_comment_registration', '__return_zero' );
212 - add_filter( 'pre_option_require_name_email', '__return_zero' );
213 193 }
214 194
215 195 /**
216 - * Allow a logged in user to post as a guest, or FB credentialed request.
196 + * Allow a logged in user to post as a guest, FB, or twitter credentialed request.
217 197 * Bypasses WordPress' core overrides that force a logged in user to comment as that user.
218 198 * Respects comment_registration option.
219 199 *
220 - * @since 1.4
221 - * @param array $comment_data All data for a specific comment.
222 - * @return array Modified comment data, or an error if the required fields or a valid email address are not entered.
200 + * @since JetpackComments (1.4)
201 + * @param array $comment_data
202 + * @return int
223 203 */
224 - public function allow_logged_in_user_to_comment_as_guest( $comment_data ) {
225 - // Bail if user registration is allowed.
204 + function allow_logged_in_user_to_comment_as_guest( $comment_data ) {
205 + // Bail if user registration is allowed
226 206 if ( get_option( 'comment_registration' ) ) {
227 207 return $comment_data;
228 208 }
229 209
230 - // Bail if user is not logged in or not a post request.
231 - if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) || ! is_user_logged_in() ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- simple comparison
210 + // Bail if user is not logged in or not a post request
211 + if ( 'POST' != strtoupper( $_SERVER['REQUEST_METHOD'] ) || !is_user_logged_in() ) {
232 212 return $comment_data;
233 213 }
234 214
235 - // Bail if this is not a guest or external service credentialed request.
236 - if ( ! $this->is_highlander_comment_post( 'guest', 'facebook' ) ) {
215 + // Bail if this is not a guest or external service credentialed request
216 + if ( !$this->is_highlander_comment_post( 'guest', 'facebook', 'twitter', 'googleplus' ) ) {
237 217 return $comment_data;
238 218 }
239 219
240 220 $user = wp_get_current_user();
241 221
242 - foreach ( array(
243 - 'comment_author' => 'display_name',
244 - 'comment_author_email' => 'user_email',
245 - 'comment_author_url' => 'user_url',
246 - ) as $comment_field => $user_field ) {
247 - if ( addslashes( $user->$user_field ) !== $comment_data[ $comment_field ] ) {
248 - return $comment_data; // some other plugin already did something funky.
222 + foreach ( array( 'comment_author' => 'display_name', 'comment_author_email' => 'user_email', 'comment_author_url' => 'user_url' ) as $comment_field => $user_field ) {
223 + if ( $comment_data[$comment_field] != addslashes( $user->$user_field ) ) {
224 + return $comment_data; // some other plugin already did something funky
249 225 }
250 226 }
251 227
252 - // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verification should happen in Jetpack_Comments::pre_comment_on_post()
253 - // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitization too
254 228 if ( get_option( 'require_name_email' ) ) {
255 - if ( isset( $_POST['email'] ) && 6 > strlen( wp_unslash( $_POST['email'] ) ) || empty( $_POST['author'] ) ) {
256 - wp_die( esc_html__( 'Error: please fill the required fields (name, email).', 'jetpack' ), 400 );
257 - } elseif ( ! isset( $_POST['email'] ) || ! is_email( wp_unslash( $_POST['email'] ) ) ) {
258 - wp_die( esc_html__( 'Error: please enter a valid email address.', 'jetpack' ), 400 );
229 + if ( 6 > strlen( $_POST['email'] ) || empty( $_POST['author'] ) ) {
230 + wp_die( __( 'Error: please fill the required fields (name, email).', 'jetpack' ) );
231 + } elseif ( ! is_email( $_POST['email'] ) ) {
232 + wp_die( __( 'Error: please enter a valid email address.', 'jetpack' ) );
259 233 }
260 234 }
261 235
262 236 $author_change = false;
263 - foreach ( array(
264 - 'comment_author' => 'author',
265 - 'comment_author_email' => 'email',
266 - 'comment_author_url' => 'url',
267 - ) as $comment_field => $post_field ) {
268 - if ( ( ! isset( $_POST[ $post_field ] ) || $comment_data[ $comment_field ] !== $_POST[ $post_field ] ) && 'url' !== $post_field ) {
237 + foreach ( array( 'comment_author' => 'author', 'comment_author_email' => 'email', 'comment_author_url' => 'url' ) as $comment_field => $post_field ) {
238 + if ( $comment_data[$comment_field] != $_POST[$post_field] && 'url' != $post_field ) {
269 239 $author_change = true;
270 240 }
271 - $comment_data[ $comment_field ] = isset( $_POST[ $post_field ] ) ? wp_unslash( $_POST[ $post_field ] ) : null;
241 + $comment_data[$comment_field] = $_POST[$post_field];
272 242 }
273 - // phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
274 243
275 - // Mark as guest comment if name or email were changed.
244 + // Mark as guest comment if name or email were changed
276 245 if ( $author_change ) {
277 - $comment_data['user_ID'] = 0;
278 - $comment_data['user_id'] = $comment_data['user_ID'];
246 + $comment_data['user_id'] = $comment_data['user_ID'] = 0;
279 247 }
280 248
281 249 return $comment_data;
282 250 }
@@ -283,13 +251,14 @@
283 251
284 252 /**
285 253 * Set the comment cookies or bail if comment is invalid
286 254 *
287 - * @since 1.4
288 - * @param int $comment_id The comment ID.
255 + * @since JetpackComments (1.4)
256 + * @param type $comment_id
257 + * @return If comment is invalid
289 258 */
290 259 public function set_comment_cookies( $comment_id ) {
291 - // Get comment and bail if it's invalid somehow.
260 + // Get comment and bail if it's invalid somehow
292 261 $comment = get_comment( $comment_id );
293 262 if ( empty( $comment ) || is_wp_error( $comment ) ) {
294 263 return;
295 264 }
@@ -298,29 +267,28 @@
298 267 if ( empty( $id_source ) ) {
299 268 return;
300 269 }
301 270
302 - // Set comment author cookies.
303 - // phpcs:ignore WordPress.WP.CapitalPDangit
304 - if ( ( 'wordpress' !== $id_source ) && is_user_logged_in() ) {
271 + // Set comment author cookies
272 + if ( ( 'wordpress' != $id_source ) && is_user_logged_in() ) {
305 273 /** This filter is already documented in core/wp-includes/comment-functions.php */
306 274 $comment_cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
307 - setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
308 - setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
309 - setcookie( 'comment_author_url_' . COOKIEHASH, esc_url( $comment->comment_author_url ), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
275 + setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN );
276 + setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN );
277 + setcookie( 'comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN );
310 278 }
311 279 }
312 280
313 281 /**
314 - * Get an avatar from Photon
315 - *
316 - * @since 1.4
317 - * @param string $url The avatar URL.
318 - * @param int $size The avatar size.
319 - * @return string
320 - */
282 + * Get an avatar from Photon
283 + *
284 + * @since JetpackComments (1.4)
285 + * @param string $url
286 + * @param int $size
287 + * @return string
288 + */
321 289 protected function photon_avatar( $url, $size ) {
322 290 $size = (int) $size;
323 291
324 - return Image_CDN_Core::cdn_url( $url, array( 'resize' => "$size,$size" ) );
292 + return jetpack_photon_url( $url, array( 'resize' => "$size,$size" ) );
325 293 }
326 294 }