在没有exec的情况下创建zip或tar.gz存档

时间:2011-08-10 01:36:28

标签: php zip tar

是否有任何安全的方法可以在不使用exec命令的情况下从php创建zip存档或tar.gz?

感谢

5 个答案:

答案 0 :(得分:40)

如果你想创建tar.gz而你正在使用PHP 5.3+,你可以使用PharData class:

try
{
    $a = new PharData('archive.tar');

    // ADD FILES TO archive.tar FILE
    $a->addFile('data.xls');
    $a->addFile('index.php');

    // COMPRESS archive.tar FILE. COMPRESSED FILE WILL BE archive.tar.gz
    $a->compress(Phar::GZ);

    // NOTE THAT BOTH FILES WILL EXISTS. SO IF YOU WANT YOU CAN UNLINK archive.tar
    unlink('archive.tar');
} 
catch (Exception $e) 
{
    echo "Exception : " . $e;
}

答案 1 :(得分:22)

您可以使用PHP的Zip类创建zip文件,使用ZLib创建gzip文件。

创建.zip文件:

$zip = new ZipArchive();
$res = $zip->open('test.zip', ZipArchive::CREATE);
$zip->addFromString('test.txt', 'file content goes here');
$zip->addFile('data.txt', 'entryname.txt');
$zip->close();

创建.gz文件:

$file = "test.txt";
$gzfile = "test.gz";
$fp = gzopen($gzfile, 'w9'); // w == write, 9 == highest compression
gzwrite($fp, file_get_contents($file));
gzclose($fp);

答案 2 :(得分:4)

请改用系统命令

http://php.net/manual/en/function.system.php

请注意有关如何防止恶意输入的说明部分。

编辑:使用ZipArchive类通过open()命令http://www.php.net/manual/en/class.ziparchive.php

创建一个新的zip

答案 3 :(得分:1)

有一种非常简单的方法可以直接在PHP中创建Tar-archives - 您可以在LGPL下的Dennis Wronka找到sourceforge的CLASS,这样您也可以在商业脚本中使用。

<?php
/**
 * @package PHPClassCollection
 * @subpackage Tar
 * @link classes
 * @author Dennis Wronka <reptiler@users.sourceforge.net>
 */
/**
 * @package PHPClassCollection
 * @subpackage Tar
 * @link classes
 * @author Dennis Wronka <reptiler@users.sourceforge.net>
 * @version 1.1
 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPL 2.1
 */
class tar
{
/**
 * The name of the tar-file to create.
 *
 * @var string
 */
var $filename;
/**
 * The list of files to add to the archive.
 *
 * @var array
 */
var $filelist=array();

/**
 * Constructor
 *
 * @param string $filename
 */
function tar($filename)
{
    $this->filename=$filename;
}

/**
 * Add a file.
 *
 * @param string $filename
 */
function add($filename)
{
    if ((file_exists($filename)) && (is_readable($filename)))
    {
        $this->filelist[]=$filename;
    }
}

/**
 * Write the tar-file.
 *
 * @return bool
 */
function write()
{
    sort($this->filelist);
    $tarfile=@fopen($this->filename,'w');
    if ($tarfile==false)
    {
        return false;
    }
    for ($x=0;$x<count($this->filelist);$x++)
    {
        $filename=$this->filelist[$x];
        if ((is_dir($this->filelist[$x])) && (substr($this->filelist[$x],-1)!='/'))
        {
            $filename.='/';
        }
        while (strlen($filename)<100)
        {
            $filename.=chr(0);
        }
        $permissions=sprintf('%o',fileperms($this->filelist[$x])).chr(0);
        while (strlen($permissions)<8)
        {
            $permissions='0'.$permissions;
        }
        $userid=sprintf('%o',fileowner($this->filelist[$x])).chr(0);
        while (strlen($userid)<8)
        {
            $userid='0'.$userid;
        }
        $groupid=sprintf('%o',filegroup($this->filelist[$x])).chr(0);
        while (strlen($groupid)<8)
        {
            $groupid='0'.$groupid;
        }
        if (is_dir($this->filelist[$x]))
        {
            $filesize='0'.chr(0);
        }
        else
        {
            $filesize=sprintf('%o',filesize($this->filelist[$x])).chr(0);
        }
        while (strlen($filesize)<12)
        {
            $filesize='0'.$filesize;
        }
        $modtime=sprintf('%o',filectime($this->filelist[$x])).chr(0);
        $checksum='        ';
        if (is_dir($this->filelist[$x]))
        {
            $indicator=5;
        }
        else
        {
            $indicator=0;
        }
        $linkname='';
        while (strlen($linkname)<100)
        {
            $linkname.=chr(0);
        }
        $ustar='ustar  '.chr(0);
        if (function_exists('posix_getpwuid'))
        {
            $user=posix_getpwuid(octdec($userid));
            $user=$user['name'];
        }
        else
        {
            $user='';
        }
        while (strlen($user)<32)
        {
            $user.=chr(0);
        }
        if (function_exists('posix_getgrgid'))
        {
            $group=posix_getgrgid(octdec($groupid));
            $group=$group['name'];
        }
        else
        {
            $group='';
        }
        while (strlen($group)<32)
        {
            $group.=chr(0);
        }
        $devmajor='';
        while (strlen($devmajor)<8)
        {
            $devmajor.=chr(0);
        }
        $devminor='';
        while (strlen($devminor)<8)
        {
            $devminor.=chr(0);
        }
        $prefix='';
        while (strlen($prefix)<155)
        {
            $prefix.=chr(0);
        }
        $header=$filename.$permissions.$userid.$groupid.$filesize.$modtime.$checksum.$indicator.$linkname.$ustar.$user.$group.$devmajor.$devminor.$prefix;
        while (strlen($header)<512)
        {
            $header.=chr(0);
        }
        $checksum=0;
        for ($y=0;$y<strlen($header);$y++)
        {
            $checksum+=ord($header[$y]);
        }
        $checksum=sprintf('%o',$checksum).chr(0).' ';
        while (strlen($checksum)<8)
        {
            $checksum='0'.$checksum;
        }
        $header=$filename.$permissions.$userid.$groupid.$filesize.$modtime.$checksum.$indicator.$linkname.$ustar.$user.$group.$devmajor.$devminor.$prefix;
        while (strlen($header)<512)
        {
            $header.=chr(0);
        }
        fwrite($tarfile,$header);
        if ($indicator==0)
        {
            $contentfile=fopen($this->filelist[$x],'r');
            $data=fread($contentfile,filesize($this->filelist[$x]));
            while (strlen($data)%512!=0)
            {
                $data.=chr(0);
            }
            fwrite($tarfile,$data);
        }
    }
    fclose($tarfile);
    return true;
}
}
?>

我还有一个简单而纯粹的ZIP类:

<?php /* 110 Lines */
/*
//  ZIP File Creation Class - http://www.pkware.com/appnote.txt

//  Download ZIP File
    include_once 'zip.inc.php';
    $zipfile = new zipfile();
    $fileonserver = 'path/to/file/oldfilename.txt';
    $fileinarchive = 'newfilename.txt';
    $zipfile->addFile(file_get_contents($fileonserver), $fileinarchive);
    header('Content-type: application/octet-stream');
    header('Content-disposition: attachment; filename=archive.zip');
    echo $zipfile->file();

//  Save ZIP File To Server
    include_once 'zip.inc.php';
    $zipfile = new zipfile();
    $fileonserver = 'path/to/file/oldfilename.txt';
    $fileinarchive = 'newfilename.txt';
    $zipfile->addFile(file_get_contents($fileonserver), $fileinarchive);
    $contents = $zipfile->file();
    file_put_contents('archive.zip', $contents);
*/

$zipfile = new zipfile();
$zipfile->addFile(file_get_contents(dirname(__FILE__).'/zip.inc.php'), 'zip.inc.php');
file_put_contents('archive.zip', $zipfile->file());

class zipfile { 
  var $datasec = array(); 
  var $ctrl_dir = array(); 
  var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; 
  var $old_offset = 0; 
  function unix2DosTime($unixtime = 0) { 
    $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime); 
    if ($timearray['year'] < 1980) { 
      $timearray['year'] = 1980; 
      $timearray['mon'] = 1; 
      $timearray['mday'] = 1; 
      $timearray['hours'] = 0; 
      $timearray['minutes'] = 0; 
      $timearray['seconds'] = 0;
    } 
    return 
      (($timearray['year'] - 1980) << 25) | 
      ($timearray['mon'] << 21) | 
      ($timearray['mday'] << 16) | 
      ($timearray['hours'] << 11) | 
      ($timearray['minutes'] << 5) | 
      ($timearray['seconds'] >> 1);
  }
  function addFile($data, $name, $time = 0) { 
    $name = str_replace('\\', '/', $name); 
    $dtime = dechex($this->unix2DosTime($time)); 
    $hexdtime = '\x' . $dtime[6] . $dtime[7] . 
                '\x' . $dtime[4] . $dtime[5] . 
                '\x' . $dtime[2] . $dtime[3] . 
                '\x' . $dtime[0] . $dtime[1]; 
    eval('$hexdtime = "' . $hexdtime . '";'); 
    $fr = "\x50\x4b\x03\x04"; 
    $fr .= "\x14\x00"; 
    $fr .= "\x00\x00"; 
    $fr .= "\x08\x00"; 
    $fr .= $hexdtime; 
    $unc_len = strlen($data); 
    $crc = crc32($data); 
    $zdata = gzcompress($data); 
    $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); 
    $c_len = strlen($zdata); 
    $fr .= pack('V', $crc); 
    $fr .= pack('V', $c_len); 
    $fr .= pack('V', $unc_len); 
    $fr .= pack('v', strlen($name)); 
    $fr .= pack('v', 0); 
    $fr .= $name; 
    $fr .= $zdata; 
    $this -> datasec[] = $fr; 
    $cdrec = "\x50\x4b\x01\x02"; 
    $cdrec .= "\x00\x00"; 
    $cdrec .= "\x14\x00"; 
    $cdrec .= "\x00\x00"; 
    $cdrec .= "\x08\x00"; 
    $cdrec .= $hexdtime; 
    $cdrec .= pack('V', $crc); 
    $cdrec .= pack('V', $c_len); 
    $cdrec .= pack('V', $unc_len); 
    $cdrec .= pack('v', strlen($name) ); 
    $cdrec .= pack('v', 0 ); 
    $cdrec .= pack('v', 0 ); 
    $cdrec .= pack('v', 0 ); 
    $cdrec .= pack('v', 0 ); 
    $cdrec .= pack('V', 32 ); 
    $cdrec .= pack('V', $this -> old_offset ); 
    $this -> old_offset += strlen($fr); 
    $cdrec .= $name; 
    $this -> ctrl_dir[] = $cdrec;
  }
  function file() { 
    $data = implode('', $this -> datasec); 
    $ctrldir = implode('', $this -> ctrl_dir); 
    return $data . $ctrldir . 
      $this -> eof_ctrl_dir . 
      pack('v', sizeof($this -> ctrl_dir)) . 
      pack('v', sizeof($this -> ctrl_dir)) . 
      pack('V', strlen($ctrldir)) . 
      pack('V', strlen($data)) . 
      "\x00\x00";
  }
} 

答案 4 :(得分:0)

您还可以使用PHP compression stream wrappers在一行中压缩和解压缩文件:

// Reads file.txt, passes it throyuh the zlib wrapper and writes the archive file.txt.gz
copy('data.xls', 'compress.zlib://' . 'data.xls.gz');

// Reads the archive file.txt.gz using zlib wrapper, writes uncompressed file
copy('compress.zlib://' . 'data.xls.gz', 'data.xls');