简体   繁体   中英

Check if a file is archive (zip or rar) using php

How can i check if a file is archived (zip or rar) without knowing the extension. I need to find it using php.

I cannot use Fileinfo because its not installed and installation of any other packages on the server its out of the question.

UPDATE:

Zip module its not installed and i cannot install extra packages. I don't want to use mime_content_type because its deprecated

Thank you

Output from od -c :

  0000000    R   a   r   ! 032  \a  \0 317 220   s  \0  \0  \r  \0  \0  \0

  0000000    P   K 003 004  \n  \0  \0  \0  \0  \0  \0  \0   !  \0  \0  \0

You could use something like this:

<?php

$fh = @fopen($argv[1], "r");

if (!$fh) {
  print "ERROR: couldn't open file.\n";
  exit(126);
}

$blob = fgets($fh, 5);

fclose($fh);

if (strpos($blob, 'Rar') !== false) {
  print "Looks like a Rar.\n";
} else
if (strpos($blob, 'PK') !== false) {
  print "Looks like a ZIP.\n";
} else {
  print "I dunno.\n";
  exit(1);
}

?>

And my output:

ghoti@baz:~ 423$ ./filephp.php A2.rar
Looks like a Rar.
ghoti@baz:~ 424$ ./filephp.php OLDIE.zip 
Looks like a ZIP.
ghoti@baz:~ 425$ ./filephp.php 1-11-1.PDF 
I dunno.
ghoti@baz:~ 426$ 

To test whether a file is a zip archive, you can attempt to open it as a zip using open_zip function. For rar, you need to have PECL rar (preferably version at least 2.0.0) installed - see http://php.net/manual/en/book.rar.php for more details. The code could look like this:

if(is_resource($zip = zip_open($filename)))
{
    zip_close($zip);
    //this is a zip archive
}
elseif(($rar = RarArchive::open($filename)) !== FALSE)
{
    $rar->close();
    //this is a rar archive
}
else
{
    //this is not a zip or rar archive
}

You may need to do a bit extra work if the archives are password-protected. Read the corresponding php manual pages for more details.

Read first 10 bytes of the file. If they are (80, 75, 3, 4, 20, 0, 0, 0, 8, 0) it is a ZIP file. RAR files have the following 7 first bytes: (82, 97, 114, 33, 26, 7, 0) If you open a ZIP file in a text editor (for instance, Notepad++) you will see: PK[ETX][EOT][DC4][NUL][NUL][NUL][BS][NUL]....-> the Ascii codes for the characters are listed above. For the RAR files the picture is: Rar![SUB][BEL][NUL].... So, just read the 10 first bytes of a file and you can tell if it is ZIP or RAR archive. Cheers

The fileinfo functions should help you with this, by checking the file's mime type:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $filename); // This will return the mime-type
finfo_close($finfo);

You could output the info from unix file command and parse it(assuming you can execute system commands, which is bad practice).

This is example of centos "file filename " output.

[rr@localhost images] (master)# file ui-anim_basic_16x16.gif ui-anim_basic_16x16.gif: GIF image data, version 89a, 16 x 16

[rr@localhost images] (master)# file ui-icons_454545_256x240.png ui-icons_454545_256x240.png: PNG image data, 256 x 240, 8-bit colormap, non-interlaced

[rr@localhost vendors] (master)# file jquery-validation-1.9.0.zip jquery-validation-1.9.0.zip: Zip archive data, at least v1.0 to extract

also like other people suggested, you could read few bytes and check if they match signature.

for rar

Identifying characters Hex: 52 61 72 21 1A 07 00 , ASCII: Rar!

for zip

Identifying characters Hex: 50 4B 03 04 , ASCII: PK

<?php

function isZipFile($filepath){
    $fh = fopen($filepath,'r');
    $bytes = fread($fh,4);
    fclose($fh);
    return ('504b0304' === bin2hex($bytes));
}

Thanks to flu for the helpful link to the zip file specification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM