субота, 14 лютого 2009 р.

ZIP-архіви в PHP: старі приклади та важливі обмеження

Для роботи із ZIP я зберіг посилання на http://blog.webmasterschool.ru/php/48/ та клас Create ZIP File з http://www.phpclasses.org. Нижче — приклади роботи зі старим стороннім класом і процедурним ZIP API.

Створення архіву

Клас createZip не є вбудованим класом PHP. Його реалізації у статті немає; приклад залежить від окремого файла createZip.inc.php:

// Подключаем класс для работы с zip-архивами

include_once("createZip.inc.php");

$createZip = new createZip; 



// Добавляем директорию

$createZip -> addDirectory("dir/");



// Добавляем файл

$fileContents = file_get_contents("img.jpg"); 

$createZip -> addFile($fileContents, "dir/img.jpg"); 



// Создаем архив

$fileName = "archive.zip";

$fd = fopen ($fileName, "wb");

$out = fwrite ($fd, $createZip -> getZippedfile());

fclose ($fd);



// Отдаем архив браузеру

$createZip -> forceDownload($fileName);

@unlink($fileName);

?>

Функція розпакування та її параметри

У прикладі $dir задає каталог призначення, $file — шлях до архіву, а $log вмикає діагностичний вивід. Функція проходить елементи архіву, створює каталоги та записує вміст файлів:

/**

* Распаковывает zip-архив в указанный каталог.

* $dir  - полный путь к каталогу.

* $file - полный путь к zip-архиву.

* $log  - флаг вывода диагностики.

*/

function unpackZip($dir, $file, $log=0) {

if ($log) echo "Start unpack [$file] into [$dir] directory... 

";



if ($zip = zip_open($file)) {

if ($zip) {

// создать каталог, если он не существует

if (! file_exists($dir)) mkdir($dir);



while ($zip_entry = zip_read($zip)) {

$name = zip_entry_name($zip_entry);

if ($log) echo "   <b>unpack </b>: $name 

";



// последний символ имени

$last = substr($name, strlen($name)-1);



// если это каталог

if ($last == "/" || $last == "\\") {

$subdir = $dir."/".$name;

// создать каталог, если он не существует

if (! file_exists($subdir)) mkdir ($subdir);

} else {

// распаковать файл

if (zip_entry_open($zip, $zip_entry, "r")) {

$buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));

$fp = fopen($dir."/".zip_entry_name($zip_entry), "w");

fwrite($fp, $buf);

zip_entry_close($zip_entry);

} else {

return false;

}

}

}

zip_close($zip);

}

} else {

return false;

}



return true;

}

?>

Що потрібно врахувати перед використанням

Ці фрагменти не є готовим рішенням для обробки недовірених архівів. У функції шлях запису складається безпосередньо з імені елемента ZIP: немає перевірки виходу за межі каталогу, обмежень обсягу розпакування чи надійного контролю помилок. Дескриптор записуваного файла явно не закривається; вкладені каталоги також обробляються неповно.

Крім того, zip_open() може повертати числовий код помилки, тому проста перевірка істинності не гарантує успішного відкриття. Цю функцію позначено застарілою з PHP 8.0 на користь об'єктного API ZipArchive.

Для нового коду звертайтеся до документації ZipArchive та перевіряйте шляхи, ліміти ресурсів і всі результати операцій. Довідка щодо старого виклику: zip_open. Історичний код збережено для розбору; не запускайте його без адаптації на довільних завантаженнях.

Немає коментарів:

Калькулятор K2: від запитання про ціну до готової комерційної пропозиції

«А скільки коштуватиме інша комплектація?» — природне запитання покупця. Якщо для відповіді менеджер щоразу відкриває таблицю, шукає коефіці...