PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
16.3-a.3 16.3-a.1 16.2 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 All 504 releases
← All changes | modules/carousel/jetpack-carousel.php +128 -77 12.9.516.2 View file →
@@ -7,10 +7,18 @@
7 7
8 8 use Automattic\Jetpack\Assets;
9 9 use Automattic\Jetpack\Stats\Options as Stats_Options;
10 10 use Automattic\Jetpack\Status;
11 +use Automattic\Jetpack\Status\Host;
12 +
13 +if ( ! defined( 'ABSPATH' ) ) {
14 + exit( 0 );
15 +}
16 +
11 17 /**
12 18 * Jetpack_Carousel class.
19 + *
20 + * @phan-constructor-used-for-side-effects
13 21 */
14 22 class Jetpack_Carousel {
15 23 /**
16 24 * Defines Carousel pre-built widths
@@ -42,9 +50,9 @@
42 50 */
43 51 public $in_gallery = false;
44 52
45 53 /**
46 - * Determines whether the Jetpack class and method exists. Default is true.
54 + * Determines whether the module runs in the Jetpack plugin, as opposed to WP.com Simple site environment
47 55 *
48 56 * @var bool
49 57 */
50 58 public $in_jetpack = true;
@@ -77,9 +85,9 @@
77 85 if ( $this->maybe_disable_jp_carousel() ) {
78 86 return;
79 87 }
80 88
81 - $this->in_jetpack = ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'enable_module_configurable' ) ) ? true : false;
89 + $this->in_jetpack = ! ( new Host() )->is_wpcom_simple();
82 90
83 91 $this->single_image_gallery_enabled = ! $this->maybe_disable_jp_carousel_single_images();
84 92 $this->single_image_gallery_enabled_media_file = $this->maybe_enable_jp_carousel_single_images_media_file();
85 93
@@ -122,8 +130,10 @@
122 130 if ( $this->single_image_gallery_enabled ) {
123 131 add_filter( 'the_content', array( $this, 'add_data_img_tags_and_enqueue_assets' ) );
124 132 }
125 133
134 + add_filter( 'render_block_data', array( $this, 'remove_core_lightbox_in_gallery' ), 10, 3 );
135 +
126 136 // `is_amp_request()` can't be called until the 'wp' filter.
127 137 add_action( 'wp', array( $this, 'check_amp_support' ) );
128 138 }
129 139
@@ -334,8 +344,28 @@
334 344 return $content;
335 345 }
336 346
337 347 /**
348 + * Remove core lightbox settings from images in a gallery, if Carousel is enabled.
349 + *
350 + * @param array $parsed_block An associative array of the block being rendered.
351 + * @param array $source_block An un-modified copy of `$parsed_block`, as it appeared in the source content.
352 + * @param WP_Block|null $parent_block If this is a nested block, a reference to the parent block.
353 + * @return array The modified block data.
354 + */
355 + public function remove_core_lightbox_in_gallery( $parsed_block, $source_block, $parent_block ) {
356 + if (
357 + ! empty( $parsed_block['blockName'] ) &&
358 + 'core/image' === $parsed_block['blockName'] &&
359 + ! empty( $parent_block->name ) &&
360 + 'core/gallery' === $parent_block->name
361 + ) {
362 + unset( $parsed_block['attrs']['lightbox'] );
363 + }
364 + return $parsed_block;
365 + }
366 +
367 + /**
338 368 * Enrich the gallery block content using the render_block_{$this->name} filter.
339 369 * This function is triggered after block render to make sure we track galleries within
340 370 * reusable blocks.
341 371 *
@@ -355,9 +385,9 @@
355 385 }
356 386
357 387 $this->enqueue_assets();
358 388
359 - if ( ! isset( $post ) ) {
389 + if ( ! $post instanceof WP_Post ) {
360 390 return $block_content;
361 391 }
362 392
363 393 $blog_id = (int) get_current_blog_id();
@@ -388,9 +418,9 @@
388 418 $extra_attributes = implode(
389 419 ' ',
390 420 array_map(
391 421 function ( $data_key, $data_values ) {
392 - return esc_attr( $data_key ) . "='" . wp_json_encode( $data_values ) . "'";
422 + return esc_attr( $data_key ) . "='" . esc_attr( wp_json_encode( $data_values, JSON_UNESCAPED_SLASHES | JSON_HEX_AMP ) ) . "'";
393 423 },
394 424 array_keys( $extra_data ),
395 425 array_values( $extra_data )
396 426 )
@@ -421,12 +451,9 @@
421 451 true
422 452 );
423 453
424 454 $swiper_library_path = array(
425 - 'url' => Assets::get_file_url_for_environment(
426 - '_inc/build/carousel/swiper-bundle.min.js',
427 - 'modules/carousel/swiper-bundle.js'
428 - ),
455 + 'url' => plugins_url( '_inc/blocks/swiper.js', JETPACK__PLUGIN_FILE ),
429 456 );
430 457 wp_localize_script( 'jetpack-carousel', 'jetpackSwiperLibraryPath', $swiper_library_path );
431 458
432 459 // Note: using home_url() instead of admin_url() for ajaxurl to be sure to get same domain on wpcom when using mapped domains (also works on self-hosted).
@@ -448,8 +475,9 @@
448 475 'comment' => __( 'Comment', 'jetpack' ),
449 476 'post_comment' => __( 'Post Comment', 'jetpack' ),
450 477 'write_comment' => __( 'Write a Comment...', 'jetpack' ),
451 478 'loading_comments' => __( 'Loading Comments...', 'jetpack' ),
479 + 'image_label' => __( 'Open image in full-screen.', 'jetpack' ),
452 480 'download_original' => sprintf(
453 481 /* translators: %1s is the full-size image width, and %2s is the height. */
454 482 __( 'View full size <span class="photo-size">%1$s<span class="photo-size-times">&times;</span>%2$s</span>', 'jetpack' ),
455 483 '{0}',
@@ -513,12 +541,12 @@
513 541 */
514 542 $localize_strings = apply_filters( 'jp_carousel_localize_strings', $localize_strings );
515 543 wp_localize_script( 'jetpack-carousel', 'jetpackCarouselStrings', $localize_strings );
516 544 wp_enqueue_style(
517 - 'jetpack-carousel-swiper-css',
518 - plugins_url( 'swiper-bundle.css', __FILE__ ),
545 + 'jetpack-swiper-library',
546 + plugins_url( '_inc/blocks/swiper.css', JETPACK__PLUGIN_FILE ),
519 547 array(),
520 - $this->asset_version( JETPACK__VERSION )
548 + JETPACK__VERSION
521 549 );
522 550 wp_enqueue_style( 'jetpack-carousel', plugins_url( 'jetpack-carousel.css', __FILE__ ), array(), $this->asset_version( JETPACK__VERSION ) );
523 551 wp_style_add_data( 'jetpack-carousel', 'rtl', 'replace' );
524 552
@@ -554,12 +582,13 @@
554 582 $current_user = wp_get_current_user();
555 583 $require_name_email = (int) get_option( 'require_name_email' );
556 584 /* translators: %s is replaced with a field name in the form, e.g. "Email" */
557 585 $required = ( $require_name_email ) ? __( '%s (Required)', 'jetpack' ) : '%s';
586 + require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-spinner.php';
558 587 ?>
559 - <div id="jp-carousel-loading-overlay">
588 + <div id="jp-carousel-loading-overlay" style="display: none;">
560 589 <div id="jp-carousel-loading-wrapper">
561 - <span id="jp-carousel-library-loading">&nbsp;</span>
590 + <span id="jp-carousel-library-loading"><?php echo Jetpack_Spinner::render( 40 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static SVG markup. ?></span>
562 591 </div>
563 592 </div>
564 593 <div class="jp-carousel-overlay<?php echo( $is_light ? ' jp-carousel-light' : '' ); ?>" style="display: none;">
565 594
@@ -565,9 +594,9 @@
565 594
566 595 <div class="jp-carousel-container<?php echo( $is_light ? ' jp-carousel-light' : '' ); ?>">
567 596 <!-- The Carousel Swiper -->
568 597 <div
569 - class="jp-carousel-wrap swiper-container jp-carousel-swiper-container jp-carousel-transitions"
598 + class="jp-carousel-wrap swiper jp-carousel-swiper-container jp-carousel-transitions"
570 599 itemscope
571 600 itemtype="https://schema.org/ImageGallery">
572 601 <div class="jp-carousel swiper-wrapper"></div>
573 602 <div class="jp-swiper-button-prev swiper-button-prev">
@@ -609,9 +638,9 @@
609 638 <div class="jp-swiper-pagination swiper-pagination"></div>
610 639 <div class="jp-carousel-pagination"></div>
611 640 </div>
612 641 <div class="jp-carousel-photo-title-container">
613 - <h2 class="jp-carousel-photo-caption"></h2>
642 + <div class="jp-carousel-photo-caption"></div>
614 643 </div>
615 644 <div class="jp-carousel-photo-icons-container">
616 645 <a href="#" class="jp-carousel-icon-btn jp-carousel-icon-info" aria-label="<?php esc_attr_e( 'Toggle photo metadata visibility', 'jetpack' ); ?>">
617 646 <span class="jp-carousel-icon">
@@ -645,9 +674,9 @@
645 674 </div>
646 675 <div class="jp-carousel-info-extra">
647 676 <div class="jp-carousel-info-content-wrapper">
648 677 <div class="jp-carousel-photo-title-container">
649 - <h2 class="jp-carousel-photo-title"></h2>
678 + <div class="jp-carousel-photo-title"></div>
650 679 </div>
651 680 <div class="jp-carousel-comments-wrapper">
652 681 <?php if ( $localize_strings['display_comments'] ) : ?>
653 682 <div id="jp-carousel-comments-loading">
@@ -654,9 +683,9 @@
654 683 <span><?php echo esc_html( $localize_strings['loading_comments'] ); ?></span>
655 684 </div>
656 685 <div class="jp-carousel-comments"></div>
657 686 <div id="jp-carousel-comment-form-container">
658 - <span id="jp-carousel-comment-form-spinner">&nbsp;</span>
687 + <span id="jp-carousel-comment-form-spinner"><?php echo Jetpack_Spinner::render( 20 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static SVG markup. ?></span>
659 688 <div id="jp-carousel-comment-post-results"></div>
660 689 <?php if ( $use_local_comments ) : ?>
661 690 <?php if ( ! $localize_strings['is_logged_in'] && $localize_strings['comment_registration'] ) : ?>
662 691 <div id="jp-carousel-comment-form-commenting-as">
@@ -725,15 +754,14 @@
725 754 </div>
726 755 <div class="jp-carousel-image-meta">
727 756 <div class="jp-carousel-title-and-caption">
728 757 <div class="jp-carousel-photo-info">
729 - <h3 class="jp-carousel-caption" itemprop="caption description"></h3>
758 + <div class="jp-carousel-caption" itemprop="caption description"></div>
730 759 </div>
731 760
732 761 <div class="jp-carousel-photo-description"></div>
733 762 </div>
734 - <ul class="jp-carousel-image-exif" style="display: none;"></ul>
735 - <a class="jp-carousel-image-download" href="#" target="_blank" style="display: none;">
763 + <a class="jp-carousel-image-download" href="#" aria-label="<?php esc_attr_e( 'Download image', 'jetpack' ); ?>" target="_blank" style="display: none;">
736 764 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
737 765 <mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="3" width="19" height="18">
738 766 <path fill-rule="evenodd" clip-rule="evenodd" d="M5.84615 5V19H19.7775V12H21.7677V19C21.7677 20.1 20.8721 21 19.7775 21H5.84615C4.74159 21 3.85596 20.1 3.85596 19V5C3.85596 3.9 4.74159 3 5.84615 3H12.8118V5H5.84615ZM14.802 5V3H21.7677V10H19.7775V6.41L9.99569 16.24L8.59261 14.83L18.3744 5H14.802Z" fill="white"/>
739 767 </mask>
@@ -784,8 +812,11 @@
784 812 * @param string $content HTML content of the post.
785 813 * @return string
786 814 */
787 815 public function add_data_img_tags_and_enqueue_assets( $content ) {
816 + if ( ! is_string( $content ) || $content === '' ) {
817 + return '';
818 + }
788 819 if (
789 820 class_exists( 'Jetpack_AMP_Support' )
790 821 && Jetpack_AMP_Support::is_amp_request()
791 822 ) {
@@ -796,11 +827,19 @@
796 827 return $content;
797 828 }
798 829 $selected_images = array();
799 830 foreach ( $matches[0] as $image_html ) {
831 + // This image already carries the attributes this method adds, so adding
832 + // them again would emit every one of them twice. Tiled Gallery output
833 + // reaches this filter twice: once as 'jetpack_tiled_galleries_block_content'
834 + // from inside the block's render callback, and again as 'the_content' when
835 + // single image galleries are enabled. See JETPACK-1990.
836 + if ( str_contains( $image_html, 'data-attachment-id=' ) ) {
837 + continue;
838 + }
800 839 if (
801 840 preg_match( '/(wp-image-|data-id=)\"?([0-9]+)\"?/i', $image_html, $class_id )
802 - && ! preg_match( '/wp-block-jetpack-slideshow_image/', $image_html )
841 + && ! str_contains( $image_html, 'wp-block-jetpack-slideshow_image' )
803 842 ) {
804 843 /**
805 844 * Allow filtering the attachment ID used to fetch and populate metadata about an image in a gallery.
806 845 *
@@ -852,9 +891,13 @@
852 891 *
853 892 * This is meant as a relatively quick fix, as a better fix is likely to update the get_posts call above to only
854 893 * include attachments.
855 894 */
856 - if ( ! isset( $attachment->ID ) || ! wp_attachment_is_image( $attachment->ID ) ) {
895 + if (
896 + ! isset( $attachment->ID )
897 + || ! wp_attachment_is_image( $attachment->ID )
898 + || ! isset( $selected_images[ $attachment->ID ] )
899 + ) {
857 900 continue;
858 901 }
859 902 $image_elements = $selected_images[ $attachment->ID ];
860 903
@@ -883,10 +926,10 @@
883 926 *
884 927 * @see add_data_img_tags_and_enqueue_assets()
885 928 * @see https://developer.wordpress.org/reference/functions/wp_get_attachment_image/ Documentation about wp_get_attachment_image
886 929 *
887 - * @param string[] $attr Array of attribute values for the image markup, keyed by attribute name.
888 - * @param WP_Post $attachment Image attachment post.
930 + * @param string[] $attr Array of attribute values for the image markup, keyed by attribute name.
931 + * @param null|WP_Post $attachment Image attachment post.
889 932 *
890 933 * @return string[] Modified image attributes.
891 934 */
892 935 public function add_data_to_images( $attr, $attachment = null ) {
@@ -896,19 +939,24 @@
896 939 ) {
897 940 return $attr;
898 941 }
899 942
900 - $attachment_id = (int) $attachment->ID;
901 - if ( ! wp_attachment_is_image( $attachment_id ) ) {
943 + if (
944 + ! $attachment instanceof WP_Post
945 + || ! isset( $attachment->ID )
946 + || ! wp_attachment_is_image( $attachment )
947 + ) {
902 948 return $attr;
903 949 }
904 950
951 + $attachment_id = (int) $attachment->ID;
905 952 $orig_file = wp_get_attachment_image_src( $attachment_id, 'full' );
906 - $orig_file = isset( $orig_file[0] ) ? $orig_file[0] : wp_get_attachment_url( $attachment_id );
953 + $orig_file = $orig_file[0] ?? wp_get_attachment_url( $attachment_id );
907 954 $meta = wp_get_attachment_metadata( $attachment_id );
908 955 $size = isset( $meta['width'] ) ? (int) $meta['width'] . ',' . (int) $meta['height'] : '';
909 956 $img_meta = ( ! empty( $meta['image_meta'] ) ) ? (array) $meta['image_meta'] : array();
910 957 $comments_opened = (int) comments_open( $attachment_id );
958 + $display_exif = $this->test_1or0_option( Jetpack_Options::get_option_and_ensure_autoload( 'carousel_display_exif', true ) );
911 959
912 960 /**
913 961 * Note: Cannot generate a filename from the width and height wp_get_attachment_image_src() returns because
914 962 * it takes the $content_width global variable themes can set in consideration, therefore returning sizes
@@ -923,39 +971,36 @@
923 971 * EG with Twenty Ten activated:
924 972 * array(4) { [0]=> string(82) "http://vanillawpinstall.blah/wp-content/uploads/2012/06/IMG_3534-1024x764.jpg" [1]=> int(640) [2]=> int(477) [3]=> bool(true) }
925 973 */
926 974
927 - $medium_file_info = wp_get_attachment_image_src( $attachment_id, 'medium' );
928 - $medium_file = isset( $medium_file_info[0] ) ? $medium_file_info[0] : '';
929 -
930 975 $large_file_info = wp_get_attachment_image_src( $attachment_id, 'large' );
931 - $large_file = isset( $large_file_info[0] ) ? $large_file_info[0] : '';
976 + $large_file = $large_file_info[0] ?? '';
932 977
933 - $attachment = get_post( $attachment_id );
934 - $attachment_title = ! empty( $attachment ) ? wptexturize( $attachment->post_title ) : '';
935 - $attachment_desc = ! empty( $attachment ) ? wpautop( wptexturize( $attachment->post_content ) ) : '';
936 - $attachment_caption = ! empty( $attachment ) ? wpautop( wptexturize( $attachment->post_excerpt ) ) : '';
978 + $attachment_title = wptexturize( $attachment->post_title );
979 + $attachment_desc = wpautop( wptexturize( $attachment->post_content ) );
980 + $attachment_caption = wpautop( wptexturize( $attachment->post_excerpt ) );
937 981
938 - // See https://github.com/Automattic/jetpack/issues/2765.
939 - if ( isset( $img_meta['keywords'] ) ) {
940 - unset( $img_meta['keywords'] );
941 - }
942 -
943 - $img_meta = wp_json_encode( array_map( 'strval', array_filter( $img_meta, 'is_scalar' ) ) );
944 -
945 982 $attr['data-attachment-id'] = $attachment_id;
946 983 $attr['data-permalink'] = esc_attr( get_permalink( $attachment_id ) );
947 984 $attr['data-orig-file'] = esc_attr( $orig_file );
948 985 $attr['data-orig-size'] = $size;
949 986 $attr['data-comments-opened'] = $comments_opened;
950 - $attr['data-image-meta'] = esc_attr( $img_meta );
987 +
988 + if ( $display_exif ) {
989 + // See https://github.com/Automattic/jetpack/issues/2765.
990 + if ( isset( $img_meta['keywords'] ) ) {
991 + unset( $img_meta['keywords'] );
992 + }
993 +
994 + $img_meta = wp_json_encode( array_map( 'strval', array_filter( $img_meta, 'is_scalar' ) ), JSON_UNESCAPED_SLASHES | JSON_HEX_AMP );
995 + $attr['data-image-meta'] = esc_attr( $img_meta );
996 + }
997 +
951 998 // The lines below use `esc_attr( htmlspecialchars( ) )` because esc_attr tries to be too smart and won't double-encode, and we need that here.
952 999 $attr['data-image-title'] = esc_attr( htmlspecialchars( $attachment_title, ENT_COMPAT ) );
953 1000 $attr['data-image-description'] = esc_attr( htmlspecialchars( $attachment_desc, ENT_COMPAT ) );
954 1001 $attr['data-image-caption'] = esc_attr( htmlspecialchars( $attachment_caption, ENT_COMPAT ) );
955 - $attr['data-medium-file'] = esc_attr( $medium_file );
956 1002 $attr['data-large-file'] = esc_attr( $large_file );
957 -
958 1003 return $attr;
959 1004 }
960 1005
961 1006 /**
@@ -994,12 +1039,12 @@
994 1039 * @param array $extra_data Array of data about the site and the post.
995 1040 */
996 1041 $extra_data = apply_filters( 'jp_carousel_add_data_to_container', $extra_data );
997 1042 foreach ( (array) $extra_data as $data_key => $data_values ) {
998 - $html = str_replace( '<div ', '<div ' . esc_attr( $data_key ) . "='" . wp_json_encode( $data_values ) . "' ", $html );
999 - $html = str_replace( '<ul class="wp-block-gallery', '<ul ' . esc_attr( $data_key ) . "='" . wp_json_encode( $data_values ) . "' class=\"wp-block-gallery", $html );
1000 - $html = str_replace( '<ul class="blocks-gallery-grid', '<ul ' . esc_attr( $data_key ) . "='" . wp_json_encode( $data_values ) . "' class=\"blocks-gallery-grid", $html );
1001 - $html = preg_replace( '/\<figure([^>]*)class="(wp-block-gallery[^"]*?has-nested-images.*?)"/', '<figure ' . esc_attr( $data_key ) . "='" . wp_json_encode( $data_values ) . "' $1 class=\"$2\"", $html );
1043 + $html = str_replace( '<div ', '<div ' . esc_attr( $data_key ) . "='" . esc_attr( wp_json_encode( $data_values, JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ) . "' ", $html );
1044 + $html = str_replace( '<ul class="wp-block-gallery', '<ul ' . esc_attr( $data_key ) . "='" . esc_attr( wp_json_encode( $data_values, JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ) . "' class=\"wp-block-gallery", $html );
1045 + $html = str_replace( '<ul class="blocks-gallery-grid', '<ul ' . esc_attr( $data_key ) . "='" . esc_attr( wp_json_encode( $data_values, JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ) . "' class=\"blocks-gallery-grid", $html );
1046 + $html = preg_replace( '/\<figure([^>]*)class="(wp-block-gallery[^"]*?has-nested-images.*?)"/', '<figure ' . esc_attr( $data_key ) . "='" . esc_attr( wp_json_encode( $data_values, JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ) . "' $1 class=\"$2\"", $html );
1002 1047 }
1003 1048 }
1004 1049
1005 1050 return $html;
@@ -1044,9 +1089,9 @@
1044 1089
1045 1090 /**
1046 1091 * Retrieves comment information
1047 1092 *
1048 - * @return string
1093 + * @return never
1049 1094 */
1050 1095 public function get_attachment_comments() {
1051 1096 if ( ! headers_sent() ) {
1052 1097 header( 'Content-type: text/javascript' );
@@ -1070,11 +1115,11 @@
1070 1115
1071 1116 if ( ! $attachment_id ) {
1072 1117 wp_send_json_error(
1073 1118 __( 'Missing attachment ID.', 'jetpack' ),
1074 - 403
1119 + 403,
1120 + JSON_UNESCAPED_SLASHES
1075 1121 );
1076 - return;
1077 1122 }
1078 1123
1079 1124 $attachment_post = get_post( $attachment_id );
1080 1125 // If we have no info about that attachment, bail.
@@ -1080,11 +1125,11 @@
1080 1125 // If we have no info about that attachment, bail.
1081 1126 if ( ! ( $attachment_post instanceof WP_Post ) ) {
1082 1127 wp_send_json_error(
1083 1128 __( 'Missing attachment info.', 'jetpack' ),
1084 - 403
1129 + 403,
1130 + JSON_UNESCAPED_SLASHES
1085 1131 );
1086 - return;
1087 1132 }
1088 1133
1089 1134 // This AJAX call should only be used to fetch comments of attachments.
1090 1135 if ( 'attachment' !== $attachment_post->post_type ) {
@@ -1089,11 +1134,11 @@
1089 1134 // This AJAX call should only be used to fetch comments of attachments.
1090 1135 if ( 'attachment' !== $attachment_post->post_type ) {
1091 1136 wp_send_json_error(
1092 1137 __( 'You aren’t authorized to do that.', 'jetpack' ),
1093 - 403
1138 + 403,
1139 + JSON_UNESCAPED_SLASHES
1094 1140 );
1095 - return;
1096 1141 }
1097 1142
1098 1143 $parent_post = get_post_parent( $attachment_id );
1099 1144
@@ -1111,11 +1156,11 @@
1111 1156 $current_user = wp_get_current_user();
1112 1157 if ( ! ( $current_user instanceof WP_User ) ) {
1113 1158 wp_send_json_error(
1114 1159 __( 'Missing user info.', 'jetpack' ),
1115 - 403
1160 + 403,
1161 + JSON_UNESCAPED_SLASHES
1116 1162 );
1117 - return;
1118 1163 }
1119 1164
1120 1165 /*
1121 1166 * If a post is private / draft
@@ -1127,11 +1172,11 @@
1127 1172 && ! current_user_can( 'read_post', $parent_post->ID )
1128 1173 ) {
1129 1174 wp_send_json_error(
1130 1175 __( 'You aren’t authorized to do that.', 'jetpack' ),
1131 - 403
1176 + 403,
1177 + JSON_UNESCAPED_SLASHES
1132 1178 );
1133 - return;
1134 1179 }
1135 1180 }
1136 1181
1137 1182 if ( $offset < 1 ) {
@@ -1165,13 +1210,15 @@
1165 1210 'content' => wpautop( $comment->comment_content ),
1166 1211 );
1167 1212 }
1168 1213
1169 - die( wp_json_encode( $out ) );
1214 + wp_send_json( $out, null, JSON_UNESCAPED_SLASHES );
1170 1215 }
1171 1216
1172 1217 /**
1173 1218 * Adds a new comment to the database
1219 + *
1220 + * @return never
1174 1221 */
1175 1222 public function post_attachment_comment() {
1176 1223 if ( ! headers_sent() ) {
1177 1224 header( 'Content-type: text/javascript' );
@@ -1177,9 +1224,9 @@
1177 1224 header( 'Content-type: text/javascript' );
1178 1225 }
1179 1226
1180 1227 if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'carousel_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WP Core doesn't unslash or sanitize nonces either
1181 - die( wp_json_encode( array( 'error' => __( 'Nonce verification failed.', 'jetpack' ) ) ) );
1228 + die( wp_json_encode( array( 'error' => __( 'Nonce verification failed.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1182 1229 }
1183 1230
1184 1231 $_blog_id = isset( $_POST['blog_id'] ) ? (int) $_POST['blog_id'] : 0;
1185 1232 $_post_id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
@@ -1185,17 +1232,17 @@
1185 1232 $_post_id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
1186 1233 $comment = isset( $_POST['comment'] ) ? filter_var( wp_unslash( $_POST['comment'] ) ) : null;
1187 1234
1188 1235 if ( empty( $_blog_id ) ) {
1189 - die( wp_json_encode( array( 'error' => __( 'Missing target blog ID.', 'jetpack' ) ) ) );
1236 + die( wp_json_encode( array( 'error' => __( 'Missing target blog ID.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1190 1237 }
1191 1238
1192 1239 if ( empty( $_post_id ) ) {
1193 - die( wp_json_encode( array( 'error' => __( 'Missing target post ID.', 'jetpack' ) ) ) );
1240 + die( wp_json_encode( array( 'error' => __( 'Missing target post ID.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1194 1241 }
1195 1242
1196 1243 if ( empty( $comment ) ) {
1197 - die( wp_json_encode( array( 'error' => __( 'No comment text was submitted.', 'jetpack' ) ) ) );
1244 + die( wp_json_encode( array( 'error' => __( 'No comment text was submitted.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1198 1245 }
1199 1246
1200 1247 // Used in context like NewDash.
1201 1248 $switched = false;
@@ -1210,9 +1257,9 @@
1210 1257 if ( ! comments_open( $_post_id ) ) {
1211 1258 if ( $switched ) {
1212 1259 restore_current_blog();
1213 1260 }
1214 - die( wp_json_encode( array( 'error' => __( 'Comments on this post are closed.', 'jetpack' ) ) ) );
1261 + die( wp_json_encode( array( 'error' => __( 'Comments on this post are closed.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1215 1262 }
1216 1263
1217 1264 if ( is_user_logged_in() ) {
1218 1265 $user = wp_get_current_user();
@@ -1224,15 +1271,18 @@
1224 1271 if ( empty( $user_id ) ) {
1225 1272 if ( $switched ) {
1226 1273 restore_current_blog();
1227 1274 }
1228 - die( wp_json_encode( array( 'error' => __( 'Sorry, but we could not authenticate your request.', 'jetpack' ) ) ) );
1275 + die( wp_json_encode( array( 'error' => __( 'Sorry, but we could not authenticate your request.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1229 1276 }
1230 1277 } else {
1231 1278 $user_id = 0;
1232 1279 $display_name = isset( $_POST['author'] ) ? sanitize_text_field( wp_unslash( $_POST['author'] ) ) : null;
1233 - $email = isset( $_POST['email'] ) ? wp_unslash( $_POST['email'] ) : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Checked or sanitized below.
1234 - $url = isset( $_POST['url'] ) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : null;
1280 + $email = null;
1281 + if ( isset( $_POST['email'] ) && is_string( $_POST['email'] ) ) {
1282 + $email = wp_unslash( $_POST['email'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Checked or sanitized below.
1283 + }
1284 + $url = isset( $_POST['url'] ) && is_string( $_POST['url'] ) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : null;
1235 1285
1236 1286 if ( get_option( 'require_name_email' ) ) {
1237 1287 if ( empty( $display_name ) ) {
1238 1288 if ( $switched ) {
@@ -1237,9 +1287,9 @@
1237 1287 if ( empty( $display_name ) ) {
1238 1288 if ( $switched ) {
1239 1289 restore_current_blog();
1240 1290 }
1241 - die( wp_json_encode( array( 'error' => __( 'Please provide your name.', 'jetpack' ) ) ) );
1291 + die( wp_json_encode( array( 'error' => __( 'Please provide your name.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1242 1292 }
1243 1293
1244 1294 if ( empty( $email ) ) {
1245 1295 if ( $switched ) {
@@ -1244,9 +1294,9 @@
1244 1294 if ( empty( $email ) ) {
1245 1295 if ( $switched ) {
1246 1296 restore_current_blog();
1247 1297 }
1248 - die( wp_json_encode( array( 'error' => __( 'Please provide an email address.', 'jetpack' ) ) ) );
1298 + die( wp_json_encode( array( 'error' => __( 'Please provide an email address.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1249 1299 }
1250 1300
1251 1301 if ( ! is_email( $email ) ) {
1252 1302 if ( $switched ) {
@@ -1251,9 +1301,9 @@
1251 1301 if ( ! is_email( $email ) ) {
1252 1302 if ( $switched ) {
1253 1303 restore_current_blog();
1254 1304 }
1255 - die( wp_json_encode( array( 'error' => __( 'Please provide a valid email address.', 'jetpack' ) ) ) );
1305 + die( wp_json_encode( array( 'error' => __( 'Please provide a valid email address.', 'jetpack' ) ), JSON_UNESCAPED_SLASHES ) );
1256 1306 }
1257 1307 } else {
1258 1308 $email = $email !== null ? sanitize_email( $email ) : null;
1259 1309 }
@@ -1294,9 +1344,10 @@
1294 1344 wp_json_encode(
1295 1345 array(
1296 1346 'comment_id' => $comment_id,
1297 1347 'comment_status' => $comment_status,
1298 - )
1348 + ),
1349 + JSON_UNESCAPED_SLASHES
1299 1350 )
1300 1351 );
1301 1352 }
1302 1353
@@ -1424,9 +1475,9 @@
1424 1475 * Sanitize input for the `carousel_display_exif` setting.
1425 1476 *
1426 1477 * @param mixed $value User input setting value.
1427 1478 *
1428 - * @return number Sanitized value, only 1 or 0.
1479 + * @return int Sanitized value, only 1 or 0.
1429 1480 */
1430 1481 public function carousel_display_exif_sanitize( $value ) {
1431 1482 return $this->sanitize_1or0_option( $value );
1432 1483 }
@@ -1433,11 +1484,11 @@
1433 1484
1434 1485 /**
1435 1486 * Return sanitized option for value that controls whether comments will be hidden or not.
1436 1487 *
1437 - * @param number $value Value to sanitize.
1488 + * @param mixed $value Value to sanitize.
1438 1489 *
1439 - * @return number Sanitized value, only 1 or 0.
1490 + * @return int Sanitized value, only 1 or 0.
1440 1491 */
1441 1492 public function carousel_display_comments_sanitize( $value ) {
1442 1493 return $this->sanitize_1or0_option( $value );
1443 1494 }
@@ -1477,9 +1528,9 @@
1477 1528 * Sanitize input for the `carousel_enable_it` setting.
1478 1529 *
1479 1530 * @param mixed $value User input.
1480 1531 *
1481 - * @return number Sanitized value, only 1 or 0.
1532 + * @return int Sanitized value, only 1 or 0.
1482 1533 */
1483 1534 public function carousel_enable_it_sanitize( $value ) {
1484 1535 return $this->sanitize_1or0_option( $value );
1485 1536 }