Problem/Motivation

When you upload a file there are several reasons why it might be renamed:

  1. For security reasons if it ends in .php
  2. Because there is an existing file

Why is this a bug? If the file is renamed due to file_create_filename() detecting an existing file the file entity's filename field is not updated. It updated if the name is munged or changed for security reasons. This means that currently \Drupal\file\Entity\File::getFilename() does not always return the file name - which is a little bit woah?!?

This issue has been split off from #2492171: Provide options to sanitize filenames (transliterate, lowercase, replace whitespace, etc)

Proposed resolution

Set the filename to the real filename before saving the file entity in _file_save_upload_single()

Notes:

  • This makes the UI work the same as REST or anything else using \Drupal\file\Plugin\rest\resource\FileUploadResource
  • It also makes this the same as file_save_data() which sets the names of files after calling \Drupal\Core\File\FileSystem::prepareDestination()
  • It makes \Drupal\file\Entity\File::getFilename() return the actual filename
  • The database field called "filename" contains the actual filename

Remaining tasks

  1. Commit

User interface changes

Filenames match reality

API changes

None

Data model changes

None

Release notes snippet

@todo

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Note this brings the logic inline with what is happening for Rest / JsonAPI and at some point UI and API file uploads should share more code. See #2940383: Unify file upload logic of REST and JSON:API

alexpott’s picture

Status: Active » Needs review
FileSize
3.85 KB

Note this change also brings everything into line. We already do

  if (!empty($extensions)) {
    // Munge the filename to protect against possible malicious extension
    // hiding within an unknown file type (ie: filename.html.foo).
    $file->setFilename(file_munge_filename($file->getFilename(), $extensions));
  }

So munged file entities are renamed.

alexpott’s picture

We should have a test-only patch as this is a bug fix.

Berdir’s picture

FWIW, #2940383: Unify file upload logic of REST and JSON:API currently does not have a goal to share with the UI, I explicitly asked about that in regards to naming. But maybe it should :)

Wim Leers’s picture

Seems sensible 👍

Note: this will disrupt some contrib modules: those that have functional tests involving file uploads may need to be updated.

The last submitted patch, 3: 3032376-3.patch, failed testing. View results

The last submitted patch, 4: 3032376-3.test-only.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 4: 3032376-3.patch, failed testing. View results

alexpott’s picture

dww’s picture

Status: Needs review » Reviewed & tested by the community

Yup, looks good to me, too. It will be nice to consistently have the file entity reflect reality.

Do we need a CR for this?

Otherwise, RTBC from me.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3032376-10.patch, failed testing. View results

dww’s picture

Status: Needs work » Reviewed & tested by the community

Pretty sure the bot is confused. Requeued #10 for 8.6.x and 8.7.x.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3032376-10.patch, failed testing. View results

dww’s picture

Version: 8.6.x-dev » 8.7.x-dev
Status: Needs work » Needs review
FileSize
4.51 KB
5.11 KB

Sad confused bot. :/ Let's try a new test-only from #10 and a re-upload of identically #10.

The last submitted patch, 15: 3032376-15.test-only.patch, failed testing. View results

dww’s picture

Status: Needs review » Reviewed & tested by the community

That's better. Back to RTBC.

Berdir’s picture

I always thought it is by design that we don't rename the filename as that is the name that the user gave it and the renamings that we are doing so far are just for technical reasons. That is changing with the event and more renaming-reasons we are introducing, so I can see why this makes sense.

It does make me wonder whether we need to have a dedicated field for that at all, but entity types without a label field are... icky, e.g. the user entity, which needs custom logic to handle autocomplete and so on.

frob’s picture

@Berdir, I am sorry I don't follow your comment in #18. Can you clarify.

alexpott’s picture

Issue summary: View changes

I've updated the issue summary to be clearer about why this bug should be fixed - and why it is a bug in the first place. Note in HEAD we do change the filename when it changes for security reasons - the only case where we don't change it is when we updated it because a file with the same name already exists.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 15: 3032376-15.10-again.patch, failed testing. View results

dww’s picture

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 15: 3032376-15.10-again.patch, failed testing. View results

alexpott’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community

Random fail fixed. Back to rtbc,

larowlan’s picture

Issue tags: +Needs change record

Can we get a change record on the basis of #6

larowlan’s picture

  • larowlan committed 9431a1c on 8.7.x
    Issue #3032376 by alexpott, dww, Berdir: Files renamed by \...

  • larowlan committed 3211ad3 on 8.6.x
    Issue #3032376 by alexpott, dww, Berdir: Files renamed by \...
larowlan’s picture

Version: 8.7.x-dev » 8.6.x-dev
Status: Reviewed & tested by the community » Fixed

Committed 9431a1c and pushed to 8.7.x. Thanks!

c/p as 3211ad36c2 and pushed to 8.6.x

Published the change record.

This commit was brought to you by 'we're not alone' by dinosaur jr 🎶

Wim Leers’s picture

This commit was brought to you by 'we're not alone' by dinosaur jr 🎶

😆

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

claudiu.cristea’s picture

@Wim Leers

Note: this will disrupt some contrib modules: those that have functional tests involving file uploads may need to be updated.

Just hit this in Behat tests :)

henokmikre’s picture

We just discovered that this change affects the D8 version of upload_replace, which lives in 2868450 as a patch and https://github.com/cgmonroe/upload_replace as a module (until the patch is committed by maintainers).

Since this change updates the filename before upload_replace_file_update() (an implementation of hook_ENTITY_TYPE_update()) sees the original filename, the following check in upload_replace.module is no longer valid:

+    //If the filename has be modified by adding a _0 value, or
+    //on certain situations the filepath will not match the filepath in the db, such as
+    //when reverting a revision.  When reverting a revision change the filename as well
+    if (!strpos($new_file->getFileUri(), $new_file->getFileUri())) {
+      //the filename is not in the filepath, so drupal must have added a "_0" before the extension
+      //find the file that is blocking this file from keeping the correct path

I previously thought upload_replace could instead rely on the fid once 2241865 is committed, but that wouldn't make a difference since _file_save_upload_single is called with FILE_EXISTS_RENAME.

richard.thomas’s picture

So it looks like this change means that the original filename that the browser sent is lost and therefore when displaying the file link it gets the _0/_1 appended? I note that the description of FileInterface->getFilename() says:

This may differ from the basename of the URI if the file is renamed to
avoid overwriting an existing file.

So I don't think this property was intended to reflect the actual path to the file, that's what the URI is for?

In practical terms, it means that when a user uploads a file with the same name to a bunch of different nodes it displays a link with the suffix included, which isn't what I would expect (and looks bad). If we didn't want to revert the change, could we store the original filename as another property?

frob’s picture

@henokmikre @richard.thomas, If bugs come from this issue please open new issues about them and reference this one. No one will see your comments here and nothing will be resolved if there is a problem.

vipin.mittal18’s picture

bkosborne’s picture

Very happy to see this has been fixed! This was always a major point of confusion having a filename property that wasn't actually representative of the actual filename.

semiaddict’s picture

I do agree with @Berdir in his comment #18.
There needs to be a way to get the original file's name before it was automatically renamed, as that was the name the user gave it before uploading it, and might be important to preserve.
Ideally, I think this should be saved in an "original_filename" column in the file_managed table.