Php получить версию файла

PHP: Как получить версию из файла Android .apk?

Я пытаюсь создать PHP скрипт, чтобы получить версию приложения из файла APK от Android. Извлечение XML файла из файла APK (zip), а затем синтаксический анализ XML — один из способов, но я думаю, это должно быть проще. Что-то вроде Руководство PHP, пример № 3. Любые идеи о создании script?

5 ответов

Если у вас установлен Android SDK на сервере, вы можете использовать PHP exec (или аналогичный) для выполнения инструмента aapt (в $ANDROID_HOME/platforms/android-X/tools ).

$ aapt dump badging myapp.apk
package: name='com.example.myapp' versionCode='1530' versionName='1.5.3'

Если вы не можете установить Android SDK, по какой-то причине, вам нужно будет разобрать Android-формат XML. Файл AndroidManifest.xml внутри структуры ZIP APK является не простым текстом.

Вам нужно будет поместить утилиту такую ​​как AXMLParser с Java на PHP.

Без Android SDK на сервере, с PHP-скриптом. Я ищу решение, как в ссылке, которую я разместил (пример № 3)

@ChristopherOrr Можете ли вы привести пример первого способа, я не могу запустить его через мой Windows Server!

@ChristopherOrr Мой код exec(«e:\\Develop files\\androidsdk\\platform-tools\\aapt.exe \\aapt dump badging bz.apk»,$resultSet); print_r($resultSet);

Я создал набор функций PHP, которые найдут только код версии APK. Это основано на том, что файл AndroidMainfest.xml содержит код версии в качестве первого тега и основан на формате axml (двоичный формат Android XML) в качестве описанном здесь

  > > zip_close($zip); return $versionCode; > //Get the contents of the file in hex format function getHex($zip, $zip_entry) < if (zip_entry_open($zip, $zip_entry, 'r')) < $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); $hex = unpack("H*", $buf); return current($hex); >> //Given a hex byte stream, return an array of words function convert2wordArray($hex) < $wordArr = array(); $numwords = strlen($hex)/8; for ($i = 0; $i < $numwords; $i++) $wordArr[] = substr($hex, $i * 8, 8); return $wordArr; >//Given an array of words, convert them to Little Endian format (LSB first) function convert2LEWwordArray($wordArr) < $LEWArr = array(); foreach($wordArr as $word) < $LEWword = ""; for ($i = 0; $i < strlen($word)/2; $i++) $LEWword .= substr($word, (strlen($word) - ($i*2) - 2), 2); $LEWArr[] = $LEWword; >return $LEWArr; > //Find a word in the word array and return its index value function findWord($wordArr, $wordToFind) < $currentword = 0; foreach ($wordArr as $word) < if ($word == $wordToFind) return $currentword; else $currentword++; >> ?> 

Формат дампа немного странный и не самый простой для работы. Чтобы развернуть некоторые другие ответы, это оболочка script, которую я использую для анализа имени и версии из файлов APK.

aapt d badging PACKAGE | gawk $'match($0, /^application-label:\'([^\']*)\'/, a) < n = a[1] >match($0, /versionName=\'([^\']*)\'/, b) < v=b[1] >END < if ( length(n)>0 && length(v)>0 ) < print n, v >>' 

Если вы просто хотите версию, то, очевидно, это может быть намного проще.

aapt d badging PACKAGE | gawk $'match($0, /versionName=\'([^\']*)\'/, v) < print v[1] >' 

Вот варианты, подходящие как для gawk, так и для mawk (немного менее прочный, если формат дампа изменяется, но должен быть хорошим):

aapt d badging PACKAGE | mawk -F\' '$1 ~ /^application-label:$/ < n=$2 >$5 ~ /^ versionName=$/ < v=$6 >END< if ( length(n)>0 && length(v)>0 ) < print n, v >>' aapt d badging PACKAGE | mawk -F\' '$5 ~ /^ versionName=$/ < print $6 >' 

Источник

Узнать версию файла на сервере

Как вытащить средствами РНР версию файла например 2.0 ?
Например:
Пишут же «Ваш продукт устарел обновите по ссылке», идем по ссылки и видим «Доступны обновления 2.0.0.1» или тому подобное
Или на сервере заливать файл как то нужно, но не знаю суть в том что нужно получить версию файла с сайта?
Помогите пж, хотя бы укажите ссылку куда копать?
Заранее благодарчик

Узнать версию ОС
хотелось бы попробовать пример с оператором исполнения, но прежде чем его использовать(например.

Можно ли узнать о система? Например, версию винды, запускать какую нибуд прогу?
Можно ли узнать о система? Например, версию винды, запускать какую нибуд прогу?

Узнать дату файлов на сервере
Привет, следующий код отображает дату изменения файла если указать название файла в коде, можно.

Узнать дату файлов на сервере
Есть сервер в корне.tmp/ лежат файлы как узнать день месяц из даты файла имя не обязательно. Делаю.

тогда придется при каждой загрузки новой версии файла на сервер, лазить в БД.
Сделал так, раз уж все равно лезим на сервер по FTP, создал файл *.txt в том каталоге где и файл для скачки *.exe и туда написал версию файла. Если хотим узнать версию файла, просто считываем с *.txt Файла данные. Думаю это тоже не оптимальный вариант решения, так как при каждой загрузки *.exe опять же открываем и записываем версию в *.txt, если забыли обновить версию в файле *.txt, все конец света! =)

Эксперт PHP

radaslav, можно так:
— Создаёте отдельную папку для вашей программы, потом с помощью вот такого скрипта смотрите версию:

1 2 3 4 5 6 7 8 9 10 11 12
 # Ищем exe-файл в папке $file_name = glob('ваша папка/*.exe'); # Вытягиваем версию preg_match( '#_([0-9\.]*)\.exe#i', $file_name[0], $mathes ); # Присваниваем переменной $version = $mathes[1]; echo $version; ?>

Только нужно обязательно соблюдать правило именования файла:
Имя должно иметь такой вид: любые символы_версия.exe

Источник

Получить версию exe через PHP

Я хотел получить то же самое, поэтому я закодировал это: он возвращает FALSE, если он не может получить информацию о версии, или ARRAY из четырех элементов с полями версии файла (числа, которые разделены.) Он работает только для 32- битных файлов PE (так как мне не нужны были другие форматы).

function GetFileVersion($FileName) < $handle=fopen($FileName,'rb'); if (!$handle) return FALSE; $Header=fread ($handle,64); if (substr($Header,0,2)!='MZ') return FALSE; $PEOffset=unpack("V",substr($Header,60,4)); if ($PEOffset[1]<64) return FALSE; fseek($handle,$PEOffset[1],SEEK_SET); $Header=fread ($handle,24); if (substr($Header,0,2)!='PE') return FALSE; $Machine=unpack("v",substr($Header,4,2)); if ($Machine[1]!=332) return FALSE; $NoSections=unpack("v",substr($Header,6,2)); $OptHdrSize=unpack("v",substr($Header,20,2)); fseek($handle,$OptHdrSize[1],SEEK_CUR); $ResFound=FALSE; for ($x=0;$x<$NoSections[1];$x++) < //$x fixed here $SecHdr=fread($handle,40); if (substr($SecHdr,0,5)=='.rsrc') < //resource section $ResFound=TRUE; break; >> if (!$ResFound) return FALSE; $InfoVirt=unpack("V",substr($SecHdr,12,4)); $InfoSize=unpack("V",substr($SecHdr,16,4)); $InfoOff=unpack("V",substr($SecHdr,20,4)); fseek($handle,$InfoOff[1],SEEK_SET); $Info=fread($handle,$InfoSize[1]); $NumDirs=unpack("v",substr($Info,14,2)); $InfoFound=FALSE; for ($x=0;$x <$NumDirs[1];$x++) < $Type=unpack("V",substr($Info,($x*8)+16,4)); if($Type[1]==16) < //FILEINFO resource $InfoFound=TRUE; $SubOff=unpack("V",substr($Info,($x*8)+20,4)); break; >> if (!$InfoFound) return FALSE; $SubOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$SubOff[1]+20,4)); //offset of first FILEINFO $InfoOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$InfoOff[1]+20,4)); //offset to data $DataOff=unpack("V",substr($Info,$InfoOff[1],4)); $DataSize=unpack("V",substr($Info,$InfoOff[1]+4,4)); $CodePage=unpack("V",substr($Info,$InfoOff[1]+8,4)); $DataOff[1]-=$InfoVirt[1]; $Version=unpack("v4",substr($Info,$DataOff[1]+48,8)); $x=$Version[2]; $Version[2]=$Version[1]; $Version[1]=$x; $x=$Version[4]; $Version[4]=$Version[3]; $Version[3]=$x; return $Version; > 

На машине win32 вы можете использовать расширение COM и метод FileSystemObject.GetFileVersion () для получения информации о версии. например

$path = getenv('SystemRoot').'\\NOTEPAD.EXE'; $fso = new COM('Scripting.FileSystemObject'); echo $path, ' : ', $fso->GetFileVersion($path); 

(на моей машине) C:\WINDOWS\NOTEPAD.EXE : 5.1.2600.5512

Недавно я перенес наш хостинг из Windows в Linux. Это было довольно легко сделать с VBScript с учетом объектов Microsoft, но в Linux и PHP я ничего не мог найти. Мы написали эту функцию в PHP, чтобы отсканировать файл .exe и извлечь «Версию продукта», в которой было приложение VB.Net. Вы можете изменить ключ $, чтобы быть любой строкой, которую вы можете найти с информацией о версии и нулевым терминатором.

Обратите внимание, что это сканирует файлы в 64k кусках, ища строку $ key. Если у вас большой .exe, это может занять несколько секунд. Мой .exe – 52k, так что это почти мгновенно. Если у вас больше EXE, вы можете изменить сканирование.

 fclose($fptr); if (strpos($data, $key)===FALSE) return ""; $pos = strpos($data, $key)+strlen($key); $version = ""; for ($i=$pos; $data[$i]!="\x00"; $i+=2) $version .= $data[$i]; return $version; > echo get_product_version("/path_to_file/foo.exe"); ?> 

Я предполагаю, что вы не в Windows, и вы имеете в виду информацию о версии, которая может быть сохранена в исполняемых файлах Windows, и появляется в диалоговом окне свойств для такого файла в проводнике Windows.

Эта информация, похоже, хранится в блоке VS_VERSION_INFO исполняемого файла (см., Например, этот вопрос ). Я не знаю никакого инструмента, который извлекает эту информацию простым способом, даже не в самой Windows.

Кажется, есть несколько способов получить эту информацию через Windows API (см. Пример Perl здесь ), но я не вижу никакого подхода, который работает «с нуля», просто анализируя исполняемый файл.

Если вы копаете немного, вы можете найти описание формата файла, которое объясняет, как читать информацию VS_VERSION_INFO из EXE-файла. Будьте готовы к большой работе, чтобы заставить это работать надежно.

Будьте готовы потратить много времени и усилий, если вы хотите это сделать.

Выработка ответа на вопрос Тони. Один из проектов на рабочем месте имел специальный атрибут, запеченный в этой секции ресурсов. На машине linux мы не хотели устанавливать perl для использования функции windows для получения значений. Вместо этого можно использовать этот вариант GetFileVersion для получения любого значения, которое вы ищете. (FileVersion, ProductVersion, ProductName, CompanyName, CompanyWebsite) Он должен возвращать false для значений, которые не существуют, и он функционирует довольно быстро.

 $handle=fopen($FileName,'rb'); if (!$handle) return FALSE; $Header=fread ($handle,64); if (substr($Header,0,2)!='MZ') return FALSE; $PEOffset=unpack("V",substr($Header,60,4)); if ($PEOffset[1] <64) return FALSE; fseek($handle,$PEOffset[1],SEEK_SET); $Header=fread ($handle,24); if (substr($Header,0,2)!='PE') return FALSE; $Machine=unpack("v",substr($Header,4,2)); if ($Machine[1]!=332) return FALSE; $NoSections=unpack("v",substr($Header,6,2)); $OptHdrSize=unpack("v",substr($Header,20,2)); fseek($handle,$OptHdrSize[1],SEEK_CUR); $ResFound=FALSE; for ($x=0;$x<$NoSections[1];$x++) < $SecHdr=fread($handle,40); if (substr($SecHdr,0,5)=='.rsrc') < //resource section $ResFound=TRUE; break; >> if (!$ResFound) return FALSE; $InfoVirt=unpack("V",substr($SecHdr,12,4)); $InfoSize=unpack("V",substr($SecHdr,16,4)); $InfoOff=unpack("V",substr($SecHdr,20,4)); fseek($handle,$InfoOff[1],SEEK_SET); $Info=fread($handle,$InfoSize[1]); $NumDirs=unpack("v",substr($Info,14,2)); $InfoFound=FALSE; for ($x=0;$x <$NumDirs[1];$x++) < $Type=unpack("V",substr($Info,($x*8)+16,4)); if($Type[1]==16) < //FILEINFO resource $InfoFound=TRUE; $SubOff=unpack("V",substr($Info,($x*8)+20,4)); //echo $Info; break; >> if (!$InfoFound) return FALSE; // i bypassed this, but if you knew the layout you could prolly do a little better then $ulgyRemainderOfData /* $SubOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$SubOff[1]+20,4)); //offset of first FILEINFO $InfoOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$InfoOff[1]+20,4)); //offset to data $DataOff=unpack("V",substr($Info,$InfoOff[1],4)); $DataSize=unpack("V",substr($Info,$InfoOff[1]+4,4)); $CodePage=unpack("V",substr($Info,$InfoOff[1]+8,4)); $DataOff[1]-=$InfoVirt[1]; $Version=unpack("v4",substr($Info,$DataOff[1]+48,8)); // swap 1-2 3-4 / endian ecoding issue $x=$Version[2]; $Version[2]=$Version[1]; $Version[1]=$x; $x=$Version[4]; $Version[4]=$Version[3]; $Version[3]=$x; return $Version; */ //view data. //echo print_r(explode("\x00\x00\x00", $Info)); // could prolly substr on VS_VERSION_INFO $encodedKey = implode("\x00",str_split($seeking)); $StartOfSeekingKey = strpos($Info, $encodedKey); if ($StartOfSeekingKey !== false) < $ulgyRemainderOfData = substr($Info, $StartOfSeekingKey); $ArrayOfValues = explode("\x00\x00\x00", $ulgyRemainderOfData); // the key your are seeking is 0, where the value is one return trim($ArrayOfValues[1]); >return false; > $fileVersion = GetValueOfSeeking("./the/path/to/some.exe", 'FileVersion'); $myAttribute = GetValueOfSeeking("./the/path/to/some.exe", 'CustomAttribute'); 

Для меня, чтобы получить код от Тони для работы, мне пришлось сделать небольшое изменение:

function GetFileVersion($FileName) < $handle=fopen($FileName,'rb'); if (!$handle) return FALSE; $Header=fread ($handle,64); if (substr($Header,0,2)!='MZ') return FALSE; $PEOffset=unpack("V",substr($Header,60,4)); if ($PEOffset[1]<64) return FALSE; fseek($handle,$PEOffset[1],SEEK_SET); $Header=fread ($handle,24); if (substr($Header,0,2)!='PE') return FALSE; $Machine=unpack("v",substr($Header,4,2)); if ($Machine[1]!=332) return FALSE; $NoSections=unpack("v",substr($Header,6,2)); $OptHdrSize=unpack("v",substr($Header,20,2)); fseek($handle,$OptHdrSize[1],SEEK_CUR); $ResFound=FALSE; for ($x=0;$x<$NoSections[1];$x++) < //$x fixed here $SecHdr=fread($handle,40); if (substr($SecHdr,0,5)=='.rsrc') < //resource section $ResFound=TRUE; break; >> if (!$ResFound) return FALSE; $InfoVirt=unpack("V",substr($SecHdr,12,4)); $InfoSize=unpack("V",substr($SecHdr,16,4)); $InfoOff=unpack("V",substr($SecHdr,20,4)); fseek($handle,$InfoOff[1],SEEK_SET); $Info=fread($handle,$InfoSize[1]); $NumDirs=unpack("v",substr($Info,16,2)); $InfoFound=FALSE; for ($x=0;$x <$NumDirs[1];$x++) < $Type=unpack("V",substr($Info,($x*8)+16,4)); if($Type[1]==16) < //FILEINFO resource $InfoFound=TRUE; $SubOff=unpack("V",substr($Info,($x*8)+20,4)); break; >> if (!$InfoFound) return FALSE; $SubOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$SubOff[1]+20,4)); //offset of first FILEINFO $InfoOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$InfoOff[1]+20,4)); //offset to data $DataOff=unpack("V",substr($Info,$InfoOff[1],4)); $DataSize=unpack("V",substr($Info,$InfoOff[1]+4,4)); $CodePage=unpack("V",substr($Info,$InfoOff[1]+8,4)); $DataOff[1]-=$InfoVirt[1]; $Version=unpack("v4",substr($Info,$DataOff[1]+48,8)); $x=$Version[2]; $Version[2]=$Version[1]; $Version[1]=$x; $x=$Version[4]; $Version[4]=$Version[3]; $Version[3]=$x; return $Version; > 

Где я только изменил 14 – 16 в строке

$NumDirs=unpack("v",substr($Info,16,2)); 

Возможно, это имеет какое-то отношение к тому, что j_schultz уже добавил в комментариях.

Я объединил ответы вместе и добавил исправление NamedDirs. Также хочу подчеркнуть, что не использовать код NeuD, смещение должно оставаться 16; 14 определенно неверно. Надеюсь, это поможет кому-то.

function GetFileVersion($FileName) < return GetValueOfSeeking($FileName, "FileVersion"); >function GetValueOfSeeking($FileName, $seeking) < $handle = fopen($FileName, 'rb'); if (!$handle) return FALSE; $Header = fread($handle, 64); if (substr($Header, 0, 2) != 'MZ') return FALSE; $PEOffset = unpack("V", substr($Header, 60, 4)); if ($PEOffset[1]<64) return FALSE; fseek($handle, $PEOffset[1], SEEK_SET); $Header = fread ($handle, 24); if (substr($Header, 0, 2) != 'PE') return FALSE; $Machine = unpack("v", substr($Header, 4, 2)); if ($Machine[1] != 332) return FALSE; $NoSections = unpack("v", substr($Header, 6, 2)); $OptHdrSize = unpack("v", substr($Header, 20, 2)); fseek($handle, $OptHdrSize[1], SEEK_CUR); $ResFound = FALSE; for ($x = 0; $x < $NoSections[1]; $x++) < //$x fixed here $SecHdr = fread($handle, 40); if (substr($SecHdr, 0, 5) == '.rsrc') < //resource section $ResFound = TRUE; break; >> if (!$ResFound) return FALSE; $InfoVirt = unpack("V", substr($SecHdr, 12, 4)); $InfoSize = unpack("V", substr($SecHdr, 16, 4)); $InfoOff = unpack("V", substr($SecHdr, 20, 4)); fseek($handle, $InfoOff[1], SEEK_SET); $Info = fread($handle, $InfoSize[1]); $NumNamedDirs = unpack("v",substr($Info, 12, 2)); $NumDirs = unpack("v", substr($Info, 14, 2)); $InfoFound = FALSE; for ($x = 0; $x < ($NumDirs[1] + $NumNamedDirs[1]); $x++) < $Type = unpack("V", substr($Info, ($x * 8) + 16, 4)); if($Type[1] == 16) < //FILEINFO resource $InfoFound = TRUE; $SubOff = unpack("V", substr($Info, ($x * 8) + 20, 4)); break; >> if (!$InfoFound) return FALSE; if (0) < $SubOff[1] &= 0x7fffffff; $InfoOff = unpack("V", substr($Info, $SubOff[1] + 20, 4)); //offset of first FILEINFO $InfoOff[1] &= 0x7fffffff; $InfoOff = unpack("V", substr($Info, $InfoOff[1] + 20, 4)); //offset to data $DataOff = unpack("V", substr($Info, $InfoOff[1], 4)); $DataSize = unpack("V", substr($Info, $InfoOff[1] + 4, 4)); $CodePage = unpack("V", substr($Info, $InfoOff[1] + 8, 4)); $DataOff[1] -= $InfoVirt[1]; $Version = unpack("v4", substr($Info, $DataOff[1] + 48, 8)); $x = $Version[2]; $Version[2] = $Version[1]; $Version[1] = $x; $x = $Version[4]; $Version[4] = $Version[3]; $Version[3] = $x; return $Version; >//view data. //echo print_r(explode("\x00\x00\x00", $Info)); // could prolly substr on VS_VERSION_INFO $encodedKey = implode("\x00",str_split($seeking)); $StartOfSeekingKey = strpos($Info, $encodedKey); if ($StartOfSeekingKey !== false) < $ulgyRemainderOfData = substr($Info, $StartOfSeekingKey); $ArrayOfValues = explode("\x00\x00\x00", $ulgyRemainderOfData); // the key your are seeking is 0, where the value is one return trim($ArrayOfValues[1]); >return false; > 

Источник

Читайте также:  Java error illegal argument
Оцените статью