Is there is any safe way to create a zip archive, or tar.gz from php without using exec command ?
thanks
If you want to create tar.gz and you are using PHP 5.3+, you can use 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;
}
There is a very simple way to create Tar-archives directly within PHP - you can find a CLASS at sourceforge from Dennis Wronka under LGPL so you can use also in commercial scripts.
<?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;
}
}
?>
I also have a simple and pure PHP class for 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";
}
}
You can use PHP's Zip class to create zip files, and ZLib to create gzip files.
Creating a .zip
file:
$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();
Creating a .gz
file:
$file = "test.txt";
$gzfile = "test.gz";
$fp = gzopen($gzfile, 'w9'); // w == write, 9 == highest compression
gzwrite($fp, file_get_contents($file));
gzclose($fp);
You can also use PHP compression stream wrappers to compress and uncompress files in one line:
// 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');
Use the system command instead
http://php.net/manual/en/function.system.php
Pay attention to the notes section on how to protect from malicious input.
EDIT: Use the ZipArchive class to create a new zip via the open() command http://www.php.net/manual/en/class.ziparchive.php