Make WordPress Core

Opened 8 months ago

#60349 new defect (bug)

Rest API media upload utf8 urlencoded filename not decoded on server

Reported by: ypjzjn's profile ypjzjn Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.4.2
Component: REST API Keywords: has-patch
Focuses: Cc:

Description

Files uploaded with the rest api media endpoint, containing utf8 characters in the filename, does not get urldecoded if the filename is urlencoded.

Example:

Content-Disposition: attachment; filename=\"My-nice-filename.jpg\"

The file is correctly called My-nice-filename.jpg on the server.

Content-Disposition: attachment; filename=\"%D1%82%D0%B0%D1%82%D0%B0%D1%82%D0%B0.jpg\"

File named татата.jpg ends incorrectly up as D182D0B0D182D0B0D182D0B0.jpg on the server.

Under is a POC patch allowing urlencoded filenames to be urldecoded on the server.

Content-Disposition: attachment; filename*=UTF-8''%D1%82%D0%B0%D1%82%D0%B0%D1%82%D0%B0.jpg

The file is correctly named татата.jpg on the server.

A number of http clients, example winhttp, doesn't support utf8 characters in the headers, and the files end up with wrong names on the server.

--- class-wp-rest-attachments-controller.php.orig       2024-01-25 13:43:43.898485027 +0100
+++ class-wp-rest-attachments-controller.php    2024-01-25 13:44:02.206740466 +0100
@@ -1139,16 +1139,26 @@
                                $attributes[ trim( $key ) ] = trim( $value );
                        }

-                       if ( empty( $attributes['filename'] ) ) {
-                               continue;
-                       }
+                        if ( ! empty( $attributes['filename'] ) ) {
+                               $filename = trim( $attributes['filename'] );

-                       $filename = trim( $attributes['filename'] );
+                               // Unquote quoted filename, but after trimming.
+                               if ( str_starts_with( $filename, '"' ) && str_ends_with( $filename, '"' ) ) {
+                                       $filename = substr( $filename, 1, -1 );
+                               }
+                        } else if ( ! empty( $attributes['filename*'] ) ) {
+
+                               if ( str_contains( $attributes['filename*'], '\'\'') ) {
+                                       list( $key, $value ) = explode( '\'\'', $attributes['filename*'], 2);
+                                       // key is encoding
+                                       $filename = trim( urldecode( $value ) );
+                               } else {
+                                       continue;
+                               }
+                        } else {
+                               continue;
+                        }

-                       // Unquote quoted filename, but after trimming.
-                       if ( str_starts_with( $filename, '"' ) && str_ends_with( $filename, '"' ) ) {
-                               $filename = substr( $filename, 1, -1 );
-                       }
                }

                return $filename;

Change History (0)

Note: See TracTickets for help on using tickets.