Тоже решил пару кусков из своих исходников выдрать
Распаковщик zip-ов. Пригодится тем у кого php без --with-zip
Поддерживает только методы сжатия deflate и no_compression.
Большинство зипов по умолчанию зажаты именно deflate, так что 95% архивов открывает без проблем. Запароленные не распаковывает.
Распаковывает также и вордовский docx (для чего, собственно, и был сделан, т.к. популярная либа PclZip, спотыкалась на куче нулей, которые ворд щедро пихает в свои файлы, видимо для того, чтобы размер файла не казался подозрительно маленьким
)
Код: <?php
// Radchand (C) radchand(a)mail.ru
$GLOBALS['unzip_error'] = 'Ok'; // Строка с описанием ошибки
/** Главная (и единственная) низкоуровняя ф-я для распаковки архива
// @desc Распаковывает текущий файл в архиве.
// Предназначана для работы в цикле.
// Если $target не задан, то просто перемещает указатель на следующий файл в архиве не распаковывая.
// Чтобы распаковать все файлы в архиве нужно вызывать эту ф-ю с одним и тем же handle до тех пор пока она не вернет false
// Аргументы:
// @param $file - имя файла или handle (возвращает fopen)
// @param $target - имя файла для распаковки, если не совпадает, то просто перемещает указатель в архиве на следующий файл, но возващает имя файла, его размер и пр.
// true - распаковывает любой файл
// @return Возвращает ассоциативный массив:
// FName - имя файла,
// Date, Time - дата и время в 2-х байтном MS-DOS формате,
// ExtractedLen - размер,
// Data - содержимое файла,
// Extra - дополн. данные
// если произошла какая-то ошибка, то возвращает false, скорее всего, последующие вызовы тоже вернут false, т.к. наверняка указатель сползет
// в случае ошибки из-за неподдерживаемого алгоритма распаковки, все же можно прочитать список файлов ($target=false)
*/
function Unzip($file, $target=false)
{
$h = is_string($file) ? fopen($file, 'rb') : $file;
if($h===false)
{ $GLOBALS['unzip_error'] = "Can't open file"; return FALSE; }
$offset = ftell($h);
// ReadLocalFileHeader
$hdr = unpack('V1Sign/v1Ver/v1Flags/v1Method/v1Time/v1Date/V1CRC/V1DataLen/V1ExtractedLen/v1FNameLen/v1ExtraLen', fread($h, 30));
if($hdr['Sign'] == 0x02014b50)
{ $GLOBALS['unzip_error'] = 'End of file'; return FALSE; }
if($hdr['Sign'] != 0x04034b50)
{ $GLOBALS['unzip_error'] = 'Invalid sign!'; return FALSE; }
if($hdr['Flags'] & 0x0008) // Descriptor after data. Need read directory at first.
{ $GLOBALS['unzip_error'] = 'Descriptor after data'; return FALSE; }
$hdr['Offset'] = $offset;
$hdr['FName'] = fread($h, $hdr['FNameLen']);
if($target == $hdr['FName'] || $target === true)
{
if($hdr['Method']!=8 && $hdr['Method']!=0) // only deflate & no_compression method implemented
{ $GLOBALS['unzip_error'] = 'Only deflate & no_compression method implemented'; return FALSE; }
if($hdr['ExtraLen']>0)
$hdr['Extra'] = fread($h, $hdr['ExtraLen']);
if($hdr['DataLen']>0)
{
$hdr['Data'] = fread($h, $hdr['DataLen']);
if($hdr['Flags'] & 0x0001)
{ $GLOBALS['unzip_error'] = 'Encrypted'; return FALSE; }
if($hdr['Method'] == 8)
$hdr['Data'] = gzinflate($hdr['Data']); // deflate
}
if(strlen($hdr['Data']) != $hdr['ExtractedLen']) // bad length
{ $GLOBALS['unzip_error'] = 'Bad length'; return FALSE; }
if(crc32($hdr['Data']) != $hdr['CRC'])
{ $GLOBALS['unzip_error'] = 'Bad CRC'; return FALSE; }
}
else
fseek($h, $hdr['ExtraLen']+$hdr['DataLen'], SEEK_CUR);
if(is_string($file)) fclose($h);
return $hdr;
}
// Пара утилиток
/** @desc возвращает список файлов в архиве
* @param путь к архиву */
function ZipList($file)
{
$ret = array();
$h = fopen($file,'rb');
do {
$data = Unzip($h);
if(isset($data['FName']))
$ret[] = $data['FName'];
} while($data && !feof($h));
fclose($h);
return $ret;
}
/** @desc возвращает содержимое заданного файла из архива
* @param путь к архиву
* @param путь (имя файла) в архиве
*/
function UnzipFile($arcfile, $file)
{
$h = fopen($arcfile, 'rb');
do {
$data = Unzip($h, $file);
if(isset($data['Data']))
{
fclose($h);
return $data['Data'];
}
} while($data && !feof($h));
fclose($h);
return false;
}
/** @desc возвращает ассоц. массив [имяфайла]=содержимое со всеми файлами из архива
* @param путь к архиву */
function UnzipAll($arcfile)
{
$ret = array();
$h = fopen($arcfile, 'rb');
do {
$data = Unzip($h, $file);
if($data && isset($data['FName'], $data['Data']))
$ret[$data['FName']] = $data['Data'];
} while($data && !feof($h));
fclose($h);
return $ret;
}
?>