2
// --------------------------------------------------------------------------------
3
// PhpConcept Library - Zip Module 2.8.2
4
// --------------------------------------------------------------------------------
5
// License GNU/LGPL - Vincent Blavet - August 2009
6
// http://www.phpconcept.net
7
// --------------------------------------------------------------------------------
10
// PclZip is a PHP library that manage ZIP archives.
11
// So far tests show that archives generated by PclZip are readable by
12
// WinZip application and other tools.
15
// See readme.txt and http://www.phpconcept.net
18
// This library and the associated files are non commercial, non professional
20
// It should not have unexpected results. However if any damage is caused by
21
// this software the author can not be responsible.
22
// The use of this software is at the risk of the user.
24
// --------------------------------------------------------------------------------
25
// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
26
// --------------------------------------------------------------------------------
29
if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
30
define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
33
// ----- File list separator
34
// In version 1.x of PclZip, the separator for file list is a space
35
// (which is not a very smart choice, specifically for windows paths !).
36
// A better separator should be a comma (,). This constant gives you the
37
// abilty to change that.
38
// However notice that changing this value, may have impact on existing
39
// scripts, using space separated filenames.
40
// Recommanded values for compatibility with older versions :
41
//define( 'PCLZIP_SEPARATOR', ' ' );
42
// Recommanded values for smart separation of filenames.
43
if (!defined('PCLZIP_SEPARATOR')) {
44
define( 'PCLZIP_SEPARATOR', ',' );
47
// ----- Error configuration
48
// 0 : PclZip Class integrated error handling
49
// 1 : PclError external library error handling. By enabling this
50
// you must ensure that you have included PclError library.
51
// [2,...] : reserved for futur use
52
if (!defined('PCLZIP_ERROR_EXTERNAL')) {
53
define( 'PCLZIP_ERROR_EXTERNAL', 0 );
56
// ----- Optional static temporary directory
57
// By default temporary files are generated in the script current
60
// - MUST BE terminated by a '/'.
61
// - MUST be a valid, already created directory
63
// define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
64
// define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
65
if (!defined('PCLZIP_TEMPORARY_DIR')) {
66
define( 'PCLZIP_TEMPORARY_DIR', '' );
69
// ----- Optional threshold ratio for use of temporary files
70
// Pclzip sense the size of the file to add/extract and decide to
71
// use or not temporary file. The algorythm is looking for
72
// memory_limit of PHP and apply a ratio.
73
// threshold = memory_limit * ratio.
74
// Recommended values are under 0.5. Default 0.47.
76
// define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
77
if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
78
define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
81
// --------------------------------------------------------------------------------
82
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
83
// --------------------------------------------------------------------------------
85
// ----- Global variables
86
$g_pclzip_version = "2.8.2";
89
// -1 : Unable to open file in binary write mode
90
// -2 : Unable to open file in binary read mode
91
// -3 : Invalid parameters
92
// -4 : File does not exist
93
// -5 : Filename is too long (max. 255)
94
// -6 : Not a valid zip file
95
// -7 : Invalid extracted file size
96
// -8 : Unable to create directory
97
// -9 : Invalid archive extension
98
// -10 : Invalid archive format
99
// -11 : Unable to delete file (unlink)
100
// -12 : Unable to rename file (rename)
101
// -13 : Invalid header checksum
102
// -14 : Invalid archive size
103
define( 'PCLZIP_ERR_USER_ABORTED', 2 );
104
define( 'PCLZIP_ERR_NO_ERROR', 0 );
105
define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
106
define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
107
define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
108
define( 'PCLZIP_ERR_MISSING_FILE', -4 );
109
define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
110
define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
111
define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
112
define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
113
define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
114
define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
115
define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
116
define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
117
define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
118
define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
119
define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
120
define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
121
define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
122
define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
123
define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
124
define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
125
define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
127
// ----- Options values
128
define( 'PCLZIP_OPT_PATH', 77001 );
129
define( 'PCLZIP_OPT_ADD_PATH', 77002 );
130
define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
131
define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
132
define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
133
define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
134
define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
135
define( 'PCLZIP_OPT_BY_NAME', 77008 );
136
define( 'PCLZIP_OPT_BY_INDEX', 77009 );
137
define( 'PCLZIP_OPT_BY_EREG', 77010 );
138
define( 'PCLZIP_OPT_BY_PREG', 77011 );
139
define( 'PCLZIP_OPT_COMMENT', 77012 );
140
define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
141
define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
142
define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
143
define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
144
define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
145
// Having big trouble with crypt. Need to multiply 2 long int
146
// which is not correctly supported by PHP ...
147
//define( 'PCLZIP_OPT_CRYPT', 77018 );
148
define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
149
define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
150
define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
151
define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
152
define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
153
define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
154
define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
156
// ----- File description attributes
157
define( 'PCLZIP_ATT_FILE_NAME', 79001 );
158
define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
159
define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
160
define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
161
define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
162
define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
164
// ----- Call backs values
165
define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
166
define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
167
define( 'PCLZIP_CB_PRE_ADD', 78003 );
168
define( 'PCLZIP_CB_POST_ADD', 78004 );
170
define( 'PCLZIP_CB_PRE_LIST', 78005 );
171
define( 'PCLZIP_CB_POST_LIST', 78006 );
172
define( 'PCLZIP_CB_PRE_DELETE', 78007 );
173
define( 'PCLZIP_CB_POST_DELETE', 78008 );
176
// --------------------------------------------------------------------------------
179
// PclZip is the class that represent a Zip archive.
180
// The public methods allow the manipulation of the archive.
182
// Attributes must not be accessed directly.
184
// PclZip() : Object creator
185
// create() : Creates the Zip archive
186
// listContent() : List the content of the Zip archive
187
// extract() : Extract the content of the archive
188
// properties() : List the properties of the archive
189
// --------------------------------------------------------------------------------
192
// ----- Filename of the zip file
195
// ----- File descriptor of the zip file
198
// ----- Internal error handling
200
var $error_string = '';
202
// ----- Current status of the magic_quotes_runtime
203
// This value store the php configuration for magic_quotes
204
// The class can then disable the magic_quotes and reset it after
205
var $magic_quotes_status;
207
// --------------------------------------------------------------------------------
208
// Function : PclZip()
210
// Creates a PclZip object and set the name of the associated Zip archive
212
// Note that no real action is taken, if the archive does not exist it is not
213
// created. Use create() for that.
214
// --------------------------------------------------------------------------------
215
function PclZip($p_zipname)
218
// ----- Tests the zlib
219
if (!function_exists('gzopen'))
221
die('Abort '.basename(__FILE__).' : Missing zlib extensions');
224
// ----- Set the attributes
225
$this->zipname = $p_zipname;
227
$this->magic_quotes_status = -1;
232
// --------------------------------------------------------------------------------
234
// --------------------------------------------------------------------------------
236
// create($p_filelist, $p_add_dir="", $p_remove_dir="")
237
// create($p_filelist, $p_option, $p_option_value, ...)
239
// This method supports two different synopsis. The first one is historical.
240
// This method creates a Zip Archive. The Zip file is created in the
241
// filesystem. The files and directories indicated in $p_filelist
242
// are added in the archive. See the parameters description for the
243
// supported format of $p_filelist.
244
// When a directory is in the list, the directory and its content is added
246
// In this synopsis, the function takes an optional variable list of
247
// options. See bellow the supported options.
249
// $p_filelist : An array containing file or directory names, or
250
// a string containing one filename or one directory name, or
251
// a string containing a list of filenames and/or directory
252
// names separated by spaces.
253
// $p_add_dir : A path to add before the real path of the archived file,
254
// in order to have it memorized in the archive.
255
// $p_remove_dir : A path to remove from the real path of the file to archive,
256
// in order to have a shorter path memorized in the archive.
257
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
258
// is removed first, before $p_add_dir is added.
260
// PCLZIP_OPT_ADD_PATH :
261
// PCLZIP_OPT_REMOVE_PATH :
262
// PCLZIP_OPT_REMOVE_ALL_PATH :
263
// PCLZIP_OPT_COMMENT :
264
// PCLZIP_CB_PRE_ADD :
265
// PCLZIP_CB_POST_ADD :
268
// The list of the added files, with a status of the add action.
269
// (see PclZip::listContent() for list entry format)
270
// --------------------------------------------------------------------------------
271
function create($p_filelist)
275
// ----- Reset the error handler
276
$this->privErrorReset();
278
// ----- Set default values
279
$v_options = array();
280
$v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
282
// ----- Look for variable options arguments
283
$v_size = func_num_args();
285
// ----- Look for arguments
287
// ----- Get the arguments
288
$v_arg_list = func_get_args();
290
// ----- Remove from the options list the first argument
291
array_shift($v_arg_list);
294
// ----- Look for first arg
295
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
297
// ----- Parse the options
298
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
299
array (PCLZIP_OPT_REMOVE_PATH => 'optional',
300
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
301
PCLZIP_OPT_ADD_PATH => 'optional',
302
PCLZIP_CB_PRE_ADD => 'optional',
303
PCLZIP_CB_POST_ADD => 'optional',
304
PCLZIP_OPT_NO_COMPRESSION => 'optional',
305
PCLZIP_OPT_COMMENT => 'optional',
306
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
307
PCLZIP_OPT_TEMP_FILE_ON => 'optional',
308
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
309
//, PCLZIP_OPT_CRYPT => 'optional'
311
if ($v_result != 1) {
316
// ----- Look for 2 args
317
// Here we need to support the first historic synopsis of the
321
// ----- Get the first argument
322
$v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
324
// ----- Look for the optional second argument
326
$v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
328
else if ($v_size > 2) {
329
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
330
"Invalid number / type of arguments");
336
// ----- Look for default option values
337
$this->privOptionDefaultThreshold($v_options);
340
$v_string_list = array();
341
$v_att_list = array();
342
$v_filedescr_list = array();
343
$p_result_list = array();
345
// ----- Look if the $p_filelist is really an array
346
if (is_array($p_filelist)) {
348
// ----- Look if the first element is also an array
349
// This will mean that this is a file description entry
350
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
351
$v_att_list = $p_filelist;
354
// ----- The list is a list of string names
356
$v_string_list = $p_filelist;
360
// ----- Look if the $p_filelist is a string
361
else if (is_string($p_filelist)) {
362
// ----- Create a list from the string
363
$v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
366
// ----- Invalid variable type for $p_filelist
368
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
372
// ----- Reformat the string list
373
if (sizeof($v_string_list) != 0) {
374
foreach ($v_string_list as $v_string) {
375
if ($v_string != '') {
376
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
383
// ----- For each file in the list check the attributes
384
$v_supported_attributes
385
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
386
,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
387
,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
388
,PCLZIP_ATT_FILE_MTIME => 'optional'
389
,PCLZIP_ATT_FILE_CONTENT => 'optional'
390
,PCLZIP_ATT_FILE_COMMENT => 'optional'
392
foreach ($v_att_list as $v_entry) {
393
$v_result = $this->privFileDescrParseAtt($v_entry,
396
$v_supported_attributes);
397
if ($v_result != 1) {
402
// ----- Expand the filelist (expand directories)
403
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
404
if ($v_result != 1) {
408
// ----- Call the create fct
409
$v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
410
if ($v_result != 1) {
415
return $p_result_list;
417
// --------------------------------------------------------------------------------
419
// --------------------------------------------------------------------------------
421
// add($p_filelist, $p_add_dir="", $p_remove_dir="")
422
// add($p_filelist, $p_option, $p_option_value, ...)
424
// This method supports two synopsis. The first one is historical.
425
// This methods add the list of files in an existing archive.
426
// If a file with the same name already exists, it is added at the end of the
427
// archive, the first one is still present.
428
// If the archive does not exist, it is created.
430
// $p_filelist : An array containing file or directory names, or
431
// a string containing one filename or one directory name, or
432
// a string containing a list of filenames and/or directory
433
// names separated by spaces.
434
// $p_add_dir : A path to add before the real path of the archived file,
435
// in order to have it memorized in the archive.
436
// $p_remove_dir : A path to remove from the real path of the file to archive,
437
// in order to have a shorter path memorized in the archive.
438
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
439
// is removed first, before $p_add_dir is added.
441
// PCLZIP_OPT_ADD_PATH :
442
// PCLZIP_OPT_REMOVE_PATH :
443
// PCLZIP_OPT_REMOVE_ALL_PATH :
444
// PCLZIP_OPT_COMMENT :
445
// PCLZIP_OPT_ADD_COMMENT :
446
// PCLZIP_OPT_PREPEND_COMMENT :
447
// PCLZIP_CB_PRE_ADD :
448
// PCLZIP_CB_POST_ADD :
451
// The list of the added files, with a status of the add action.
452
// (see PclZip::listContent() for list entry format)
453
// --------------------------------------------------------------------------------
454
function add($p_filelist)
458
// ----- Reset the error handler
459
$this->privErrorReset();
461
// ----- Set default values
462
$v_options = array();
463
$v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
465
// ----- Look for variable options arguments
466
$v_size = func_num_args();
468
// ----- Look for arguments
470
// ----- Get the arguments
471
$v_arg_list = func_get_args();
473
// ----- Remove form the options list the first argument
474
array_shift($v_arg_list);
477
// ----- Look for first arg
478
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
480
// ----- Parse the options
481
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
482
array (PCLZIP_OPT_REMOVE_PATH => 'optional',
483
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
484
PCLZIP_OPT_ADD_PATH => 'optional',
485
PCLZIP_CB_PRE_ADD => 'optional',
486
PCLZIP_CB_POST_ADD => 'optional',
487
PCLZIP_OPT_NO_COMPRESSION => 'optional',
488
PCLZIP_OPT_COMMENT => 'optional',
489
PCLZIP_OPT_ADD_COMMENT => 'optional',
490
PCLZIP_OPT_PREPEND_COMMENT => 'optional',
491
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
492
PCLZIP_OPT_TEMP_FILE_ON => 'optional',
493
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
494
//, PCLZIP_OPT_CRYPT => 'optional'
496
if ($v_result != 1) {
501
// ----- Look for 2 args
502
// Here we need to support the first historic synopsis of the
506
// ----- Get the first argument
507
$v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
509
// ----- Look for the optional second argument
511
$v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
513
else if ($v_size > 2) {
515
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
523
// ----- Look for default option values
524
$this->privOptionDefaultThreshold($v_options);
527
$v_string_list = array();
528
$v_att_list = array();
529
$v_filedescr_list = array();
530
$p_result_list = array();
532
// ----- Look if the $p_filelist is really an array
533
if (is_array($p_filelist)) {
535
// ----- Look if the first element is also an array
536
// This will mean that this is a file description entry
537
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
538
$v_att_list = $p_filelist;
541
// ----- The list is a list of string names
543
$v_string_list = $p_filelist;
547
// ----- Look if the $p_filelist is a string
548
else if (is_string($p_filelist)) {
549
// ----- Create a list from the string
550
$v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
553
// ----- Invalid variable type for $p_filelist
555
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
559
// ----- Reformat the string list
560
if (sizeof($v_string_list) != 0) {
561
foreach ($v_string_list as $v_string) {
562
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
566
// ----- For each file in the list check the attributes
567
$v_supported_attributes
568
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
569
,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
570
,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
571
,PCLZIP_ATT_FILE_MTIME => 'optional'
572
,PCLZIP_ATT_FILE_CONTENT => 'optional'
573
,PCLZIP_ATT_FILE_COMMENT => 'optional'
575
foreach ($v_att_list as $v_entry) {
576
$v_result = $this->privFileDescrParseAtt($v_entry,
579
$v_supported_attributes);
580
if ($v_result != 1) {
585
// ----- Expand the filelist (expand directories)
586
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
587
if ($v_result != 1) {
591
// ----- Call the create fct
592
$v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
593
if ($v_result != 1) {
598
return $p_result_list;
600
// --------------------------------------------------------------------------------
602
// --------------------------------------------------------------------------------
603
// Function : listContent()
605
// This public method, gives the list of the files and directories, with their
607
// The properties of each entries in the list are (used also in other functions) :
608
// filename : Name of the file. For a create or add action it is the filename
609
// given by the user. For an extract function it is the filename
610
// of the extracted file.
611
// stored_filename : Name of the file / directory stored in the archive.
612
// size : Size of the stored file.
613
// compressed_size : Size of the file's data compressed in the archive
614
// (without the headers overhead)
615
// mtime : Last known modification date of the file (UNIX timestamp)
616
// comment : Comment associated with the file
617
// folder : true | false
618
// index : index of the file in the archive
619
// status : status of the action (depending of the action) :
622
// filtered : the file / dir is not extracted (filtered by user)
623
// already_a_directory : the file can not be extracted because a
624
// directory with the same name already exists
625
// write_protected : the file can not be extracted because a file
626
// with the same name already exists and is
628
// newer_exist : the file was not extracted because a newer file exists
629
// path_creation_fail : the file is not extracted because the folder
630
// does not exist and can not be created
631
// write_error : the file was not extracted because there was a
632
// error while writing the file
633
// read_error : the file was not extracted because there was a error
634
// while reading the file
635
// invalid_header : the file was not extracted because of an archive
636
// format error (bad file header)
637
// Note that each time a method can continue operating when there
638
// is an action error on a file, the error is only logged in the file status.
640
// 0 on an unrecoverable failure,
641
// The list of the files in the archive.
642
// --------------------------------------------------------------------------------
643
function listContent()
647
// ----- Reset the error handler
648
$this->privErrorReset();
650
// ----- Check archive
651
if (!$this->privCheckFormat()) {
655
// ----- Call the extracting fct
657
if (($v_result = $this->privList($p_list)) != 1)
666
// --------------------------------------------------------------------------------
668
// --------------------------------------------------------------------------------
670
// extract($p_path="./", $p_remove_path="")
671
// extract([$p_option, $p_option_value, ...])
673
// This method supports two synopsis. The first one is historical.
674
// This method extract all the files / directories from the archive to the
675
// folder indicated in $p_path.
676
// If you want to ignore the 'root' part of path of the memorized files
677
// you can indicate this in the optional $p_remove_path parameter.
678
// By default, if a newer file with the same name already exists, the
679
// file is not extracted.
681
// If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
682
// are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
683
// at the end of the path value of PCLZIP_OPT_PATH.
685
// $p_path : Path where the files and directories are to be extracted
686
// $p_remove_path : First part ('root' part) of the memorized path
687
// (if any similar) to remove while extracting.
690
// PCLZIP_OPT_ADD_PATH :
691
// PCLZIP_OPT_REMOVE_PATH :
692
// PCLZIP_OPT_REMOVE_ALL_PATH :
693
// PCLZIP_CB_PRE_EXTRACT :
694
// PCLZIP_CB_POST_EXTRACT :
696
// 0 or a negative value on failure,
697
// The list of the extracted files, with a status of the action.
698
// (see PclZip::listContent() for list entry format)
699
// --------------------------------------------------------------------------------
704
// ----- Reset the error handler
705
$this->privErrorReset();
707
// ----- Check archive
708
if (!$this->privCheckFormat()) {
712
// ----- Set default values
713
$v_options = array();
717
$v_remove_all_path = false;
719
// ----- Look for variable options arguments
720
$v_size = func_num_args();
722
// ----- Default values for option
723
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
725
// ----- Look for arguments
727
// ----- Get the arguments
728
$v_arg_list = func_get_args();
730
// ----- Look for first arg
731
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
733
// ----- Parse the options
734
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
735
array (PCLZIP_OPT_PATH => 'optional',
736
PCLZIP_OPT_REMOVE_PATH => 'optional',
737
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
738
PCLZIP_OPT_ADD_PATH => 'optional',
739
PCLZIP_CB_PRE_EXTRACT => 'optional',
740
PCLZIP_CB_POST_EXTRACT => 'optional',
741
PCLZIP_OPT_SET_CHMOD => 'optional',
742
PCLZIP_OPT_BY_NAME => 'optional',
743
PCLZIP_OPT_BY_EREG => 'optional',
744
PCLZIP_OPT_BY_PREG => 'optional',
745
PCLZIP_OPT_BY_INDEX => 'optional',
746
PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
747
PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
748
PCLZIP_OPT_REPLACE_NEWER => 'optional'
749
,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
750
,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
751
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
752
PCLZIP_OPT_TEMP_FILE_ON => 'optional',
753
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
755
if ($v_result != 1) {
759
// ----- Set the arguments
760
if (isset($v_options[PCLZIP_OPT_PATH])) {
761
$v_path = $v_options[PCLZIP_OPT_PATH];
763
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
764
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
766
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
767
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
769
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
770
// ----- Check for '/' in last path char
771
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
774
$v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
778
// ----- Look for 2 args
779
// Here we need to support the first historic synopsis of the
783
// ----- Get the first argument
784
$v_path = $v_arg_list[0];
786
// ----- Look for the optional second argument
788
$v_remove_path = $v_arg_list[1];
790
else if ($v_size > 2) {
792
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
800
// ----- Look for default option values
801
$this->privOptionDefaultThreshold($v_options);
805
// ----- Call the extracting fct
807
$v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
808
$v_remove_all_path, $v_options);
817
// --------------------------------------------------------------------------------
820
// --------------------------------------------------------------------------------
822
// extractByIndex($p_index, $p_path="./", $p_remove_path="")
823
// extractByIndex($p_index, [$p_option, $p_option_value, ...])
825
// This method supports two synopsis. The first one is historical.
826
// This method is doing a partial extract of the archive.
827
// The extracted files or folders are identified by their index in the
828
// archive (from 0 to n).
829
// Note that if the index identify a folder, only the folder entry is
830
// extracted, not all the files included in the archive.
832
// $p_index : A single index (integer) or a string of indexes of files to
833
// extract. The form of the string is "0,4-6,8-12" with only numbers
834
// and '-' for range or ',' to separate ranges. No spaces or ';'
836
// $p_path : Path where the files and directories are to be extracted
837
// $p_remove_path : First part ('root' part) of the memorized path
838
// (if any similar) to remove while extracting.
841
// PCLZIP_OPT_ADD_PATH :
842
// PCLZIP_OPT_REMOVE_PATH :
843
// PCLZIP_OPT_REMOVE_ALL_PATH :
844
// PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
846
// The resulting content is in a new field 'content' in the file
848
// This option must be used alone (any other options are ignored).
849
// PCLZIP_CB_PRE_EXTRACT :
850
// PCLZIP_CB_POST_EXTRACT :
853
// The list of the extracted files, with a status of the action.
854
// (see PclZip::listContent() for list entry format)
855
// --------------------------------------------------------------------------------
856
//function extractByIndex($p_index, options...)
857
function extractByIndex($p_index)
861
// ----- Reset the error handler
862
$this->privErrorReset();
864
// ----- Check archive
865
if (!$this->privCheckFormat()) {
869
// ----- Set default values
870
$v_options = array();
874
$v_remove_all_path = false;
876
// ----- Look for variable options arguments
877
$v_size = func_num_args();
879
// ----- Default values for option
880
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
882
// ----- Look for arguments
884
// ----- Get the arguments
885
$v_arg_list = func_get_args();
887
// ----- Remove form the options list the first argument
888
array_shift($v_arg_list);
891
// ----- Look for first arg
892
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
894
// ----- Parse the options
895
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
896
array (PCLZIP_OPT_PATH => 'optional',
897
PCLZIP_OPT_REMOVE_PATH => 'optional',
898
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
899
PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
900
PCLZIP_OPT_ADD_PATH => 'optional',
901
PCLZIP_CB_PRE_EXTRACT => 'optional',
902
PCLZIP_CB_POST_EXTRACT => 'optional',
903
PCLZIP_OPT_SET_CHMOD => 'optional',
904
PCLZIP_OPT_REPLACE_NEWER => 'optional'
905
,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
906
,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
907
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
908
PCLZIP_OPT_TEMP_FILE_ON => 'optional',
909
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
911
if ($v_result != 1) {
915
// ----- Set the arguments
916
if (isset($v_options[PCLZIP_OPT_PATH])) {
917
$v_path = $v_options[PCLZIP_OPT_PATH];
919
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
920
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
922
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
923
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
925
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
926
// ----- Check for '/' in last path char
927
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
930
$v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
932
if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
933
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
939
// ----- Look for 2 args
940
// Here we need to support the first historic synopsis of the
944
// ----- Get the first argument
945
$v_path = $v_arg_list[0];
947
// ----- Look for the optional second argument
949
$v_remove_path = $v_arg_list[1];
951
else if ($v_size > 2) {
953
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
964
// Here I want to reuse extractByRule(), so I need to parse the $p_index
965
// with privParseOptions()
966
$v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
967
$v_options_trick = array();
968
$v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
969
array (PCLZIP_OPT_BY_INDEX => 'optional' ));
970
if ($v_result != 1) {
973
$v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
975
// ----- Look for default option values
976
$this->privOptionDefaultThreshold($v_options);
978
// ----- Call the extracting fct
979
if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
986
// --------------------------------------------------------------------------------
988
// --------------------------------------------------------------------------------
990
// delete([$p_option, $p_option_value, ...])
992
// This method removes files from the archive.
993
// If no parameters are given, then all the archive is emptied.
995
// None or optional arguments.
997
// PCLZIP_OPT_BY_INDEX :
998
// PCLZIP_OPT_BY_NAME :
999
// PCLZIP_OPT_BY_EREG :
1000
// PCLZIP_OPT_BY_PREG :
1003
// The list of the files which are still present in the archive.
1004
// (see PclZip::listContent() for list entry format)
1005
// --------------------------------------------------------------------------------
1010
// ----- Reset the error handler
1011
$this->privErrorReset();
1013
// ----- Check archive
1014
if (!$this->privCheckFormat()) {
1018
// ----- Set default values
1019
$v_options = array();
1021
// ----- Look for variable options arguments
1022
$v_size = func_num_args();
1024
// ----- Look for arguments
1026
// ----- Get the arguments
1027
$v_arg_list = func_get_args();
1029
// ----- Parse the options
1030
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
1031
array (PCLZIP_OPT_BY_NAME => 'optional',
1032
PCLZIP_OPT_BY_EREG => 'optional',
1033
PCLZIP_OPT_BY_PREG => 'optional',
1034
PCLZIP_OPT_BY_INDEX => 'optional' ));
1035
if ($v_result != 1) {
1040
// ----- Magic quotes trick
1041
$this->privDisableMagicQuotes();
1043
// ----- Call the delete fct
1045
if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1046
$this->privSwapBackMagicQuotes();
1051
// ----- Magic quotes trick
1052
$this->privSwapBackMagicQuotes();
1057
// --------------------------------------------------------------------------------
1059
// --------------------------------------------------------------------------------
1060
// Function : deleteByIndex()
1062
// ***** Deprecated *****
1063
// delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1064
// --------------------------------------------------------------------------------
1065
function deleteByIndex($p_index)
1068
$p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
1073
// --------------------------------------------------------------------------------
1075
// --------------------------------------------------------------------------------
1076
// Function : properties()
1078
// This method gives the properties of the archive.
1079
// The properties are :
1080
// nb : Number of files in the archive
1081
// comment : Comment associated with the archive file
1082
// status : not_exist, ok
1087
// An array with the archive properties.
1088
// --------------------------------------------------------------------------------
1089
function properties()
1092
// ----- Reset the error handler
1093
$this->privErrorReset();
1095
// ----- Magic quotes trick
1096
$this->privDisableMagicQuotes();
1098
// ----- Check archive
1099
if (!$this->privCheckFormat()) {
1100
$this->privSwapBackMagicQuotes();
1104
// ----- Default properties
1106
$v_prop['comment'] = '';
1108
$v_prop['status'] = 'not_exist';
1110
// ----- Look if file exists
1111
if (@is_file($this->zipname))
1113
// ----- Open the zip file
1114
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
1116
$this->privSwapBackMagicQuotes();
1119
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1125
// ----- Read the central directory informations
1126
$v_central_dir = array();
1127
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1129
$this->privSwapBackMagicQuotes();
1133
// ----- Close the zip file
1134
$this->privCloseFd();
1136
// ----- Set the user attributes
1137
$v_prop['comment'] = $v_central_dir['comment'];
1138
$v_prop['nb'] = $v_central_dir['entries'];
1139
$v_prop['status'] = 'ok';
1142
// ----- Magic quotes trick
1143
$this->privSwapBackMagicQuotes();
1148
// --------------------------------------------------------------------------------
1150
// --------------------------------------------------------------------------------
1151
// Function : duplicate()
1153
// This method creates an archive by copying the content of an other one. If
1154
// the archive already exist, it is replaced by the new one without any warning.
1156
// $p_archive : The filename of a valid archive, or
1157
// a valid PclZip object.
1160
// 0 or a negative value on error (error code).
1161
// --------------------------------------------------------------------------------
1162
function duplicate($p_archive)
1166
// ----- Reset the error handler
1167
$this->privErrorReset();
1169
// ----- Look if the $p_archive is a PclZip object
1170
if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
1173
// ----- Duplicate the archive
1174
$v_result = $this->privDuplicate($p_archive->zipname);
1177
// ----- Look if the $p_archive is a string (so a filename)
1178
else if (is_string($p_archive))
1181
// ----- Check that $p_archive is a valid zip file
1182
// TBC : Should also check the archive format
1183
if (!is_file($p_archive)) {
1185
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1186
$v_result = PCLZIP_ERR_MISSING_FILE;
1189
// ----- Duplicate the archive
1190
$v_result = $this->privDuplicate($p_archive);
1194
// ----- Invalid variable
1198
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1199
$v_result = PCLZIP_ERR_INVALID_PARAMETER;
1205
// --------------------------------------------------------------------------------
1207
// --------------------------------------------------------------------------------
1208
// Function : merge()
1210
// This method merge the $p_archive_to_add archive at the end of the current
1212
// If the archive ($this) does not exist, the merge becomes a duplicate.
1213
// If the $p_archive_to_add archive does not exist, the merge is a success.
1215
// $p_archive_to_add : It can be directly the filename of a valid zip archive,
1216
// or a PclZip object archive.
1219
// 0 or negative values on error (see below).
1220
// --------------------------------------------------------------------------------
1221
function merge($p_archive_to_add)
1225
// ----- Reset the error handler
1226
$this->privErrorReset();
1228
// ----- Check archive
1229
if (!$this->privCheckFormat()) {
1233
// ----- Look if the $p_archive_to_add is a PclZip object
1234
if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
1237
// ----- Merge the archive
1238
$v_result = $this->privMerge($p_archive_to_add);
1241
// ----- Look if the $p_archive_to_add is a string (so a filename)
1242
else if (is_string($p_archive_to_add))
1245
// ----- Create a temporary archive
1246
$v_object_archive = new PclZip($p_archive_to_add);
1248
// ----- Merge the archive
1249
$v_result = $this->privMerge($v_object_archive);
1252
// ----- Invalid variable
1256
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1257
$v_result = PCLZIP_ERR_INVALID_PARAMETER;
1263
// --------------------------------------------------------------------------------
1267
// --------------------------------------------------------------------------------
1268
// Function : errorCode()
1271
// --------------------------------------------------------------------------------
1272
function errorCode()
1274
if (PCLZIP_ERROR_EXTERNAL == 1) {
1275
return(PclErrorCode());
1278
return($this->error_code);
1281
// --------------------------------------------------------------------------------
1283
// --------------------------------------------------------------------------------
1284
// Function : errorName()
1287
// --------------------------------------------------------------------------------
1288
function errorName($p_with_code=false)
1290
$v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1291
PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1292
PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1293
PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1294
PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1295
PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1296
PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1297
PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1298
PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1299
PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1300
PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1301
PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1302
PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1303
PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1304
PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1305
PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1306
PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1307
PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1308
PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
1309
,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
1310
,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
1313
if (isset($v_name[$this->error_code])) {
1314
$v_value = $v_name[$this->error_code];
1317
$v_value = 'NoName';
1321
return($v_value.' ('.$this->error_code.')');
1327
// --------------------------------------------------------------------------------
1329
// --------------------------------------------------------------------------------
1330
// Function : errorInfo()
1333
// --------------------------------------------------------------------------------
1334
function errorInfo($p_full=false)
1336
if (PCLZIP_ERROR_EXTERNAL == 1) {
1337
return(PclErrorString());
1341
return($this->errorName(true)." : ".$this->error_string);
1344
return($this->error_string." [code ".$this->error_code."]");
1348
// --------------------------------------------------------------------------------
1351
// --------------------------------------------------------------------------------
1352
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1354
// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1355
// --------------------------------------------------------------------------------
1359
// --------------------------------------------------------------------------------
1360
// Function : privCheckFormat()
1362
// This method check that the archive exists and is a valid zip archive.
1363
// Several level of check exists. (futur)
1365
// $p_level : Level of check. Default 0.
1366
// 0 : Check the first bytes (magic codes) (default value))
1367
// 1 : 0 + Check the central directory (futur)
1368
// 2 : 1 + Check each file header (futur)
1371
// false on error, the error code is set.
1372
// --------------------------------------------------------------------------------
1373
function privCheckFormat($p_level=0)
1377
// ----- Reset the file system cache
1380
// ----- Reset the error handler
1381
$this->privErrorReset();
1383
// ----- Look if the file exits
1384
if (!is_file($this->zipname)) {
1386
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1390
// ----- Check that the file is readeable
1391
if (!is_readable($this->zipname)) {
1393
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1397
// ----- Check the magic code
1400
// ----- Check the central header
1403
// ----- Check each file header
1409
// --------------------------------------------------------------------------------
1411
// --------------------------------------------------------------------------------
1412
// Function : privParseOptions()
1414
// This internal methods reads the variable list of arguments ($p_options_list,
1415
// $p_size) and generate an array with the options and values ($v_result_list).
1416
// $v_requested_options contains the options that can be present and those that
1418
// $v_requested_options is an array, with the option value as key, and 'optional',
1419
// or 'mandatory' as value.
1425
// --------------------------------------------------------------------------------
1426
function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1430
// ----- Read the options
1432
while ($i<$p_size) {
1434
// ----- Check if the option is supported
1435
if (!isset($v_requested_options[$p_options_list[$i]])) {
1437
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1440
return PclZip::errorCode();
1443
// ----- Look for next option
1444
switch ($p_options_list[$i]) {
1445
// ----- Look for options that request a path value
1446
case PCLZIP_OPT_PATH :
1447
case PCLZIP_OPT_REMOVE_PATH :
1448
case PCLZIP_OPT_ADD_PATH :
1449
// ----- Check the number of parameters
1450
if (($i+1) >= $p_size) {
1452
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1455
return PclZip::errorCode();
1458
// ----- Get the value
1459
$v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1463
case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
1464
// ----- Check the number of parameters
1465
if (($i+1) >= $p_size) {
1466
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1467
return PclZip::errorCode();
1470
// ----- Check for incompatible options
1471
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1472
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1473
return PclZip::errorCode();
1476
// ----- Check the value
1477
$v_value = $p_options_list[$i+1];
1478
if ((!is_integer($v_value)) || ($v_value<0)) {
1479
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1480
return PclZip::errorCode();
1483
// ----- Get the value (and convert it in bytes)
1484
$v_result_list[$p_options_list[$i]] = $v_value*1048576;
1488
case PCLZIP_OPT_TEMP_FILE_ON :
1489
// ----- Check for incompatible options
1490
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1491
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1492
return PclZip::errorCode();
1495
$v_result_list[$p_options_list[$i]] = true;
1498
case PCLZIP_OPT_TEMP_FILE_OFF :
1499
// ----- Check for incompatible options
1500
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
1501
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
1502
return PclZip::errorCode();
1504
// ----- Check for incompatible options
1505
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1506
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1507
return PclZip::errorCode();
1510
$v_result_list[$p_options_list[$i]] = true;
1513
case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
1514
// ----- Check the number of parameters
1515
if (($i+1) >= $p_size) {
1517
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1520
return PclZip::errorCode();
1523
// ----- Get the value
1524
if ( is_string($p_options_list[$i+1])
1525
&& ($p_options_list[$i+1] != '')) {
1526
$v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1533
// ----- Look for options that request an array of string for value
1534
case PCLZIP_OPT_BY_NAME :
1535
// ----- Check the number of parameters
1536
if (($i+1) >= $p_size) {
1538
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1541
return PclZip::errorCode();
1544
// ----- Get the value
1545
if (is_string($p_options_list[$i+1])) {
1546
$v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1548
else if (is_array($p_options_list[$i+1])) {
1549
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1553
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1556
return PclZip::errorCode();
1561
// ----- Look for options that request an EREG or PREG expression
1562
case PCLZIP_OPT_BY_EREG :
1563
// ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
1564
// to PCLZIP_OPT_BY_PREG
1565
$p_options_list[$i] = PCLZIP_OPT_BY_PREG;
1566
case PCLZIP_OPT_BY_PREG :
1567
//case PCLZIP_OPT_CRYPT :
1568
// ----- Check the number of parameters
1569
if (($i+1) >= $p_size) {
1571
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1574
return PclZip::errorCode();
1577
// ----- Get the value
1578
if (is_string($p_options_list[$i+1])) {
1579
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1583
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1586
return PclZip::errorCode();
1591
// ----- Look for options that takes a string
1592
case PCLZIP_OPT_COMMENT :
1593
case PCLZIP_OPT_ADD_COMMENT :
1594
case PCLZIP_OPT_PREPEND_COMMENT :
1595
// ----- Check the number of parameters
1596
if (($i+1) >= $p_size) {
1598
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
1599
"Missing parameter value for option '"
1600
.PclZipUtilOptionText($p_options_list[$i])
1604
return PclZip::errorCode();
1607
// ----- Get the value
1608
if (is_string($p_options_list[$i+1])) {
1609
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1613
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
1614
"Wrong parameter value for option '"
1615
.PclZipUtilOptionText($p_options_list[$i])
1619
return PclZip::errorCode();
1624
// ----- Look for options that request an array of index
1625
case PCLZIP_OPT_BY_INDEX :
1626
// ----- Check the number of parameters
1627
if (($i+1) >= $p_size) {
1629
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1632
return PclZip::errorCode();
1635
// ----- Get the value
1636
$v_work_list = array();
1637
if (is_string($p_options_list[$i+1])) {
1639
// ----- Remove spaces
1640
$p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1642
// ----- Parse items
1643
$v_work_list = explode(",", $p_options_list[$i+1]);
1645
else if (is_integer($p_options_list[$i+1])) {
1646
$v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1648
else if (is_array($p_options_list[$i+1])) {
1649
$v_work_list = $p_options_list[$i+1];
1653
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1656
return PclZip::errorCode();
1659
// ----- Reduce the index list
1660
// each index item in the list must be a couple with a start and
1661
// an end value : [0,3], [5-5], [8-10], ...
1662
// ----- Check the format of each item
1665
for ($j=0; $j<sizeof($v_work_list); $j++) {
1666
// ----- Explode the item
1667
$v_item_list = explode("-", $v_work_list[$j]);
1668
$v_size_item_list = sizeof($v_item_list);
1670
// ----- TBC : Here we might check that each item is a
1673
// ----- Look for single value
1674
if ($v_size_item_list == 1) {
1675
// ----- Set the option value
1676
$v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1677
$v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1679
elseif ($v_size_item_list == 2) {
1680
// ----- Set the option value
1681
$v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1682
$v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1686
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1689
return PclZip::errorCode();
1693
// ----- Look for list sort
1694
if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1697
// ----- TBC : An automatic sort should be writen ...
1699
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1702
return PclZip::errorCode();
1704
$v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1707
// ----- Sort the items
1709
// TBC : To Be Completed
1712
// ----- Next option
1716
// ----- Look for options that request no value
1717
case PCLZIP_OPT_REMOVE_ALL_PATH :
1718
case PCLZIP_OPT_EXTRACT_AS_STRING :
1719
case PCLZIP_OPT_NO_COMPRESSION :
1720
case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1721
case PCLZIP_OPT_REPLACE_NEWER :
1722
case PCLZIP_OPT_STOP_ON_ERROR :
1723
$v_result_list[$p_options_list[$i]] = true;
1726
// ----- Look for options that request an octal value
1727
case PCLZIP_OPT_SET_CHMOD :
1728
// ----- Check the number of parameters
1729
if (($i+1) >= $p_size) {
1731
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1734
return PclZip::errorCode();
1737
// ----- Get the value
1738
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1742
// ----- Look for options that request a call-back
1743
case PCLZIP_CB_PRE_EXTRACT :
1744
case PCLZIP_CB_POST_EXTRACT :
1745
case PCLZIP_CB_PRE_ADD :
1746
case PCLZIP_CB_POST_ADD :
1748
case PCLZIP_CB_PRE_DELETE :
1749
case PCLZIP_CB_POST_DELETE :
1750
case PCLZIP_CB_PRE_LIST :
1751
case PCLZIP_CB_POST_LIST :
1753
// ----- Check the number of parameters
1754
if (($i+1) >= $p_size) {
1756
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1759
return PclZip::errorCode();
1762
// ----- Get the value
1763
$v_function_name = $p_options_list[$i+1];
1765
// ----- Check that the value is a valid existing function
1766
if (!function_exists($v_function_name)) {
1768
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1771
return PclZip::errorCode();
1774
// ----- Set the attribute
1775
$v_result_list[$p_options_list[$i]] = $v_function_name;
1781
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1782
"Unknown parameter '"
1783
.$p_options_list[$i]."'");
1786
return PclZip::errorCode();
1789
// ----- Next options
1793
// ----- Look for mandatory options
1794
if ($v_requested_options !== false) {
1795
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1796
// ----- Look for mandatory option
1797
if ($v_requested_options[$key] == 'mandatory') {
1798
// ----- Look if present
1799
if (!isset($v_result_list[$key])) {
1801
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1804
return PclZip::errorCode();
1810
// ----- Look for default values
1811
if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1818
// --------------------------------------------------------------------------------
1820
// --------------------------------------------------------------------------------
1821
// Function : privOptionDefaultThreshold()
1825
// --------------------------------------------------------------------------------
1826
function privOptionDefaultThreshold(&$p_options)
1830
if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
1831
|| isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
1835
// ----- Get 'memory_limit' configuration value
1836
$v_memory_limit = ini_get('memory_limit');
1837
$v_memory_limit = trim($v_memory_limit);
1838
$last = strtolower(substr($v_memory_limit, -1));
1841
//$v_memory_limit = $v_memory_limit*1024*1024*1024;
1842
$v_memory_limit = $v_memory_limit*1073741824;
1844
//$v_memory_limit = $v_memory_limit*1024*1024;
1845
$v_memory_limit = $v_memory_limit*1048576;
1847
$v_memory_limit = $v_memory_limit*1024;
1849
$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
1852
// ----- Sanity check : No threshold if value lower than 1M
1853
if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
1854
unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
1860
// --------------------------------------------------------------------------------
1862
// --------------------------------------------------------------------------------
1863
// Function : privFileDescrParseAtt()
1869
// --------------------------------------------------------------------------------
1870
function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
1874
// ----- For each file in the list check the attributes
1875
foreach ($p_file_list as $v_key => $v_value) {
1877
// ----- Check if the option is supported
1878
if (!isset($v_requested_options[$v_key])) {
1880
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
1883
return PclZip::errorCode();
1886
// ----- Look for attribute
1888
case PCLZIP_ATT_FILE_NAME :
1889
if (!is_string($v_value)) {
1890
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1891
return PclZip::errorCode();
1894
$p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
1896
if ($p_filedescr['filename'] == '') {
1897
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
1898
return PclZip::errorCode();
1903
case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
1904
if (!is_string($v_value)) {
1905
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1906
return PclZip::errorCode();
1909
$p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
1911
if ($p_filedescr['new_short_name'] == '') {
1912
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
1913
return PclZip::errorCode();
1917
case PCLZIP_ATT_FILE_NEW_FULL_NAME :
1918
if (!is_string($v_value)) {
1919
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1920
return PclZip::errorCode();
1923
$p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
1925
if ($p_filedescr['new_full_name'] == '') {
1926
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
1927
return PclZip::errorCode();
1931
// ----- Look for options that takes a string
1932
case PCLZIP_ATT_FILE_COMMENT :
1933
if (!is_string($v_value)) {
1934
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1935
return PclZip::errorCode();
1938
$p_filedescr['comment'] = $v_value;
1941
case PCLZIP_ATT_FILE_MTIME :
1942
if (!is_integer($v_value)) {
1943
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
1944
return PclZip::errorCode();
1947
$p_filedescr['mtime'] = $v_value;
1950
case PCLZIP_ATT_FILE_CONTENT :
1951
$p_filedescr['content'] = $v_value;
1956
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1957
"Unknown parameter '".$v_key."'");
1960
return PclZip::errorCode();
1963
// ----- Look for mandatory options
1964
if ($v_requested_options !== false) {
1965
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1966
// ----- Look for mandatory option
1967
if ($v_requested_options[$key] == 'mandatory') {
1968
// ----- Look if present
1969
if (!isset($p_file_list[$key])) {
1970
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1971
return PclZip::errorCode();
1983
// --------------------------------------------------------------------------------
1985
// --------------------------------------------------------------------------------
1986
// Function : privFileDescrExpand()
1988
// This method look for each item of the list to see if its a file, a folder
1989
// or a string to be added as file. For any other type of files (link, other)
1990
// just ignore the item.
1991
// Then prepare the information that will be stored for that file.
1992
// When its a folder, expand the folder with all the files that are in that
1993
// folder (recursively).
1998
// --------------------------------------------------------------------------------
1999
function privFileDescrExpand(&$p_filedescr_list, &$p_options)
2003
// ----- Create a result list
2004
$v_result_list = array();
2006
// ----- Look each entry
2007
for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
2009
// ----- Get filedescr
2010
$v_descr = $p_filedescr_list[$i];
2012
// ----- Reduce the filename
2013
$v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
2014
$v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
2016
// ----- Look for real file or folder
2017
if (file_exists($v_descr['filename'])) {
2018
if (@is_file($v_descr['filename'])) {
2019
$v_descr['type'] = 'file';
2021
else if (@is_dir($v_descr['filename'])) {
2022
$v_descr['type'] = 'folder';
2024
else if (@is_link($v_descr['filename'])) {
2034
// ----- Look for string added as file
2035
else if (isset($v_descr['content'])) {
2036
$v_descr['type'] = 'virtual_file';
2039
// ----- Missing file
2042
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
2045
return PclZip::errorCode();
2048
// ----- Calculate the stored filename
2049
$this->privCalculateStoredFilename($v_descr, $p_options);
2051
// ----- Add the descriptor in result list
2052
$v_result_list[sizeof($v_result_list)] = $v_descr;
2054
// ----- Look for folder
2055
if ($v_descr['type'] == 'folder') {
2056
// ----- List of items in folder
2057
$v_dirlist_descr = array();
2059
if ($v_folder_handler = @opendir($v_descr['filename'])) {
2060
while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
2062
// ----- Skip '.' and '..'
2063
if (($v_item_handler == '.') || ($v_item_handler == '..')) {
2067
// ----- Compose the full filename
2068
$v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
2070
// ----- Look for different stored filename
2071
// Because the name of the folder was changed, the name of the
2072
// files/sub-folders also change
2073
if (($v_descr['stored_filename'] != $v_descr['filename'])
2074
&& (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
2075
if ($v_descr['stored_filename'] != '') {
2076
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
2079
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
2086
@closedir($v_folder_handler);
2089
// TBC : unable to open folder in read mode
2092
// ----- Expand each element of the list
2093
if ($v_dirlist_nb != 0) {
2095
if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
2099
// ----- Concat the resulting list
2100
$v_result_list = array_merge($v_result_list, $v_dirlist_descr);
2105
// ----- Free local array
2106
unset($v_dirlist_descr);
2110
// ----- Get the result list
2111
$p_filedescr_list = $v_result_list;
2116
// --------------------------------------------------------------------------------
2118
// --------------------------------------------------------------------------------
2119
// Function : privCreate()
2123
// --------------------------------------------------------------------------------
2124
function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
2127
$v_list_detail = array();
2129
// ----- Magic quotes trick
2130
$this->privDisableMagicQuotes();
2132
// ----- Open the file in write mode
2133
if (($v_result = $this->privOpenFd('wb')) != 1)
2139
// ----- Add the list of files
2140
$v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2143
$this->privCloseFd();
2145
// ----- Magic quotes trick
2146
$this->privSwapBackMagicQuotes();
2151
// --------------------------------------------------------------------------------
2153
// --------------------------------------------------------------------------------
2154
// Function : privAdd()
2158
// --------------------------------------------------------------------------------
2159
function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2162
$v_list_detail = array();
2164
// ----- Look if the archive exists or is empty
2165
if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
2168
// ----- Do a create
2169
$v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2174
// ----- Magic quotes trick
2175
$this->privDisableMagicQuotes();
2177
// ----- Open the zip file
2178
if (($v_result=$this->privOpenFd('rb')) != 1)
2180
// ----- Magic quotes trick
2181
$this->privSwapBackMagicQuotes();
2187
// ----- Read the central directory informations
2188
$v_central_dir = array();
2189
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2191
$this->privCloseFd();
2192
$this->privSwapBackMagicQuotes();
2196
// ----- Go to beginning of File
2197
@rewind($this->zip_fd);
2199
// ----- Creates a temporay file
2200
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2202
// ----- Open the temporary file in write mode
2203
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
2205
$this->privCloseFd();
2206
$this->privSwapBackMagicQuotes();
2208
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2211
return PclZip::errorCode();
2214
// ----- Copy the files from the archive to the temporary file
2215
// TBC : Here I should better append the file and go back to erase the central dir
2216
$v_size = $v_central_dir['offset'];
2217
while ($v_size != 0)
2219
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2220
$v_buffer = fread($this->zip_fd, $v_read_size);
2221
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2222
$v_size -= $v_read_size;
2225
// ----- Swap the file descriptor
2226
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
2227
// the following methods on the temporary fil and not the real archive
2228
$v_swap = $this->zip_fd;
2229
$this->zip_fd = $v_zip_temp_fd;
2230
$v_zip_temp_fd = $v_swap;
2232
// ----- Add the files
2233
$v_header_list = array();
2234
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2236
fclose($v_zip_temp_fd);
2237
$this->privCloseFd();
2238
@unlink($v_zip_temp_name);
2239
$this->privSwapBackMagicQuotes();
2245
// ----- Store the offset of the central dir
2246
$v_offset = @ftell($this->zip_fd);
2248
// ----- Copy the block of file headers from the old archive
2249
$v_size = $v_central_dir['size'];
2250
while ($v_size != 0)
2252
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2253
$v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2254
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
2255
$v_size -= $v_read_size;
2258
// ----- Create the Central Dir files header
2259
for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
2261
// ----- Create the file header
2262
if ($v_header_list[$i]['status'] == 'ok') {
2263
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2264
fclose($v_zip_temp_fd);
2265
$this->privCloseFd();
2266
@unlink($v_zip_temp_name);
2267
$this->privSwapBackMagicQuotes();
2275
// ----- Transform the header to a 'usable' info
2276
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2279
// ----- Zip file comment
2280
$v_comment = $v_central_dir['comment'];
2281
if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2282
$v_comment = $p_options[PCLZIP_OPT_COMMENT];
2284
if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
2285
$v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
2287
if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
2288
$v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2291
// ----- Calculate the size of the central header
2292
$v_size = @ftell($this->zip_fd)-$v_offset;
2294
// ----- Create the central dir footer
2295
if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
2297
// ----- Reset the file list
2298
unset($v_header_list);
2299
$this->privSwapBackMagicQuotes();
2305
// ----- Swap back the file descriptor
2306
$v_swap = $this->zip_fd;
2307
$this->zip_fd = $v_zip_temp_fd;
2308
$v_zip_temp_fd = $v_swap;
2311
$this->privCloseFd();
2313
// ----- Close the temporary file
2314
@fclose($v_zip_temp_fd);
2316
// ----- Magic quotes trick
2317
$this->privSwapBackMagicQuotes();
2319
// ----- Delete the zip file
2320
// TBC : I should test the result ...
2321
@unlink($this->zipname);
2323
// ----- Rename the temporary file
2324
// TBC : I should test the result ...
2325
//@rename($v_zip_temp_name, $this->zipname);
2326
PclZipUtilRename($v_zip_temp_name, $this->zipname);
2331
// --------------------------------------------------------------------------------
2333
// --------------------------------------------------------------------------------
2334
// Function : privOpenFd()
2337
// --------------------------------------------------------------------------------
2338
function privOpenFd($p_mode)
2342
// ----- Look if already open
2343
if ($this->zip_fd != 0)
2346
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2349
return PclZip::errorCode();
2352
// ----- Open the zip file
2353
if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
2356
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2359
return PclZip::errorCode();
2365
// --------------------------------------------------------------------------------
2367
// --------------------------------------------------------------------------------
2368
// Function : privCloseFd()
2371
// --------------------------------------------------------------------------------
2372
function privCloseFd()
2376
if ($this->zip_fd != 0)
2377
@fclose($this->zip_fd);
2383
// --------------------------------------------------------------------------------
2385
// --------------------------------------------------------------------------------
2386
// Function : privAddList()
2388
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2389
// different from the real path of the file. This is usefull if you want to have PclTar
2390
// running in any directory, and memorize relative path from an other directory.
2392
// $p_list : An array containing the file or directory names to add in the tar
2393
// $p_result_list : list of added files with their properties (specially the status field)
2394
// $p_add_dir : Path to add in the filename path archived
2395
// $p_remove_dir : Path to remove in the filename path archived
2397
// --------------------------------------------------------------------------------
2398
// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2399
function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2403
// ----- Add the files
2404
$v_header_list = array();
2405
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2411
// ----- Store the offset of the central dir
2412
$v_offset = @ftell($this->zip_fd);
2414
// ----- Create the Central Dir files header
2415
for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
2417
// ----- Create the file header
2418
if ($v_header_list[$i]['status'] == 'ok') {
2419
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2426
// ----- Transform the header to a 'usable' info
2427
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2430
// ----- Zip file comment
2432
if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2433
$v_comment = $p_options[PCLZIP_OPT_COMMENT];
2436
// ----- Calculate the size of the central header
2437
$v_size = @ftell($this->zip_fd)-$v_offset;
2439
// ----- Create the central dir footer
2440
if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
2442
// ----- Reset the file list
2443
unset($v_header_list);
2452
// --------------------------------------------------------------------------------
2454
// --------------------------------------------------------------------------------
2455
// Function : privAddFileList()
2458
// $p_filedescr_list : An array containing the file description
2459
// or directory names to add in the zip
2460
// $p_result_list : list of added files with their properties (specially the status field)
2462
// --------------------------------------------------------------------------------
2463
function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2466
$v_header = array();
2468
// ----- Recuperate the current number of elt in list
2469
$v_nb = sizeof($p_result_list);
2471
// ----- Loop on the files
2472
for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2473
// ----- Format the filename
2474
$p_filedescr_list[$j]['filename']
2475
= PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2478
// ----- Skip empty file names
2479
// TBC : Can this be possible ? not checked in DescrParseAtt ?
2480
if ($p_filedescr_list[$j]['filename'] == "") {
2484
// ----- Check the filename
2485
if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
2486
&& (!file_exists($p_filedescr_list[$j]['filename']))) {
2487
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2488
return PclZip::errorCode();
2491
// ----- Look if it is a file or a dir with no all path remove option
2492
// or a dir with all its path removed
2493
// if ( (is_file($p_filedescr_list[$j]['filename']))
2494
// || ( is_dir($p_filedescr_list[$j]['filename'])
2495
if ( ($p_filedescr_list[$j]['type'] == 'file')
2496
|| ($p_filedescr_list[$j]['type'] == 'virtual_file')
2497
|| ( ($p_filedescr_list[$j]['type'] == 'folder')
2498
&& ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
2499
|| !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
2502
// ----- Add the file
2503
$v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
2505
if ($v_result != 1) {
2509
// ----- Store the file infos
2510
$p_result_list[$v_nb++] = $v_header;
2517
// --------------------------------------------------------------------------------
2519
// --------------------------------------------------------------------------------
2520
// Function : privAddFile()
2524
// --------------------------------------------------------------------------------
2525
function privAddFile($p_filedescr, &$p_header, &$p_options)
2529
// ----- Working variable
2530
$p_filename = $p_filedescr['filename'];
2532
// TBC : Already done in the fileAtt check ... ?
2533
if ($p_filename == "") {
2535
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2538
return PclZip::errorCode();
2541
// ----- Look for a stored different filename
2543
if (isset($p_filedescr['stored_filename'])) {
2544
$v_stored_filename = $p_filedescr['stored_filename'];
2547
$v_stored_filename = $p_filedescr['stored_filename'];
2551
// ----- Set the file properties
2553
$p_header['version'] = 20;
2554
$p_header['version_extracted'] = 10;
2555
$p_header['flag'] = 0;
2556
$p_header['compression'] = 0;
2557
$p_header['crc'] = 0;
2558
$p_header['compressed_size'] = 0;
2559
$p_header['filename_len'] = strlen($p_filename);
2560
$p_header['extra_len'] = 0;
2561
$p_header['disk'] = 0;
2562
$p_header['internal'] = 0;
2563
$p_header['offset'] = 0;
2564
$p_header['filename'] = $p_filename;
2565
// TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
2566
$p_header['stored_filename'] = $p_filedescr['stored_filename'];
2567
$p_header['extra'] = '';
2568
$p_header['status'] = 'ok';
2569
$p_header['index'] = -1;
2571
// ----- Look for regular file
2572
if ($p_filedescr['type']=='file') {
2573
$p_header['external'] = 0x00000000;
2574
$p_header['size'] = filesize($p_filename);
2577
// ----- Look for regular folder
2578
else if ($p_filedescr['type']=='folder') {
2579
$p_header['external'] = 0x00000010;
2580
$p_header['mtime'] = filemtime($p_filename);
2581
$p_header['size'] = filesize($p_filename);
2584
// ----- Look for virtual file
2585
else if ($p_filedescr['type'] == 'virtual_file') {
2586
$p_header['external'] = 0x00000000;
2587
$p_header['size'] = strlen($p_filedescr['content']);
2591
// ----- Look for filetime
2592
if (isset($p_filedescr['mtime'])) {
2593
$p_header['mtime'] = $p_filedescr['mtime'];
2595
else if ($p_filedescr['type'] == 'virtual_file') {
2596
$p_header['mtime'] = time();
2599
$p_header['mtime'] = filemtime($p_filename);
2602
// ------ Look for file comment
2603
if (isset($p_filedescr['comment'])) {
2604
$p_header['comment_len'] = strlen($p_filedescr['comment']);
2605
$p_header['comment'] = $p_filedescr['comment'];
2608
$p_header['comment_len'] = 0;
2609
$p_header['comment'] = '';
2612
// ----- Look for pre-add callback
2613
if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
2615
// ----- Generate a local information
2616
$v_local_header = array();
2617
$this->privConvertHeader2FileInfo($p_header, $v_local_header);
2619
// ----- Call the callback
2620
// Here I do not use call_user_func() because I need to send a reference to the
2622
$v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
2623
if ($v_result == 0) {
2624
// ----- Change the file status
2625
$p_header['status'] = "skipped";
2629
// ----- Update the informations
2630
// Only some fields can be modified
2631
if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2632
$p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2636
// ----- Look for empty stored filename
2637
if ($p_header['stored_filename'] == "") {
2638
$p_header['status'] = "filtered";
2641
// ----- Check the path length
2642
if (strlen($p_header['stored_filename']) > 0xFF) {
2643
$p_header['status'] = 'filename_too_long';
2646
// ----- Look if no error, or file not skipped
2647
if ($p_header['status'] == 'ok') {
2649
// ----- Look for a file
2650
if ($p_filedescr['type'] == 'file') {
2651
// ----- Look for using temporary file to zip
2652
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
2653
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
2654
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
2655
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
2656
$v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
2657
if ($v_result < PCLZIP_ERR_NO_ERROR) {
2662
// ----- Use "in memory" zip algo
2665
// ----- Open the source file
2666
if (($v_file = @fopen($p_filename, "rb")) == 0) {
2667
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2668
return PclZip::errorCode();
2671
// ----- Read the file content
2672
$v_content = @fread($v_file, $p_header['size']);
2674
// ----- Close the file
2677
// ----- Calculate the CRC
2678
$p_header['crc'] = @crc32($v_content);
2680
// ----- Look for no compression
2681
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2682
// ----- Set header parameters
2683
$p_header['compressed_size'] = $p_header['size'];
2684
$p_header['compression'] = 0;
2687
// ----- Look for normal compression
2689
// ----- Compress the content
2690
$v_content = @gzdeflate($v_content);
2692
// ----- Set header parameters
2693
$p_header['compressed_size'] = strlen($v_content);
2694
$p_header['compression'] = 8;
2697
// ----- Call the header generation
2698
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2703
// ----- Write the compressed (or not) content
2704
@fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2710
// ----- Look for a virtual file (a file from string)
2711
else if ($p_filedescr['type'] == 'virtual_file') {
2713
$v_content = $p_filedescr['content'];
2715
// ----- Calculate the CRC
2716
$p_header['crc'] = @crc32($v_content);
2718
// ----- Look for no compression
2719
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2720
// ----- Set header parameters
2721
$p_header['compressed_size'] = $p_header['size'];
2722
$p_header['compression'] = 0;
2725
// ----- Look for normal compression
2727
// ----- Compress the content
2728
$v_content = @gzdeflate($v_content);
2730
// ----- Set header parameters
2731
$p_header['compressed_size'] = strlen($v_content);
2732
$p_header['compression'] = 8;
2735
// ----- Call the header generation
2736
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2741
// ----- Write the compressed (or not) content
2742
@fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2745
// ----- Look for a directory
2746
else if ($p_filedescr['type'] == 'folder') {
2747
// ----- Look for directory last '/'
2748
if (@substr($p_header['stored_filename'], -1) != '/') {
2749
$p_header['stored_filename'] .= '/';
2752
// ----- Set the file properties
2753
$p_header['size'] = 0;
2754
//$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
2755
$p_header['external'] = 0x00000010; // Value for a folder : to be checked
2757
// ----- Call the header generation
2758
if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
2765
// ----- Look for post-add callback
2766
if (isset($p_options[PCLZIP_CB_POST_ADD])) {
2768
// ----- Generate a local information
2769
$v_local_header = array();
2770
$this->privConvertHeader2FileInfo($p_header, $v_local_header);
2772
// ----- Call the callback
2773
// Here I do not use call_user_func() because I need to send a reference to the
2775
$v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
2776
if ($v_result == 0) {
2781
// ----- Update the informations
2782
// Nothing can be modified
2788
// --------------------------------------------------------------------------------
2790
// --------------------------------------------------------------------------------
2791
// Function : privAddFileUsingTempFile()
2795
// --------------------------------------------------------------------------------
2796
function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
2798
$v_result=PCLZIP_ERR_NO_ERROR;
2800
// ----- Working variable
2801
$p_filename = $p_filedescr['filename'];
2804
// ----- Open the source file
2805
if (($v_file = @fopen($p_filename, "rb")) == 0) {
2806
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2807
return PclZip::errorCode();
2810
// ----- Creates a compressed temporary file
2811
$v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
2812
if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
2814
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
2815
return PclZip::errorCode();
2818
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2819
$v_size = filesize($p_filename);
2820
while ($v_size != 0) {
2821
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2822
$v_buffer = @fread($v_file, $v_read_size);
2823
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2824
@gzputs($v_file_compressed, $v_buffer, $v_read_size);
2825
$v_size -= $v_read_size;
2828
// ----- Close the file
2830
@gzclose($v_file_compressed);
2832
// ----- Check the minimum file size
2833
if (filesize($v_gzip_temp_name) < 18) {
2834
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
2835
return PclZip::errorCode();
2838
// ----- Extract the compressed attributes
2839
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2840
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2841
return PclZip::errorCode();
2844
// ----- Read the gzip file header
2845
$v_binary_data = @fread($v_file_compressed, 10);
2846
$v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
2848
// ----- Check some parameters
2849
$v_data_header['os'] = bin2hex($v_data_header['os']);
2851
// ----- Read the gzip file footer
2852
@fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
2853
$v_binary_data = @fread($v_file_compressed, 8);
2854
$v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
2856
// ----- Set the attributes
2857
$p_header['compression'] = ord($v_data_header['cm']);
2858
//$p_header['mtime'] = $v_data_header['mtime'];
2859
$p_header['crc'] = $v_data_footer['crc'];
2860
$p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
2862
// ----- Close the file
2863
@fclose($v_file_compressed);
2865
// ----- Call the header generation
2866
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2870
// ----- Add the compressed data
2871
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
2873
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2874
return PclZip::errorCode();
2877
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2878
fseek($v_file_compressed, 10);
2879
$v_size = $p_header['compressed_size'];
2880
while ($v_size != 0)
2882
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2883
$v_buffer = @fread($v_file_compressed, $v_read_size);
2884
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2885
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
2886
$v_size -= $v_read_size;
2889
// ----- Close the file
2890
@fclose($v_file_compressed);
2892
// ----- Unlink the temporary file
2893
@unlink($v_gzip_temp_name);
2898
// --------------------------------------------------------------------------------
2900
// --------------------------------------------------------------------------------
2901
// Function : privCalculateStoredFilename()
2903
// Based on file descriptor properties and global options, this method
2904
// calculate the filename that will be stored in the archive.
2907
// --------------------------------------------------------------------------------
2908
function privCalculateStoredFilename(&$p_filedescr, &$p_options)
2912
// ----- Working variables
2913
$p_filename = $p_filedescr['filename'];
2914
if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
2915
$p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
2920
if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
2921
$p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
2926
if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
2927
$p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
2930
$p_remove_all_dir = 0;
2934
// ----- Look for full name change
2935
if (isset($p_filedescr['new_full_name'])) {
2936
// ----- Remove drive letter if any
2937
$v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
2940
// ----- Look for path and/or short name change
2943
// ----- Look for short name change
2944
// Its when we cahnge just the filename but not the path
2945
if (isset($p_filedescr['new_short_name'])) {
2946
$v_path_info = pathinfo($p_filename);
2948
if ($v_path_info['dirname'] != '') {
2949
$v_dir = $v_path_info['dirname'].'/';
2951
$v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2954
// ----- Calculate the stored filename
2955
$v_stored_filename = $p_filename;
2958
// ----- Look for all path to remove
2959
if ($p_remove_all_dir) {
2960
$v_stored_filename = basename($p_filename);
2962
// ----- Look for partial path remove
2963
else if ($p_remove_dir != "") {
2964
if (substr($p_remove_dir, -1) != '/')
2965
$p_remove_dir .= "/";
2967
if ( (substr($p_filename, 0, 2) == "./")
2968
|| (substr($p_remove_dir, 0, 2) == "./")) {
2970
if ( (substr($p_filename, 0, 2) == "./")
2971
&& (substr($p_remove_dir, 0, 2) != "./")) {
2972
$p_remove_dir = "./".$p_remove_dir;
2974
if ( (substr($p_filename, 0, 2) != "./")
2975
&& (substr($p_remove_dir, 0, 2) == "./")) {
2976
$p_remove_dir = substr($p_remove_dir, 2);
2980
$v_compare = PclZipUtilPathInclusion($p_remove_dir,
2981
$v_stored_filename);
2982
if ($v_compare > 0) {
2983
if ($v_compare == 2) {
2984
$v_stored_filename = "";
2987
$v_stored_filename = substr($v_stored_filename,
2988
strlen($p_remove_dir));
2993
// ----- Remove drive letter if any
2994
$v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
2996
// ----- Look for path to add
2997
if ($p_add_dir != "") {
2998
if (substr($p_add_dir, -1) == "/")
2999
$v_stored_filename = $p_add_dir.$v_stored_filename;
3001
$v_stored_filename = $p_add_dir."/".$v_stored_filename;
3005
// ----- Filename (reduce the path of stored name)
3006
$v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
3007
$p_filedescr['stored_filename'] = $v_stored_filename;
3012
// --------------------------------------------------------------------------------
3014
// --------------------------------------------------------------------------------
3015
// Function : privWriteFileHeader()
3019
// --------------------------------------------------------------------------------
3020
function privWriteFileHeader(&$p_header)
3024
// ----- Store the offset position of the file
3025
$p_header['offset'] = ftell($this->zip_fd);
3027
// ----- Transform UNIX mtime to DOS format mdate/mtime
3028
$v_date = getdate($p_header['mtime']);
3029
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3030
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3032
// ----- Packed data
3033
$v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
3034
$p_header['version_extracted'], $p_header['flag'],
3035
$p_header['compression'], $v_mtime, $v_mdate,
3036
$p_header['crc'], $p_header['compressed_size'],
3038
strlen($p_header['stored_filename']),
3039
$p_header['extra_len']);
3041
// ----- Write the first 148 bytes of the header in the archive
3042
fputs($this->zip_fd, $v_binary_data, 30);
3044
// ----- Write the variable fields
3045
if (strlen($p_header['stored_filename']) != 0)
3047
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3049
if ($p_header['extra_len'] != 0)
3051
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3057
// --------------------------------------------------------------------------------
3059
// --------------------------------------------------------------------------------
3060
// Function : privWriteCentralFileHeader()
3064
// --------------------------------------------------------------------------------
3065
function privWriteCentralFileHeader(&$p_header)
3070
//for(reset($p_header); $key = key($p_header); next($p_header)) {
3073
// ----- Transform UNIX mtime to DOS format mdate/mtime
3074
$v_date = getdate($p_header['mtime']);
3075
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3076
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3079
// ----- Packed data
3080
$v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
3081
$p_header['version'], $p_header['version_extracted'],
3082
$p_header['flag'], $p_header['compression'],
3083
$v_mtime, $v_mdate, $p_header['crc'],
3084
$p_header['compressed_size'], $p_header['size'],
3085
strlen($p_header['stored_filename']),
3086
$p_header['extra_len'], $p_header['comment_len'],
3087
$p_header['disk'], $p_header['internal'],
3088
$p_header['external'], $p_header['offset']);
3090
// ----- Write the 42 bytes of the header in the zip file
3091
fputs($this->zip_fd, $v_binary_data, 46);
3093
// ----- Write the variable fields
3094
if (strlen($p_header['stored_filename']) != 0)
3096
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3098
if ($p_header['extra_len'] != 0)
3100
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3102
if ($p_header['comment_len'] != 0)
3104
fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
3110
// --------------------------------------------------------------------------------
3112
// --------------------------------------------------------------------------------
3113
// Function : privWriteCentralHeader()
3117
// --------------------------------------------------------------------------------
3118
function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
3122
// ----- Packed data
3123
$v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
3124
$p_nb_entries, $p_size,
3125
$p_offset, strlen($p_comment));
3127
// ----- Write the 22 bytes of the header in the zip file
3128
fputs($this->zip_fd, $v_binary_data, 22);
3130
// ----- Write the variable fields
3131
if (strlen($p_comment) != 0)
3133
fputs($this->zip_fd, $p_comment, strlen($p_comment));
3139
// --------------------------------------------------------------------------------
3141
// --------------------------------------------------------------------------------
3142
// Function : privList()
3146
// --------------------------------------------------------------------------------
3147
function privList(&$p_list)
3151
// ----- Magic quotes trick
3152
$this->privDisableMagicQuotes();
3154
// ----- Open the zip file
3155
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
3157
// ----- Magic quotes trick
3158
$this->privSwapBackMagicQuotes();
3161
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
3164
return PclZip::errorCode();
3167
// ----- Read the central directory informations
3168
$v_central_dir = array();
3169
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3171
$this->privSwapBackMagicQuotes();
3175
// ----- Go to beginning of Central Dir
3176
@rewind($this->zip_fd);
3177
if (@fseek($this->zip_fd, $v_central_dir['offset']))
3179
$this->privSwapBackMagicQuotes();
3182
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3185
return PclZip::errorCode();
3188
// ----- Read each entry
3189
for ($i=0; $i<$v_central_dir['entries']; $i++)
3191
// ----- Read the file header
3192
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3194
$this->privSwapBackMagicQuotes();
3197
$v_header['index'] = $i;
3199
// ----- Get the only interesting attributes
3200
$this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
3204
// ----- Close the zip file
3205
$this->privCloseFd();
3207
// ----- Magic quotes trick
3208
$this->privSwapBackMagicQuotes();
3213
// --------------------------------------------------------------------------------
3215
// --------------------------------------------------------------------------------
3216
// Function : privConvertHeader2FileInfo()
3218
// This function takes the file informations from the central directory
3219
// entries and extract the interesting parameters that will be given back.
3220
// The resulting file infos are set in the array $p_info
3221
// $p_info['filename'] : Filename with full path. Given by user (add),
3222
// extracted in the filesystem (extract).
3223
// $p_info['stored_filename'] : Stored filename in the archive.
3224
// $p_info['size'] = Size of the file.
3225
// $p_info['compressed_size'] = Compressed size of the file.
3226
// $p_info['mtime'] = Last modification date of the file.
3227
// $p_info['comment'] = Comment associated with the file.
3228
// $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3229
// $p_info['status'] = status of the action on the file.
3230
// $p_info['crc'] = CRC of the file content.
3233
// --------------------------------------------------------------------------------
3234
function privConvertHeader2FileInfo($p_header, &$p_info)
3238
// ----- Get the interesting attributes
3239
$v_temp_path = PclZipUtilPathReduction($p_header['filename']);
3240
$p_info['filename'] = $v_temp_path;
3241
$v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']);
3242
$p_info['stored_filename'] = $v_temp_path;
3243
$p_info['size'] = $p_header['size'];
3244
$p_info['compressed_size'] = $p_header['compressed_size'];
3245
$p_info['mtime'] = $p_header['mtime'];
3246
$p_info['comment'] = $p_header['comment'];
3247
$p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3248
$p_info['index'] = $p_header['index'];
3249
$p_info['status'] = $p_header['status'];
3250
$p_info['crc'] = $p_header['crc'];
3255
// --------------------------------------------------------------------------------
3257
// --------------------------------------------------------------------------------
3258
// Function : privExtractByRule()
3260
// Extract a file or directory depending of rules (by index, by name, ...)
3262
// $p_file_list : An array where will be placed the properties of each
3264
// $p_path : Path to add while writing the extracted files
3265
// $p_remove_path : Path to remove (from the file memorized path) while writing the
3266
// extracted files. If the path does not match the file path,
3267
// the file is extracted with its memorized path.
3268
// $p_remove_path does not apply to 'list' mode.
3269
// $p_path and $p_remove_path are commulative.
3271
// 1 on success,0 or less on error (see error code list)
3272
// --------------------------------------------------------------------------------
3273
function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3277
// ----- Magic quotes trick
3278
$this->privDisableMagicQuotes();
3280
// ----- Check the path
3281
if ( ($p_path == "")
3282
|| ( (substr($p_path, 0, 1) != "/")
3283
&& (substr($p_path, 0, 3) != "../")
3284
&& (substr($p_path,1,2)!=":/")))
3285
$p_path = "./".$p_path;
3287
// ----- Reduce the path last (and duplicated) '/'
3288
if (($p_path != "./") && ($p_path != "/"))
3290
// ----- Look for the path end '/'
3291
while (substr($p_path, -1) == "/")
3293
$p_path = substr($p_path, 0, strlen($p_path)-1);
3297
// ----- Look for path to remove format (should end by /)
3298
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
3300
$p_remove_path .= '/';
3302
$p_remove_path_size = strlen($p_remove_path);
3304
// ----- Open the zip file
3305
if (($v_result = $this->privOpenFd('rb')) != 1)
3307
$this->privSwapBackMagicQuotes();
3311
// ----- Read the central directory informations
3312
$v_central_dir = array();
3313
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3315
// ----- Close the zip file
3316
$this->privCloseFd();
3317
$this->privSwapBackMagicQuotes();
3322
// ----- Start at beginning of Central Dir
3323
$v_pos_entry = $v_central_dir['offset'];
3325
// ----- Read each entry
3327
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3330
// ----- Read next Central dir entry
3331
@rewind($this->zip_fd);
3332
if (@fseek($this->zip_fd, $v_pos_entry))
3334
// ----- Close the zip file
3335
$this->privCloseFd();
3336
$this->privSwapBackMagicQuotes();
3339
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3342
return PclZip::errorCode();
3345
// ----- Read the file header
3346
$v_header = array();
3347
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3349
// ----- Close the zip file
3350
$this->privCloseFd();
3351
$this->privSwapBackMagicQuotes();
3356
// ----- Store the index
3357
$v_header['index'] = $i;
3359
// ----- Store the file position
3360
$v_pos_entry = ftell($this->zip_fd);
3362
// ----- Look for the specific extract rules
3365
// ----- Look for extract by name rule
3366
if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
3367
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
3369
// ----- Look if the filename is in the list
3370
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
3372
// ----- Look for a directory
3373
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
3375
// ----- Look if the directory is in the filename path
3376
if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
3377
&& (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
3381
// ----- Look for a filename
3382
elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
3388
// ----- Look for extract by ereg rule
3389
// ereg() is deprecated with PHP 5.3
3391
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
3392
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
3394
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
3400
// ----- Look for extract by preg rule
3401
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
3402
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
3404
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
3409
// ----- Look for extract by index rule
3410
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
3411
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
3413
// ----- Look if the index is in the list
3414
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
3416
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
3419
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
3423
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
3429
// ----- Look for no rule, which means extract all the archive
3434
// ----- Check compression method
3436
&& ( ($v_header['compression'] != 8)
3437
&& ($v_header['compression'] != 0))) {
3438
$v_header['status'] = 'unsupported_compression';
3440
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3441
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3442
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3444
$this->privSwapBackMagicQuotes();
3446
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
3447
"Filename '".$v_header['stored_filename']."' is "
3448
."compressed by an unsupported compression "
3449
."method (".$v_header['compression'].") ");
3451
return PclZip::errorCode();
3455
// ----- Check encrypted files
3456
if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3457
$v_header['status'] = 'unsupported_encryption';
3459
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3460
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3461
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3463
$this->privSwapBackMagicQuotes();
3465
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
3466
"Unsupported encryption for "
3467
." filename '".$v_header['stored_filename']
3470
return PclZip::errorCode();
3474
// ----- Look for real extraction
3475
if (($v_extract) && ($v_header['status'] != 'ok')) {
3476
$v_result = $this->privConvertHeader2FileInfo($v_header,
3477
$p_file_list[$v_nb_extracted++]);
3478
if ($v_result != 1) {
3479
$this->privCloseFd();
3480
$this->privSwapBackMagicQuotes();
3487
// ----- Look for real extraction
3491
// ----- Go to the file position
3492
@rewind($this->zip_fd);
3493
if (@fseek($this->zip_fd, $v_header['offset']))
3495
// ----- Close the zip file
3496
$this->privCloseFd();
3498
$this->privSwapBackMagicQuotes();
3501
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3504
return PclZip::errorCode();
3507
// ----- Look for extraction as string
3508
if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
3512
// ----- Extracting the file
3513
$v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
3514
if ($v_result1 < 1) {
3515
$this->privCloseFd();
3516
$this->privSwapBackMagicQuotes();
3520
// ----- Get the only interesting attributes
3521
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
3523
// ----- Close the zip file
3524
$this->privCloseFd();
3525
$this->privSwapBackMagicQuotes();
3530
// ----- Set the file content
3531
$p_file_list[$v_nb_extracted]['content'] = $v_string;
3533
// ----- Next extracted file
3536
// ----- Look for user callback abort
3537
if ($v_result1 == 2) {
3541
// ----- Look for extraction in standard output
3542
elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
3543
&& ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
3544
// ----- Extracting the file in standard output
3545
$v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
3546
if ($v_result1 < 1) {
3547
$this->privCloseFd();
3548
$this->privSwapBackMagicQuotes();
3552
// ----- Get the only interesting attributes
3553
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3554
$this->privCloseFd();
3555
$this->privSwapBackMagicQuotes();
3559
// ----- Look for user callback abort
3560
if ($v_result1 == 2) {
3564
// ----- Look for normal extraction
3566
// ----- Extracting the file
3567
$v_result1 = $this->privExtractFile($v_header,
3568
$p_path, $p_remove_path,
3571
if ($v_result1 < 1) {
3572
$this->privCloseFd();
3573
$this->privSwapBackMagicQuotes();
3577
// ----- Get the only interesting attributes
3578
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
3580
// ----- Close the zip file
3581
$this->privCloseFd();
3582
$this->privSwapBackMagicQuotes();
3587
// ----- Look for user callback abort
3588
if ($v_result1 == 2) {
3595
// ----- Close the zip file
3596
$this->privCloseFd();
3597
$this->privSwapBackMagicQuotes();
3602
// --------------------------------------------------------------------------------
3604
// --------------------------------------------------------------------------------
3605
// Function : privExtractFile()
3611
// PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3612
// --------------------------------------------------------------------------------
3613
function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3617
// ----- Read the file header
3618
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3625
// ----- Check that the file header is coherent with $p_entry info
3626
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3630
// ----- Look for all path to remove
3631
if ($p_remove_all_path == true) {
3632
// ----- Look for folder entry that not need to be extracted
3633
if (($p_entry['external']&0x00000010)==0x00000010) {
3635
$p_entry['status'] = "filtered";
3640
// ----- Get the basename of the path
3641
$p_entry['filename'] = basename($p_entry['filename']);
3644
// ----- Look for path to remove
3645
else if ($p_remove_path != "")
3647
if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
3650
// ----- Change the file status
3651
$p_entry['status'] = "filtered";
3657
$p_remove_path_size = strlen($p_remove_path);
3658
if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
3661
// ----- Remove the path
3662
$p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
3667
// ----- Add the path
3668
if ($p_path != '') {
3669
$p_entry['filename'] = $p_path."/".$p_entry['filename'];
3672
// ----- Check a base_dir_restriction
3673
if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
3675
= PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
3676
$p_entry['filename']);
3677
if ($v_inclusion == 0) {
3679
PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
3680
"Filename '".$p_entry['filename']."' is "
3681
."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
3683
return PclZip::errorCode();
3687
// ----- Look for pre-extract callback
3688
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
3690
// ----- Generate a local information
3691
$v_local_header = array();
3692
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3694
// ----- Call the callback
3695
// Here I do not use call_user_func() because I need to send a reference to the
3697
$v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
3698
if ($v_result == 0) {
3699
// ----- Change the file status
3700
$p_entry['status'] = "skipped";
3704
// ----- Look for abort result
3705
if ($v_result == 2) {
3706
// ----- This status is internal and will be changed in 'skipped'
3707
$p_entry['status'] = "aborted";
3708
$v_result = PCLZIP_ERR_USER_ABORTED;
3711
// ----- Update the informations
3712
// Only some fields can be modified
3713
$p_entry['filename'] = $v_local_header['filename'];
3717
// ----- Look if extraction should be done
3718
if ($p_entry['status'] == 'ok') {
3720
// ----- Look for specific actions while the file exist
3721
if (file_exists($p_entry['filename']))
3724
// ----- Look if file is a directory
3725
if (is_dir($p_entry['filename']))
3728
// ----- Change the file status
3729
$p_entry['status'] = "already_a_directory";
3731
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3732
// For historical reason first PclZip implementation does not stop
3733
// when this kind of error occurs.
3734
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3735
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3737
PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
3738
"Filename '".$p_entry['filename']."' is "
3739
."already used by an existing directory");
3741
return PclZip::errorCode();
3744
// ----- Look if file is write protected
3745
else if (!is_writeable($p_entry['filename']))
3748
// ----- Change the file status
3749
$p_entry['status'] = "write_protected";
3751
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3752
// For historical reason first PclZip implementation does not stop
3753
// when this kind of error occurs.
3754
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3755
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3757
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3758
"Filename '".$p_entry['filename']."' exists "
3759
."and is write protected");
3761
return PclZip::errorCode();
3765
// ----- Look if the extracted file is older
3766
else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
3768
// ----- Change the file status
3769
if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
3770
&& ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
3773
$p_entry['status'] = "newer_exist";
3775
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3776
// For historical reason first PclZip implementation does not stop
3777
// when this kind of error occurs.
3778
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3779
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3781
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3782
"Newer version of '".$p_entry['filename']."' exists "
3783
."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
3785
return PclZip::errorCode();
3793
// ----- Check the directory availability and create it if necessary
3795
if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
3796
$v_dir_to_check = $p_entry['filename'];
3797
else if (!strstr($p_entry['filename'], "/"))
3798
$v_dir_to_check = "";
3800
$v_dir_to_check = dirname($p_entry['filename']);
3802
if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
3804
// ----- Change the file status
3805
$p_entry['status'] = "path_creation_fail";
3814
// ----- Look if extraction should be done
3815
if ($p_entry['status'] == 'ok') {
3817
// ----- Do the extraction (if not a folder)
3818
if (!(($p_entry['external']&0x00000010)==0x00000010))
3820
// ----- Look for not compressed file
3821
if ($p_entry['compression'] == 0) {
3823
// ----- Opening destination file
3824
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
3827
// ----- Change the file status
3828
$p_entry['status'] = "write_error";
3835
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3836
$v_size = $p_entry['compressed_size'];
3837
while ($v_size != 0)
3839
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3840
$v_buffer = @fread($this->zip_fd, $v_read_size);
3841
/* Try to speed up the code
3842
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3843
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
3845
@fwrite($v_dest_file, $v_buffer, $v_read_size);
3846
$v_size -= $v_read_size;
3849
// ----- Closing the destination file
3850
fclose($v_dest_file);
3852
// ----- Change the file mtime
3853
touch($p_entry['filename'], $p_entry['mtime']);
3859
// Need to be finished
3860
if (($p_entry['flag'] & 1) == 1) {
3861
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
3862
return PclZip::errorCode();
3866
// ----- Look for using temporary file to unzip
3867
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
3868
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
3869
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
3870
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
3871
$v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
3872
if ($v_result < PCLZIP_ERR_NO_ERROR) {
3877
// ----- Look for extract in memory
3881
// ----- Read the compressed file in a buffer (one shot)
3882
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3884
// ----- Decompress the file
3885
$v_file_content = @gzinflate($v_buffer);
3887
if ($v_file_content === FALSE) {
3889
// ----- Change the file status
3891
$p_entry['status'] = "error";
3896
// ----- Opening destination file
3897
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3899
// ----- Change the file status
3900
$p_entry['status'] = "write_error";
3905
// ----- Write the uncompressed data
3906
@fwrite($v_dest_file, $v_file_content, $p_entry['size']);
3907
unset($v_file_content);
3909
// ----- Closing the destination file
3910
@fclose($v_dest_file);
3914
// ----- Change the file mtime
3915
@touch($p_entry['filename'], $p_entry['mtime']);
3918
// ----- Look for chmod option
3919
if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
3921
// ----- Change the mode of the file
3922
@chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
3928
// ----- Change abort status
3929
if ($p_entry['status'] == "aborted") {
3930
$p_entry['status'] = "skipped";
3933
// ----- Look for post-extract callback
3934
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
3936
// ----- Generate a local information
3937
$v_local_header = array();
3938
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3940
// ----- Call the callback
3941
// Here I do not use call_user_func() because I need to send a reference to the
3943
$v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
3945
// ----- Look for abort result
3946
if ($v_result == 2) {
3947
$v_result = PCLZIP_ERR_USER_ABORTED;
3954
// --------------------------------------------------------------------------------
3956
// --------------------------------------------------------------------------------
3957
// Function : privExtractFileUsingTempFile()
3961
// --------------------------------------------------------------------------------
3962
function privExtractFileUsingTempFile(&$p_entry, &$p_options)
3966
// ----- Creates a temporary file
3967
$v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
3968
if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
3970
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
3971
return PclZip::errorCode();
3975
// ----- Write gz file format header
3976
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
3977
@fwrite($v_dest_file, $v_binary_data, 10);
3979
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3980
$v_size = $p_entry['compressed_size'];
3981
while ($v_size != 0)
3983
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3984
$v_buffer = @fread($this->zip_fd, $v_read_size);
3985
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3986
@fwrite($v_dest_file, $v_buffer, $v_read_size);
3987
$v_size -= $v_read_size;
3990
// ----- Write gz file format footer
3991
$v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
3992
@fwrite($v_dest_file, $v_binary_data, 8);
3994
// ----- Close the temporary file
3995
@fclose($v_dest_file);
3997
// ----- Opening destination file
3998
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3999
$p_entry['status'] = "write_error";
4003
// ----- Open the temporary gz file
4004
if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
4005
@fclose($v_dest_file);
4006
$p_entry['status'] = "read_error";
4007
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
4008
return PclZip::errorCode();
4012
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
4013
$v_size = $p_entry['size'];
4014
while ($v_size != 0) {
4015
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4016
$v_buffer = @gzread($v_src_file, $v_read_size);
4017
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
4018
@fwrite($v_dest_file, $v_buffer, $v_read_size);
4019
$v_size -= $v_read_size;
4021
@fclose($v_dest_file);
4022
@gzclose($v_src_file);
4024
// ----- Delete the temporary file
4025
@unlink($v_gzip_temp_name);
4030
// --------------------------------------------------------------------------------
4032
// --------------------------------------------------------------------------------
4033
// Function : privExtractFileInOutput()
4037
// --------------------------------------------------------------------------------
4038
function privExtractFileInOutput(&$p_entry, &$p_options)
4042
// ----- Read the file header
4043
if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
4048
// ----- Check that the file header is coherent with $p_entry info
4049
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4053
// ----- Look for pre-extract callback
4054
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4056
// ----- Generate a local information
4057
$v_local_header = array();
4058
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4060
// ----- Call the callback
4061
// Here I do not use call_user_func() because I need to send a reference to the
4063
// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4064
$v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4065
if ($v_result == 0) {
4066
// ----- Change the file status
4067
$p_entry['status'] = "skipped";
4071
// ----- Look for abort result
4072
if ($v_result == 2) {
4073
// ----- This status is internal and will be changed in 'skipped'
4074
$p_entry['status'] = "aborted";
4075
$v_result = PCLZIP_ERR_USER_ABORTED;
4078
// ----- Update the informations
4079
// Only some fields can be modified
4080
$p_entry['filename'] = $v_local_header['filename'];
4085
// ----- Look if extraction should be done
4086
if ($p_entry['status'] == 'ok') {
4088
// ----- Do the extraction (if not a folder)
4089
if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4090
// ----- Look for not compressed file
4091
if ($p_entry['compressed_size'] == $p_entry['size']) {
4093
// ----- Read the file in a buffer (one shot)
4094
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4096
// ----- Send the file to the output
4102
// ----- Read the compressed file in a buffer (one shot)
4103
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4105
// ----- Decompress the file
4106
$v_file_content = gzinflate($v_buffer);
4109
// ----- Send the file to the output
4110
echo $v_file_content;
4111
unset($v_file_content);
4116
// ----- Change abort status
4117
if ($p_entry['status'] == "aborted") {
4118
$p_entry['status'] = "skipped";
4121
// ----- Look for post-extract callback
4122
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4124
// ----- Generate a local information
4125
$v_local_header = array();
4126
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4128
// ----- Call the callback
4129
// Here I do not use call_user_func() because I need to send a reference to the
4131
$v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4133
// ----- Look for abort result
4134
if ($v_result == 2) {
4135
$v_result = PCLZIP_ERR_USER_ABORTED;
4141
// --------------------------------------------------------------------------------
4143
// --------------------------------------------------------------------------------
4144
// Function : privExtractFileAsString()
4148
// --------------------------------------------------------------------------------
4149
function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
4153
// ----- Read the file header
4154
$v_header = array();
4155
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
4162
// ----- Check that the file header is coherent with $p_entry info
4163
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4167
// ----- Look for pre-extract callback
4168
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4170
// ----- Generate a local information
4171
$v_local_header = array();
4172
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4174
// ----- Call the callback
4175
// Here I do not use call_user_func() because I need to send a reference to the
4177
$v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4178
if ($v_result == 0) {
4179
// ----- Change the file status
4180
$p_entry['status'] = "skipped";
4184
// ----- Look for abort result
4185
if ($v_result == 2) {
4186
// ----- This status is internal and will be changed in 'skipped'
4187
$p_entry['status'] = "aborted";
4188
$v_result = PCLZIP_ERR_USER_ABORTED;
4191
// ----- Update the informations
4192
// Only some fields can be modified
4193
$p_entry['filename'] = $v_local_header['filename'];
4197
// ----- Look if extraction should be done
4198
if ($p_entry['status'] == 'ok') {
4200
// ----- Do the extraction (if not a folder)
4201
if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4202
// ----- Look for not compressed file
4203
// if ($p_entry['compressed_size'] == $p_entry['size'])
4204
if ($p_entry['compression'] == 0) {
4206
// ----- Reading the file
4207
$p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
4211
// ----- Reading the file
4212
$v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
4214
// ----- Decompress the file
4215
if (($p_string = @gzinflate($v_data)) === FALSE) {
4223
// TBC : error : can not extract a folder in a string
4228
// ----- Change abort status
4229
if ($p_entry['status'] == "aborted") {
4230
$p_entry['status'] = "skipped";
4233
// ----- Look for post-extract callback
4234
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4236
// ----- Generate a local information
4237
$v_local_header = array();
4238
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4240
// ----- Swap the content to header
4241
$v_local_header['content'] = $p_string;
4244
// ----- Call the callback
4245
// Here I do not use call_user_func() because I need to send a reference to the
4247
$v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4249
// ----- Swap back the content to header
4250
$p_string = $v_local_header['content'];
4251
unset($v_local_header['content']);
4253
// ----- Look for abort result
4254
if ($v_result == 2) {
4255
$v_result = PCLZIP_ERR_USER_ABORTED;
4262
// --------------------------------------------------------------------------------
4264
// --------------------------------------------------------------------------------
4265
// Function : privReadFileHeader()
4269
// --------------------------------------------------------------------------------
4270
function privReadFileHeader(&$p_header)
4274
// ----- Read the 4 bytes signature
4275
$v_binary_data = @fread($this->zip_fd, 4);
4276
$v_data = unpack('Vid', $v_binary_data);
4278
// ----- Check signature
4279
if ($v_data['id'] != 0x04034b50)
4283
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4286
return PclZip::errorCode();
4289
// ----- Read the first 42 bytes of the header
4290
$v_binary_data = fread($this->zip_fd, 26);
4292
// ----- Look for invalid block size
4293
if (strlen($v_binary_data) != 26)
4295
$p_header['filename'] = "";
4296
$p_header['status'] = "invalid_header";
4299
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4302
return PclZip::errorCode();
4305
// ----- Extract the values
4306
$v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
4308
// ----- Get filename
4309
$p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
4311
// ----- Get extra_fields
4312
if ($v_data['extra_len'] != 0) {
4313
$p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
4316
$p_header['extra'] = '';
4319
// ----- Extract properties
4320
$p_header['version_extracted'] = $v_data['version'];
4321
$p_header['compression'] = $v_data['compression'];
4322
$p_header['size'] = $v_data['size'];
4323
$p_header['compressed_size'] = $v_data['compressed_size'];
4324
$p_header['crc'] = $v_data['crc'];
4325
$p_header['flag'] = $v_data['flag'];
4326
$p_header['filename_len'] = $v_data['filename_len'];
4328
// ----- Recuperate date in UNIX format
4329
$p_header['mdate'] = $v_data['mdate'];
4330
$p_header['mtime'] = $v_data['mtime'];
4331
if ($p_header['mdate'] && $p_header['mtime'])
4333
// ----- Extract time
4334
$v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4335
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4336
$v_seconde = ($p_header['mtime'] & 0x001F)*2;
4338
// ----- Extract date
4339
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4340
$v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4341
$v_day = $p_header['mdate'] & 0x001F;
4343
// ----- Get UNIX date format
4344
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4349
$p_header['mtime'] = time();
4353
//for(reset($v_data); $key = key($v_data); next($v_data)) {
4356
// ----- Set the stored filename
4357
$p_header['stored_filename'] = $p_header['filename'];
4359
// ----- Set the status field
4360
$p_header['status'] = "ok";
4365
// --------------------------------------------------------------------------------
4367
// --------------------------------------------------------------------------------
4368
// Function : privReadCentralFileHeader()
4372
// --------------------------------------------------------------------------------
4373
function privReadCentralFileHeader(&$p_header)
4377
// ----- Read the 4 bytes signature
4378
$v_binary_data = @fread($this->zip_fd, 4);
4379
$v_data = unpack('Vid', $v_binary_data);
4381
// ----- Check signature
4382
if ($v_data['id'] != 0x02014b50)
4386
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4389
return PclZip::errorCode();
4392
// ----- Read the first 42 bytes of the header
4393
$v_binary_data = fread($this->zip_fd, 42);
4395
// ----- Look for invalid block size
4396
if (strlen($v_binary_data) != 42)
4398
$p_header['filename'] = "";
4399
$p_header['status'] = "invalid_header";
4402
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4405
return PclZip::errorCode();
4408
// ----- Extract the values
4409
$p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
4411
// ----- Get filename
4412
if ($p_header['filename_len'] != 0)
4413
$p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
4415
$p_header['filename'] = '';
4418
if ($p_header['extra_len'] != 0)
4419
$p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
4421
$p_header['extra'] = '';
4423
// ----- Get comment
4424
if ($p_header['comment_len'] != 0)
4425
$p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
4427
$p_header['comment'] = '';
4429
// ----- Extract properties
4431
// ----- Recuperate date in UNIX format
4432
//if ($p_header['mdate'] && $p_header['mtime'])
4433
// TBC : bug : this was ignoring time with 0/0/0
4436
// ----- Extract time
4437
$v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4438
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4439
$v_seconde = ($p_header['mtime'] & 0x001F)*2;
4441
// ----- Extract date
4442
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4443
$v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4444
$v_day = $p_header['mdate'] & 0x001F;
4446
// ----- Get UNIX date format
4447
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4452
$p_header['mtime'] = time();
4455
// ----- Set the stored filename
4456
$p_header['stored_filename'] = $p_header['filename'];
4458
// ----- Set default status to ok
4459
$p_header['status'] = 'ok';
4461
// ----- Look if it is a directory
4462
if (substr($p_header['filename'], -1) == '/') {
4463
//$p_header['external'] = 0x41FF0010;
4464
$p_header['external'] = 0x00000010;
4471
// --------------------------------------------------------------------------------
4473
// --------------------------------------------------------------------------------
4474
// Function : privCheckFileHeaders()
4480
// --------------------------------------------------------------------------------
4481
function privCheckFileHeaders(&$p_local_header, &$p_central_header)
4485
// ----- Check the static values
4487
if ($p_local_header['filename'] != $p_central_header['filename']) {
4489
if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4491
if ($p_local_header['flag'] != $p_central_header['flag']) {
4493
if ($p_local_header['compression'] != $p_central_header['compression']) {
4495
if ($p_local_header['mtime'] != $p_central_header['mtime']) {
4497
if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
4500
// ----- Look for flag bit 3
4501
if (($p_local_header['flag'] & 8) == 8) {
4502
$p_local_header['size'] = $p_central_header['size'];
4503
$p_local_header['compressed_size'] = $p_central_header['compressed_size'];
4504
$p_local_header['crc'] = $p_central_header['crc'];
4510
// --------------------------------------------------------------------------------
4512
// --------------------------------------------------------------------------------
4513
// Function : privReadEndCentralDir()
4517
// --------------------------------------------------------------------------------
4518
function privReadEndCentralDir(&$p_central_dir)
4522
// ----- Go to the end of the zip file
4523
$v_size = filesize($this->zipname);
4524
@fseek($this->zip_fd, $v_size);
4525
if (@ftell($this->zip_fd) != $v_size)
4528
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
4531
return PclZip::errorCode();
4534
// ----- First try : look if this is an archive with no commentaries (most of the time)
4535
// in this case the end of central dir is at 22 bytes of the file end
4538
@fseek($this->zip_fd, $v_size-22);
4539
if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
4542
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4545
return PclZip::errorCode();
4548
// ----- Read for bytes
4549
$v_binary_data = @fread($this->zip_fd, 4);
4550
$v_data = @unpack('Vid', $v_binary_data);
4552
// ----- Check signature
4553
if ($v_data['id'] == 0x06054b50) {
4557
$v_pos = ftell($this->zip_fd);
4560
// ----- Go back to the maximum possible size of the Central Dir End Record
4562
$v_maximum_size = 65557; // 0xFFFF + 22;
4563
if ($v_maximum_size > $v_size)
4564
$v_maximum_size = $v_size;
4565
@fseek($this->zip_fd, $v_size-$v_maximum_size);
4566
if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
4569
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4572
return PclZip::errorCode();
4575
// ----- Read byte per byte in order to find the signature
4576
$v_pos = ftell($this->zip_fd);
4577
$v_bytes = 0x00000000;
4578
while ($v_pos < $v_size)
4580
// ----- Read a byte
4581
$v_byte = @fread($this->zip_fd, 1);
4583
// ----- Add the byte
4584
//$v_bytes = ($v_bytes << 8) | Ord($v_byte);
4585
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
4586
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
4587
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
4589
// ----- Compare the bytes
4590
if ($v_bytes == 0x504b0506)
4599
// ----- Look if not found end of central dir
4600
if ($v_pos == $v_size)
4604
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
4607
return PclZip::errorCode();
4611
// ----- Read the first 18 bytes of the header
4612
$v_binary_data = fread($this->zip_fd, 18);
4614
// ----- Look for invalid block size
4615
if (strlen($v_binary_data) != 18)
4619
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
4622
return PclZip::errorCode();
4625
// ----- Extract the values
4626
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
4628
// ----- Check the global size
4629
if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
4631
// ----- Removed in release 2.2 see readme file
4632
// The check of the file size is a little too strict.
4633
// Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
4634
// While decrypted, zip has training 0 bytes
4637
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
4638
'The central dir is not at the end of the archive.'
4639
.' Some trailing bytes exists after the archive.');
4642
return PclZip::errorCode();
4646
// ----- Get comment
4647
if ($v_data['comment_size'] != 0) {
4648
$p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
4651
$p_central_dir['comment'] = '';
4653
$p_central_dir['entries'] = $v_data['entries'];
4654
$p_central_dir['disk_entries'] = $v_data['disk_entries'];
4655
$p_central_dir['offset'] = $v_data['offset'];
4656
$p_central_dir['size'] = $v_data['size'];
4657
$p_central_dir['disk'] = $v_data['disk'];
4658
$p_central_dir['disk_start'] = $v_data['disk_start'];
4661
//for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
4667
// --------------------------------------------------------------------------------
4669
// --------------------------------------------------------------------------------
4670
// Function : privDeleteByRule()
4674
// --------------------------------------------------------------------------------
4675
function privDeleteByRule(&$p_result_list, &$p_options)
4678
$v_list_detail = array();
4680
// ----- Open the zip file
4681
if (($v_result=$this->privOpenFd('rb')) != 1)
4687
// ----- Read the central directory informations
4688
$v_central_dir = array();
4689
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
4691
$this->privCloseFd();
4695
// ----- Go to beginning of File
4696
@rewind($this->zip_fd);
4698
// ----- Scan all the files
4699
// ----- Start at beginning of Central Dir
4700
$v_pos_entry = $v_central_dir['offset'];
4701
@rewind($this->zip_fd);
4702
if (@fseek($this->zip_fd, $v_pos_entry))
4704
// ----- Close the zip file
4705
$this->privCloseFd();
4708
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4711
return PclZip::errorCode();
4714
// ----- Read each entry
4715
$v_header_list = array();
4717
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
4720
// ----- Read the file header
4721
$v_header_list[$v_nb_extracted] = array();
4722
if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
4724
// ----- Close the zip file
4725
$this->privCloseFd();
4731
// ----- Store the index
4732
$v_header_list[$v_nb_extracted]['index'] = $i;
4734
// ----- Look for the specific extract rules
4737
// ----- Look for extract by name rule
4738
if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
4739
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
4741
// ----- Look if the filename is in the list
4742
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
4744
// ----- Look for a directory
4745
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
4747
// ----- Look if the directory is in the filename path
4748
if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
4749
&& (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4752
elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
4753
&& ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4757
// ----- Look for a filename
4758
elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
4764
// ----- Look for extract by ereg rule
4765
// ereg() is deprecated with PHP 5.3
4767
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
4768
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
4770
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4776
// ----- Look for extract by preg rule
4777
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
4778
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
4780
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4785
// ----- Look for extract by index rule
4786
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
4787
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
4789
// ----- Look if the index is in the list
4790
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
4792
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
4795
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
4799
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
4808
// ----- Look for deletion
4811
unset($v_header_list[$v_nb_extracted]);
4819
// ----- Look if something need to be deleted
4820
if ($v_nb_extracted > 0) {
4822
// ----- Creates a temporay file
4823
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4825
// ----- Creates a temporary zip archive
4826
$v_temp_zip = new PclZip($v_zip_temp_name);
4828
// ----- Open the temporary zip file in write mode
4829
if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4830
$this->privCloseFd();
4836
// ----- Look which file need to be kept
4837
for ($i=0; $i<sizeof($v_header_list); $i++) {
4839
// ----- Calculate the position of the header
4840
@rewind($this->zip_fd);
4841
if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
4842
// ----- Close the zip file
4843
$this->privCloseFd();
4844
$v_temp_zip->privCloseFd();
4845
@unlink($v_zip_temp_name);
4848
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4851
return PclZip::errorCode();
4854
// ----- Read the file header
4855
$v_local_header = array();
4856
if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
4857
// ----- Close the zip file
4858
$this->privCloseFd();
4859
$v_temp_zip->privCloseFd();
4860
@unlink($v_zip_temp_name);
4866
// ----- Check that local file header is same as central file header
4867
if ($this->privCheckFileHeaders($v_local_header,
4868
$v_header_list[$i]) != 1) {
4871
unset($v_local_header);
4873
// ----- Write the file header
4874
if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4875
// ----- Close the zip file
4876
$this->privCloseFd();
4877
$v_temp_zip->privCloseFd();
4878
@unlink($v_zip_temp_name);
4884
// ----- Read/write the data block
4885
if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4886
// ----- Close the zip file
4887
$this->privCloseFd();
4888
$v_temp_zip->privCloseFd();
4889
@unlink($v_zip_temp_name);
4896
// ----- Store the offset of the central dir
4897
$v_offset = @ftell($v_temp_zip->zip_fd);
4899
// ----- Re-Create the Central Dir files header
4900
for ($i=0; $i<sizeof($v_header_list); $i++) {
4901
// ----- Create the file header
4902
if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4903
$v_temp_zip->privCloseFd();
4904
$this->privCloseFd();
4905
@unlink($v_zip_temp_name);
4911
// ----- Transform the header to a 'usable' info
4912
$v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4916
// ----- Zip file comment
4918
if (isset($p_options[PCLZIP_OPT_COMMENT])) {
4919
$v_comment = $p_options[PCLZIP_OPT_COMMENT];
4922
// ----- Calculate the size of the central header
4923
$v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
4925
// ----- Create the central dir footer
4926
if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
4927
// ----- Reset the file list
4928
unset($v_header_list);
4929
$v_temp_zip->privCloseFd();
4930
$this->privCloseFd();
4931
@unlink($v_zip_temp_name);
4938
$v_temp_zip->privCloseFd();
4939
$this->privCloseFd();
4941
// ----- Delete the zip file
4942
// TBC : I should test the result ...
4943
@unlink($this->zipname);
4945
// ----- Rename the temporary file
4946
// TBC : I should test the result ...
4947
//@rename($v_zip_temp_name, $this->zipname);
4948
PclZipUtilRename($v_zip_temp_name, $this->zipname);
4950
// ----- Destroy the temporary archive
4954
// ----- Remove every files : reset the file
4955
else if ($v_central_dir['entries'] != 0) {
4956
$this->privCloseFd();
4958
if (($v_result = $this->privOpenFd('wb')) != 1) {
4962
if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
4966
$this->privCloseFd();
4972
// --------------------------------------------------------------------------------
4974
// --------------------------------------------------------------------------------
4975
// Function : privDirCheck()
4977
// Check if a directory exists, if not it creates it and all the parents directory
4978
// which may be useful.
4980
// $p_dir : Directory path to check.
4983
// -1 : Unable to create directory
4984
// --------------------------------------------------------------------------------
4985
function privDirCheck($p_dir, $p_is_dir=false)
4990
// ----- Remove the final '/'
4991
if (($p_is_dir) && (substr($p_dir, -1)=='/'))
4993
$p_dir = substr($p_dir, 0, strlen($p_dir)-1);
4996
// ----- Check the directory availability
4997
if ((is_dir($p_dir)) || ($p_dir == ""))
5002
// ----- Extract parent directory
5003
$p_parent_dir = dirname($p_dir);
5005
// ----- Just a check
5006
if ($p_parent_dir != $p_dir)
5008
// ----- Look for parent directory
5009
if ($p_parent_dir != "")
5011
if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
5018
// ----- Create the directory
5019
if (!@mkdir($p_dir, 0777))
5022
PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
5025
return PclZip::errorCode();
5031
// --------------------------------------------------------------------------------
5033
// --------------------------------------------------------------------------------
5034
// Function : privMerge()
5036
// If $p_archive_to_add does not exist, the function exit with a success result.
5039
// --------------------------------------------------------------------------------
5040
function privMerge(&$p_archive_to_add)
5044
// ----- Look if the archive_to_add exists
5045
if (!is_file($p_archive_to_add->zipname))
5048
// ----- Nothing to merge, so merge is a success
5055
// ----- Look if the archive exists
5056
if (!is_file($this->zipname))
5059
// ----- Do a duplicate
5060
$v_result = $this->privDuplicate($p_archive_to_add->zipname);
5066
// ----- Open the zip file
5067
if (($v_result=$this->privOpenFd('rb')) != 1)
5073
// ----- Read the central directory informations
5074
$v_central_dir = array();
5075
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
5077
$this->privCloseFd();
5081
// ----- Go to beginning of File
5082
@rewind($this->zip_fd);
5084
// ----- Open the archive_to_add file
5085
if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
5087
$this->privCloseFd();
5093
// ----- Read the central directory informations
5094
$v_central_dir_to_add = array();
5095
if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
5097
$this->privCloseFd();
5098
$p_archive_to_add->privCloseFd();
5103
// ----- Go to beginning of File
5104
@rewind($p_archive_to_add->zip_fd);
5106
// ----- Creates a temporay file
5107
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
5109
// ----- Open the temporary file in write mode
5110
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
5112
$this->privCloseFd();
5113
$p_archive_to_add->privCloseFd();
5115
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
5118
return PclZip::errorCode();
5121
// ----- Copy the files from the archive to the temporary file
5122
// TBC : Here I should better append the file and go back to erase the central dir
5123
$v_size = $v_central_dir['offset'];
5124
while ($v_size != 0)
5126
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5127
$v_buffer = fread($this->zip_fd, $v_read_size);
5128
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5129
$v_size -= $v_read_size;
5132
// ----- Copy the files from the archive_to_add into the temporary file
5133
$v_size = $v_central_dir_to_add['offset'];
5134
while ($v_size != 0)
5136
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5137
$v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
5138
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5139
$v_size -= $v_read_size;
5142
// ----- Store the offset of the central dir
5143
$v_offset = @ftell($v_zip_temp_fd);
5145
// ----- Copy the block of file headers from the old archive
5146
$v_size = $v_central_dir['size'];
5147
while ($v_size != 0)
5149
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5150
$v_buffer = @fread($this->zip_fd, $v_read_size);
5151
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5152
$v_size -= $v_read_size;
5155
// ----- Copy the block of file headers from the archive_to_add
5156
$v_size = $v_central_dir_to_add['size'];
5157
while ($v_size != 0)
5159
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5160
$v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
5161
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5162
$v_size -= $v_read_size;
5165
// ----- Merge the file comments
5166
$v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
5168
// ----- Calculate the size of the (new) central header
5169
$v_size = @ftell($v_zip_temp_fd)-$v_offset;
5171
// ----- Swap the file descriptor
5172
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
5173
// the following methods on the temporary fil and not the real archive fd
5174
$v_swap = $this->zip_fd;
5175
$this->zip_fd = $v_zip_temp_fd;
5176
$v_zip_temp_fd = $v_swap;
5178
// ----- Create the central dir footer
5179
if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
5181
$this->privCloseFd();
5182
$p_archive_to_add->privCloseFd();
5183
@fclose($v_zip_temp_fd);
5184
$this->zip_fd = null;
5186
// ----- Reset the file list
5187
unset($v_header_list);
5193
// ----- Swap back the file descriptor
5194
$v_swap = $this->zip_fd;
5195
$this->zip_fd = $v_zip_temp_fd;
5196
$v_zip_temp_fd = $v_swap;
5199
$this->privCloseFd();
5200
$p_archive_to_add->privCloseFd();
5202
// ----- Close the temporary file
5203
@fclose($v_zip_temp_fd);
5205
// ----- Delete the zip file
5206
// TBC : I should test the result ...
5207
@unlink($this->zipname);
5209
// ----- Rename the temporary file
5210
// TBC : I should test the result ...
5211
//@rename($v_zip_temp_name, $this->zipname);
5212
PclZipUtilRename($v_zip_temp_name, $this->zipname);
5217
// --------------------------------------------------------------------------------
5219
// --------------------------------------------------------------------------------
5220
// Function : privDuplicate()
5224
// --------------------------------------------------------------------------------
5225
function privDuplicate($p_archive_filename)
5229
// ----- Look if the $p_archive_filename exists
5230
if (!is_file($p_archive_filename))
5233
// ----- Nothing to duplicate, so duplicate is a success.
5240
// ----- Open the zip file
5241
if (($v_result=$this->privOpenFd('wb')) != 1)
5247
// ----- Open the temporary file in write mode
5248
if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
5250
$this->privCloseFd();
5252
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
5255
return PclZip::errorCode();
5258
// ----- Copy the files from the archive to the temporary file
5259
// TBC : Here I should better append the file and go back to erase the central dir
5260
$v_size = filesize($p_archive_filename);
5261
while ($v_size != 0)
5263
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5264
$v_buffer = fread($v_zip_temp_fd, $v_read_size);
5265
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
5266
$v_size -= $v_read_size;
5270
$this->privCloseFd();
5272
// ----- Close the temporary file
5273
@fclose($v_zip_temp_fd);
5278
// --------------------------------------------------------------------------------
5280
// --------------------------------------------------------------------------------
5281
// Function : privErrorLog()
5284
// --------------------------------------------------------------------------------
5285
function privErrorLog($p_error_code=0, $p_error_string='')
5287
if (PCLZIP_ERROR_EXTERNAL == 1) {
5288
PclError($p_error_code, $p_error_string);
5291
$this->error_code = $p_error_code;
5292
$this->error_string = $p_error_string;
5295
// --------------------------------------------------------------------------------
5297
// --------------------------------------------------------------------------------
5298
// Function : privErrorReset()
5301
// --------------------------------------------------------------------------------
5302
function privErrorReset()
5304
if (PCLZIP_ERROR_EXTERNAL == 1) {
5308
$this->error_code = 0;
5309
$this->error_string = '';
5312
// --------------------------------------------------------------------------------
5314
// --------------------------------------------------------------------------------
5315
// Function : privDisableMagicQuotes()
5319
// --------------------------------------------------------------------------------
5320
function privDisableMagicQuotes()
5324
// ----- Look if function exists
5325
if ( (!function_exists("get_magic_quotes_runtime"))
5326
|| (!function_exists("set_magic_quotes_runtime"))) {
5330
// ----- Look if already done
5331
if ($this->magic_quotes_status != -1) {
5335
// ----- Get and memorize the magic_quote value
5336
$this->magic_quotes_status = @get_magic_quotes_runtime();
5338
// ----- Disable magic_quotes
5339
if ($this->magic_quotes_status == 1) {
5340
@set_magic_quotes_runtime(0);
5346
// --------------------------------------------------------------------------------
5348
// --------------------------------------------------------------------------------
5349
// Function : privSwapBackMagicQuotes()
5353
// --------------------------------------------------------------------------------
5354
function privSwapBackMagicQuotes()
5358
// ----- Look if function exists
5359
if ( (!function_exists("get_magic_quotes_runtime"))
5360
|| (!function_exists("set_magic_quotes_runtime"))) {
5364
// ----- Look if something to do
5365
if ($this->magic_quotes_status != -1) {
5369
// ----- Swap back magic_quotes
5370
if ($this->magic_quotes_status == 1) {
5371
@set_magic_quotes_runtime($this->magic_quotes_status);
5377
// --------------------------------------------------------------------------------
5381
// --------------------------------------------------------------------------------
5383
// --------------------------------------------------------------------------------
5384
// Function : PclZipUtilPathReduction()
5388
// --------------------------------------------------------------------------------
5389
function PclZipUtilPathReduction($p_dir)
5393
// ----- Look for not empty path
5395
// ----- Explode path by directory names
5396
$v_list = explode("/", $p_dir);
5398
// ----- Study directories from last to first
5400
for ($i=sizeof($v_list)-1; $i>=0; $i--) {
5401
// ----- Look for current path
5402
if ($v_list[$i] == ".") {
5403
// ----- Ignore this directory
5404
// Should be the first $i=0, but no check is done
5406
else if ($v_list[$i] == "..") {
5409
else if ($v_list[$i] == "") {
5410
// ----- First '/' i.e. root slash
5412
$v_result = "/".$v_result;
5414
// ----- It is an invalid path, so the path is not modified
5420
// ----- Last '/' i.e. indicates a directory
5421
else if ($i == (sizeof($v_list)-1)) {
5422
$v_result = $v_list[$i];
5424
// ----- Double '/' inside the path
5426
// ----- Ignore only the double '//' in path,
5427
// but not the first and last '/'
5431
// ----- Look for item to skip
5436
$v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
5441
// ----- Look for skip
5443
while ($v_skip > 0) {
5444
$v_result = '../'.$v_result;
5453
// --------------------------------------------------------------------------------
5455
// --------------------------------------------------------------------------------
5456
// Function : PclZipUtilPathInclusion()
5458
// This function indicates if the path $p_path is under the $p_dir tree. Or,
5459
// said in an other way, if the file or sub-dir $p_path is inside the dir
5461
// The function indicates also if the path is exactly the same as the dir.
5462
// This function supports path with duplicated '/' like '//', but does not
5463
// support '.' or '..' statements.
5466
// 0 if $p_path is not inside directory $p_dir
5467
// 1 if $p_path is inside directory $p_dir
5468
// 2 if $p_path is exactly the same as $p_dir
5469
// --------------------------------------------------------------------------------
5470
function PclZipUtilPathInclusion($p_dir, $p_path)
5474
// ----- Look for path beginning by ./
5475
if ( ($p_dir == '.')
5476
|| ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
5477
$p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
5479
if ( ($p_path == '.')
5480
|| ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
5481
$p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
5484
// ----- Explode dir and path by directory separator
5485
$v_list_dir = explode("/", $p_dir);
5486
$v_list_dir_size = sizeof($v_list_dir);
5487
$v_list_path = explode("/", $p_path);
5488
$v_list_path_size = sizeof($v_list_path);
5490
// ----- Study directories paths
5493
while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
5495
// ----- Look for empty dir (path reduction)
5496
if ($v_list_dir[$i] == '') {
5500
if ($v_list_path[$j] == '') {
5505
// ----- Compare the items
5506
if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
5515
// ----- Look if everything seems to be the same
5517
// ----- Skip all the empty items
5518
while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
5519
while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
5521
if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
5522
// ----- There are exactly the same
5525
else if ($i < $v_list_dir_size) {
5526
// ----- The path is shorter than the dir
5534
// --------------------------------------------------------------------------------
5536
// --------------------------------------------------------------------------------
5537
// Function : PclZipUtilCopyBlock()
5540
// $p_mode : read/write compression mode
5541
// 0 : src & dest normal
5542
// 1 : src gzip, dest normal
5543
// 2 : src normal, dest gzip
5544
// 3 : src & dest gzip
5546
// --------------------------------------------------------------------------------
5547
function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
5553
while ($p_size != 0)
5555
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5556
$v_buffer = @fread($p_src, $v_read_size);
5557
@fwrite($p_dest, $v_buffer, $v_read_size);
5558
$p_size -= $v_read_size;
5561
else if ($p_mode==1)
5563
while ($p_size != 0)
5565
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5566
$v_buffer = @gzread($p_src, $v_read_size);
5567
@fwrite($p_dest, $v_buffer, $v_read_size);
5568
$p_size -= $v_read_size;
5571
else if ($p_mode==2)
5573
while ($p_size != 0)
5575
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5576
$v_buffer = @fread($p_src, $v_read_size);
5577
@gzwrite($p_dest, $v_buffer, $v_read_size);
5578
$p_size -= $v_read_size;
5581
else if ($p_mode==3)
5583
while ($p_size != 0)
5585
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5586
$v_buffer = @gzread($p_src, $v_read_size);
5587
@gzwrite($p_dest, $v_buffer, $v_read_size);
5588
$p_size -= $v_read_size;
5595
// --------------------------------------------------------------------------------
5597
// --------------------------------------------------------------------------------
5598
// Function : PclZipUtilRename()
5600
// This function tries to do a simple rename() function. If it fails, it
5601
// tries to copy the $p_src file in a new $p_dest file and then unlink the
5604
// $p_src : Old filename
5605
// $p_dest : New filename
5607
// 1 on success, 0 on failure.
5608
// --------------------------------------------------------------------------------
5609
function PclZipUtilRename($p_src, $p_dest)
5613
// ----- Try to rename the files
5614
if (!@rename($p_src, $p_dest)) {
5616
// ----- Try to copy & unlink the src
5617
if (!@copy($p_src, $p_dest)) {
5620
else if (!@unlink($p_src)) {
5628
// --------------------------------------------------------------------------------
5630
// --------------------------------------------------------------------------------
5631
// Function : PclZipUtilOptionText()
5633
// Translate option value in text. Mainly for debug purpose.
5635
// $p_option : the option value.
5637
// The option text value.
5638
// --------------------------------------------------------------------------------
5639
function PclZipUtilOptionText($p_option)
5642
$v_list = get_defined_constants();
5643
for (reset($v_list); $v_key = key($v_list); next($v_list)) {
5644
$v_prefix = substr($v_key, 0, 10);
5645
if (( ($v_prefix == 'PCLZIP_OPT')
5646
|| ($v_prefix == 'PCLZIP_CB_')
5647
|| ($v_prefix == 'PCLZIP_ATT'))
5648
&& ($v_list[$v_key] == $p_option)) {
5653
$v_result = 'Unknown';
5657
// --------------------------------------------------------------------------------
5659
// --------------------------------------------------------------------------------
5660
// Function : PclZipUtilTranslateWinPath()
5662
// Translate windows path by replacing '\' by '/' and optionally removing
5665
// $p_path : path to translate.
5666
// $p_remove_disk_letter : true | false
5668
// The path translated.
5669
// --------------------------------------------------------------------------------
5670
function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
5672
if (stristr(php_uname(), 'windows')) {
5673
// ----- Look for potential disk letter
5674
if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
5675
$p_path = substr($p_path, $v_position+1);
5677
// ----- Change potential windows directory separator
5678
if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
5679
$p_path = strtr($p_path, '\\', '/');
5684
// --------------------------------------------------------------------------------