files-upload-handler.php (3618B)
1 <?php 2 3 namespace Elementor\Core\Files\Assets; 4 5 if ( ! defined( 'ABSPATH' ) ) { 6 exit; // Exit if accessed directly. 7 } 8 9 abstract class Files_Upload_Handler { 10 const OPTION_KEY = 'elementor_unfiltered_files_upload'; 11 12 public function __construct() { 13 add_filter( 'upload_mimes', [ $this, 'support_unfiltered_files_upload' ] ); 14 add_filter( 'wp_handle_upload_prefilter', [ $this, 'handle_upload_prefilter' ] ); 15 add_filter( 'wp_check_filetype_and_ext', [ $this, 'check_filetype_and_ext' ], 10, 4 ); 16 } 17 18 abstract public function get_mime_type(); 19 20 abstract public function get_file_type(); 21 22 /** 23 * is_elementor_media_upload 24 * @return bool 25 */ 26 private function is_elementor_media_upload() { 27 return isset( $_POST['uploadTypeCaller'] ) && 'elementor-wp-media-upload' === $_POST['uploadTypeCaller']; // phpcs:ignore 28 } 29 30 /** 31 * @return bool 32 */ 33 final public static function is_enabled() { 34 $enabled = ! ! get_option( self::OPTION_KEY ) && self::file_sanitizer_can_run(); 35 36 /** 37 * @deprecated 3.0.0 Use `elementor/document/urls/edit` filter instead. 38 */ 39 $enabled = apply_filters( 'elementor/files/svg/enabled', $enabled ); 40 41 /** 42 * Allow Unfiltered Files Upload. 43 * 44 * Determines whether to enable unfiltered file uploads. 45 * 46 * @since 3.0.0 47 * 48 * @param bool $enabled Whether upload is enabled or not. 49 */ 50 $enabled = apply_filters( 'elementor/files/allow_unfiltered_upload', $enabled ); 51 52 return $enabled; 53 } 54 55 final public function support_unfiltered_files_upload( $existing_mimes ) { 56 if ( $this->is_elementor_media_upload() && $this->is_enabled() ) { 57 $existing_mimes[ $this->get_file_type() ] = $this->get_mime_type(); 58 } 59 60 return $existing_mimes; 61 } 62 63 /** 64 * handle_upload_prefilter 65 * @param $file 66 * 67 * @return mixed 68 */ 69 public function handle_upload_prefilter( $file ) { 70 if ( ! $this->is_file_should_handled( $file ) ) { 71 return $file; 72 } 73 74 $ext = pathinfo( $file['name'], PATHINFO_EXTENSION ); 75 $file_type = $this->get_file_type(); 76 $display_type = strtoupper( $file_type ); 77 78 if ( $file_type !== $ext ) { 79 $file['error'] = sprintf( esc_html__( 'The uploaded %1$s file is not supported. Please upload a valid %2$s file', 'elementor' ), $ext, $display_type ); 80 return $file; 81 } 82 83 if ( ! self::is_enabled() ) { 84 $file['error'] = sprintf( esc_html__( '%1$s file is not allowed for security reasons', 'elementor' ), $display_type ); 85 return $file; 86 } 87 88 return $file; 89 } 90 91 protected function is_file_should_handled( $file ) { 92 $ext = pathinfo( $file['name'], PATHINFO_EXTENSION ); 93 94 return $this->is_elementor_media_upload() && $this->get_file_type() === $ext; 95 } 96 97 /** 98 * file_sanitizer_can_run 99 * @return bool 100 */ 101 public static function file_sanitizer_can_run() { 102 return class_exists( 'DOMDocument' ) && class_exists( 'SimpleXMLElement' ); 103 } 104 105 /** 106 * Check filetype and ext 107 * 108 * A workaround for upload validation which relies on a PHP extension (fileinfo) 109 * with inconsistent reporting behaviour. 110 * ref: https://core.trac.wordpress.org/ticket/39550 111 * ref: https://core.trac.wordpress.org/ticket/40175 112 * 113 * @param $data 114 * @param $file 115 * @param $filename 116 * @param $mimes 117 * 118 * @return mixed 119 */ 120 public function check_filetype_and_ext( $data, $file, $filename, $mimes ) { 121 if ( ! empty( $data['ext'] ) && ! empty( $data['type'] ) ) { 122 return $data; 123 } 124 125 $wp_file_type = wp_check_filetype( $filename, $mimes ); 126 $file_type = strtolower( $this->get_file_type() ); 127 128 if ( $file_type === $wp_file_type['ext'] ) { 129 $data['ext'] = $file_type; 130 $data['type'] = $this->get_mime_type(); 131 } 132 133 return $data; 134 } 135 }