Is getting the version of a exe possible with php? I\'d like to print the version of a file that can be downloaded...
Windows exe and php is running on linux server<
For me to get the code from Toni to work I had to do a small change:
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;
}
Where I only changed 14 to 16 in the line
$NumDirs=unpack("v",substr($Info,16,2));
Maybe this has something to do with what j_schultz already added in the comments.
I combined the answers together and added the NamedDirs fix. Also want to highlight not to use the code by NeuD, the offset should remain 16; 14 is definitely wrong. Hope it helps someone.
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;
}