Function to list file formats inside a ZIP file

Discussion in 'PHP' started by archard, Sep 29, 2007.

  1. #1
    I'm looking for a function that will take a specified ZIP file, and list the file extensions of each file in the ZIP. For example, if the ZIP has a text file and a MIDI file in it, I'd like it to print ".txt, .mid"
     
    archard, Sep 29, 2007 IP
  2. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #2
    
    $file = 'full/path/to/file.zip';
    
    $contents = array();
    
    if (is_resource(($zip = zip_open($file))))
    {
    	while ($zip_entry = zip_read($zip))
    	{
    		$contents[] = end(explode('.', zip_entry_name($zip_entry)));		
    	}
    
    	zip_close($zip);
    }
    
    echo implode(', ', $contents);
    
    PHP:
     
    nico_swd, Sep 29, 2007 IP
  3. archard

    archard Peon

    Messages:
    221
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Didn't work unfortunately. In fact it sorta blows up whatever page you put this on. I put this into a drupal page and all that returned was a blank white page. Then I tried just putting it into a raw .php file and uploaded it to my public_html directory, still just a blank page.
     
    archard, Sep 29, 2007 IP
  4. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #4
    I tested it and it does work. You need to specify the FULL path to the file.

    If you're unsure, try something like this.
    
    $file = getcwd() . '/file.zip';
    
    PHP:

    As for Drupal, I have no idea, I think it might not be possible to enter it just like that. I'm not sure if they're using templates or something, but echoing the output just randomly in the middle could possibly cause errors.
     
    nico_swd, Sep 29, 2007 IP
  5. archard

    archard Peon

    Messages:
    221
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #5
    Hmm, I must be doing something stupid then, cause its just not working. I'm using PHP 5.2.3 if that's relevant.
     
    archard, Sep 29, 2007 IP
  6. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #6
    Perhaps you don't have the ZIP library installed. But you should get an undefined function error then.

    Try setting these 2 lines at the top of the script to see if you get any errors.
    
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
    
    PHP:
     
    nico_swd, Sep 29, 2007 IP
  7. archard

    archard Peon

    Messages:
    221
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #7
    Yep, looks like you got it:

    Fatal error: Call to undefined function zip_open() in /home/gametabs/public_html/zip.php on line 10
    Code (markup):
    I was gonna say, where are the $zip and $zip_open variables declared? But I'm assuming they're a part of a ZIP library I don't have installed. Or at least $zip_open is.
     
    archard, Sep 29, 2007 IP
  8. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #8
    Before complicating our lives, let's take a native class from phpclasses.org.

    This one to be exact.

    class.zip.php
    
    <?php
    
    class zipfile
    {
    	/*
    		zipfile class, for reading or writing .zip files
    		See http://www.gamingg.net for more of my work
    		Based on tutorial given by John Coggeshall at http://www.zend.com/zend/spotlight/creating-zip-files3.php
    		Copyright (C) Joshua Townsend and licensed under the GPL
    		Version 1.0
    	*/
    	var $datasec = array(); // array to store compressed data
    	var $files = array(); // array of uncompressed files
    	var $dirs = array(); // array of directories that have been created already
    	var $ctrl_dir = array(); // central directory
    	var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; //end of Central directory record
    	var $old_offset = 0;
    	var $basedir = ".";
    
    
    
    
    	function read_zip($name)
    	{
    		// Clear current file
    		$this->datasec = array();
    
    		// File information
    		$this->name = $name;
    		$this->mtime = filemtime($name);
    		$this->size = filesize($name);
    
    		// Read file
    		$fh = fopen($name, "rb");
    		$filedata = fread($fh, $this->size);
    		fclose($fh);
    
    		// Break into sections
    		$filesecta = explode("\x50\x4b\x05\x06", $filedata);
    
    		// ZIP Comment
    		$unpackeda = unpack('x16/v1length', $filesecta[1]);
    		$this->comment = substr($filesecta[1], 18, $unpackeda['length']);
    		$this->comment = str_replace(array("\r\n", "\r"), "\n", $this->comment); // CR + LF and CR -> LF
    
    		// Cut entries from the central directory
    		$filesecta = explode("\x50\x4b\x01\x02", $filedata);
    		$filesecta = explode("\x50\x4b\x03\x04", $filesecta[0]);
    		array_shift($filesecta); // Removes empty entry/signature
    
    		foreach($filesecta as $filedata)
    		{
    			// CRC:crc, FD:file date, FT: file time, CM: compression method, GPF: general purpose flag, VN: version needed, CS: compressed size, UCS: uncompressed size, FNL: filename length
    			$entrya = array();
    			$entrya['error'] = "";
    
    			$unpackeda = unpack("v1version/v1general_purpose/v1compress_method/v1file_time/v1file_date/V1crc/V1size_compressed/V1size_uncompressed/v1filename_length", $filedata);
    
    			// Check for encryption
    			$isencrypted = (($unpackeda['general_purpose'] & 0x0001) ? true : false);
    
    			// Check for value block after compressed data
    			if($unpackeda['general_purpose'] & 0x0008)
    			{
    				$unpackeda2 = unpack("V1crc/V1size_compressed/V1size_uncompressed", substr($filedata, -12));
    
    				$unpackeda['crc'] = $unpackeda2['crc'];
    				$unpackeda['size_compressed'] = $unpackeda2['size_uncompressed'];
    				$unpackeda['size_uncompressed'] = $unpackeda2['size_uncompressed'];
    
    				unset($unpackeda2);
    			}
    
    			$entrya['name'] = substr($filedata, 26, $unpackeda['filename_length']);
    
    			if(substr($entrya['name'], -1) == "/") // skip directories
    			{
    				continue;
    			}
    
    			$entrya['dir'] = dirname($entrya['name']);
    			$entrya['dir'] = ($entrya['dir'] == "." ? "" : $entrya['dir']);
    			$entrya['name'] = basename($entrya['name']);
    
    
    			$filedata = substr($filedata, 26 + $unpackeda['filename_length']);
    
    			if(strlen($filedata) != $unpackeda['size_compressed'])
    			{
    				$entrya['error'] = "Compressed size is not equal to the value given in header.";
    			}
    
    			if($isencrypted)
    			{
    				$entrya['error'] = "Encryption is not supported.";
    			}
    			else
    			{
    				switch($unpackeda['compress_method'])
    				{
    					case 0: // Stored
    						// Not compressed, continue
    					break;
    					case 8: // Deflated
    						$filedata = gzinflate($filedata);
    					break;
    					case 12: // BZIP2
    						if(!extension_loaded("bz2"))
    						{
    							@dl((strtolower(substr(PHP_OS, 0, 3)) == "win") ? "php_bz2.dll" : "bz2.so");
    						}
    
    						if(extension_loaded("bz2"))
    						{
    							$filedata = bzdecompress($filedata);
    						}
    						else
    						{
    							$entrya['error'] = "Required BZIP2 Extension not available.";
    						}
    					break;
    					default:
    						$entrya['error'] = "Compression method ({$unpackeda['compress_method']}) not supported.";
    				}
    
    				if(!$entrya['error'])
    				{
    					if($filedata === false)
    					{
    						$entrya['error'] = "Decompression failed.";
    					}
    					elseif(strlen($filedata) != $unpackeda['size_uncompressed'])
    					{
    						$entrya['error'] = "File size is not equal to the value given in header.";
    					}
    					elseif(crc32($filedata) != $unpackeda['crc'])
    					{
    						$entrya['error'] = "CRC32 checksum is not equal to the value given in header.";
    					}
    				}
    
    				$entrya['filemtime'] = mktime(($unpackeda['file_time']  & 0xf800) >> 11,($unpackeda['file_time']  & 0x07e0) >>  5, ($unpackeda['file_time']  & 0x001f) <<  1, ($unpackeda['file_date']  & 0x01e0) >>  5, ($unpackeda['file_date']  & 0x001f), (($unpackeda['file_date'] & 0xfe00) >>  9) + 1980);
    				$entrya['data'] = $filedata;
    			}
    
    			$this->files[] = $entrya;
    		}
    
    		return $this->files;
    	}
    
    }
    ?>
    
    PHP:
    (Note: I removed all unnecessary methods from the class)

    
    <?php
    
    include 'class.zip.php';
    
    $file = 'file.zip';
    
    $zip = new zipfile();
    $content = array();
    
    foreach ($zip->read_zip($file) AS $filedata)
    {
    	$content[] = end(explode('.', $filedata['name']));
    }
    
    echo implode(', ', $content);
    
    ?>
    
    PHP:
     
    nico_swd, Sep 29, 2007 IP
    archard likes this.
  9. archard

    archard Peon

    Messages:
    221
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #9
    You sir, are a god amongst men :D
     
    archard, Sep 29, 2007 IP
  10. archard

    archard Peon

    Messages:
    221
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #10
    MY host just installed zlib for me. Do I still need to include the zipfile class?
     
    archard, Sep 29, 2007 IP
  11. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #11
    If they installed zlib you can use the first code without any includes.
     
    nico_swd, Sep 30, 2007 IP