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

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


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.

Tags:

Php