$max_bytes ) { return sprintf( /* translators: %s: the maximum allowed file size, e.g. "10 MB" */ __( 'The uploaded file is too large. Maximum size: %s.', 'chargeforms' ), self::format_bytes( $max_bytes ) ); } $ext = strtolower( pathinfo( (string) ( $file['name'] ?? '' ), PATHINFO_EXTENSION ) ); if ( ! in_array( $ext, $extensions, true ) ) { return sprintf( /* translators: %s: comma-separated list of allowed file extensions */ __( 'That file type is not allowed. Expected: %s.', 'chargeforms' ), implode( ', ', $extensions ) ); } // CSV is a text interchange format; libmagic's label varies by PHP and // platform. Validate the bytes directly and avoid rejecting valid CSV // solely because its sniffed MIME is not one of the browser labels. if ( 'csv' === $ext ) { $csv_contents = @file_get_contents( $file['tmp_name'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- temporary upload inspection. if ( false === $csv_contents || 1 === preg_match( '/[^\x09\x0A\x0D\x20-\x7E]/', $csv_contents ) ) { return __( "The file's contents do not match its file type.", 'chargeforms' ); } return ''; } // Belt-and-braces against a file merely renamed to look like the right // extension — sniff its actual content type where the fileinfo // extension is available (it's a core PHP extension, but not // guaranteed present in every environment). if ( function_exists( 'finfo_open' ) ) { $finfo = finfo_open( FILEINFO_MIME_TYPE ); $mime = $finfo ? finfo_file( $finfo, $file['tmp_name'] ) : false; if ( $finfo ) { finfo_close( $finfo ); } // Some PHP/libmagic combinations classify a small, extension-named // CSV made only of ASCII text as an unexpected MIME type. // Keep the content check strict: only printable text files with a // CSV extension get this compatibility fallback; binary payloads and // JSON imports still fail closed. $is_printable_csv = 'csv' === $ext && self::is_printable_text( $file['tmp_name'] ); if ( $mime && ! in_array( $mime, $mime_types, true ) && ! $is_printable_csv ) { return __( "The file's contents do not match its file type.", 'chargeforms' ); } } return ''; } private static function format_bytes( $bytes ) { if ( function_exists( 'size_format' ) ) { return size_format( $bytes ); } return round( $bytes / 1048576, 1 ) . ' MB'; } private static function is_printable_text( $path ) { $contents = @file_get_contents( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- bounded temporary upload inspection. return false !== $contents && '' !== $contents && false === preg_match( '/[^\x09\x0A\x0D\x20-\x7E]/', $contents ); } }