<?php

/**
* HILLS在线PHP压缩/解压程序(zip) Version-1.0.423 (RelyHills Online CDEC V1.0.423)
*
* 发布日期:2010.4.23 11:03
*
* 作者主页:http://www.abzz.net
*
* 作者腾讯QQ:3303911
*/

date_default_timezone_set('prc');

$zip = new engine_compress_decompress();

if (isset($_POST))
{
$sourcePath = ''; //默认位置

if (isset($_FILES['upfile'])) //上传文件
{
$stmp = $zip->fileUpload('upfile');
$sourcePath = $stmp['sourcefile'];
$upfileError = $stmp['error'];
}
elseif (isset($_POST['inputfile'])) //输入目录或者文件
{
$sourcePath = $_POST['inputfile'];
}
elseif (isset($_POST['decompresssourcefiles'])) //解压缩提交
{
$isDecompress = $zip->decompress($_POST['decompresssourcefiles'], $_POST['topath']);
if (!empty($isDecompress['filelist']))
{
$href = '<script type="text/javascript" language="javascript">window.location.href=\'#decompress\'</script>';
}

}

$fileList = $zip->fileArray($sourcePath); //解压缩文件列表

if (isset($_POST['compressinputfileorfolder'])) //压缩文件目录或者文件输入
{
$sourcePath = $_POST['compressinputfileorfolder'];
$href = '<script type="text/javascript" language="javascript">window.location.href=\'#compress\'</script>';
$compressFilelist = $zip->compressFileArray($sourcePath); //压缩文件列表
}
elseif ((isset($_POST['selectcompressfilelist'])) && (isset($_POST['compresssavefilename'])))
{
$compressFiles = $zip->compress($_POST['selectcompressfilelist'], $_POST['compresssavefilename']); //真实检测
$isCompress = $zip->CompileZipFile($compressFiles, $zip->savePath, 'all');
if (!empty($isCompress))
{
$href = '<script type="text/javascript" language="javascript">window.location.href=\'#compress\'</script>';
}
}
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Language" content="zh-cn" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="author" content="hills" />
<meta name="keywords" content="keywords" />
<meta name="description" content="description" />
<title>HILLS在线PHP压缩/解压程序(zip) | RelyHills Online CDEC V1.0.423</title>
<?php
echo (isset($href)) ? $href : '';
?>
<style>
<!--
body, div, form, input, select, h1, h2, h3, hr, span, ul, li
{
margin: 0px;
padding: 0px;
border: none;
}
body
{
font-size: 12px;
}
h2
{
height: 30px;
color: white;
background-color: #0FB1FF;
border-bottom: 2px solid #B0D8FF;
margin: 2px auto 8px auto;
}
form
{
margin: 14px 0px;
}
input
{
border: 1px solid silver;
}
a
{
text-decoration: none;
}
#decompress, #compress, .header, .copyright
{
width: 820px;
padding: 10px;
margin: 2% auto;
background-color: #F2F9FF;
border: 4px solid #B0D8FF;
}
.header
{
text-align: center;
}
.succeed, .notsucceed
{
font-size: 14px;
margin: 0px;
padding: 10px;
}
.succeed h4, .notsucceed h4
{
margin: 0px;
padding: 4px;
border: 1px solid blue;
}
.succeed
{
color: green;
}
.succeed h4, .notsucceed h4
{
border-bottom: 3px;
}
.succeed pre
{
margin: 0px;
padding: 10px;
border: 1px solid blue;
border-left: 4px solid blue;
line-height: 22px;
}
.notsucceed
{
color: red;
}
.copyright, .copyright a
{
color: #bbbbbb;
}
.copyright a
{
font-weight: bold;
}
.copyright:hover
{
background-color: #004000;
color: #ffffff;
}
-->
</style>
<script type="text/javascript" language="javascript">
<!--
function checkAll(inputname) //全选
{
var hills = document.getElementsByTagName('input');
var leg = hills.length;
var i;
for (i = 0; i < leg; i++)
{
if ((hills[i].type == 'checkbox') && (hills[i].name == inputname))
{
hills[i].checked = true;
}
}
}

function uncheckAll(inputname) // 取消全选
{
var hills = document.getElementsByTagName('input');
var leg = hills.length;
var i;
for (i = 0; i < leg; i++)
{
if ((hills[i].type == 'checkbox') && (hills[i].name == inputname))
{
hills[i].checked = false;
}
}
}

function reverseCheckAll(inputname) //反选
{
var hills = document.getElementsByTagName('input');
var leg = hills.length;
var i;
for (i = 0; i < leg; i++)
{
if ((hills[i].type == 'checkbox') && (hills[i].name == inputname))
{
hills[i].checked = !hills[i].checked;
}
}
}

function checkForm(checkboxname, inputtextname) //提交表单检测checkForm(复选框控件名, 要检测的ID名称)
{
if (checkboxname != '')
{
var hillsc = document.getElementsByTagName('input');
var leg = hillsc.length;
var i;
var ckbox = false;

for (i = 0; i < leg; i++)
{
if ((hillsc[i].type == 'checkbox') && (hillsc[i].name == checkboxname))
{
if (hillsc[i].checked == true)
{
ckbox = true;
}
}
}

if (ckbox == false)
{
alert('至少选择一个文件');
return false;
}
}

if (inputtextname != '')
{
var hills = document.getElementById(inputtextname);

if (hills.value == '')
{
alert('必填项目,不能为空!');
return false
}
}
}
-->
</script>
</head>
<body>
<div class="header"><h1>HILLS在线PHP压缩/解压程序(zip)</h1></div>
<div id="decompress">
<h2>解压缩(请使用标准ZIP压缩包)</h2>
<form name="uploadcompressform" action="" method="post" enctype="multipart/form-data">
<h3>方式一:</h3>
<span>上传一个压缩包文件(仅支持ZIP格式,大小超过2M的文件只能通过FTP上传)</span>
<br />
<input type="file" name="upfile" />
<input type="submit" value="确定上传" />
<span><?php echo (isset($upfileError)) ? $upfileError : '';?></span>
</form>
<form name="inputcompressform" action="" method="post">
<h3>方式二:</h3>
<span>直接输入文件位置(可以是完整文件名路径也可以使是目录, 相对于域名根目录)</span>
<br />
<input type="text" name="inputfile" value="/" />
<input type="submit" value="确定输入" />
</form>
<form name="selectcompressform" action="" method="post">
<br />
<h3>选择压缩文件</h3>
<br />
<span>选择来源文件:</span>
<?php
if (isset($fileList))
{
if (is_array($fileList))
{
if (!isset($fileList['pleaseinput']))
{
echo ' <select name="decompresssourcefiles">' . "\n";
foreach ($fileList as $select)
{
echo ' <option value="' . $select . '">' . $select . '</option>' . "\n";
}
echo ' </select>' . "\n";
}
else
{
echo ' <span style="color:red;">' . $fileList['pleaseinput'] . '</span>' . "\n";
}
}
}
?>
<br />
<br />
<span>填写解压缩目标目录:</span>
<br />
<input type="text" name="topath" value="__decompress__" />
<input type="submit" value="确定解压" />
<span>(不存在尝试自动创建,相对于域名根目录, 默认为域名根目录下的 __decompress__ )</span>
</form>
<?php
if (isset($isDecompress))
{
if (empty($isDecompress['error']))
{
$filelistTemp = $isDecompress;
?>
<div class="succeed" name="decompress">
<h4>解压缩成功 共创建: <font color="red"><?php echo (isset($filelistTemp['totalfolder'])) ? $filelistTemp['totalfolder'] : ''?></font>个目录,<font color="blue"><?php echo (isset($filelistTemp['totalfiles'])) ? $filelistTemp['totalfiles'] : ''?></font>个文件 </h4>
<?php
if (is_array($filelistTemp['filelist']))
{
?>
<form name="listfiledecompressform" action="" method="post" οnsubmit="return checkForm('listfiledecompress[]');">
<pre>
<?php
if (!empty($filelistTemp['filelist']))
{
foreach ($filelistTemp['filelist'] as $key => $value)
{
echo '<input type="checkbox" name="listfiledecompress[]" value="' . $filelistTemp['fileroot'] . $key . '" />';
if ($value == 1)
{
echo '文件:';
}
else
{
echo '目录:';
}
echo '<a href="' . $filelistTemp['linkurl'] . $key . '">';
echo $filelistTemp['fileroot'] . $key . "</a>\n";

}
}
?>
</pre>
<h4>
<input type="button" value="返回" οnclick="window.location.href='<?php echo $_SERVER['PHP_SELF'];?>';" />

<input type="button" value="全选" οnclick="checkAll('listfiledecompress[]');" />
<input type="button" value="反选" οnclick="reverseCheckAll('listfiledecompress[]');" />
<input type="button" value="取消选择" οnclick="uncheckAll('listfiledecompress[]');" />

<input type="submit" value="删 除选中" />
</h4>
</form>
<?php
}
?>
</div>
<?php
}
else
{
?>
<div class="notsucceed">
<h4>解压缩失败</h4>
</div>
<?php
}
}
elseif (isset($_POST['listfiledecompress'])) //删除文件操作
{
$deleteList = $_POST['listfiledecompress'];
if (!empty($deleteList))
{
if (is_array($deleteList))
{
?>
<pre>
<?php
foreach ($deleteList as $dkey => $dvalue)
{
$delete[$dkey] = $_SERVER['DOCUMENT_ROOT'] . $deleteList[$dkey];
if (is_file($delete[$dkey]))
{
if (@unlink($delete[$dkey]))
{
echo '<font color="blue">文件: ' . $deleteList[$dkey] . ' 已删除</font>' . "\n";
}
else
{
echo '<font color="red">文件: ' . $deleteList[$dkey] . ' 删除失败</font>' . "\n";
}
}
elseif (is_dir($delete[$dkey]))
{
if (@rmdir($delete[$dkey]))
{
echo '<font color="blue">目录: ' . $deleteList[$dkey] . ' 已删除</font>' . "\n";
}
else
{
echo '<font color="red">目录: ' . $deleteList[$dkey] . ' 删除失败(目录非空)</font>' . "\n";
}
}
}

echo '<input type="button" value="操作完成,点击这里返回" οnclick="window.location.href=\'' . $_SERVER['PHP_SELF'] . '\'" />';
?>
</pre>
<?php
}
}
}
?>
</div>

<div id="compress" name="compress">
<h2>压缩,打包</h2>
<form name="inputcompressorfileform" action="" method="post">
<h3>第一步:输入需要打包的文件夹:</h3>
<span>(相对本程序目录,如果不输入则为相对本程序目录下的所有文件及文件夹)</span>
<br />
<input type="text" name="compressinputfileorfolder" value="" />
<input type="submit" value="确认目录" />
</form>
<form name="compressselectfileorfolder" action="" method="post" οnsubmit="return checkForm('selectcompressfilelist[]', 'compresssavefilename');">
<h3>第二步:选择要打包的文件, 并填写压缩文件名</h3>
压缩文件名(相对本程序目录, 可使用路径+文件名):
<input type="text" name="compresssavefilename" id="compresssavefilename" value="hillsOnlineCompress.zip" />
<input type="submit" value="确认打包" />
<br /><br /><br />
<?php
if (isset($compressFilelist['files']))
{
?>
<input type="button" value="全选" οnclick="checkAll('selectcompressfilelist[]'); window.location.href='#compress'" />
<input type="button" value="反选" οnclick="reverseCheckAll('selectcompressfilelist[]'); window.location.href='#compress'" />
<input type="button" value="取消选择" οnclick="uncheckAll('selectcompressfilelist[]'); window.location.href='#compress'" />
<br />
<?php
if (is_array($compressFilelist['files']))
{
echo " <pre>\n";
foreach ($compressFilelist['files'] as $cvalue)
{
?>
<input type="checkbox" name="selectcompressfilelist[]" value="<?php echo $cvalue;?>" checked="checked" /><?php echo $cvalue . "\n";?>
<?php
}
echo " </pre>\n";
}
}
?>
</form>
<?php
if (isset($compressFilelist['error']))
{
echo ' <font color="red">' . $compressFilelist['error'] . '</font>';
}
if (isset($isCompress))
{
if ($isCompress > 0)
{
?>
<div class="succeed">
<h4>压缩成功, 共压缩 <?php echo $isCompress;?> 个文件</h4>
<br /><br />
<input type="button" value="操作完成,返回" οnclick="window.location.href='<?php echo $_SERVER['PHP_SELF'] ;?>'" />
</div>
<?php
}
elseif ($isCompress == 0)
{
?>
<div class="notsucceed">
<h4>压缩失败</h4>
<br /><br />
<input type="button" value="操作错误,返回" οnclick="window.location.href='<?php echo $_SERVER['PHP_SELF'] ;?>'" />
</div>
<?php
}
}
?>
</div>
<div class="copyright">
<ul>
<li>Copyright:©2010 RelyHills(abzz.net).All rights reserved.</li>
<li>Powered by <a href="http://abzz.net/">abzz.net</a>. </li>
<li>Author/hills. Contact way/Tencent QQ : 3303911, Email : <a href="mailto:hackhgs@qq.com" target="_blank">hackhgs@qq.com</a></li>
<li>Release date: 2010-04-23, Versions: RelyHills Online CDEC V1.0.423</li>
</ul>
</div>
</body>
</html>
<?php

/**
* @class engine_compress_decompress
* @function 压缩文件操作引擎
* @version 1.0.4
* @date 2010-4-19 19:50
* @author hills
* @copyright 2010-2012 RelyHills All rights reserved.
*/

class engine_compress_decompress
{
public $sourcePath = ''; //文件操作源路径
public $savePath = ''; //文件操作目标路径
public $object = false; //wscript.shell实例对象
public $resultInfo = array(); //返回信息
public $documentRoot = ''; //站点根目录

public $datasec, $ctrl_dir = array();
public $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
public $old_offset = 0;
public $dirs = array(".");

/**
* 构造函数
*/
public function __construct()
{
$this->documentRoot = $_SERVER['DOCUMENT_ROOT']; //站点本目录
}

/**
* decompress($sourcePath, $toPath)
* $sourcePath : 来源文件路径
* $toPath : 解压缩目标
* 作用:解压缩文件
*/
public function decompress($sourceFile, $toPath)
{
$sourceFile = $this->documentRoot . $sourceFile; //转换为绝对目录
$toPath = ((substr($toPath, 0, 1) == '/') || (substr($toPath, 0, 1) == '\\')) ? $toPath : '/' . $toPath;
$toPath = $this->documentRoot . str_replace($this->documentRoot, '', $toPath); //转换为绝对目录

$errorTmp = null;

if (is_file($sourceFile) == false)
{
$errorTmp = '不是有效文件 : ' . $this->sourcePath;
}
else
{
$this->sourcePath = $this->replacePath($sourceFile);
$fileName = @strtolower(@substr(@strrchr($this->sourcePath, '/'), 1)); //取最后一个反斜线以后的字符串,文件名
$fileRoot = @substr($this->sourcePath, 0, (@strlen($this->sourcePath) - @strlen($fileName))); //获得源文件目录路径
}

if (is_dir($toPath) == false) //判断目标目录是否存在
{
$isToPath = $this->dirCreate($toPath); //创建不存在的目录
if ($isToPath !== true)
{
$errorTmp = '无法自动创建目录 : ' . $toPath; //无法创建目标目录错误信息
}
}

if (is_dir($toPath) == false)
{
$errorTmp = '目标目录不正确';
}
else
{
if (substr($toPath, 0, -1) != '/')
{
$toPath = $this->replacePath($toPath);
}
$this->savePath = $toPath;
}

if (empty($errorTmp))
{
$resultTemp = $this->ExtractAll($this->sourcePath, $this->savePath); //执行解压
if ($resultTemp == -1)
{
$this->resultInfo['error'] = '文件: ' . $fileName . ' 解压缩失败';
}
else
{
$this->resultInfo['filelist'] = $resultTemp;
$totalFolder = 0;
$totalFiles = 0;
foreach ($this->resultInfo['filelist'] as $value)
{
if ($value == (1))
{
$totalFiles += 1;
}
if ($value === (-1))
{
$totalFolder += 1;
}
}
$this->resultInfo['totalfolder'] = $totalFolder; //解压的总目录数
$this->resultInfo['totalfiles'] = $totalFiles; //解压的总文件数
$this->resultInfo['linkurl'] = 'http://' . $_SERVER['HTTP_HOST'] . str_replace($this->documentRoot, '', $this->savePath); //文件解压缩目标路径
$this->resultInfo['fileroot'] = str_replace($this->documentRoot, '', $this->savePath);
}
}
else
{
$this->resultInfo['error'] = $errorTmp;
}

return $this->resultInfo;
}

/**
* compress($sourcePath = '', $toPath = '')
* $sourceFileName : 来源文件路径
* $toPath : 保存目标路径
* 作用:压缩文件
*/
public function compress($sourcePath = array(), $toPath = '')
{
$errorC = null;
$filesA = array();
//$fileList = '';
if ((!empty($sourcePath)) && (!empty($toPath)))
{
//修正输入的不规则目录
$toPath = str_replace('\\', '/', $toPath);
if (substr($toPath, 0, 1) == '/')
{
$toPath = substr($toPath, 1);
}
$this->savePath = str_replace($this->documentRoot . dirname($_SERVER['PHP_SELF']), '', $toPath);

if (is_array($sourcePath)) //是数组
{
if (!empty($sourcePath)) //不为空
{
foreach ($sourcePath as $value)
{
if (file_exists($value)) //文件存在
{
if ((is_dir($value)) && (substr($value, 0, -1) != '/'))
{
$value = $value . '/';
}
$filesA[] = $value;
}
else
{
$errorC = '文件' . $value . '不存在';
}
}
}
}
}
else
{
$errorC = '请完整输入';
}

if ((empty($errorC)) && (!empty($filesA))) //条件都成立时执行打包压缩
{
return $filesA;
}

}

/**
* fileUpload($inputName = '')
* $inputName : 文件上传表单控件名
* 作用:文件上传
*/
public function fileUpload($inputName = '')
{
$fuResult = array();
$sourcePath = ''; //上传移动后的文件名路径
if ($inputName == '')
{
$inputName = 'upfile';
}

if ($this->fileext($_FILES["{$inputName}"]['name']) == 'zip')
{
$sourceFile = $_FILES["{$inputName}"]['tmp_name'];
$targetFile = dirname($_SERVER['PHP_SELF']) . '/' . $_FILES["{$inputName}"]['name'];

$isMove = @move_uploaded_file($sourceFile, $_SERVER['DOCUMENT_ROOT'] . $targetFile);
if ($isMove != false)
{
$sourcePath = $targetFile;
$upfileError = '<font color="green">文件上传成功</font>';
}
else
{
/*
UPLOAD_ERR_OK
其值为 0,没有错误发生,文件上传成功。
UPLOAD_ERR_INI_SIZE
其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
UPLOAD_ERR_FORM_SIZE
其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
UPLOAD_ERR_PARTIAL
其值为 3,文件只有部分被上传。
UPLOAD_ERR_NO_FILE
其值为 4,没有文件被上传。
UPLOAD_ERR_NO_TMP_DIR
其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
UPLOAD_ERR_CANT_WRITE
其值为 7,文件写入失败。PHP 5.1.0 引进。
*/
if ($_FILES["{$inputName}"]['error'] == 4)
{
$upfileError = '<font color="red">上传文件不能为空</font>';
}
elseif (($_FILES["{$inputName}"]['error'] == 1) || $_FILES["{$inputName}"]['error'] == 2)
{
$upfileError = '<font color="red">上传文件大小超过限制</font>';
}
elseif ($_FILES["{$inputName}"]['error'] == 6)
{
$upfileError = '<font color="red">上传文件转移时发生错误</font>';
}
elseif ($_FILES["{$inputName}"]['error'] == 7)
{
$upfileError = '<font color="red">上传文件写入失败</font>';
}
elseif ($_FILES["{$inputName}"]['error'] == 3)
{
$upfileError = '<font color="red">只有部分文件被上传</font>';
}
else
{
$upfileError = '<font color="red">上传失败,未知错误</font>';
}
}
}
else
{
$upfileError= '<font color="red">文件只能是ZIP类型</font>';
}
$fuResult['sourcefile'] = $sourcePath;
$fuResult['error'] = $upfileError;
return $fuResult;
}

/**
* fileArray($sourceFile = '')
* $sourceFile : 来源文件名(可包括完整物理路径)
* 获得文件(数组)
*/
public function fileArray($sourceFile = '')
{
$filearray = array(); //文件列表

if (!empty($sourceFile))
{
if (stristr($sourceFile, $this->documentRoot) != false)
{
$sourceFile = str_replace($this->documentRoot, '', $sourceFile);
}

if (substr($sourceFile, 0, 1) != '/')
{
$sourceFile = '/' . $sourceFile;
}

if (is_file($this->documentRoot . $sourceFile)) //文件存在时
{
if ($this->fileext($sourceFile) == 'zip') //找出ZIP类型文件
{
$filearray[] = str_replace($this->documentRoot, '', $sourceFile); //得到文件列表(数组)
}
else
{
$filearray['pleaseinput'] = '文件只能是ZIP类型';
}
}
else //指定文件不存在则尝试在本文件目录搜索压缩格式文件,并列表
{
if (is_dir($this->documentRoot . $sourceFile))
{
$flieList = $this->fileList($this->documentRoot . $sourceFile);
foreach ($flieList as $value) //遍历文件列表数组
{
if ($this->fileext($value) == 'zip') //找出ZIP类型文件
{
$filearray[] = str_replace($this->documentRoot, '', $value); //得到文件列表(数组)
}
}
}
else
{
$filearray['pleaseinput'] = '不是有效文件或目录, 请重新输入';
}
}
}
else
{
$filearray['pleaseinput'] = '请在上一步骤输入需要操作的文件路径或者文件夹来获取文件';
}

if (empty($filearray))
{
$filearray['pleaseinput'] = '该目录没有任何可解压缩的文件';
}
return $filearray;
}

/**
* compressFileArray($sourceFile = '')
$sourceFile : 来源文件名(可包括完整物理路径)
* 获得文件(数组)
*/
public function compressFileArray($sourceFile)
{
$resultArray= array(); //返回值
$filearray = array(); //文件列表
$errorarray = ''; //错误信息

if (isset($sourceFile))
{
if (stristr($sourceFile, $this->documentRoot) != false) //检测是否是绝对路径
{
$sourceFile = str_replace($this->documentRoot, '', $sourceFile);
}

if (($sourceFile == '/') || ($sourceFile == ''))
{
$sourceFile = './';
}

$this->sourcePath = $sourceFile;

if (is_file($this->sourcePath)) //文件存在时
{
$filearray[] = $this->sourcePath; //得到文件列表(数组)
}
else //指定文件不存在则尝试在本文件目录搜索压缩格式文件,并列表
{
if (is_dir($this->sourcePath))
{
$flieList = $this->fileListC($this->sourcePath);
foreach ($flieList as $value) //遍历文件列表数组
{
$newValue = str_replace($this->documentRoot, '', $value); //得到文件列表(数组)
if (substr($newValue, 0, 3) == '../')
{
continue;
}
/*
elseif (is_dir($newValue))
{
continue;
}
*/
elseif (substr($newValue, 0, 2) == './')
{
$newValue = substr($newValue, 2);
}
$filearray[] = $newValue;
}
}
else
{
$errorarray = '不是有效文件或目录, 请重新输入';
}
}
}
else
{
$errorarray = '请在上一步骤输入需要操作的文件路径或者文件夹来获取文件';
}

if ((empty($filearray)) && (empty($errorarray)))
{
$resultArray['error'] = '该目录没有任何可解压缩的文件';
}
elseif (!empty($errorarray))
{
$resultArray['error'] = $errorarray;
}
else
{
$resultArray['files'] = $filearray;
}

return $resultArray;
}

/**
* fileext($filename);
* $filename : 完整文件名
* 作用:获得文件扩展名
*/
public function fileext($filename)
{
return @strtolower(@substr(@strrchr($filename, '.'), 1,10));
}

/**
* dirReplace($dirString)
* $dirString : 路径字符串
* 作用:替换WINDOWS目录路径中的反斜线"\"为"/", 并返回最后带"/"的路径字符串
*/
public function replacePath($dirString)
{
$temp = str_replace('\\', '/', $dirString);

if ((substr($temp, 0, -1) != '/') && (is_file($temp) == false))
{
$temp .= '/';
}
$temp = str_replace('//', '/', $temp);
$temp = str_replace('\\/', '/', $temp);
$temp = str_replace('/\\', '/', $temp);
return $temp;
}

/**
* dirCreate($dirName)
* $dirName : 目录名
* 作用:创建目录, 支持多级目录,直接输入root1/root2/root3....
* 发生错误返回错误数组否则返回true
*/
public function dirCreate($dirName)
{
$dirName = $this->replacePath($dirName);
$dirTemp = explode('/', $dirName);
$dirCount = count($dirTemp) - 1;
$dirCur = '';
$dirCreateError = array();

for ($j = 0; $j < $dirCount; $j++)
{
$dirCur .= $dirTemp[$j] . '/';
if (is_dir($dirCur)) //如果目录存在,跳出本次循环
{
continue;
}
$isMkdir = @mkdir($dirCur, 0777);
if ($isMkdir == false)
{
$dirCreateError[$j] = $dirTemp[$j];
}
}

if (empty($dirCreateError))
{
return true;
}
else
{
return $dirCreateError;
}
}

/**
* fileList($dir, $list = array())
* 作用:获得目录及子目录的压缩格式文件列表数组
*/
public function fileList($dir, $list = array())
{
if (!is_array($list))
{
$list = array();
}

if (empty($dir)) //路径为空转换为当前
{
$dir = './';
}

$dir = str_replace('//', '/', $this->replacePath($dir));

$files = glob($dir . '*');

foreach ($files as $value)
{
$list[] = $value;
if (is_dir($value))
{
$list = $this->fileList($value, $list);
}
}
return $list;
}

/**
* fileListC($dir, $list = array())
* 作用:获得目录及子目录的压缩格式文件列表数组
*/
public function fileListC($dir, $list = array())
{
if (!is_array($list))
{
$list = array();
}

$dir = str_replace('//', '/', $this->replacePath($dir));

$files = glob($dir . '*');

foreach ($files as $value)
{
if (is_dir($value))
{
$list = $this->fileList($value, $list);
}
else
{
$list[] = $value;
}
}
return $list;
}

/**
* 网友的方法
*/
public function get_List($zip_name)
{
$ret = '';
$zip = @fopen($zip_name, 'rb');
if (!$zip)
{
return (0);
}
$centd = $this->ReadCentralDir($zip, $zip_name);
@rewind($zip);
@fseek($zip, $centd['offset']);
for ($i = 0; $i < $centd['entries']; $i++)
{
$header = $this->ReadCentralFileHeaders($zip);
$header['index'] = $i;
$info['filename'] = $header['filename'];
$info['stored_filename'] = $header['stored_filename'];
$info['size'] = $header['size'];
$info['compressed_size'] = $header['compressed_size'];
$info['crc'] = strtoupper(dechex($header['crc']));
$info['mtime'] = $header['mtime'];
$info['comment'] = $header['comment'];
$info['folder'] = ($header['external'] == 0x41FF0010 || $header['external'] == 16) ? 1 : 0;
$info['index'] = $header['index'];
$info['status'] = $header['status'];
$ret[] = $info;
unset($header);
}
return $ret;
}

public function Add($files, $compact)
{
if (!is_array($files[0]))
{
$files = array($files);
}
for ($i = 0; $files[$i]; $i++)
{
$fn = $files[$i];
if (!in_Array(dirname($fn[0]), $this->dirs))
{
$this->add_Dir(dirname($fn[0]));
}
if (basename($fn[0]))
{
$ret[basename($fn[0])] = $this->add_File($fn[1], $fn[0], $compact);
}
}
return $ret;
}

public function get_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";
}

public function add_dir($name)
{
$name = str_replace("\\", "/", $name);
$fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
$fr .= pack("V", 0) . pack("V", 0) . pack("V", 0) . pack("v", strlen($name));
$fr .= pack("v", 0) . $name . pack("V", 0) . pack("V", 0) . pack("V", 0);
$this->datasec[] = $fr;
$new_offset = strlen(implode("", $this->datasec));
$cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
$cdrec .= pack("V", 0) . pack("V", 0) . pack("V", 0) . pack("v", strlen($name));
$cdrec .= pack("v", 0) . pack("v", 0) . pack("v", 0) . pack("v", 0);
$ext = "\xff\xff\xff\xff";
$cdrec .= pack("V", 16) . pack("V", $this->old_offset) . $name;
$this->ctrl_dir[] = $cdrec;
$this->old_offset = $new_offset;
$this->dirs[] = $name;
}


public function CompileZipFile($filename, $tozipfilename, $ftype = 'dir')
{
if (@function_exists('gzcompress'))
{
if ($ftype == 'dir')
{
$filelist = $this->ListDirFiles($filename);
}
elseif ($ftype == 'file')
{
$filelist[] = $filename;
}
else
{
$filelist = $filename;
}
$i = 0;
if (count($filelist) > 0)
{
foreach ($filelist as $filename)
{
if (is_file($filename))
{
$i++;
$fd = fopen($filename, "r");
if (filesize($filename) > 0)
{
$content = fread($fd, filesize($filename));
}
else
{
$content = ' ';
}
fclose($fd);

$this->add_File($content, $filename);
}
}

$out = $this->get_file();
$fp = fopen($tozipfilename, "w");
fwrite($fp, $out, strlen($out));
fclose($fp);
}
return $i;
}
else
{
return 0;
}
}

//读取某文件夹的所有文件-原
public function ListDirFiles($dirname)
{
$files = array();

if (is_dir($dirname))
{
$fh = opendir($dirname);
while (($file = readdir($fh)) !== false)
{
if (strcmp($file, '.') == 0 || strcmp($file, '..') == 0)
{
continue;
}
$filepath = $dirname . '/' . $file;
if (is_dir($filepath))
{
$files = array_merge($files, $this->ListDirFiles($filepath));
}
else
{
array_push($files, $filepath);
}
}
closedir($fh);
}
else
{
$files = false;
//$files += $dirname;
}

return $files;
}

public function add_File($data, $name, $compact = 1)
{
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->DosTime());

$hexdtime = '\x' . $dtime[6] . $dtime[7] . '\x' . $dtime[4] . $dtime[5] . '\x' . $dtime[2] . $dtime[3] . '\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
if ($compact) $fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00" . $hexdtime;
else
{
$fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00" . $hexdtime;
}
$unc_len = strlen($data);
$crc = crc32($data);
if ($compact)
{
$zdata = gzcompress($data);
$c_len = strlen($zdata);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
}
else
{
$zdata = $data;
}
$c_len = strlen($zdata);
$fr .= pack('V', $crc) . pack('V', $c_len) . pack('V', $unc_len);
$fr .= pack('v', strlen($name)) . pack('v', 0) . $name . $zdata;
$fr .= pack('V', $crc) . pack('V', $c_len) . pack('V', $unc_len);
$this->datasec[] = $fr;
$new_offset = strlen(implode('', $this->datasec));
if ($compact)
{
$cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";
}
else
{
$cdrec = "\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00";
}
$cdrec .= $hexdtime . pack('V', $crc) . pack('V', $c_len) . pack('V', $unc_len);
$cdrec .= pack('v', strlen($name)) . pack('v', 0) . pack('v', 0);
$cdrec .= pack('v', 0) . pack('v', 0) . pack('V', 32);
$cdrec .= pack('V', $this->old_offset);
$this->old_offset = $new_offset;
$cdrec .= $name;
$this->ctrl_dir[] = $cdrec;
return true;
}

public function DosTime()
{
$timearray = getdate();
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);
}

//解压整个压缩包
//直接用 Extract 会有路径问题,本函数先从列表中获得文件信息并创建好所有目录然后才运行 Extract
public function ExtractAll($zn, $to)
{
if (substr($to, -1) != "/")
{
$to .= "/";
}
$files = $this->get_List($zn);
$cn = count($files);
if (is_array($files))
{
for ($i = 0; $i < $cn; $i++)
{
if ($files[$i]['folder'] == 1)
{
@mkdir($to . $files[$i]['filename'], $GLOBALS['cfg_dir_purview']);
@chmod($to . $files[$i]['filename'], $GLOBALS['cfg_dir_purview']);
}
}
}
return $this->Extract($zn, $to);
}

public function Extract($zn, $to, $index = array(-1))
{
$ok = 0;
$zip = @fopen($zn, 'rb');
if (!$zip)
{
return (-1);
}
$cdir = $this->ReadCentralDir($zip, $zn);
$pos_entry = $cdir['offset'];
if (!is_array($index))
{
$index = array($index);
}
for ($i = 0; isset($index[$i]); $i++)
{
if (intval($index[$i]) != $index[$i] || $index[$i] > $cdir['entries'])
{
return (-1);
}
}
for ($i = 0; $i < $cdir['entries']; $i++)
{
@fseek($zip, $pos_entry);
$header = $this->ReadCentralFileHeaders($zip);
$header['index'] = $i;
$pos_entry = ftell($zip);
@rewind($zip);
fseek($zip, $header['offset']);
if (in_array("-1", $index) || in_array($i, $index))
{
$stat[$header['filename']] = $this->ExtractFile($header, $to, $zip);
}

}
fclose($zip);
return $stat;
}

public function ReadFileHeader($zip)
{
$binary_data = fread($zip, 30);
$data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
$header['filename'] = fread($zip, $data['filename_len']);
if ($data['extra_len'] != 0)
{
$header['extra'] = fread($zip, $data['extra_len']);
}
else
{
$header['extra'] = '';
}
$header['compression'] = $data['compression'];
$header['size'] = $data['size'];
$header['compressed_size'] = $data['compressed_size'];
$header['crc'] = $data['crc'];
$header['flag'] = $data['flag'];
$header['mdate'] = $data['mdate'];
$header['mtime'] = $data['mtime'];
if ($header['mdate'] && $header['mtime'])
{
$hour = ($header['mtime'] & 0xF800) >> 11;
$minute = ($header['mtime'] & 0x07E0) >> 5;
$seconde = ($header['mtime'] & 0x001F) * 2;
$year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
$month = ($header['mdate'] & 0x01E0) >> 5;
$day = $header['mdate'] & 0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
}
else
{
$header['mtime'] = time();
}
$header['stored_filename'] = $header['filename'];
$header['status'] = "ok";
return $header;
}

public function ReadCentralFileHeaders($zip)
{
$binary_data = fread($zip, 46);
$header = unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $binary_data);
if ($header['filename_len'] != 0)
{
$header['filename'] = fread($zip, $header['filename_len']);
}
else
{
$header['filename'] = '';
}
if ($header['extra_len'] != 0)
{
$header['extra'] = fread($zip, $header['extra_len']);
}
else
{
$header['extra'] = '';
}
if ($header['comment_len'] != 0)
{
$header['comment'] = fread($zip, $header['comment_len']);
}
else
{
$header['comment'] = '';
}
if ($header['mdate'] && $header['mtime'])
{
$hour = ($header['mtime'] & 0xF800) >> 11;
$minute = ($header['mtime'] & 0x07E0) >> 5;
$seconde = ($header['mtime'] & 0x001F) * 2;
$year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
$month = ($header['mdate'] & 0x01E0) >> 5;
$day = $header['mdate'] & 0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
}
else
{
$header['mtime'] = time();
}
$header['stored_filename'] = $header['filename'];
$header['status'] = 'ok';
if (substr($header['filename'], -1) == '/')
{
$header['external'] = 0x41FF0010;
}
return $header;
}

public function ReadCentralDir($zip, $zip_name)
{
$size = filesize($zip_name);
if ($size < 277)
{
$maximum_size = $size;
}
else
{
$maximum_size = 277;
}
@fseek($zip, $size - $maximum_size);
$pos = ftell($zip);
$bytes = 0x00000000;

while ($pos < $size)
{
$byte = @fread($zip, 1);
$bytes = ($bytes << 8) | ord($byte);
if ($bytes == 0x504b0506)
{
$pos++;
break;
}
$pos++;
}
$data = @unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', fread($zip, 18));
if ($data['comment_size'] != 0)
{
$centd['comment'] = fread($zip, $data['comment_size']);
}
else
{
$centd['comment'] = '';
$centd['entries'] = $data['entries'];
}
$centd['disk_entries'] = $data['disk_entries'];
$centd['offset'] = $data['offset'];
$centd['disk_start'] = $data['disk_start'];
$centd['size'] = $data['size'];
$centd['disk'] = $data['disk'];
return $centd;
}

public function ExtractFile($header, $to, $zip)
{
$header = $this->readfileheader($zip);
$header['external'] = (!isset($header['external']) ? 0 : $header['external']);
if (substr($to, -1) != "/")
{
$to .= "/";
}
if (!@is_dir($to))
{
@mkdir($to, $GLOBALS['cfg_dir_purview']);
}
if (!($header['external'] == 0x41FF0010) && !($header['external'] == 16))
{
if ($header['compression'] == 0)
{
$fp = @fopen($to . $header['filename'], 'wb');
if (!$fp)
{
return (-1);
}
$size = $header['compressed_size'];
while ($size != 0)
{
$read_size = ($size < 2048 ? $size : 2048);
$buffer = fread($zip, $read_size);
$binary_data = pack('a' . $read_size, $buffer);
@fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}
fclose($fp);
touch($to . $header['filename'], $header['mtime']);
}
else
{
$fp = @fopen($to . $header['filename'] . '.gz', 'wb');
if (!$fp)
{
return (-1);
}
$binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
fwrite($fp, $binary_data, 10);
$size = $header['compressed_size'];
while ($size != 0)
{
$read_size = ($size < 1024 ? $size : 1024);
$buffer = fread($zip, $read_size);
$binary_data = pack('a' . $read_size, $buffer);
@fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}

$binary_data = pack('VV', $header['crc'], $header['size']);
fwrite($fp, $binary_data, 8);
fclose($fp);
$gzp = @gzopen($to . $header['filename'] . '.gz', 'rb') or die("Cette archive est compress");
if (!$gzp)
{
return (-2);
}
$fp = @fopen($to . $header['filename'], 'wb');
if (!$fp)
{
return (-1);
}
$size = $header['size'];
while ($size != 0)
{
$read_size = ($size < 2048 ? $size : 2048);
$buffer = gzread($gzp, $read_size);
$binary_data = pack('a' . $read_size, $buffer);
@fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}
fclose($fp);
gzclose($gzp);
touch($to . $header['filename'], $header['mtime']);
@unlink($to . $header['filename'] . '.gz');
}
}
return true;
}
}
?>