Source for file _zip_archives.php
Documentation is available at _zip_archives.php
* TAR/GZIP/BZIP2/ZIP ARCHIVE CLASSES 2.1
* Copyright (c) 2005 Devin Doucette
* Email bugs/suggestions to darksnoopy@shaw.ca
* @link http://www.phpclasses.org/browse/package/945.html
* This script has been created and released under
* the GNU GPL and is free to use and redistribute
* only if this copyright statement is not removed
* b2evolution - {@link http://b2evolution.net/}
* Released under GNU GPL License - {@link http://b2evolution.net/about/license.html}
* @copyright (c)2003-2010 by Francois PLANQUE - {@link http://fplanque.net/}
* @author Devin Doucette - darksnoopy@shaw.ca
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
$this->exclude =
array ();
$this->storeonly =
array ();
foreach ($options as $key =>
$value)
$this->options[$key] =
$value;
if (!empty ($this->options['basedir']))
$this->options['basedir'] =
str_replace("\\", "/", $this->options['basedir']);
$this->options['basedir'] =
preg_replace("/\/+/", "/", $this->options['basedir']);
$this->options['basedir'] =
preg_replace("/\/$/", "", $this->options['basedir']);
if (!empty ($this->options['name']))
$this->options['name'] =
str_replace("\\", "/", $this->options['name']);
$this->options['name'] =
preg_replace("/\/+/", "/", $this->options['name']);
if (!empty ($this->options['prepend']))
$this->options['prepend'] =
str_replace("\\", "/", $this->options['prepend']);
$this->options['prepend'] =
preg_replace("/^(\.*\/+)+/", "", $this->options['prepend']);
$this->options['prepend'] =
preg_replace("/\/+/", "/", $this->options['prepend']);
$this->options['prepend'] =
preg_replace("/\/$/", "", $this->options['prepend']) .
"/";
if ($this->options['inmemory'] ==
0)
chdir($this->options['basedir']);
if ($this->options['overwrite'] ==
0 &&
file_exists($this->options['name'] .
($this->options['type'] ==
"gzip" ||
$this->options['type'] ==
"bzip" ?
".tmp" :
"")))
$this->error[] =
"File {$this->options['name']} already exists.
";
else if ($this->archive =
@fopen($this->options['name'] .
($this->options['type'] ==
"gzip" ||
$this->options['type'] ==
"bzip" ?
".tmp" :
""), "wb+"))
$this->error[] =
"Could not open {$this->options['name']} for writing.
";
switch ($this->options['type'])
if (!$this->create_zip())
$this->error[] =
"Could not create zip file.";
if (!$this->create_tar())
$this->error[] =
"Could not create tar file.";
if (!$this->create_bzip())
$this->error[] =
"Could not create bzip2 file.";
if (!$this->create_tar())
$this->error[] =
"Could not create tar file.";
if (!$this->create_gzip())
$this->error[] =
"Could not create gzip file.";
if (!$this->create_tar())
$this->error[] =
"Could not create tar file.";
if ($this->options['inmemory'] ==
0)
if ($this->options['type'] ==
"gzip" ||
$this->options['type'] ==
"bzip")
unlink($this->options['basedir'] .
"/" .
$this->options['name'] .
".tmp");
if ($this->options['inmemory'] ==
0)
fwrite($this->archive, $data);
if (!empty ($this->exclude))
foreach ($this->files as $key =>
$value)
foreach ($this->exclude as $current)
if ($value['name'] ==
$current['name'])
unset
($this->files[$key]);
if (!empty ($this->storeonly))
foreach ($this->files as $key =>
$value)
foreach ($this->storeonly as $current)
if ($value['name'] ==
$current['name'])
$this->files[$key]['method'] =
0;
unset
($this->exclude, $this->storeonly);
foreach ($temp as $current)
$this->files[] =
$current;
foreach ($temp as $current)
$this->exclude[] =
$current;
foreach ($temp as $current)
$this->storeonly[] =
$current;
chdir($this->options['basedir']);
foreach ($list as $current)
$regex =
preg_replace("/([\\\^\$\.\[\]\|\(\)\?\+\{\}\/])/", "\\\\\\1", $current);
foreach ($temp as $current2)
if (preg_match("/^{$regex}$/i", $current2['name']))
unset
($regex, $dir, $temp, $current);
$files[] =
array ('name' =>
$current, 'name2' =>
$this->options['prepend'] .
preg_replace("/(\.+\/+)+/", "", ($this->options['storepaths'] ==
0 &&
strstr($current, "/")) ?
'type' =>
@is_link($current) &&
$this->options['followlinks'] ==
0 ?
2 :
0,
usort($files, array ("archive", "sort_files"));
if ($this->options['storepaths'] ==
1 &&
!preg_match("/^(\.+\/*)+$/", $dirname))
$files =
array (array ('name' =>
$dirname, 'name2' =>
$this->options['prepend'] .
preg_replace("/(\.+\/+)+/", "", ($this->options['storepaths'] ==
0 &&
strstr($dirname, "/")) ?
substr($dirname, strrpos($dirname, "/") +
1) :
$dirname), 'type' =>
5, 'stat' =>
stat($dirname)));
$fullname =
$dirname .
"/" .
$file;
if ($file ==
"." ||
$file ==
"..")
if (empty ($this->options['recurse']))
foreach ($temp as $file2)
$files[] =
array ('name' =>
$fullname, 'name2' =>
$this->options['prepend'] .
preg_replace("/(\.+\/+)+/", "", ($this->options['storepaths'] ==
0 &&
strstr($fullname, "/")) ?
'type' =>
@is_link($fullname) &&
$this->options['followlinks'] ==
0 ?
2 :
0,
if ($a['type'] !=
$b['type'])
if ($a['type'] ==
5 ||
$b['type'] ==
2)
else if ($a['type'] ==
2 ||
$b['type'] ==
5)
else if ($a['type'] ==
5)
else if ($a['ext'] !=
$b['ext'])
return strcmp($a['ext'], $b['ext']);
else if ($a['stat'][7] !=
$b['stat'][7])
return $a['stat'][7] >
$b['stat'][7] ? -
1 :
1;
if ($this->options['inmemory'] ==
0)
$this->error[] =
"Can only use download_file() if archive is in memory. Redirect to file otherwise, it is faster.";
switch ($this->options['type'])
header("Content-Type: application/zip");
header("Content-Type: application/x-bzip2");
header("Content-Type: application/x-gzip");
header("Content-Type: application/x-tar");
$header =
"Content-Disposition: attachment; filename=\"";
$header .=
strstr($this->options['name'], "/") ?
substr($this->options['name'], strrpos($this->options['name'], "/") +
1) :
$this->options['name'];
header("Content-Transfer-Encoding: binary");
header("Cache-Control: no-cache, must-revalidate, max-age=60");
header("Expires: Sat, 01 Jan 2000 12:00:00 GMT");
$this->options['type'] =
"tar";
chdir($this->options['basedir']);
foreach ($this->files as $current)
if ($current['name'] ==
$this->options['name'])
if (strlen($current['name2']) >
99)
$path =
substr($current['name2'], 0, strpos($current['name2'], "/", strlen($current['name2']) -
100) +
1);
$current['name2'] =
substr($current['name2'], strlen($path));
$this->error[] =
"Could not add {$path}{$current['name2']} to archive because the filename is too long.";
$block =
pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155a12", $current['name2'], sprintf("%07o",
$current['stat'][2]), sprintf("%07o", $current['stat'][4]), sprintf("%07o", $current['stat'][5]),
sprintf("%011o", $current['type'] ==
2 ?
0 :
$current['stat'][7]), sprintf("%011o", $current['stat'][9]),
" ", $current['type'], $current['type'] ==
2 ?
@readlink($current['name']) :
"", "ustar ", " ",
"Unknown", "Unknown", "", "", !empty ($path) ?
$path :
"", "");
for ($i =
0; $i <
512; $i++
)
if ($current['type'] ==
2 ||
$current['stat'][7] ==
0)
else if ($fp =
@fopen($current['name'], "rb"))
while ($temp =
fread($fp, 1048576))
if ($current['stat'][7] %
512 >
0)
for ($i =
0; $i <
512 -
$current['stat'][7] %
512; $i++
)
$this->error[] =
"Could not open file {$current['name']} for reading. It was not added.";
chdir($this->options['basedir']);
if ($this->options['inmemory'] ==
1)
while ($block =
fread($fp, 512))
$temp =
unpack("a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2temp/a32temp/a32temp/a8temp/a8temp/a155prefix/a12temp", $block);
'name' =>
$temp['prefix'] .
$temp['name'],
'checksum' =>
octdec($temp['checksum']),
'magic' =>
$temp['magic'],
if ($file['checksum'] ==
0x00000000)
else if (substr($file['magic'], 0, 5) !=
"ustar")
$this->error[] =
"This script does not support extracting this type of tar file.";
for ($i =
0; $i <
512; $i++
)
if ($file['checksum'] !=
$checksum)
$this->error[] =
"Could not extract from {$this->options['name']}, it is corrupt.
";
if ($this->options['inmemory'] ==
1)
$file['data'] =
fread($fp, $file['stat'][7]);
fread($fp, (512 -
$file['stat'][7] %
512) ==
512 ?
0 :
(512 -
$file['stat'][7] %
512));
unset
($file['checksum'], $file['magic']);
else if ($file['type'] ==
5)
mkdir($file['name'], $file['stat'][2]);
else if ($this->options['overwrite'] ==
0 &&
file_exists($file['name']))
$this->error[] =
"{
$file['name']} already exists.
";
else if ($file['type'] ==
2)
symlink($temp['symlink'], $file['name']);
chmod($file['name'], $file['stat'][2]);
else if ($new =
@fopen($file['name'], "wb"))
fread($fp, (512 -
$file['stat'][7] %
512) ==
512 ?
0 :
(512 -
$file['stat'][7] %
512));
chmod($file['name'], $file['stat'][2]);
$this->error[] =
"Could not open {$file['name']} for writing.";
chown($file['name'], $file['stat'][4]);
chgrp($file['name'], $file['stat'][5]);
touch($file['name'], $file['stat'][9]);
$this->error[] =
"Could not open file {$this->options['name']}";
return @fopen($this->options['name'], "rb");
$this->options['type'] =
"gzip";
if ($this->options['inmemory'] ==
0)
chdir($this->options['basedir']);
if ($fp =
gzopen($this->options['name'], "wb{$this->options['level']}"))
fseek($this->archive, 0);
while ($temp =
fread($this->archive, 1048576))
$this->error[] =
"Could not open {$this->options['name']} for writing.
";
$this->archive =
gzencode($this->archive, $this->options['level']);
return @gzopen($this->options['name'], "rb");
$this->options['type'] =
"bzip";
if ($this->options['inmemory'] ==
0)
chdir($this->options['basedir']);
if ($fp =
bzopen($this->options['name'], "wb"))
fseek($this->archive, 0);
while ($temp =
fread($this->archive, 1048576))
$this->error[] =
"Could not open {$this->options['name']} for writing.
";
$this->archive =
bzcompress($this->archive, $this->options['level']);
return @bzopen($this->options['name'], "r");
$this->options['type'] =
"zip";
if (!empty ($this->options['sfx']))
if ($fp =
@fopen($this->options['sfx'], "rb"))
$this->error[] =
"Could not open sfx module from {$this->options['sfx']}.
";
chdir($this->options['basedir']);
foreach ($this->files as $current)
if ($current['name'] ==
$this->options['name'])
$timedate =
explode(" ", date("Y n j G i s", $current['stat'][9]));
$timedate =
($timedate[0] -
1980 <<
25) |
($timedate[1] <<
21) |
($timedate[2] <<
16) |
($timedate[3] <<
11) |
($timedate[4] <<
5) |
($timedate[5]);
$block =
pack("VvvvV", 0x04034b50, 0x000A, 0x0000, (isset
($current['method']) ||
$this->options['method'] ==
0) ?
0x0000 :
0x0008, $timedate);
if ($current['stat'][7] ==
0 &&
$current['type'] ==
5)
$block .=
pack("VVVvv", 0x00000000, 0x00000000, 0x00000000, strlen($current['name2']) +
1, 0x0000);
$block .=
$current['name2'] .
"/";
$central .=
pack("VvvvvVVVVvvvvvVV", 0x02014b50, 0x0014, $this->options['method'] ==
0 ?
0x0000 :
0x000A, 0x0000,
(isset
($current['method']) ||
$this->options['method'] ==
0) ?
0x0000 :
0x0008, $timedate,
0x00000000, 0x00000000, 0x00000000, strlen($current['name2']) +
1, 0x0000, 0x0000, 0x0000, 0x0000, $current['type'] ==
5 ?
0x00000010 :
0x00000000, $offset);
$central .=
$current['name2'] .
"/";
$offset +=
(31 +
strlen($current['name2']));
else if ($current['stat'][7] ==
0)
$block .=
pack("VVVvv", 0x00000000, 0x00000000, 0x00000000, strlen($current['name2']), 0x0000);
$block .=
$current['name2'];
$central .=
pack("VvvvvVVVVvvvvvVV", 0x02014b50, 0x0014, $this->options['method'] ==
0 ?
0x0000 :
0x000A, 0x0000,
(isset
($current['method']) ||
$this->options['method'] ==
0) ?
0x0000 :
0x0008, $timedate,
0x00000000, 0x00000000, 0x00000000, strlen($current['name2']), 0x0000, 0x0000, 0x0000, 0x0000, $current['type'] ==
5 ?
0x00000010 :
0x00000000, $offset);
$central .=
$current['name2'];
$offset +=
(30 +
strlen($current['name2']));
else if ($fp =
@fopen($current['name'], "rb"))
$temp =
fread($fp, $current['stat'][7]);
if (!isset
($current['method']) &&
$this->options['method'] ==
1)
$temp =
gzcompress($temp, $this->options['level']);
$temp =
substr($temp, 2, $size);
$block .=
pack("VVVvv", $crc32, $size, $current['stat'][7], strlen($current['name2']), 0x0000);
$block .=
$current['name2'];
$central .=
pack("VvvvvVVVVvvvvvVV", 0x02014b50, 0x0014, $this->options['method'] ==
0 ?
0x0000 :
0x000A, 0x0000,
(isset
($current['method']) ||
$this->options['method'] ==
0) ?
0x0000 :
0x0008, $timedate,
$crc32, $size, $current['stat'][7], strlen($current['name2']), 0x0000, 0x0000, 0x0000, 0x0000, 0x00000000, $offset);
$central .=
$current['name2'];
$offset +=
(30 +
strlen($current['name2']) +
$size);
$this->error[] =
"Could not open file {$current['name']} for reading. It was not added.";
$this->add_data(pack("VvvvvVVv", 0x06054b50, 0x0000, 0x0000, $files, $files, strlen($central), $offset,
!empty ($this->options['comment']) ?
strlen($this->options['comment']) :
0x0000));
if (!empty ($this->options['comment']))
$this->add_data($this->options['comment']);
* $Log: _zip_archives.php,v $
* Revision 1.7 2010/02/08 17:52:06 efy-yury
* Revision 1.6 2009/12/12 04:59:07 blueyed
* Revision 1.5 2009/04/08 11:33:55 tblue246
* Renaming file _zip_archives.class.php back to _zip_archives.php to prevent inclusion into the autogenerated __autoload() list (when it gets regenerated).
* Revision 1.1 2009/04/06 20:18:29 sam2kb
* class renamed, see http://forums.b2evolution.net/viewtopic.php?t=18455
* Revision 1.3 2009/03/08 23:57:41 fplanque
* Revision 1.2 2008/01/21 09:35:25 fplanque
* Revision 1.1 2007/06/25 10:59:12 fplanque
* MODULES (refactored MVC)
* Revision 1.3 2007/04/26 00:11:12 fplanque
* Revision 1.2 2006/07/04 17:32:30 fplanque
* Revision 1.1 2006/02/23 21:12:33 fplanque
* File reorganization to MVC (Model View Controller) architecture.
* See index.hml files in folders.
* (Sorry for all the remaining bugs induced by the reorg... :/)
* Revision 1.5 2005/09/06 17:14:12 fplanque
* stop processing early if referer spam has been detected
* Revision 1.4 2005/08/19 17:20:52 blueyed
* Revision 1.3 2005/02/28 09:06:44 blueyed
* removed constants for DB config (allows to override it from _config_TEST.php), introduced EVO_CONFIG_LOADED
* Revision 1.2 2004/10/16 01:31:24 blueyed
* Revision 1.1 2004/10/13 22:46:34 fplanque