ZF-9320: Zend_Validate_File_MimeType erroneously specifies magic file

Description

If no MAGIC environment variable is set, Zend_Validate_File_MimeType should allow finfo() to fall back on its internal mime database* rather than attempting to load a magic mime file from one of its preset search paths. This is preferable because the internal database is guaranteed to be compatible with libmagic; whereas, the magic files in the file-system are not. In some cases (e.g. Mac OS X 10.5) the magic file in the file-system is incompatible and will produce errors.

*The fileinfo extension (finfo) comes bundled with an internal magic mime database. If no magic file is specified, the internal magic database gets used. This is an undocumented feature of finfo. See: http://svn.php.net/viewvc/php/…

Comments

Note that ZF actually supports also PHP 5.2 and is not limited to PHP 5.3.

Additionally the internal magic database can be excluded from a distribution. There were some severe issues on some linux distributions with the internal database. That was the reason why we added the automatic search, as most people do not set the correct database. And the internal database is only a limited part of the external database.

I wasn't aware that the internal database had problems. Sounds like a problem either way then.

Not sure if it helps, but this is the problem I am seeing under 10.5 (this goes away when I use the internal magic database):

Notice: finfo::finfo() [finfo.finfo]: Warning: description `8-bit ISDN mu-law compressed (CCITT G.721 ADPCM voice data enco' truncated in [...]Zend/Validate/File/MimeType.php on line 306 ...snip... Notice: finfo::finfo() [finfo.finfo]: Warning: <= not supported in [...]Zend/Validate/File/MimeType.php on line 306 ...snip... Warning: finfo::finfo() [finfo.finfo]: Failed to load magic database at '/usr/share/file/magic'. in [...]Zend/Validate/File/MimeType.php on line 306

If there were some way to suppress and detect these warnings, Zend_Validate_File_MimeType could try to fallback on the internal database. That might be difficult though as finfo is not returning false despite its failure to load the magic database.

Change from bug to improvement... A broken database file will always fail within MimeType.

Implemented new behaviour: * MagicFile will be checked by finfo. * When finfo does not complain, the database is seen as OK * When finfo fails, the next database is checked * If no database is found, the internal database is used * When also the internal database fails, finfo will not be used

Note that Notices/Warnings will not be suppressed as this is not allowed within ZF for debugging reasons.

Thanks Thomas. A couple of questions:

  1. In my environment, finfo() was not returning false even when it failed to load the magic mime db. It looks like you're checking for false. Am I missing something?

  2. If warnings/notices are not suppressed, won't this still break uploads where the app attempts a subsequent redirect?

Cheers, Stewart

According to manual: "Returns a magic database resource on success or FALSE on failure."

Also a broken database is a failure and returns FALSE (at last it does in some environments). When it does not return false in your environment when if throwing out 2 notices and one warning it is errorous itself.

You can not call finfo on a broken database.

Additionally this would mean that there is no way how we could prevent a errorous database to be loaded as finfo() accepty ANYTHING as long as it can be read and returns a resource.

Warnings and notices to not prevent code from being executed. They are just nasty as they appear within the error log. As you said that finfo does not fail on a errorous database even a supression would not bring anything as the broken file is accepted. Defining the correct mimebase all works as expected.

I can understand if there is no palatable solution; I just wanted to clarify that this patch doesn't actually fix the problem I am reporting.

I think that the problem ultimately stems from a bug in finfo() because it does not adhere to its documented behaviour. If it did, then the MimeType validator would have worked as written because isValid() already checks for a false return from finfo() (and falls back to the internal db).

The additional check in setMagicFile() is good, but it doesn't address the problem I am experiencing because of the aforementioned bug.

Regarding the warnings/notices, I was suggesting that they would interfere with a 'location' header (i.e. redirect) because they will be output in some environments (at least in development and testing).

Thanks.

Well.. ZF can not solve PHP internal bugs.

When finfo accepts broken databases without returning false but returns a finfo resource then there is no way how to prevent this behaviour per code.

I agree that ZF should not be solving internal PHP bugs.

One current issue is that on newer Debian systems (Debian Testing as of 2010-08-12), the search path for the MIME magic database hits a directory, and unfortunately finfo loads this properly, resulting in an empty database and breaking the validator.

One easy fix for this would be to change:


} else if (!is_readable($file)) {

to


} else if (!is_file($file) || !is_readable($file)) {

in the file Zend/Validate/File/MimeType.php in the method setMagicFile().

Fix integrated... thank you for your patch