Linux за българи: Форуми

Програмиране => Web development => Темата е започната от: senser в Nov 06, 2014, 18:59



Титла: PHP finfo vs command file
Публикувано от: senser в Nov 06, 2014, 18:59
Привет,

Работя върху web приложение за качване на файлове с PHP.
Искам да разбера какъв е mime-type на файла, който се качва. Когато използвам PHP finfo получавам "application/octet-stream; charset=binary"
Код:
$finfo = finfo_open(FILEINFO_MIME);
echo finfo_file($finfo,"File.odt");
finfo_close($finfo);

 в същото време, ако използвам  filе се получава "application/vnd.oasis.opendocument.text; charset=binary"
Код:
file -i File.odt

Поразрових се да видя дали finfo и file ползват една  и съща база с mime types. Файлът в Дебиан е "/usr/share/file/magic.mgc" (има няколко симлинка към него). Ако го използвам изрично с file, няма проблем - резултатът е същия:
Код:
file -i -m /usr/share/file/magic.mgc File.odt

Ако обаче дам същият файл на finfo_open, нещата не са ОК:
Код:
$finfo = finfo_open(FILEINFO_MIME, "/usr/share/file/magic.mgc");
echo finfo_file($finfo,"File.odt");
finfo_close($finfo);

Горното гърми с:
Код:
PHP Notice:  finfo_open(): Warning: offset `-' invalid in /home/senser/Desktop/CustomerFiles_Tests/finfo.php on line 4
PHP Notice:  finfo_open(): Warning: type `-' invalid in /home/senser/Desktop/CustomerFiles_Tests/finfo.php on line 4
PHP Notice:  finfo_open(): Warning: offset `.' invalid in /home/senser/Desktop/CustomerFiles_Tests/finfo.php on line 4
PHP Notice:  finfo_open(): Warning: type `.' invalid in /home/senser/Desktop/CustomerFiles_Tests/finfo.php on line 4
PHP Warning:  finfo_open(): Failed to load magic database at '/usr/share/file/magic.mgc'. in /home/senser/Desktop/CustomerFiles_Tests/finfo.php on line 4

В същото време finfo  с параметър празната директория "/usr/share/misc/magic", не гърми:
Код:
$finfo = finfo_open(FILEINFO_MIME, "/usr/share/misc/magic");
вади същия резултат "application/octet-stream; charset=binary".

И последно ако извикам file без да тества с magic files (от man file:  soft      Consults magic files):
Код:
file -i --exclude soft File.odt
имам "application/octet-stream; charset=binary"

Всичко това ме навежда на мисълта, че finfo на PHP не (може да) ползва същата mime types база.
Не намирам в същото време кой файл ползва вътрешно. Това, което намирам на сайта на РНР (http://bg2.php.net/manual/en/fileinfo.installation.php) е това:
The libmagic library is bundled with PHP, but includes PHP specific changes. A patch against libmagic named libmagic.patch is maintained and may be found within the PHP fileinfo extensions source.

Ето какво имам от phpinfo():
Код:
fileinfo
fileinfo support enabled
version 1.0.5
libmagic 517


Титла: Re: PHP finfo vs command file
Публикувано от: 4096bits в Nov 06, 2014, 19:53
Това ще свърши ли работа?
http://stackoverflow.com/questions/21906596/find-mime-type-of-file-or-url-using-php-for-all-file-format


Титла: Re: PHP finfo vs command file
Публикувано от: k0tka в Nov 06, 2014, 22:06
Когато използвам PHP finfo получавам "application/octet-stream; charset=binary"
Код:
$finfo = finfo_open(FILEINFO_MIME);
echo finfo_file($finfo,"File.odt");
finfo_close($finfo);

 в същото време, ако използвам  filе се получава "application/vnd.oasis.opendocument.text; charset=binary"
Код:
file -i File.odt


Здравей,
При мен finfo_open() връща: application/vnd.oasis.opendocument.text; charset=binary същото което и file -i something.odt

fileinfo 1.0.5-dev
PHP 5.3.3
CentOS 6.5

Не съм голям специалист с PHP но съдейки по тази ($2) тема Fileinfo работи с базата на file

Не съм и сигурен коя е тя:
yum whatprovides /etc/magic #празен файл
file-5.04-15.el6.x86_64 : A utility for determining file types

yum whatprovides /usr/share/misc/magic
file-libs-5.04-21.el6.x86_64 : Libraries for applications using libmagic

yum whatprovides /usr/share/mime/magic
No Matches found

Друга вариант е да използваш shell_exec() със file -i както е споменал 4096bits


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 07, 2014, 07:07
Да, мога да използвам shell_exec(), за да извиквам file -m, но засега ще се опитам да го избегна.

Не съм голям специалист с PHP но съдейки по тази ($2) тема Fileinfo работи с базата на file

Само, че всички опити, които направих и съм дал по-горе, сочат точно обратното според мен, вкл. и това, че резултатът от finfo & file е един и същ, когато file се извиква без проверка на mime (--exclude soft).
Отделно, че в manual-a на РНР (http://bg2.php.net/manual/en/function.finfo-open.php ($2)) пише следното:
Код:
Warning
The expected magic database format changed in PHP 5.3.11 and 5.4.1.
Due to this, the internal magic database was upgraded.
This mostly effects code where an external magic database is used: reading an older magic file will now fail.

Въпросът е дали съм прав в съжденията си, че РНР си ползва собствена mime base, мога ли да я "видя" и мога ли да го накарам да ползва "/usr/share/file/magic.mgc" вместо собствената си, защото явно резултатите на file са по-реални от finfo.
Това последното е малко вероятно, както пише в manual-a: reading an older magic file will now fail, но ми е чудно какво е наложило РНР да не ползват системния magic.mgc и да почнат да си поддържат свой (единственото, което ми идва на акъла е, че е заради windowd потребителите, които за да имат поддръжка на finfo трябва да ползват http://gnuwin32.sourceforge.net/ ($2)).


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 07, 2014, 08:30
Реших да погледна сорса на fileinfo и се натъкнах на това https://github.com/php/php-src/blob/master/ext/fileinfo/create_data_file.php ($2).

Код:
Bundle the data file - you can still use the external file if you

Явно РНР си ползва наистина собствена mime база, ако искам да ползвам системната ще трябва да се прекомпилира :(


Титла: Re: PHP finfo vs command file
Публикувано от: borovaka в Nov 07, 2014, 09:40
То си пише, че ползват собствена база.
Интересното е защо резултата при теб е такъв.
Код
GeSHi (PHP):
  1. <?php
  2. $finfo = new finfo(FILEINFO_MIME);
  3. $fres = $finfo->file('test.odt');
  4. echo $fres;
Този скрипт при мен си връща application/vnd.oasis.opendocument.text; charset=binary

Ти провери ли дали нямаш сетната MAGIC env variable? Тествай с getenv, дали проблема не е от там.

Иначе правя тест на 5.5.9 и резултата е ОК.


Титла: Re: PHP finfo vs command file
Публикувано от: k0tka в Nov 07, 2014, 09:44
Да...

при strace -e open file -i something.odt се вижда, че file търси за няколко файла:

Код:
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/usr/lib64/libmagic.so.1", O_RDONLY) = 3
open("/lib64/libz.so.1", O_RDONLY)      = 3
open("/lib64/libc.so.6", O_RDONLY)      = 3
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
open("/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 3
open("/etc/magic.mgc", O_RDONLY)        = -1 ENOENT (No such file or directory)
open("/etc/magic", O_RDONLY)            = 3
open("/usr/share/misc/magic.mgc", O_RDONLY) = 3
open("File.odt", O_RDONLY)

В същото време ако подам /usr/share/misc/magic.mgc на finfo_open() не гърми с грешки и отново работи и при strace -e open php-cgi test.php се вижда:
Код:
<?php
$mimedb = "/usr/share/misc/magic.mgc";
$finfo = finfo_open(FILEINFO_MIME, $mimedb);
echo finfo_file($finfo,"File.odt");
finfo_close($finfo);
?>
Код:
open("/usr/share/misc/magic.mgc", O_RDONLY) = 3

И се чудя ако опиташ с моя /usr/share/misc/magic.mgc дали ще заработи...  ::)


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 07, 2014, 10:23
То си пише, че ползват собствена база.
Интересното е защо резултата при теб е такъв.
Код
GeSHi (PHP):
  1. <?php
  2. $finfo = new finfo(FILEINFO_MIME);
  3. $fres = $finfo->file('test.odt');
  4. echo $fres;
Този скрипт при мен си връща application/vnd.oasis.opendocument.text; charset=binary

Ти провери ли дали нямаш сетната MAGIC env variable? Тествай с getenv, дали проблема не е от там.

Иначе правя тест на 5.5.9 и резултата е ОК.

Това зависи от файла, с който тестваш. В 90% от случаите odt файловете се разпознават коректно. Но има едни файлове, за които mime-type-а  се различава по начина, който съм описал. Навсякъде, където по-горе съм използвал File.odt съм имал впредвид такъв файл. Ако направя нов файл с офис-пакета, сейвна го и после му проверя mime-type всичко е наред - и file и fileinfo го  разпознават еднакво.
File.odt се отваря нормално от офиса пакета. Интересно, че ако го конвертирам с нещо такова:
Код:
libreoffice --headless --invisible --norestore --nologo --nolockcheck --nodefault --convert-to odt File._odt
конвертираният файл отново се разпознава като "application/octet-stream"  с fileinfo.

И се чудя ако опиташ с моя /usr/share/misc/magic.mgc дали ще заработи...  ::)

Не вярам, но ако държиш може да опитаме. Форматът, който ползва РНР се различава от този в mime.mgc - виж скрипта, който съм дал за конвертиране.
Тъпото е, че РНР-то се опъва при компилацията от сорс (current debian jessie/sid) с грешки:
Код:
undefined reference to symbol 'pthread_mutexattr_settype@@GLIBC_2.2.5'
...
undefined reference to symbol 'DSA_get_default_method@@OPENSSL_1.0.0'


Титла: Re: PHP finfo vs command file
Публикувано от: k0tka в Nov 07, 2014, 10:31
ъъъъъ чакай, ако има няколко типа odt то вероятно и при мен/нас няма да работи...аз тествах с първия който намерих... ако искаш изпразни файла и дай да тестваме пак.
Иначе ето го: http://cl.ly/1k0d3O1z390i



Титла: Re: PHP finfo vs command file
Публикувано от: borovaka в Nov 07, 2014, 10:33
Дам, ако е възможно качи някъде такъв файл да се тества.
Иначе опитах с конвертиран файл и отново резултата е нормален.


Титла: Re: PHP finfo vs command file
Публикувано от: 4096bits в Nov 07, 2014, 12:09
Ами това би трябвало лесно да може да се оправи, но ако си програмист. Явно РНР гледа хедъра на файла, за да определи mime типа. Това *.нещо-си-накрая не го ли отбелязва?!


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 08, 2014, 07:37
Ето примерен файл: https://www.dropbox.com/s/vb7ha6bi8wp8bf2/ODT_Not_ODT.odt?dl=0 ($2)


Титла: Re: PHP finfo vs command file
Публикувано от: borovaka в Nov 08, 2014, 11:59
Интересно при мен отново си работи както трябва:

Код
GeSHi (PHP):
  1. <?php
  2. $finfo = new finfo(FILEINFO_MIME,'/usr/share/misc/magic.mgc');
  3. $fres = $finfo->file('ODT_Not_ODT.odt');
  4. echo $fres;

Изход:
application/vnd.oasis.opendocument.text; charset=binary

Според мен нещо при компилацията на пакетите при Debian е сбъркано. Опита ли да прекомпилираш директно от сорс?


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 08, 2014, 13:25
Интересно при мен отново си работи както трябва:

Код
GeSHi (PHP):
  1. <?php
  2. $finfo = new finfo(FILEINFO_MIME,'/usr/share/misc/magic.mgc');
  3. $fres = $finfo->file('ODT_Not_ODT.odt');
  4. echo $fres;

Изход:
application/vnd.oasis.opendocument.text; charset=binary

С коя версия на РНР си, какво имаш в phpinfo() за fileinfo?

Според мен нещо при компилацията на пакетите при Debian е сбъркано. Опита ли да прекомпилираш директно от сорс?

Да по-горе писах - гърми при конфигурирането на сорса още с
Код:
checking for mysql_close in -lmysqlclient_r... no
checking for mysql_error in -lmysqlclient_r... no
configure: error: mysql configure failed. Please check config.log for more information.
debian/rules:287: recipe for target 'configure-apache2-stamp' failed
make: *** [configure-apache2-stamp] Error 1

В config.log грешката е:
Код:
configure:59703: checking for mysql_close in -lmysqlclient_r
configure:59728: x86_64-linux-gnu-gcc -o conftest -I/usr/include -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -O2 -Wall -fsigned-char -fno-strict-aliasin
g   -g -D_FORTIFY_SOURCE=2 -L/usr/lib/x86_64-linux-gnu -L/usr/lib -Wl,-z,relro -L/usr/lib/x86_64-linux-gnu conftest.c -lmysqlclient_r  -lonig -lstdc++ -lcrypto -lssl -ldb -l
qdbm -lbz2 -lz -lpcre -lcrypto -lssl -lrt -lm -ldl -lnsl  -lxml2 -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lxml2 >&5
/usr/bin/ld: /usr/lib/libmysqlclient_r.a(my_thr_init.c.o): undefined reference to symbol 'pthread_mutexattr_settype@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status


Титла: Re: PHP finfo vs command file
Публикувано от: borovaka в Nov 08, 2014, 14:33
fileinfo version   1.0.5-dev, версията на PHP e 5.5.9

Ти коя версия се опитваш да компилираш, с какви флагове на configure?

Виж дали това ще ти свърши работа за грешката която дъни pthread:
http://askubuntu.com/questions/521706/error-adding-symbols-dso-missing-from-command-line-while-compiling-g13-driver


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 08, 2014, 19:00
Проблемът можа да се окаже наистина дебиански - всичките РС-та, до които имам достъп в момента са все дебиански и резултатът е един и същ (все РНР 5.6.* между другото).

Проблемът с компилирането на РНР от сорс също е дебиански - взимам сорса с "apt-get source php5", и след това "dpkg-buildpackage -B", което гърми с грешката от по-горе. В същото време, ако направя стандартните "./configure && make" в директорията със сорса на РНР всичко се билдва нормално. Разучавам debian/rules да видя дали няма да мога да го компилирам по дебиански.

Има и още една подобна грешка в лога:
Код:
configure:24235: checking for DSA_get_default_method in -lssl
configure:24260: x86_64-linux-gnu-gcc -o conftest -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -O2 -Wall -fsigned-char -fno-strict-aliasing   -g -D_FORT$
/usr/bin/ld: /tmp/ccTXMexf.o: undefined reference to symbol 'DSA_get_default_method@@OPENSSL_1.0.0'
//usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
configure:24260: $? = 1


Титла: Re: PHP finfo vs command file
Публикувано от: senser в Nov 13, 2014, 09:06
Тествах на РНР 5.5.* и там файлът се разпозна правилно. На същата система обаче системната file е по-стара версия (5.18, на моята машина е 5.20), който пък казва, че файлът е "application/octet-stream; charset=binary"  ???
В същото време модерните браузъри, поддържащи HTML5 File API, се справят доста добре със задачата за познаване на MIME типа (ползват https://mimesniff.spec.whatwg.org/ ($2)).
В кр. сметка решението, което направих за мен, е комбиниране на трите (различни) резултата, от finfo, file & browser, и така избиране на "подходящ" mime.


Титла: Re: PHP finfo vs command file
Публикувано от: NorthBridge в Nov 15, 2014, 22:10
Понеже спомена mimesniff, ето ти един MimeReader клас ($2) който ползва същата спецификация. Не съм го тествал лично, няколко колеги много го хвалят. Дано ти свърши работа  [_]3