ZF-11869: Zend_File_Transfer_Adapter_Abstract::_detectMimeType should not check existence of file by its name
Description
I'm using Zend_File_Transfer to handle POSTed file uploads and ran into a nasty edge case.
Zend_File_Transfer_Adapter_Abstract line 1283 is checking the existence of the posted file by its name parameter before checking its existence by its tmp_name parameter. The problem is that the name parameter is not a path, so it's checking for its existence in the current working directory, which is my application's root directory. In my application's root dir, I have a CMakeLists.txt file. When I tried to upload a file to my application that was also named CMakeLists.txt, I got the following warning:
Warning: finfo_file() [function.finfo-file]: File or path not found 'CMakeLists.txt'
on line 1302 in file C:\xampp\htdocs\Midas3\library\Zend\File\Transfer\Adapter\Abstract.php
file_exists was returning true for the name parameter, which screwed up the rest of the method. Why do you check if the file exists by its name? The tmp_name param is the one that refers to the actual file, it seems to me that's the only one that should be used.
Thanks!
Comments
Posted by Thomas Weidner (thomas) on 2011-11-03T19:10:23.000+0000
Your assumption is not correct. Files exist only as "tmp_name" as long as they have not been downloaded. As soon as you download the file only the "name" param can be found.
So it depends on when you call this method... before downloading the file or afterwards. But the method itself does not know if you already downloaded the file or not. Therefor it checks if the given file exists or not to decide which action to use.
Posted by Zach Mullen (zach_mullen) on 2011-11-03T19:19:46.000+0000
Then this is only a bug if we call this method before downloading the file (which is my use case). Is there a precondition on calling receive() that the file must already have been downloaded, or is my use case supposed to be supported?
Posted by Zach Mullen (zach_mullen) on 2011-11-03T19:28:56.000+0000
This is how I call the transfer:
Then, I call a method that copies the posted file into a path corresponding to its md5sum, so no file exists by its original uploaded name.
Posted by Zach Mullen (zach_mullen) on 2011-11-03T19:30:24.000+0000
Ignore the 'HttpFixed', that was my workaround subclass adapter.
Posted by Thomas Weidner (thomas) on 2011-11-03T23:06:50.000+0000
In my opinion this can not work.
You are creating a file transfer according to the given $_FILES variable from a form. Then you say "download this files" by calling receive()... but then you say that !afterwards! you copy the file into another path... and the class should know that changed path before you set it???
You eighter set the name and path before you receive the file (with the rename filter) or you set it manually.
Posted by Zach Mullen (zach_mullen) on 2011-11-04T00:15:16.000+0000
The problem is happening in the very first line.
$upload = new Zend_File_Transfer();
It's actually the very first line of my controller.
Everything after that is actually working fine. The only thing failing is the mime type check. The constructor calls _prepareFiles, which is calling _detectMimeType, which is failing because it's checking if the file exists by name (in the current working directory, which is my application root dir) before it checks the existence of the tmp_name file. If we just switched the order of checking that existence, it would actually work for me. To reproduce this bug, just create a minimal zend application, place a dummy.txt file in the root directory of it, create a controller that just calls that one line of code, and then attempt to upload a different file called dummy.txt.
This block of code is the culprit:
protected function _detectMimeType($value) { if (file_exists($value['name'])) { $file = $value['name']; } else if (file_exists($value['tmp_name'])) { $file = $value['tmp_name']; }
I think that is meant to be equivalent to:
But they are not equivalent, because file_exists($value['name']) does not represent the condition that the file has already been downloaded; especially since this is happening in the constructor, so we know the file has not already been received.
Posted by Zach Mullen (zach_mullen) on 2011-11-18T19:40:28.000+0000
Any status update on this issue?
Thanks,
-Zach
Posted by Zach Mullen (zach_mullen) on 2011-12-13T19:39:16.000+0000
Are there plans to fix this in the next release?