// --------------------------------------------------------------------------------
// PhpConcept Library - Zip Module 2.8.2
// --------------------------------------------------------------------------------
// License GNU/LGPL - Vincent Blavet - August 2009
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
// PclZip is a PHP library that manage ZIP archives.
// So far tests show that archives generated by PclZip are readable by
// WinZip application and other tools.
// See readme.txt and http://www.phpconcept.net
// This library and the associated files are non commercial, non professional
// It should not have unexpected results. However if any damage is caused by
// this software the author can not be responsible.
// The use of this software is at the risk of the user.
// --------------------------------------------------------------------------------
// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
// --------------------------------------------------------------------------------
if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
// ----- File list separator
// In version 1.x of PclZip, the separator for file list is a space
// (which is not a very smart choice, specifically for windows paths !).
// A better separator should be a comma (,). This constant gives you the
// ability to change that.
// However notice that changing this value, may have impact on existing
// scripts, using space separated filenames.
// Recommended values for compatibility with older versions :
//define( 'PCLZIP_SEPARATOR', ' ' );
// Recommended values for smart separation of filenames.
if (!defined('PCLZIP_SEPARATOR')) {
define( 'PCLZIP_SEPARATOR', ',' );
// ----- Error configuration
// 0 : PclZip Class integrated error handling
// 1 : PclError external library error handling. By enabling this
// you must ensure that you have included PclError library.
// [2,...] : reserved for futur use
if (!defined('PCLZIP_ERROR_EXTERNAL')) {
define( 'PCLZIP_ERROR_EXTERNAL', 0 );
// ----- Optional static temporary directory
// By default temporary files are generated in the script current
// - MUST BE terminated by a '/'.
// - MUST be a valid, already created directory
// define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
// define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
if (!defined('PCLZIP_TEMPORARY_DIR')) {
define( 'PCLZIP_TEMPORARY_DIR', '' );
// ----- Optional threshold ratio for use of temporary files
// Pclzip sense the size of the file to add/extract and decide to
// use or not temporary file. The algorithm is looking for
// memory_limit of PHP and apply a ratio.
// threshold = memory_limit * ratio.
// Recommended values are under 0.5. Default 0.47.
// define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
// --------------------------------------------------------------------------------
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
// --------------------------------------------------------------------------------
// ----- Global variables
$g_pclzip_version = "2.8.2";
// -1 : Unable to open file in binary write mode
// -2 : Unable to open file in binary read mode
// -3 : Invalid parameters
// -4 : File does not exist
// -5 : Filename is too long (max. 255)
// -6 : Not a valid zip file
// -7 : Invalid extracted file size
// -8 : Unable to create directory
// -9 : Invalid archive extension
// -10 : Invalid archive format
// -11 : Unable to delete file (unlink)
// -12 : Unable to rename file (rename)
// -13 : Invalid header checksum
// -14 : Invalid archive size
define( 'PCLZIP_ERR_USER_ABORTED', 2 );
define( 'PCLZIP_ERR_NO_ERROR', 0 );
define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
define( 'PCLZIP_ERR_MISSING_FILE', -4 );
define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
define( 'PCLZIP_OPT_PATH', 77001 );
define( 'PCLZIP_OPT_ADD_PATH', 77002 );
define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
define( 'PCLZIP_OPT_BY_NAME', 77008 );
define( 'PCLZIP_OPT_BY_INDEX', 77009 );
define( 'PCLZIP_OPT_BY_EREG', 77010 );
define( 'PCLZIP_OPT_BY_PREG', 77011 );
define( 'PCLZIP_OPT_COMMENT', 77012 );
define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
// Having big trouble with crypt. Need to multiply 2 long int
// which is not correctly supported by PHP ...
//define( 'PCLZIP_OPT_CRYPT', 77018 );
define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
// ----- File description attributes
define( 'PCLZIP_ATT_FILE_NAME', 79001 );
define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
// ----- Call backs values
define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
define( 'PCLZIP_CB_PRE_ADD', 78003 );
define( 'PCLZIP_CB_POST_ADD', 78004 );
define( 'PCLZIP_CB_PRE_LIST', 78005 );
define( 'PCLZIP_CB_POST_LIST', 78006 );
define( 'PCLZIP_CB_PRE_DELETE', 78007 );
define( 'PCLZIP_CB_POST_DELETE', 78008 );
// --------------------------------------------------------------------------------
// PclZip is the class that represent a Zip archive.
// The public methods allow the manipulation of the archive.
// Attributes must not be accessed directly.
// PclZip() : Object creator
// create() : Creates the Zip archive
// listContent() : List the content of the Zip archive
// extract() : Extract the content of the archive
// properties() : List the properties of the archive
// --------------------------------------------------------------------------------
// ----- Filename of the zip file
// ----- File descriptor of the zip file
// ----- Internal error handling
// ----- Current status of the magic_quotes_runtime
// This value store the php configuration for magic_quotes
// The class can then disable the magic_quotes and reset it after
var $magic_quotes_status;
// --------------------------------------------------------------------------------
// Creates a PclZip object and set the name of the associated Zip archive
// Note that no real action is taken, if the archive does not exist it is not
// created. Use create() for that.
// --------------------------------------------------------------------------------
function __construct($p_zipname)
if (!function_exists('gzopen'))
die('Abort '.basename(__FILE__).' : Missing zlib extensions');
// ----- Set the attributes
$this->zipname = $p_zipname;
$this->magic_quotes_status = -1;
public function PclZip($p_zipname) {
self::__construct($p_zipname);
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// create($p_filelist, $p_add_dir="", $p_remove_dir="")
// create($p_filelist, $p_option, $p_option_value, ...)
// This method supports two different synopsis. The first one is historical.
// This method creates a Zip Archive. The Zip file is created in the
// filesystem. The files and directories indicated in $p_filelist
// are added in the archive. See the parameters description for the
// supported format of $p_filelist.
// When a directory is in the list, the directory and its content is added
// In this synopsis, the function takes an optional variable list of
// options. See below the supported options.
// $p_filelist : An array containing file or directory names, or
// a string containing one filename or one directory name, or
// a string containing a list of filenames and/or directory
// names separated by spaces.
// $p_add_dir : A path to add before the real path of the archived file,
// in order to have it memorized in the archive.
// $p_remove_dir : A path to remove from the real path of the file to archive,
// in order to have a shorter path memorized in the archive.
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
// is removed first, before $p_add_dir is added.
// PCLZIP_OPT_REMOVE_PATH :
// PCLZIP_OPT_REMOVE_ALL_PATH :
// The list of the added files, with a status of the add action.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function create($p_filelist)
// ----- Reset the error handler
// ----- Set default values
$v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Look for arguments
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Remove from the options list the first argument
array_shift($v_arg_list);
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (PCLZIP_OPT_REMOVE_PATH => 'optional',
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
PCLZIP_OPT_ADD_PATH => 'optional',
PCLZIP_CB_PRE_ADD => 'optional',
PCLZIP_CB_POST_ADD => 'optional',
PCLZIP_OPT_NO_COMPRESSION => 'optional',
PCLZIP_OPT_COMMENT => 'optional',
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
PCLZIP_OPT_TEMP_FILE_ON => 'optional',
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
//, PCLZIP_OPT_CRYPT => 'optional'
// Here we need to support the first historic synopsis of the
// ----- Get the first argument
$v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
// ----- Look for the optional second argument
$v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
"Invalid number / type of arguments");
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
$v_string_list = array();
$v_filedescr_list = array();
$p_result_list = array();
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
// ----- The list is a list of string names
$v_string_list = $p_filelist;
// ----- Look if the $p_filelist is a string
else if (is_string($p_filelist)) {
// ----- Create a list from the string
$v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
// ----- Invalid variable type for $p_filelist
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
// ----- For each file in the list check the attributes
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
,PCLZIP_ATT_FILE_MTIME => 'optional'
,PCLZIP_ATT_FILE_CONTENT => 'optional'
,PCLZIP_ATT_FILE_COMMENT => 'optional'
foreach ($v_att_list as $v_entry) {
$v_result = $this->privFileDescrParseAtt($v_entry,
$v_supported_attributes);
// ----- Expand the filelist (expand directories)
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
// ----- Call the create fct
$v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// add($p_filelist, $p_add_dir="", $p_remove_dir="")
// add($p_filelist, $p_option, $p_option_value, ...)
// This method supports two synopsis. The first one is historical.
// This methods add the list of files in an existing archive.
// If a file with the same name already exists, it is added at the end of the
// archive, the first one is still present.
// If the archive does not exist, it is created.
// $p_filelist : An array containing file or directory names, or
// a string containing one filename or one directory name, or
// a string containing a list of filenames and/or directory
// names separated by spaces.
// $p_add_dir : A path to add before the real path of the archived file,
// in order to have it memorized in the archive.
// $p_remove_dir : A path to remove from the real path of the file to archive,
// in order to have a shorter path memorized in the archive.
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
// is removed first, before $p_add_dir is added.
// PCLZIP_OPT_REMOVE_PATH :
// PCLZIP_OPT_REMOVE_ALL_PATH :
// PCLZIP_OPT_ADD_COMMENT :
// PCLZIP_OPT_PREPEND_COMMENT :
// The list of the added files, with a status of the add action.
// (see PclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function add($p_filelist)
// ----- Reset the error handler
// ----- Set default values
$v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Look for arguments
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Remove form the options list the first argument
array_shift($v_arg_list);
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (PCLZIP_OPT_REMOVE_PATH => 'optional',
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
PCLZIP_OPT_ADD_PATH => 'optional',
PCLZIP_CB_PRE_ADD => 'optional',
PCLZIP_CB_POST_ADD => 'optional',
PCLZIP_OPT_NO_COMPRESSION => 'optional',
PCLZIP_OPT_COMMENT => 'optional',
PCLZIP_OPT_ADD_COMMENT => 'optional',
PCLZIP_OPT_PREPEND_COMMENT => 'optional',
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
PCLZIP_OPT_TEMP_FILE_ON => 'optional',
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
//, PCLZIP_OPT_CRYPT => 'optional'