Changeset 3407779
- Timestamp:
- 12/02/2025 10:04:07 AM (4 months ago)
- Location:
- watermark-reloaded
- Files:
-
- 2 added
- 4 edited
-
tags/1.4.0/class-watermark-reloaded-admin.php (modified) (10 diffs)
-
tags/1.4.0/languages/watermark-reloaded.pot (added)
-
tags/1.4.0/watermark-loader.php (modified) (4 diffs)
-
trunk/class-watermark-reloaded-admin.php (modified) (10 diffs)
-
trunk/languages/watermark-reloaded.pot (added)
-
trunk/watermark-loader.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
watermark-reloaded/tags/1.4.0/class-watermark-reloaded-admin.php
r3406555 r3407779 72 72 73 73 // Add filter for watermarking images. 74 add_filter( 'wp_generate_attachment_metadata', array( $this, 'a pply_watermark' ), 10, 2 );74 add_filter( 'wp_generate_attachment_metadata', array( $this, 'attachment_metadata' ), 10, 2 ); 75 75 } 76 76 … … 130 130 $plugin_page = add_options_page( 131 131 esc_html__( 'Watermark Reloaded Settings', 'watermark-reloaded' ), 132 esc_html__( 'Watermark R eloaded', 'watermark-reloaded' ),132 esc_html__( 'Watermark RELOADED', 'watermark-reloaded' ), 133 133 'manage_options', 134 134 WR_SETTINGS_PAGE, … … 263 263 } 264 264 265 if ( ! $this->gd_exists() ) { 266 wp_die( 267 esc_html__( 268 'Watermark RELOADED requires the PHP extension GD to process images. Please enable GD to configure the plugin.', 269 'watermark-reloaded' 270 ) 271 ); 272 } 273 274 if ( ! $this->has_freetype() ) { 275 wp_die( 276 esc_html__( 'Text watermarking requires FreeType Library.', 'watermark-reloaded' ) 277 ); 278 } 279 265 280 check_admin_referer( 'wr_preview', 'wr_preview_nonce' ); 266 281 267 $watermark_text = filter_input( INPUT_GET, 'watermark_text', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY ); 268 if ( ! empty( $watermark_text ) && is_array( $watermark_text ) ) { 269 $watermark_text = $this->filter_option_value( 'watermark_text', $watermark_text ); 270 } 271 272 $this->create_preview( array( 'watermark_text' => $watermark_text ) ); 282 $get = wp_unslash( $_GET ); 283 $watermark_text = ! empty( $get['watermark_text'] ) && is_array( $get['watermark_text'] ) 284 ? $get['watermark_text'] 285 : array(); 286 287 $this->create_preview( 288 array( 289 'watermark_text' => $this->sanitize_option_value( 'watermark_text', $watermark_text ), 290 ) 291 ); 292 293 wp_die(); 294 } 295 296 /** 297 * Process attachment metadata during upload. 298 * 299 * @param array $data Attachment metadata. 300 * @param int $attachment_id Attachment ID. 301 * @return array 302 */ 303 public function attachment_metadata( $data, $attachment_id ) { 304 // If GD doesn't exist don't watermark. 305 if ( ! $this->gd_exists() || ! $this->has_freetype() ) { 306 return $data; 307 } 308 309 return $this->apply_watermark( $data, $attachment_id ); 273 310 } 274 311 … … 400 437 } 401 438 402 // Collect and sanitize POST payload.403 $post = filter_input_array( INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);439 // Collect raw POST payload (will be sanitized per-field). 440 $post = wp_unslash( $_POST ); 404 441 405 442 // Check if our form submit button was clicked. … … 436 473 foreach ( $this->options as $option => $value ) { 437 474 if ( isset( $post[ $option ] ) ) { 438 update_option( $option, $this-> filter_option_value( $option, $post[ $option ] ) );475 update_option( $option, $this->sanitize_option_value( $option, $post[ $option ] ) ); 439 476 } 440 477 } … … 653 690 * @return mixed 654 691 */ 655 private function filter_option_value( $option, $value ) {692 private function sanitize_option_value( $option, $value ) { 656 693 switch ( $option ) { 657 694 case 'watermark_on': … … 660 697 } 661 698 662 // Filter out any intruding image sizes and make sure value is 1. 663 $filtered = array_intersect_key( $value, $this->image_size_list() ); 664 return array_fill_keys( array_keys( $filtered ), 1 ); 699 $sanitized = array(); 700 $allowed_sizes = array_keys( $this->image_size_list() ); 701 foreach ( $value as $image_size => $enabled ) { 702 // Allow only registered image sizes. 703 if ( in_array( $image_size, $allowed_sizes, true ) ) { 704 $sanitized[ sanitize_key( $image_size ) ] = 1; 705 } 706 } 707 708 return $sanitized; 665 709 666 710 case 'watermark_position': 711 $value = sanitize_key( $value ); 667 712 $positions = explode( '_', $value ); 668 713 … … 678 723 } 679 724 680 // Allow only x and y axis. 681 $filtered = array_intersect_key( $value, array_flip( array_keys( $this->watermark_positions ) ) ); 682 683 return array_map( 'intval', $filtered ); 725 $offset = array(); 726 $defaults = $this->get_option( $option ); 727 foreach ( array( 'x', 'y' ) as $axis ) { 728 $offset[ $axis ] = isset( $value[ $axis ] ) ? absint( $value[ $axis ] ) : $defaults[ $axis ]; 729 } 730 731 return $offset; 684 732 685 733 case 'watermark_text': 686 734 $defaults = $this->get_option( $option ); 687 735 736 // Ensure font whitelist is populated. 737 if ( empty( $this->fonts ) ) { 738 $this->get_fonts(); 739 } 740 741 // Font field validation. 742 $font = isset( $value['font'] ) ? sanitize_file_name( $value['font'] ) : $defaults['font']; 743 $font = array_key_exists( $font, $this->fonts ) ? $font : $defaults['font']; 744 745 // Color field validation. 746 $color = isset( $value['color'] ) ? sanitize_hex_color_no_hash( $value['color'] ) : $defaults['color']; 747 $color = null !== $color && strlen( $color ) === 6 ? $color : $defaults['color']; 748 688 749 return array( 689 750 'value' => isset( $value['value'] ) ? sanitize_text_field( $value['value'] ) : $defaults['value'], 690 'font' => isset( $value['font'] ) ? sanitize_file_name( $value['font'] ) : $defaults['font'], 691 'size' => isset( $value['size'] ) ? intval( $value['size'] ) : $defaults['size'], 692 'color' => isset( $value['color'] ) && preg_match( '/^\#[a-f0-9]{6}$/si', $value['color'] ) 693 ? str_replace( '#', '', $value['color'] ) 694 : $defaults['color'], 751 'size' => isset( $value['size'] ) ? absint( $value['size'] ) : $defaults['size'], 752 'font' => $font, 753 'color' => $color, 695 754 ); 696 755 … … 716 775 } 717 776 718 $gd_info = gd_info(); 719 if ( ! $gd_info['FreeType Support'] ) { 777 if ( ! $this->has_freetype() ) { 720 778 $this->missing_dependencies[] = 'freetype'; 721 779 $this->messages['error'][] = esc_html__( 'Text watermarking requires FreeType Library.', 'watermark-reloaded' ); … … 734 792 private function gd_exists() { 735 793 return extension_loaded( 'gd' ) || function_exists( 'gd_info' ); 794 } 795 796 /** 797 * Check if FreeType is supported within GD extension. 798 * 799 * @return bool 800 */ 801 private function has_freetype() { 802 $gd_info = gd_info(); 803 return (bool) $gd_info['FreeType Support']; 736 804 } 737 805 -
watermark-reloaded/tags/1.4.0/watermark-loader.php
r3406555 r3407779 18 18 */ 19 19 20 define( 'WR_MIN_PHP_VERSION', '5. 1' );20 define( 'WR_MIN_PHP_VERSION', '5.3' ); 21 21 22 22 /** … … 49 49 50 50 /** 51 * Load plugin textdomain. 52 * 53 * @return void 54 */ 55 function watermark_reloaded_load_textdomain() { 56 load_plugin_textdomain( 57 'watermark-reloaded', 58 false, 59 dirname( plugin_basename( __FILE__ ) ) . '/languages/' 60 ); 61 } 62 63 // Use init or plugins_loaded (both are fine, and safe for WP 6.7+). 64 add_action( 'init', 'watermark_reloaded_load_textdomain' ); 65 66 /** 51 67 * Handle WordPress error scraping when PHP version is too low. 52 68 * … … 57 73 function watermark_reloaded_error_scrape() { 58 74 if ( version_compare( PHP_VERSION, WR_MIN_PHP_VERSION, '<' ) ) { 59 $action = filter_input( INPUT_GET, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); 75 // WordPress core calls this endpoint without a nonce during fatal error scraping. 76 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 77 $action = isset( $_GET['action'] ) ? sanitize_key( wp_unslash( $_GET['action'] ) ) : ''; 60 78 if ( 'error_scrape' === $action ) { 61 79 $message = sprintf( … … 76 94 } 77 95 78 watermark_reloaded_error_scrape(); 79 96 add_action( 'init', 'watermark_reloaded_error_scrape' ); 80 97 81 98 // Load Watermark RELOADED plugin core only in admin. -
watermark-reloaded/trunk/class-watermark-reloaded-admin.php
r3406555 r3407779 72 72 73 73 // Add filter for watermarking images. 74 add_filter( 'wp_generate_attachment_metadata', array( $this, 'a pply_watermark' ), 10, 2 );74 add_filter( 'wp_generate_attachment_metadata', array( $this, 'attachment_metadata' ), 10, 2 ); 75 75 } 76 76 … … 130 130 $plugin_page = add_options_page( 131 131 esc_html__( 'Watermark Reloaded Settings', 'watermark-reloaded' ), 132 esc_html__( 'Watermark R eloaded', 'watermark-reloaded' ),132 esc_html__( 'Watermark RELOADED', 'watermark-reloaded' ), 133 133 'manage_options', 134 134 WR_SETTINGS_PAGE, … … 263 263 } 264 264 265 if ( ! $this->gd_exists() ) { 266 wp_die( 267 esc_html__( 268 'Watermark RELOADED requires the PHP extension GD to process images. Please enable GD to configure the plugin.', 269 'watermark-reloaded' 270 ) 271 ); 272 } 273 274 if ( ! $this->has_freetype() ) { 275 wp_die( 276 esc_html__( 'Text watermarking requires FreeType Library.', 'watermark-reloaded' ) 277 ); 278 } 279 265 280 check_admin_referer( 'wr_preview', 'wr_preview_nonce' ); 266 281 267 $watermark_text = filter_input( INPUT_GET, 'watermark_text', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY ); 268 if ( ! empty( $watermark_text ) && is_array( $watermark_text ) ) { 269 $watermark_text = $this->filter_option_value( 'watermark_text', $watermark_text ); 270 } 271 272 $this->create_preview( array( 'watermark_text' => $watermark_text ) ); 282 $get = wp_unslash( $_GET ); 283 $watermark_text = ! empty( $get['watermark_text'] ) && is_array( $get['watermark_text'] ) 284 ? $get['watermark_text'] 285 : array(); 286 287 $this->create_preview( 288 array( 289 'watermark_text' => $this->sanitize_option_value( 'watermark_text', $watermark_text ), 290 ) 291 ); 292 293 wp_die(); 294 } 295 296 /** 297 * Process attachment metadata during upload. 298 * 299 * @param array $data Attachment metadata. 300 * @param int $attachment_id Attachment ID. 301 * @return array 302 */ 303 public function attachment_metadata( $data, $attachment_id ) { 304 // If GD doesn't exist don't watermark. 305 if ( ! $this->gd_exists() || ! $this->has_freetype() ) { 306 return $data; 307 } 308 309 return $this->apply_watermark( $data, $attachment_id ); 273 310 } 274 311 … … 400 437 } 401 438 402 // Collect and sanitize POST payload.403 $post = filter_input_array( INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);439 // Collect raw POST payload (will be sanitized per-field). 440 $post = wp_unslash( $_POST ); 404 441 405 442 // Check if our form submit button was clicked. … … 436 473 foreach ( $this->options as $option => $value ) { 437 474 if ( isset( $post[ $option ] ) ) { 438 update_option( $option, $this-> filter_option_value( $option, $post[ $option ] ) );475 update_option( $option, $this->sanitize_option_value( $option, $post[ $option ] ) ); 439 476 } 440 477 } … … 653 690 * @return mixed 654 691 */ 655 private function filter_option_value( $option, $value ) {692 private function sanitize_option_value( $option, $value ) { 656 693 switch ( $option ) { 657 694 case 'watermark_on': … … 660 697 } 661 698 662 // Filter out any intruding image sizes and make sure value is 1. 663 $filtered = array_intersect_key( $value, $this->image_size_list() ); 664 return array_fill_keys( array_keys( $filtered ), 1 ); 699 $sanitized = array(); 700 $allowed_sizes = array_keys( $this->image_size_list() ); 701 foreach ( $value as $image_size => $enabled ) { 702 // Allow only registered image sizes. 703 if ( in_array( $image_size, $allowed_sizes, true ) ) { 704 $sanitized[ sanitize_key( $image_size ) ] = 1; 705 } 706 } 707 708 return $sanitized; 665 709 666 710 case 'watermark_position': 711 $value = sanitize_key( $value ); 667 712 $positions = explode( '_', $value ); 668 713 … … 678 723 } 679 724 680 // Allow only x and y axis. 681 $filtered = array_intersect_key( $value, array_flip( array_keys( $this->watermark_positions ) ) ); 682 683 return array_map( 'intval', $filtered ); 725 $offset = array(); 726 $defaults = $this->get_option( $option ); 727 foreach ( array( 'x', 'y' ) as $axis ) { 728 $offset[ $axis ] = isset( $value[ $axis ] ) ? absint( $value[ $axis ] ) : $defaults[ $axis ]; 729 } 730 731 return $offset; 684 732 685 733 case 'watermark_text': 686 734 $defaults = $this->get_option( $option ); 687 735 736 // Ensure font whitelist is populated. 737 if ( empty( $this->fonts ) ) { 738 $this->get_fonts(); 739 } 740 741 // Font field validation. 742 $font = isset( $value['font'] ) ? sanitize_file_name( $value['font'] ) : $defaults['font']; 743 $font = array_key_exists( $font, $this->fonts ) ? $font : $defaults['font']; 744 745 // Color field validation. 746 $color = isset( $value['color'] ) ? sanitize_hex_color_no_hash( $value['color'] ) : $defaults['color']; 747 $color = null !== $color && strlen( $color ) === 6 ? $color : $defaults['color']; 748 688 749 return array( 689 750 'value' => isset( $value['value'] ) ? sanitize_text_field( $value['value'] ) : $defaults['value'], 690 'font' => isset( $value['font'] ) ? sanitize_file_name( $value['font'] ) : $defaults['font'], 691 'size' => isset( $value['size'] ) ? intval( $value['size'] ) : $defaults['size'], 692 'color' => isset( $value['color'] ) && preg_match( '/^\#[a-f0-9]{6}$/si', $value['color'] ) 693 ? str_replace( '#', '', $value['color'] ) 694 : $defaults['color'], 751 'size' => isset( $value['size'] ) ? absint( $value['size'] ) : $defaults['size'], 752 'font' => $font, 753 'color' => $color, 695 754 ); 696 755 … … 716 775 } 717 776 718 $gd_info = gd_info(); 719 if ( ! $gd_info['FreeType Support'] ) { 777 if ( ! $this->has_freetype() ) { 720 778 $this->missing_dependencies[] = 'freetype'; 721 779 $this->messages['error'][] = esc_html__( 'Text watermarking requires FreeType Library.', 'watermark-reloaded' ); … … 734 792 private function gd_exists() { 735 793 return extension_loaded( 'gd' ) || function_exists( 'gd_info' ); 794 } 795 796 /** 797 * Check if FreeType is supported within GD extension. 798 * 799 * @return bool 800 */ 801 private function has_freetype() { 802 $gd_info = gd_info(); 803 return (bool) $gd_info['FreeType Support']; 736 804 } 737 805 -
watermark-reloaded/trunk/watermark-loader.php
r3406555 r3407779 18 18 */ 19 19 20 define( 'WR_MIN_PHP_VERSION', '5. 1' );20 define( 'WR_MIN_PHP_VERSION', '5.3' ); 21 21 22 22 /** … … 49 49 50 50 /** 51 * Load plugin textdomain. 52 * 53 * @return void 54 */ 55 function watermark_reloaded_load_textdomain() { 56 load_plugin_textdomain( 57 'watermark-reloaded', 58 false, 59 dirname( plugin_basename( __FILE__ ) ) . '/languages/' 60 ); 61 } 62 63 // Use init or plugins_loaded (both are fine, and safe for WP 6.7+). 64 add_action( 'init', 'watermark_reloaded_load_textdomain' ); 65 66 /** 51 67 * Handle WordPress error scraping when PHP version is too low. 52 68 * … … 57 73 function watermark_reloaded_error_scrape() { 58 74 if ( version_compare( PHP_VERSION, WR_MIN_PHP_VERSION, '<' ) ) { 59 $action = filter_input( INPUT_GET, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); 75 // WordPress core calls this endpoint without a nonce during fatal error scraping. 76 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 77 $action = isset( $_GET['action'] ) ? sanitize_key( wp_unslash( $_GET['action'] ) ) : ''; 60 78 if ( 'error_scrape' === $action ) { 61 79 $message = sprintf( … … 76 94 } 77 95 78 watermark_reloaded_error_scrape(); 79 96 add_action( 'init', 'watermark_reloaded_error_scrape' ); 80 97 81 98 // Load Watermark RELOADED plugin core only in admin.
Note: See TracChangeset
for help on using the changeset viewer.