PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / 4.1.1
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets v4.1.1
4.1.1 3.9.5 3.9.6 4.0.0 4.0.1 4.1.0 trunk 2.12 2.13 2.14 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9 3.7.0 3.7.1 3.7.2 3.7.3 3.7.3-beta-1.0 3.7.4 3.7.4-beta-1.0 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4
wp-all-import / libraries / wpaipclzip.lib.php
wp-all-import / libraries Last commit date
ast 1 month ago XmlImportConfig.php 1 month ago XmlImportCsvParse.php 1 month ago XmlImportException.php 1 month ago XmlImportParser.php 1 month ago XmlImportReaderInterface.php 1 month ago XmlImportSQLParse.php 1 month ago XmlImportStringReader.php 1 month ago XmlImportTemplate.php 1 month ago XmlImportTemplateCodeGenerator.php 1 month ago XmlImportTemplateParser.php 1 month ago XmlImportTemplateScanner.php 2 days ago XmlImportToken.php 1 month ago XmlImportXLSParse.php 1 month ago wpaipclzip.lib.php 1 month ago
wpaipclzip.lib.php
5259 lines
1 <?php
2 // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
3 if ( ! defined( 'ABSPATH' ) ) exit;
4 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fopen
5 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fread
6 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
7 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fclose
8 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fputs
9 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_touch
10 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_chmod
11 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_mkdir
12 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
13 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_is_writeable
14 // phpcs:disable WordPress.WP.AlternativeFunctions.unlink_unlink
15 // phpcs:disable WordPress.WP.AlternativeFunctions.rename_rename
16 // phpcs:disable Squiz.PHP.DiscouragedFunctions.Discouraged
17 // --------------------------------------------------------------------------------
18 // PhpConcept Library - Zip Module 2.8.2
19 // --------------------------------------------------------------------------------
20 // License GNU/LGPL - Vincent Blavet - August 2009
21 // http://www.phpconcept.net
22 // --------------------------------------------------------------------------------
23 //
24 // Presentation :
25 // PclZip is a PHP library that manage ZIP archives.
26 // So far tests show that archives generated by PclZip are readable by
27 // WinZip application and other tools.
28 //
29 // Description :
30 // See readme.txt and http://www.phpconcept.net
31 //
32 // Warning :
33 // This library and the associated files are non commercial, non professional
34 // work.
35 // It should not have unexpected results. However if any damage is caused by
36 // this software the author can not be responsible.
37 // The use of this software is at the risk of the user.
38 //
39 // --------------------------------------------------------------------------------
40 // $Id: wpaipclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
41 // --------------------------------------------------------------------------------
42
43 if (!class_exists('WpaiPclZip')):
44
45 // ----- Constants
46 if (!defined('WPAI_PCLZIP_READ_BLOCK_SIZE')) {
47 define('WPAI_PCLZIP_READ_BLOCK_SIZE', 2048);
48 }
49
50 // ----- File list separator
51 // In version 1.x of PclZip, the separator for file list is a space
52 // (which is not a very smart choice, specifically for windows paths !).
53 // A better separator should be a comma (,). This constant gives you the
54 // abilty to change that.
55 // However notice that changing this value, may have impact on existing
56 // scripts, using space separated filenames.
57 // Recommanded values for compatibility with older versions :
58 //define('WPAI_PCLZIP_SEPARATOR', ' ');
59 // Recommanded values for smart separation of filenames.
60 if (!defined('WPAI_PCLZIP_SEPARATOR')) {
61 define('WPAI_PCLZIP_SEPARATOR', ',');
62 }
63
64 // ----- Error configuration
65 // 0 : PclZip Class integrated error handling
66 // 1 : PclError external library error handling. By enabling this
67 // you must ensure that you have included PclError library.
68 // [2,...] : reserved for futur use
69 if (!defined('WPAI_PCLZIP_ERROR_EXTERNAL')) {
70 define('WPAI_PCLZIP_ERROR_EXTERNAL', 0);
71 }
72
73 // ----- Optional static temporary directory
74 // By default temporary files are generated in the script current
75 // path.
76 // If defined :
77 // - MUST BE terminated by a '/'.
78 // - MUST be a valid, already created directory
79 // Samples :
80 // define('WPAI_PCLZIP_TEMPORARY_DIR', '/temp/');
81 // define('WPAI_PCLZIP_TEMPORARY_DIR', 'C:/Temp/');
82 if (!defined('WPAI_PCLZIP_TEMPORARY_DIR')) {
83 define('WPAI_PCLZIP_TEMPORARY_DIR', '');
84 }
85
86 // ----- Optional threshold ratio for use of temporary files
87 // Pclzip sense the size of the file to add/extract and decide to
88 // use or not temporary file. The algorythm is looking for
89 // memory_limit of PHP and apply a ratio.
90 // threshold = memory_limit * ratio.
91 // Recommended values are under 0.5. Default 0.47.
92 // Samples :
93 // define('WPAI_PCLZIP_TEMPORARY_FILE_RATIO', 0.5);
94 if (!defined('WPAI_PCLZIP_TEMPORARY_FILE_RATIO')) {
95 define('WPAI_PCLZIP_TEMPORARY_FILE_RATIO', 0.47);
96 }
97
98 // --------------------------------------------------------------------------------
99 // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
100 // --------------------------------------------------------------------------------
101
102 // ----- Global variables
103 $g_pclzip_version = "2.8.2";
104
105 // ----- Error codes
106 // -1 : Unable to open file in binary write mode
107 // -2 : Unable to open file in binary read mode
108 // -3 : Invalid parameters
109 // -4 : File does not exist
110 // -5 : Filename is too long (max. 255)
111 // -6 : Not a valid zip file
112 // -7 : Invalid extracted file size
113 // -8 : Unable to create directory
114 // -9 : Invalid archive extension
115 // -10 : Invalid archive format
116 // -11 : Unable to delete file (unlink)
117 // -12 : Unable to rename file (rename)
118 // -13 : Invalid header checksum
119 // -14 : Invalid archive size
120 define('WPAI_PCLZIP_ERR_USER_ABORTED', 2);
121 define('WPAI_PCLZIP_ERR_NO_ERROR', 0);
122 define('WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL', -1);
123 define('WPAI_PCLZIP_ERR_READ_OPEN_FAIL', -2);
124 define('WPAI_PCLZIP_ERR_INVALID_PARAMETER', -3);
125 define('WPAI_PCLZIP_ERR_MISSING_FILE', -4);
126 define('WPAI_PCLZIP_ERR_FILENAME_TOO_LONG', -5);
127 define('WPAI_PCLZIP_ERR_INVALID_ZIP', -6);
128 define('WPAI_PCLZIP_ERR_BAD_EXTRACTED_FILE', -7);
129 define('WPAI_PCLZIP_ERR_DIR_CREATE_FAIL', -8);
130 define('WPAI_PCLZIP_ERR_BAD_EXTENSION', -9);
131 define('WPAI_PCLZIP_ERR_BAD_FORMAT', -10);
132 define('WPAI_PCLZIP_ERR_DELETE_FILE_FAIL', -11);
133 define('WPAI_PCLZIP_ERR_RENAME_FILE_FAIL', -12);
134 define('WPAI_PCLZIP_ERR_BAD_CHECKSUM', -13);
135 define('WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14);
136 define('WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE', -15);
137 define('WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE', -16);
138 define('WPAI_PCLZIP_ERR_ALREADY_A_DIRECTORY', -17);
139 define('WPAI_PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18);
140 define('WPAI_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19);
141 define('WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20);
142 define('WPAI_PCLZIP_ERR_DIRECTORY_RESTRICTION', -21);
143
144 // ----- Options values
145 define('WPAI_PCLZIP_OPT_PATH', 77001);
146 define('WPAI_PCLZIP_OPT_ADD_PATH', 77002);
147 define('WPAI_PCLZIP_OPT_REMOVE_PATH', 77003);
148 define('WPAI_PCLZIP_OPT_REMOVE_ALL_PATH', 77004);
149 define('WPAI_PCLZIP_OPT_SET_CHMOD', 77005);
150 define('WPAI_PCLZIP_OPT_EXTRACT_AS_STRING', 77006);
151 define('WPAI_PCLZIP_OPT_NO_COMPRESSION', 77007);
152 define('WPAI_PCLZIP_OPT_BY_NAME', 77008);
153 define('WPAI_PCLZIP_OPT_BY_INDEX', 77009);
154 define('WPAI_PCLZIP_OPT_BY_EREG', 77010);
155 define('WPAI_PCLZIP_OPT_BY_PREG', 77011);
156 define('WPAI_PCLZIP_OPT_COMMENT', 77012);
157 define('WPAI_PCLZIP_OPT_ADD_COMMENT', 77013);
158 define('WPAI_PCLZIP_OPT_PREPEND_COMMENT', 77014);
159 define('WPAI_PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015);
160 define('WPAI_PCLZIP_OPT_REPLACE_NEWER', 77016);
161 define('WPAI_PCLZIP_OPT_STOP_ON_ERROR', 77017);
162 // Having big trouble with crypt. Need to multiply 2 long int
163 // which is not correctly supported by PHP ...
164 //define('WPAI_PCLZIP_OPT_CRYPT', 77018);
165 define('WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019);
166 define('WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020);
167 define('WPAI_PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020); // alias
168 define('WPAI_PCLZIP_OPT_TEMP_FILE_ON', 77021);
169 define('WPAI_PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021); // alias
170 define('WPAI_PCLZIP_OPT_TEMP_FILE_OFF', 77022);
171 define('WPAI_PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022); // alias
172 define('WPAI_PCLZIP_OPT_EXTRACT_EXT_RESTRICTIONS', 77023);
173 define('WPAI_PCLZIP_OPT_EXTRACT_WHITELIST_RESTRICTIONS', 77024);
174
175 // ----- File description attributes
176 define('WPAI_PCLZIP_ATT_FILE_NAME', 79001);
177 define('WPAI_PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002);
178 define('WPAI_PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003);
179 define('WPAI_PCLZIP_ATT_FILE_MTIME', 79004);
180 define('WPAI_PCLZIP_ATT_FILE_CONTENT', 79005);
181 define('WPAI_PCLZIP_ATT_FILE_COMMENT', 79006);
182
183 // ----- Call backs values
184 define('WPAI_PCLZIP_CB_PRE_EXTRACT', 78001);
185 define('WPAI_PCLZIP_CB_POST_EXTRACT', 78002);
186 define('WPAI_PCLZIP_CB_PRE_ADD', 78003);
187 define('WPAI_PCLZIP_CB_POST_ADD', 78004);
188 /* For futur use
189 define('WPAI_PCLZIP_CB_PRE_LIST', 78005);
190 define('WPAI_PCLZIP_CB_POST_LIST', 78006);
191 define('WPAI_PCLZIP_CB_PRE_DELETE', 78007);
192 define('WPAI_PCLZIP_CB_POST_DELETE', 78008);
193 */
194
195 // --------------------------------------------------------------------------------
196 // Class : PclZip
197 // Description :
198 // PclZip is the class that represent a Zip archive.
199 // The public methods allow the manipulation of the archive.
200 // Attributes :
201 // Attributes must not be accessed directly.
202 // Methods :
203 // PclZip() : Object creator
204 // create() : Creates the Zip archive
205 // listContent() : List the content of the Zip archive
206 // extract() : Extract the content of the archive
207 // properties() : List the properties of the archive
208 // --------------------------------------------------------------------------------
209 class WpaiPclZip
210 {
211 // ----- Filename of the zip file
212 public $zipname = '';
213
214 // ----- File descriptor of the zip file
215 public $zip_fd = 0;
216
217 // ----- Internal error handling
218 public $error_code = 1;
219 public $error_string = '';
220
221 // ----- Current status of the magic_quotes_runtime
222 // This value store the php configuration for magic_quotes
223 // The class can then disable the magic_quotes and reset it after
224 public $magic_quotes_status;
225
226 // --------------------------------------------------------------------------------
227 // Function : PclZip()
228 // Description :
229 // Creates a PclZip object and set the name of the associated Zip archive
230 // filename.
231 // Note that no real action is taken, if the archive does not exist it is not
232 // created. Use create() for that.
233 // --------------------------------------------------------------------------------
234 public function __construct($p_zipname)
235 {
236
237 // ----- Tests the zlib
238 if (!function_exists('gzopen')) {
239 die(esc_html('Abort '.basename(__FILE__).' : Missing zlib extensions'));
240 }
241
242 // ----- Set the attributes
243 $this->zipname = $p_zipname;
244 $this->zip_fd = 0;
245 $this->magic_quotes_status = -1;
246
247 // ----- Return
248 return;
249 }
250 // --------------------------------------------------------------------------------
251
252 // --------------------------------------------------------------------------------
253 // Function :
254 // create($p_filelist, $p_add_dir="", $p_remove_dir="")
255 // create($p_filelist, $p_option, $p_option_value, ...)
256 // Description :
257 // This method supports two different synopsis. The first one is historical.
258 // This method creates a Zip Archive. The Zip file is created in the
259 // filesystem. The files and directories indicated in $p_filelist
260 // are added in the archive. See the parameters description for the
261 // supported format of $p_filelist.
262 // When a directory is in the list, the directory and its content is added
263 // in the archive.
264 // In this synopsis, the function takes an optional variable list of
265 // options. See bellow the supported options.
266 // Parameters :
267 // $p_filelist : An array containing file or directory names, or
268 // a string containing one filename or one directory name, or
269 // a string containing a list of filenames and/or directory
270 // names separated by spaces.
271 // $p_add_dir : A path to add before the real path of the archived file,
272 // in order to have it memorized in the archive.
273 // $p_remove_dir : A path to remove from the real path of the file to archive,
274 // in order to have a shorter path memorized in the archive.
275 // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
276 // is removed first, before $p_add_dir is added.
277 // Options :
278 // WPAI_PCLZIP_OPT_ADD_PATH :
279 // WPAI_PCLZIP_OPT_REMOVE_PATH :
280 // WPAI_PCLZIP_OPT_REMOVE_ALL_PATH :
281 // WPAI_PCLZIP_OPT_COMMENT :
282 // WPAI_PCLZIP_CB_PRE_ADD :
283 // WPAI_PCLZIP_CB_POST_ADD :
284 // Return Values :
285 // 0 on failure,
286 // The list of the added files, with a status of the add action.
287 // (see WpaiPclZip::listContent() for list entry format)
288 // --------------------------------------------------------------------------------
289 public function create($p_filelist)
290 {
291 $v_result=1;
292
293 // ----- Reset the error handler
294 $this->privErrorReset();
295
296 // ----- Set default values
297 $v_options = array();
298 $v_options[WPAI_PCLZIP_OPT_NO_COMPRESSION] = false;
299
300 // ----- Look for variable options arguments
301 $v_size = func_num_args();
302
303 // ----- Look for arguments
304 if ($v_size > 1) {
305 // ----- Get the arguments
306 $v_arg_list = func_get_args();
307
308 // ----- Remove from the options list the first argument
309 array_shift($v_arg_list);
310 $v_size--;
311
312 // ----- Look for first arg
313 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
314 // ----- Parse the options
315 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
316 WPAI_PCLZIP_OPT_REMOVE_PATH => 'optional',
317 WPAI_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
318 WPAI_PCLZIP_OPT_ADD_PATH => 'optional',
319 WPAI_PCLZIP_CB_PRE_ADD => 'optional',
320 WPAI_PCLZIP_CB_POST_ADD => 'optional',
321 WPAI_PCLZIP_OPT_NO_COMPRESSION => 'optional',
322 WPAI_PCLZIP_OPT_COMMENT => 'optional',
323 WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
324 WPAI_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
325 WPAI_PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
326 //, WPAI_PCLZIP_OPT_CRYPT => 'optional'
327 ));
328 if ($v_result != 1) {
329 return 0;
330 }
331 } else {
332 // ----- Look for 2 args
333 // Here we need to support the first historic synopsis of the
334 // method.
335 // ----- Get the first argument
336 $v_options[WPAI_PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
337
338 // ----- Look for the optional second argument
339 if ($v_size == 2) {
340 $v_options[WPAI_PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
341 } elseif ($v_size > 2) {
342 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
343 return 0;
344 }
345 }
346 }
347
348 // ----- Look for default option values
349 $this->privOptionDefaultThreshold($v_options);
350
351 // ----- Init
352 $v_string_list = array();
353 $v_att_list = array();
354 $v_filedescr_list = array();
355 $p_result_list = array();
356
357 // ----- Look if the $p_filelist is really an array
358 if (is_array($p_filelist)) {
359 // ----- Look if the first element is also an array
360 // This will mean that this is a file description entry
361 if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
362 $v_att_list = $p_filelist;
363 } else {
364 // ----- The list is a list of string names
365 $v_string_list = $p_filelist;
366 }
367 } elseif (is_string($p_filelist)) {
368 // ----- Look if the $p_filelist is a string
369 // ----- Create a list from the string
370 $v_string_list = explode(WPAI_PCLZIP_SEPARATOR, $p_filelist);
371 } else {
372 // ----- Invalid variable type for $p_filelist
373 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
374 return 0;
375 }
376
377 // ----- Reformat the string list
378 if (sizeof($v_string_list) != 0) {
379 foreach ($v_string_list as $v_string) {
380 if ($v_string != '') {
381 $v_att_list[][WPAI_PCLZIP_ATT_FILE_NAME] = $v_string;
382 } else {
383 }
384 }
385 }
386
387 // ----- For each file in the list check the attributes
388 $v_supported_attributes = array(
389 WPAI_PCLZIP_ATT_FILE_NAME => 'mandatory',
390 WPAI_PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
391 WPAI_PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
392 WPAI_PCLZIP_ATT_FILE_MTIME => 'optional',
393 WPAI_PCLZIP_ATT_FILE_CONTENT => 'optional',
394 WPAI_PCLZIP_ATT_FILE_COMMENT => 'optional'
395 );
396 foreach ($v_att_list as $v_entry) {
397 $v_result = $this->privFileDescrParseAtt($v_entry, $v_filedescr_list[], $v_options, $v_supported_attributes);
398 if ($v_result != 1) {
399 return 0;
400 }
401 }
402
403 // ----- Expand the filelist (expand directories)
404 $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
405 if ($v_result != 1) {
406 return 0;
407 }
408
409 // ----- Call the create fct
410 $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
411 if ($v_result != 1) {
412 return 0;
413 }
414
415 // ----- Return
416 return $p_result_list;
417 }
418 // --------------------------------------------------------------------------------
419
420 // --------------------------------------------------------------------------------
421 // Function :
422 // add($p_filelist, $p_add_dir="", $p_remove_dir="")
423 // add($p_filelist, $p_option, $p_option_value, ...)
424 // Description :
425 // This method supports two synopsis. The first one is historical.
426 // This methods add the list of files in an existing archive.
427 // If a file with the same name already exists, it is added at the end of the
428 // archive, the first one is still present.
429 // If the archive does not exist, it is created.
430 // Parameters :
431 // $p_filelist : An array containing file or directory names, or
432 // a string containing one filename or one directory name, or
433 // a string containing a list of filenames and/or directory
434 // names separated by spaces.
435 // $p_add_dir : A path to add before the real path of the archived file,
436 // in order to have it memorized in the archive.
437 // $p_remove_dir : A path to remove from the real path of the file to archive,
438 // in order to have a shorter path memorized in the archive.
439 // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
440 // is removed first, before $p_add_dir is added.
441 // Options :
442 // WPAI_PCLZIP_OPT_ADD_PATH :
443 // WPAI_PCLZIP_OPT_REMOVE_PATH :
444 // WPAI_PCLZIP_OPT_REMOVE_ALL_PATH :
445 // WPAI_PCLZIP_OPT_COMMENT :
446 // WPAI_PCLZIP_OPT_ADD_COMMENT :
447 // WPAI_PCLZIP_OPT_PREPEND_COMMENT :
448 // WPAI_PCLZIP_CB_PRE_ADD :
449 // WPAI_PCLZIP_CB_POST_ADD :
450 // Return Values :
451 // 0 on failure,
452 // The list of the added files, with a status of the add action.
453 // (see WpaiPclZip::listContent() for list entry format)
454 // --------------------------------------------------------------------------------
455 public function add($p_filelist)
456 {
457 $v_result=1;
458
459 // ----- Reset the error handler
460 $this->privErrorReset();
461
462 // ----- Set default values
463 $v_options = array();
464 $v_options[WPAI_PCLZIP_OPT_NO_COMPRESSION] = false;
465
466 // ----- Look for variable options arguments
467 $v_size = func_num_args();
468
469 // ----- Look for arguments
470 if ($v_size > 1) {
471 // ----- Get the arguments
472 $v_arg_list = func_get_args();
473
474 // ----- Remove form the options list the first argument
475 array_shift($v_arg_list);
476 $v_size--;
477
478 // ----- Look for first arg
479 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, array (
482 WPAI_PCLZIP_OPT_REMOVE_PATH => 'optional',
483 WPAI_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
484 WPAI_PCLZIP_OPT_ADD_PATH => 'optional',
485 WPAI_PCLZIP_CB_PRE_ADD => 'optional',
486 WPAI_PCLZIP_CB_POST_ADD => 'optional',
487 WPAI_PCLZIP_OPT_NO_COMPRESSION => 'optional',
488 WPAI_PCLZIP_OPT_COMMENT => 'optional',
489 WPAI_PCLZIP_OPT_ADD_COMMENT => 'optional',
490 WPAI_PCLZIP_OPT_PREPEND_COMMENT => 'optional',
491 WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
492 WPAI_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
493 WPAI_PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
494 //, WPAI_PCLZIP_OPT_CRYPT => 'optional'
495 ));
496 if ($v_result != 1) {
497 return 0;
498 }
499 } else {
500 // ----- Look for 2 args
501 // Here we need to support the first historic synopsis of the
502 // method.
503 // ----- Get the first argument
504 $v_options[WPAI_PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
505
506 // ----- Look for the optional second argument
507 if ($v_size == 2) {
508 $v_options[WPAI_PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
509 } elseif ($v_size > 2) {
510 // ----- Error log
511 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
512
513 // ----- Return
514 return 0;
515 }
516 }
517 }
518
519 // ----- Look for default option values
520 $this->privOptionDefaultThreshold($v_options);
521
522 // ----- Init
523 $v_string_list = array();
524 $v_att_list = array();
525 $v_filedescr_list = array();
526 $p_result_list = array();
527
528 // ----- Look if the $p_filelist is really an array
529 if (is_array($p_filelist)) {
530 // ----- Look if the first element is also an array
531 // This will mean that this is a file description entry
532 if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
533 $v_att_list = $p_filelist;
534 } else {
535 // ----- The list is a list of string names
536 $v_string_list = $p_filelist;
537 }
538 } elseif (is_string($p_filelist)) {
539 // ----- Look if the $p_filelist is a string
540 // ----- Create a list from the string
541 $v_string_list = explode(WPAI_PCLZIP_SEPARATOR, $p_filelist);
542 } else {
543 // ----- Invalid variable type for $p_filelist
544 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
545 return 0;
546 }
547
548 // ----- Reformat the string list
549 if (sizeof($v_string_list) != 0) {
550 foreach ($v_string_list as $v_string) {
551 $v_att_list[][WPAI_PCLZIP_ATT_FILE_NAME] = $v_string;
552 }
553 }
554
555 // ----- For each file in the list check the attributes
556 $v_supported_attributes = array(
557 WPAI_PCLZIP_ATT_FILE_NAME => 'mandatory',
558 WPAI_PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional',
559 WPAI_PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional',
560 WPAI_PCLZIP_ATT_FILE_MTIME => 'optional',
561 WPAI_PCLZIP_ATT_FILE_CONTENT => 'optional',
562 WPAI_PCLZIP_ATT_FILE_COMMENT => 'optional',
563 );
564 foreach ($v_att_list as $v_entry) {
565 $v_result = $this->privFileDescrParseAtt($v_entry, $v_filedescr_list[], $v_options, $v_supported_attributes);
566 if ($v_result != 1) {
567 return 0;
568 }
569 }
570
571 // ----- Expand the filelist (expand directories)
572 $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
573 if ($v_result != 1) {
574 return 0;
575 }
576
577 // ----- Call the create fct
578 $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
579 if ($v_result != 1) {
580 return 0;
581 }
582
583 // ----- Return
584 return $p_result_list;
585 }
586 // --------------------------------------------------------------------------------
587
588 // --------------------------------------------------------------------------------
589 // Function : listContent()
590 // Description :
591 // This public method, gives the list of the files and directories, with their
592 // properties.
593 // The properties of each entries in the list are (used also in other functions) :
594 // filename : Name of the file. For a create or add action it is the filename
595 // given by the user. For an extract function it is the filename
596 // of the extracted file.
597 // stored_filename : Name of the file / directory stored in the archive.
598 // size : Size of the stored file.
599 // compressed_size : Size of the file's data compressed in the archive
600 // (without the headers overhead)
601 // mtime : Last known modification date of the file (UNIX timestamp)
602 // comment : Comment associated with the file
603 // folder : true | false
604 // index : index of the file in the archive
605 // status : status of the action (depending of the action) :
606 // Values are :
607 // ok : OK !
608 // filtered : the file / dir is not extracted (filtered by user)
609 // already_a_directory : the file can not be extracted because a
610 // directory with the same name already exists
611 // write_protected : the file can not be extracted because a file
612 // with the same name already exists and is
613 // write protected
614 // newer_exist : the file was not extracted because a newer file exists
615 // path_creation_fail : the file is not extracted because the folder
616 // does not exist and can not be created
617 // write_error : the file was not extracted because there was a
618 // error while writing the file
619 // read_error : the file was not extracted because there was a error
620 // while reading the file
621 // invalid_header : the file was not extracted because of an archive
622 // format error (bad file header)
623 // Note that each time a method can continue operating when there
624 // is an action error on a file, the error is only logged in the file status.
625 // Return Values :
626 // 0 on an unrecoverable failure,
627 // The list of the files in the archive.
628 // --------------------------------------------------------------------------------
629 public function listContent()
630 {
631 $v_result=1;
632
633 // ----- Reset the error handler
634 $this->privErrorReset();
635
636 // ----- Check archive
637 if (!$this->privCheckFormat()) {
638 return(0);
639 }
640
641 // ----- Call the extracting fct
642 $p_list = array();
643 if (($v_result = $this->privList($p_list)) != 1) {
644 unset($p_list);
645 return(0);
646 }
647
648 // ----- Return
649 return $p_list;
650 }
651 // --------------------------------------------------------------------------------
652
653 // --------------------------------------------------------------------------------
654 // Function :
655 // extract($p_path="./", $p_remove_path="")
656 // extract([$p_option, $p_option_value, ...])
657 // Description :
658 // This method supports two synopsis. The first one is historical.
659 // This method extract all the files / directories from the archive to the
660 // folder indicated in $p_path.
661 // If you want to ignore the 'root' part of path of the memorized files
662 // you can indicate this in the optional $p_remove_path parameter.
663 // By default, if a newer file with the same name already exists, the
664 // file is not extracted.
665 //
666 // If both WPAI_PCLZIP_OPT_PATH and WPAI_PCLZIP_OPT_ADD_PATH aoptions
667 // are used, the path indicated in WPAI_PCLZIP_OPT_ADD_PATH is append
668 // at the end of the path value of WPAI_PCLZIP_OPT_PATH.
669 // Parameters :
670 // $p_path : Path where the files and directories are to be extracted
671 // $p_remove_path : First part ('root' part) of the memorized path
672 // (if any similar) to remove while extracting.
673 // Options :
674 // WPAI_PCLZIP_OPT_PATH :
675 // WPAI_PCLZIP_OPT_ADD_PATH :
676 // WPAI_PCLZIP_OPT_REMOVE_PATH :
677 // WPAI_PCLZIP_OPT_REMOVE_ALL_PATH :
678 // WPAI_PCLZIP_CB_PRE_EXTRACT :
679 // WPAI_PCLZIP_CB_POST_EXTRACT :
680 // Return Values :
681 // 0 or a negative value on failure,
682 // The list of the extracted files, with a status of the action.
683 // (see WpaiPclZip::listContent() for list entry format)
684 // --------------------------------------------------------------------------------
685 public function extract()
686 {
687 $v_result=1;
688
689 // ----- Reset the error handler
690 $this->privErrorReset();
691
692 // ----- Check archive
693 if (!$this->privCheckFormat()) {
694 return(0);
695 }
696
697 // ----- Set default values
698 $v_options = array();
699 // $v_path = "./";
700 $v_path = '';
701 $v_remove_path = "";
702 $v_remove_all_path = false;
703
704 // ----- Look for variable options arguments
705 $v_size = func_num_args();
706
707 // ----- Default values for option
708 $v_options[WPAI_PCLZIP_OPT_EXTRACT_AS_STRING] = false;
709
710 // ----- Look for arguments
711 if ($v_size > 0) {
712 // ----- Get the arguments
713 $v_arg_list = func_get_args();
714
715 // ----- Look for first arg
716 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
717 // ----- Parse the options
718 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
719 WPAI_PCLZIP_OPT_PATH => 'optional',
720 WPAI_PCLZIP_OPT_REMOVE_PATH => 'optional',
721 WPAI_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
722 WPAI_PCLZIP_OPT_ADD_PATH => 'optional',
723 WPAI_PCLZIP_CB_PRE_EXTRACT => 'optional',
724 WPAI_PCLZIP_CB_POST_EXTRACT => 'optional',
725 WPAI_PCLZIP_OPT_SET_CHMOD => 'optional',
726 WPAI_PCLZIP_OPT_BY_NAME => 'optional',
727 WPAI_PCLZIP_OPT_BY_EREG => 'optional',
728 WPAI_PCLZIP_OPT_BY_PREG => 'optional',
729 WPAI_PCLZIP_OPT_BY_INDEX => 'optional',
730 WPAI_PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
731 WPAI_PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
732 WPAI_PCLZIP_OPT_REPLACE_NEWER => 'optional',
733 WPAI_PCLZIP_OPT_STOP_ON_ERROR => 'optional',
734 WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
735 WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
736 WPAI_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
737 WPAI_PCLZIP_OPT_TEMP_FILE_OFF => 'optional',
738 WPAI_PCLZIP_OPT_EXTRACT_EXT_RESTRICTIONS => 'optional',
739 WPAI_PCLZIP_OPT_EXTRACT_WHITELIST_RESTRICTIONS => 'optional'
740 ));
741 if ($v_result != 1) {
742 return 0;
743 }
744
745 // ----- Set the arguments
746 if (isset($v_options[WPAI_PCLZIP_OPT_PATH])) {
747 $v_path = $v_options[WPAI_PCLZIP_OPT_PATH];
748 }
749 if (isset($v_options[WPAI_PCLZIP_OPT_REMOVE_PATH])) {
750 $v_remove_path = $v_options[WPAI_PCLZIP_OPT_REMOVE_PATH];
751 }
752 if (isset($v_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH])) {
753 $v_remove_all_path = $v_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH];
754 }
755 if (isset($v_options[WPAI_PCLZIP_OPT_ADD_PATH])) {
756 // ----- Check for '/' in last path char
757 if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
758 $v_path .= '/';
759 }
760 $v_path .= $v_options[WPAI_PCLZIP_OPT_ADD_PATH];
761 }
762 } else {
763 // ----- Look for 2 args
764 // Here we need to support the first historic synopsis of the
765 // method.
766 // ----- Get the first argument
767 $v_path = $v_arg_list[0];
768
769 // ----- Look for the optional second argument
770 if ($v_size == 2) {
771 $v_remove_path = $v_arg_list[1];
772 } elseif ($v_size > 2) {
773 // ----- Error log
774 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
775
776 // ----- Return
777 return 0;
778 }
779 }
780 }
781
782 // ----- Look for default option values
783 $this->privOptionDefaultThreshold($v_options);
784
785 // ----- Trace
786
787 // ----- Call the extracting fct
788 $p_list = array();
789 $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options);
790 if ($v_result < 1) {
791 unset($p_list);
792 return(0);
793 }
794
795 // ----- Return
796 return $p_list;
797 }
798 // --------------------------------------------------------------------------------
799
800
801 // --------------------------------------------------------------------------------
802 // Function :
803 // extractByIndex($p_index, $p_path="./", $p_remove_path="")
804 // extractByIndex($p_index, [$p_option, $p_option_value, ...])
805 // Description :
806 // This method supports two synopsis. The first one is historical.
807 // This method is doing a partial extract of the archive.
808 // The extracted files or folders are identified by their index in the
809 // archive (from 0 to n).
810 // Note that if the index identify a folder, only the folder entry is
811 // extracted, not all the files included in the archive.
812 // Parameters :
813 // $p_index : A single index (integer) or a string of indexes of files to
814 // extract. The form of the string is "0,4-6,8-12" with only numbers
815 // and '-' for range or ',' to separate ranges. No spaces or ';'
816 // are allowed.
817 // $p_path : Path where the files and directories are to be extracted
818 // $p_remove_path : First part ('root' part) of the memorized path
819 // (if any similar) to remove while extracting.
820 // Options :
821 // WPAI_PCLZIP_OPT_PATH :
822 // WPAI_PCLZIP_OPT_ADD_PATH :
823 // WPAI_PCLZIP_OPT_REMOVE_PATH :
824 // WPAI_PCLZIP_OPT_REMOVE_ALL_PATH :
825 // WPAI_PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
826 // not as files.
827 // The resulting content is in a new field 'content' in the file
828 // structure.
829 // This option must be used alone (any other options are ignored).
830 // WPAI_PCLZIP_CB_PRE_EXTRACT :
831 // WPAI_PCLZIP_CB_POST_EXTRACT :
832 // Return Values :
833 // 0 on failure,
834 // The list of the extracted files, with a status of the action.
835 // (see WpaiPclZip::listContent() for list entry format)
836 // --------------------------------------------------------------------------------
837 //function extractByIndex($p_index, options...)
838 public function extractByIndex($p_index)
839 {
840 $v_result=1;
841
842 // ----- Reset the error handler
843 $this->privErrorReset();
844
845 // ----- Check archive
846 if (!$this->privCheckFormat()) {
847 return(0);
848 }
849
850 // ----- Set default values
851 $v_options = array();
852 // $v_path = "./";
853 $v_path = '';
854 $v_remove_path = "";
855 $v_remove_all_path = false;
856
857 // ----- Look for variable options arguments
858 $v_size = func_num_args();
859
860 // ----- Default values for option
861 $v_options[WPAI_PCLZIP_OPT_EXTRACT_AS_STRING] = false;
862
863 // ----- Look for arguments
864 if ($v_size > 1) {
865 // ----- Get the arguments
866 $v_arg_list = func_get_args();
867
868 // ----- Remove form the options list the first argument
869 array_shift($v_arg_list);
870 $v_size--;
871
872 // ----- Look for first arg
873 if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
874 // ----- Parse the options
875 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array(
876 WPAI_PCLZIP_OPT_PATH => 'optional',
877 WPAI_PCLZIP_OPT_REMOVE_PATH => 'optional',
878 WPAI_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
879 WPAI_PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
880 WPAI_PCLZIP_OPT_ADD_PATH => 'optional',
881 WPAI_PCLZIP_CB_PRE_EXTRACT => 'optional',
882 WPAI_PCLZIP_CB_POST_EXTRACT => 'optional',
883 WPAI_PCLZIP_OPT_SET_CHMOD => 'optional',
884 WPAI_PCLZIP_OPT_REPLACE_NEWER => 'optional',
885 WPAI_PCLZIP_OPT_STOP_ON_ERROR => 'optional',
886 WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
887 WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
888 WPAI_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
889 WPAI_PCLZIP_OPT_TEMP_FILE_OFF => 'optional',
890 WPAI_PCLZIP_OPT_EXTRACT_EXT_RESTRICTIONS => 'optional',
891 WPAI_PCLZIP_OPT_EXTRACT_WHITELIST_RESTRICTIONS => 'optional'
892 ));
893 if ($v_result != 1) {
894 return 0;
895 }
896
897 // ----- Set the arguments
898 if (isset($v_options[WPAI_PCLZIP_OPT_PATH])) {
899 $v_path = $v_options[WPAI_PCLZIP_OPT_PATH];
900 }
901 if (isset($v_options[WPAI_PCLZIP_OPT_REMOVE_PATH])) {
902 $v_remove_path = $v_options[WPAI_PCLZIP_OPT_REMOVE_PATH];
903 }
904 if (isset($v_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH])) {
905 $v_remove_all_path = $v_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH];
906 }
907 if (isset($v_options[WPAI_PCLZIP_OPT_ADD_PATH])) {
908 // ----- Check for '/' in last path char
909 if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
910 $v_path .= '/';
911 }
912 $v_path .= $v_options[WPAI_PCLZIP_OPT_ADD_PATH];
913 }
914 if (!isset($v_options[WPAI_PCLZIP_OPT_EXTRACT_AS_STRING])) {
915 $v_options[WPAI_PCLZIP_OPT_EXTRACT_AS_STRING] = false;
916 } else {
917 }
918 } else {
919 // ----- Look for 2 args
920 // Here we need to support the first historic synopsis of the
921 // method.
922
923 // ----- Get the first argument
924 $v_path = $v_arg_list[0];
925
926 // ----- Look for the optional second argument
927 if ($v_size == 2) {
928 $v_remove_path = $v_arg_list[1];
929 } elseif ($v_size > 2) {
930 // ----- Error log
931 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
932
933 // ----- Return
934 return 0;
935 }
936 }
937 }
938
939 // ----- Trace
940
941 // ----- Trick
942 // Here I want to reuse extractByRule(), so I need to parse the $p_index
943 // with privParseOptions()
944 $v_arg_trick = array (WPAI_PCLZIP_OPT_BY_INDEX, $p_index);
945 $v_options_trick = array();
946 $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, array (WPAI_PCLZIP_OPT_BY_INDEX => 'optional'));
947 if ($v_result != 1) {
948 return 0;
949 }
950 $v_options[WPAI_PCLZIP_OPT_BY_INDEX] = $v_options_trick[WPAI_PCLZIP_OPT_BY_INDEX];
951
952 // ----- Look for default option values
953 $this->privOptionDefaultThreshold($v_options);
954
955 // ----- Call the extracting fct
956 if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
957 return(0);
958 }
959
960 // ----- Return
961 return $p_list;
962 }
963 // --------------------------------------------------------------------------------
964
965 // --------------------------------------------------------------------------------
966 // Function :
967 // delete([$p_option, $p_option_value, ...])
968 // Description :
969 // This method removes files from the archive.
970 // If no parameters are given, then all the archive is emptied.
971 // Parameters :
972 // None or optional arguments.
973 // Options :
974 // WPAI_PCLZIP_OPT_BY_INDEX :
975 // WPAI_PCLZIP_OPT_BY_NAME :
976 // WPAI_PCLZIP_OPT_BY_EREG :
977 // WPAI_PCLZIP_OPT_BY_PREG :
978 // Return Values :
979 // 0 on failure,
980 // The list of the files which are still present in the archive.
981 // (see WpaiPclZip::listContent() for list entry format)
982 // --------------------------------------------------------------------------------
983 public function delete()
984 {
985 $v_result=1;
986
987 // ----- Reset the error handler
988 $this->privErrorReset();
989
990 // ----- Check archive
991 if (!$this->privCheckFormat()) {
992 return(0);
993 }
994
995 // ----- Set default values
996 $v_options = array();
997
998 // ----- Look for variable options arguments
999 $v_size = func_num_args();
1000
1001 // ----- Look for arguments
1002 if ($v_size > 0) {
1003 // ----- Get the arguments
1004 $v_arg_list = func_get_args();
1005
1006 // ----- Parse the options
1007 $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (
1008 WPAI_PCLZIP_OPT_BY_NAME => 'optional',
1009 WPAI_PCLZIP_OPT_BY_EREG => 'optional',
1010 WPAI_PCLZIP_OPT_BY_PREG => 'optional',
1011 WPAI_PCLZIP_OPT_BY_INDEX => 'optional'
1012 ));
1013 if ($v_result != 1) {
1014 return 0;
1015 }
1016 }
1017
1018 // ----- Magic quotes trick
1019 $this->privDisableMagicQuotes();
1020
1021 // ----- Call the delete fct
1022 $v_list = array();
1023 if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1024 $this->privSwapBackMagicQuotes();
1025 unset($v_list);
1026 return(0);
1027 }
1028
1029 // ----- Magic quotes trick
1030 $this->privSwapBackMagicQuotes();
1031
1032 // ----- Return
1033 return $v_list;
1034 }
1035 // --------------------------------------------------------------------------------
1036
1037 // --------------------------------------------------------------------------------
1038 // Function : deleteByIndex()
1039 // Description :
1040 // ***** Deprecated *****
1041 // delete(WPAI_PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1042 // --------------------------------------------------------------------------------
1043 public function deleteByIndex($p_index)
1044 {
1045
1046 $p_list = $this->delete(WPAI_PCLZIP_OPT_BY_INDEX, $p_index);
1047
1048 // ----- Return
1049 return $p_list;
1050 }
1051 // --------------------------------------------------------------------------------
1052
1053 // --------------------------------------------------------------------------------
1054 // Function : properties()
1055 // Description :
1056 // This method gives the properties of the archive.
1057 // The properties are :
1058 // nb : Number of files in the archive
1059 // comment : Comment associated with the archive file
1060 // status : not_exist, ok
1061 // Parameters :
1062 // None
1063 // Return Values :
1064 // 0 on failure,
1065 // An array with the archive properties.
1066 // --------------------------------------------------------------------------------
1067 public function properties()
1068 {
1069
1070 // ----- Reset the error handler
1071 $this->privErrorReset();
1072
1073 // ----- Magic quotes trick
1074 $this->privDisableMagicQuotes();
1075
1076 // ----- Check archive
1077 if (!$this->privCheckFormat()) {
1078 $this->privSwapBackMagicQuotes();
1079 return(0);
1080 }
1081
1082 // ----- Default properties
1083 $v_prop = array();
1084 $v_prop['comment'] = '';
1085 $v_prop['nb'] = 0;
1086 $v_prop['status'] = 'not_exist';
1087
1088 // ----- Look if file exists
1089 if (@is_file($this->zipname)) {
1090 // ----- Open the zip file
1091 if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) {
1092 $this->privSwapBackMagicQuotes();
1093
1094 // ----- Error log
1095 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1096
1097 // ----- Return
1098 return 0;
1099 }
1100
1101 // ----- Read the central directory informations
1102 $v_central_dir = array();
1103 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
1104 $this->privSwapBackMagicQuotes();
1105 return 0;
1106 }
1107
1108 // ----- Close the zip file
1109 $this->privCloseFd();
1110
1111 // ----- Set the user attributes
1112 $v_prop['comment'] = $v_central_dir['comment'];
1113 $v_prop['nb'] = $v_central_dir['entries'];
1114 $v_prop['status'] = 'ok';
1115 }
1116
1117 // ----- Magic quotes trick
1118 $this->privSwapBackMagicQuotes();
1119
1120 // ----- Return
1121 return $v_prop;
1122 }
1123 // --------------------------------------------------------------------------------
1124
1125 // --------------------------------------------------------------------------------
1126 // Function : duplicate()
1127 // Description :
1128 // This method creates an archive by copying the content of an other one. If
1129 // the archive already exist, it is replaced by the new one without any warning.
1130 // Parameters :
1131 // $p_archive : The filename of a valid archive, or
1132 // a valid PclZip object.
1133 // Return Values :
1134 // 1 on success.
1135 // 0 or a negative value on error (error code).
1136 // --------------------------------------------------------------------------------
1137 public function duplicate($p_archive)
1138 {
1139 $v_result = 1;
1140
1141 // ----- Reset the error handler
1142 $this->privErrorReset();
1143
1144 // ----- Look if the $p_archive is a PclZip object
1145 if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) {
1146 // ----- Duplicate the archive
1147 $v_result = $this->privDuplicate($p_archive->zipname);
1148 } elseif (is_string($p_archive)) {
1149 // ----- Look if the $p_archive is a string (so a filename)
1150 // ----- Check that $p_archive is a valid zip file
1151 // TBC : Should also check the archive format
1152 if (!is_file($p_archive)) {
1153 // ----- Error log
1154 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1155 $v_result = WPAI_PCLZIP_ERR_MISSING_FILE;
1156 } else {
1157 // ----- Duplicate the archive
1158 $v_result = $this->privDuplicate($p_archive);
1159 }
1160 } else {
1161 // ----- Invalid variable
1162 // ----- Error log
1163 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1164 $v_result = WPAI_PCLZIP_ERR_INVALID_PARAMETER;
1165 }
1166
1167 // ----- Return
1168 return $v_result;
1169 }
1170 // --------------------------------------------------------------------------------
1171
1172 // --------------------------------------------------------------------------------
1173 // Function : merge()
1174 // Description :
1175 // This method merge the $p_archive_to_add archive at the end of the current
1176 // one ($this).
1177 // If the archive ($this) does not exist, the merge becomes a duplicate.
1178 // If the $p_archive_to_add archive does not exist, the merge is a success.
1179 // Parameters :
1180 // $p_archive_to_add : It can be directly the filename of a valid zip archive,
1181 // or a PclZip object archive.
1182 // Return Values :
1183 // 1 on success,
1184 // 0 or negative values on error (see below).
1185 // --------------------------------------------------------------------------------
1186 public function merge($p_archive_to_add)
1187 {
1188 $v_result = 1;
1189
1190 // ----- Reset the error handler
1191 $this->privErrorReset();
1192
1193 // ----- Check archive
1194 if (!$this->privCheckFormat()) {
1195 return(0);
1196 }
1197
1198 // ----- Look if the $p_archive_to_add is a PclZip object
1199 if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) {
1200 // ----- Merge the archive
1201 $v_result = $this->privMerge($p_archive_to_add);
1202 } elseif (is_string($p_archive_to_add)) {
1203 // ----- Look if the $p_archive_to_add is a string (so a filename)
1204 // ----- Create a temporary archive
1205 $v_object_archive = new PclZip($p_archive_to_add);
1206
1207 // ----- Merge the archive
1208 $v_result = $this->privMerge($v_object_archive);
1209 } else {
1210 // ----- Invalid variable
1211 // ----- Error log
1212 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1213 $v_result = WPAI_PCLZIP_ERR_INVALID_PARAMETER;
1214 }
1215
1216 // ----- Return
1217 return $v_result;
1218 }
1219 // --------------------------------------------------------------------------------
1220
1221
1222
1223 // --------------------------------------------------------------------------------
1224 // Function : errorCode()
1225 // Description :
1226 // Parameters :
1227 // --------------------------------------------------------------------------------
1228 public function errorCode()
1229 {
1230 if (WPAI_PCLZIP_ERROR_EXTERNAL == 1) {
1231 // External error handling not implemented - fallback to internal
1232 return($this->error_code);
1233 } else {
1234 return($this->error_code);
1235 }
1236 }
1237 // --------------------------------------------------------------------------------
1238
1239 // --------------------------------------------------------------------------------
1240 // Function : errorName()
1241 // Description :
1242 // Parameters :
1243 // --------------------------------------------------------------------------------
1244 public function errorName($p_with_code = false)
1245 {
1246 $v_name = array(
1247 WPAI_PCLZIP_ERR_NO_ERROR => 'WPAI_PCLZIP_ERR_NO_ERROR',
1248 WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL => 'WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL',
1249 WPAI_PCLZIP_ERR_READ_OPEN_FAIL => 'WPAI_PCLZIP_ERR_READ_OPEN_FAIL',
1250 WPAI_PCLZIP_ERR_INVALID_PARAMETER => 'WPAI_PCLZIP_ERR_INVALID_PARAMETER',
1251 WPAI_PCLZIP_ERR_MISSING_FILE => 'WPAI_PCLZIP_ERR_MISSING_FILE',
1252 WPAI_PCLZIP_ERR_FILENAME_TOO_LONG => 'WPAI_PCLZIP_ERR_FILENAME_TOO_LONG',
1253 WPAI_PCLZIP_ERR_INVALID_ZIP => 'WPAI_PCLZIP_ERR_INVALID_ZIP',
1254 WPAI_PCLZIP_ERR_BAD_EXTRACTED_FILE => 'WPAI_PCLZIP_ERR_BAD_EXTRACTED_FILE',
1255 WPAI_PCLZIP_ERR_DIR_CREATE_FAIL => 'WPAI_PCLZIP_ERR_DIR_CREATE_FAIL',
1256 WPAI_PCLZIP_ERR_BAD_EXTENSION => 'WPAI_PCLZIP_ERR_BAD_EXTENSION',
1257 WPAI_PCLZIP_ERR_BAD_FORMAT => 'WPAI_PCLZIP_ERR_BAD_FORMAT',
1258 WPAI_PCLZIP_ERR_DELETE_FILE_FAIL => 'WPAI_PCLZIP_ERR_DELETE_FILE_FAIL',
1259 WPAI_PCLZIP_ERR_RENAME_FILE_FAIL => 'WPAI_PCLZIP_ERR_RENAME_FILE_FAIL',
1260 WPAI_PCLZIP_ERR_BAD_CHECKSUM => 'WPAI_PCLZIP_ERR_BAD_CHECKSUM',
1261 WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1262 WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE => 'WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE',
1263 WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE => 'WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE',
1264 WPAI_PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'WPAI_PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1265 WPAI_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'WPAI_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION',
1266 WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE',
1267 WPAI_PCLZIP_ERR_DIRECTORY_RESTRICTION => 'WPAI_PCLZIP_ERR_DIRECTORY_RESTRICTION',
1268 );
1269
1270 if (isset($v_name[$this->error_code])) {
1271 $v_value = $v_name[$this->error_code];
1272 } else {
1273 $v_value = 'NoName';
1274 }
1275
1276 if ($p_with_code) {
1277 return($v_value.' ('.$this->error_code.')');
1278 } else {
1279 return($v_value);
1280 }
1281 }
1282 // --------------------------------------------------------------------------------
1283
1284 // --------------------------------------------------------------------------------
1285 // Function : errorInfo()
1286 // Description :
1287 // Parameters :
1288 // --------------------------------------------------------------------------------
1289 public function errorInfo($p_full = false)
1290 {
1291 if (WPAI_PCLZIP_ERROR_EXTERNAL == 1) {
1292 // External error handling not implemented - fallback to internal
1293 if ($p_full) {
1294 return($this->errorName(true)." : ".$this->error_string);
1295 } else {
1296 return($this->error_string." [code ".$this->error_code."]");
1297 }
1298 } else {
1299 if ($p_full) {
1300 return($this->errorName(true)." : ".$this->error_string);
1301 } else {
1302 return($this->error_string." [code ".$this->error_code."]");
1303 }
1304 }
1305 }
1306 // --------------------------------------------------------------------------------
1307
1308
1309 // --------------------------------------------------------------------------------
1310 // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1311 // ***** *****
1312 // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1313 // --------------------------------------------------------------------------------
1314
1315
1316
1317 // --------------------------------------------------------------------------------
1318 // Function : privCheckFormat()
1319 // Description :
1320 // This method check that the archive exists and is a valid zip archive.
1321 // Several level of check exists. (futur)
1322 // Parameters :
1323 // $p_level : Level of check. Default 0.
1324 // 0 : Check the first bytes (magic codes) (default value))
1325 // 1 : 0 + Check the central directory (futur)
1326 // 2 : 1 + Check each file header (futur)
1327 // Return Values :
1328 // true on success,
1329 // false on error, the error code is set.
1330 // --------------------------------------------------------------------------------
1331 public function privCheckFormat($p_level = 0)
1332 {
1333 $v_result = true;
1334
1335 // ----- Reset the file system cache
1336 clearstatcache();
1337
1338 // ----- Reset the error handler
1339 $this->privErrorReset();
1340
1341 // ----- Look if the file exits
1342 if (!is_file($this->zipname)) {
1343 // ----- Error log
1344 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1345 return(false);
1346 }
1347
1348 // ----- Check that the file is readeable
1349 if (!is_readable($this->zipname)) {
1350 // ----- Error log
1351 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1352 return(false);
1353 }
1354
1355 // ----- Check the magic code
1356 // TBC
1357
1358 // ----- Check the central header
1359 // TBC
1360
1361 // ----- Check each file header
1362 // TBC
1363
1364 // ----- Return
1365 return $v_result;
1366 }
1367 // --------------------------------------------------------------------------------
1368
1369 // --------------------------------------------------------------------------------
1370 // Function : privParseOptions()
1371 // Description :
1372 // This internal methods reads the variable list of arguments ($p_options_list,
1373 // $p_size) and generate an array with the options and values ($v_result_list).
1374 // $v_requested_options contains the options that can be present and those that
1375 // must be present.
1376 // $v_requested_options is an array, with the option value as key, and 'optional',
1377 // or 'mandatory' as value.
1378 // Parameters :
1379 // See above.
1380 // Return Values :
1381 // 1 on success.
1382 // 0 on failure.
1383 // --------------------------------------------------------------------------------
1384 public function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options = false)
1385 {
1386 $v_result=1;
1387
1388 // ----- Read the options
1389 $i=0;
1390 while ($i<$p_size) {
1391 // ----- Check if the option is supported
1392 if (!isset($v_requested_options[$p_options_list[$i]])) {
1393 // ----- Error log
1394 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1395
1396 // ----- Return
1397 return WpaiPclZip::errorCode();
1398 }
1399
1400 // ----- Look for next option
1401 switch ($p_options_list[$i]) {
1402 // ----- Look for options that request a path value
1403 case WPAI_PCLZIP_OPT_PATH:
1404 case WPAI_PCLZIP_OPT_REMOVE_PATH:
1405 case WPAI_PCLZIP_OPT_ADD_PATH:
1406 // ----- Check the number of parameters
1407 if (($i+1) >= $p_size) {
1408 // ----- Error log
1409 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1410
1411 // ----- Return
1412 return WpaiPclZip::errorCode();
1413 }
1414
1415 // ----- Get the value
1416 $v_result_list[$p_options_list[$i]] = WpaiPclZipUtilTranslateWinPath($p_options_list[ $i + 1], false);
1417 $i++;
1418 break;
1419
1420 case WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD:
1421 // ----- Check the number of parameters
1422 if (($i+1) >= $p_size) {
1423 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1424 return WpaiPclZip::errorCode();
1425 }
1426
1427 // ----- Check for incompatible options
1428 if (isset($v_result_list[WPAI_PCLZIP_OPT_TEMP_FILE_OFF])) {
1429 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'WPAI_PCLZIP_OPT_TEMP_FILE_OFF'");
1430 return WpaiPclZip::errorCode();
1431 }
1432
1433 // ----- Check the value
1434 $v_value = $p_options_list[$i+1];
1435 if ((!is_integer($v_value)) || ($v_value<0)) {
1436 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1437 return WpaiPclZip::errorCode();
1438 }
1439
1440 // ----- Get the value (and convert it in bytes)
1441 $v_result_list[$p_options_list[$i]] = $v_value*1048576;
1442 $i++;
1443 break;
1444
1445 case WPAI_PCLZIP_OPT_TEMP_FILE_ON:
1446 // ----- Check for incompatible options
1447 if (isset($v_result_list[WPAI_PCLZIP_OPT_TEMP_FILE_OFF])) {
1448 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'WPAI_PCLZIP_OPT_TEMP_FILE_OFF'");
1449 return WpaiPclZip::errorCode();
1450 }
1451
1452 $v_result_list[$p_options_list[$i]] = true;
1453 break;
1454
1455 case WPAI_PCLZIP_OPT_TEMP_FILE_OFF:
1456 // ----- Check for incompatible options
1457 if (isset($v_result_list[WPAI_PCLZIP_OPT_TEMP_FILE_ON])) {
1458 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'WPAI_PCLZIP_OPT_TEMP_FILE_ON'");
1459 return WpaiPclZip::errorCode();
1460 }
1461 // ----- Check for incompatible options
1462 if (isset($v_result_list[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1463 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "' can not be used with option 'WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1464 return WpaiPclZip::errorCode();
1465 }
1466 $v_result_list[$p_options_list[$i]] = true;
1467 break;
1468
1469 case WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION:
1470 // ----- Check the number of parameters
1471 if (($i+1) >= $p_size) {
1472 // ----- Error log
1473 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1474 // ----- Return
1475 return WpaiPclZip::errorCode();
1476 }
1477
1478 // ----- Get the value
1479 if (is_string($p_options_list[$i+1]) && ($p_options_list[$i+1] != '')) {
1480 $v_result_list[$p_options_list[$i]] = WpaiPclZipUtilTranslateWinPath($p_options_list[ $i + 1], false);
1481 $i++;
1482 } else {
1483 }
1484 break;
1485 // ----- Look for options that request an array or string for value
1486 case WPAI_PCLZIP_OPT_BY_NAME:
1487 case WPAI_PCLZIP_OPT_EXTRACT_EXT_RESTRICTIONS:
1488 case WPAI_PCLZIP_OPT_EXTRACT_WHITELIST_RESTRICTIONS:
1489 // ----- Check the number of parameters
1490 if (($i+1) >= $p_size) {
1491 // ----- Error log
1492 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1493 // ----- Return
1494 return WpaiPclZip::errorCode();
1495 }
1496
1497 // ----- Get the value
1498 if (is_string($p_options_list[$i+1])) {
1499 $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1500 } elseif (is_array($p_options_list[$i+1])) {
1501 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1502 } else {
1503 // ----- Error log
1504 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1505 // ----- Return
1506 return WpaiPclZip::errorCode();
1507 }
1508 $i++;
1509 break;
1510 // ----- Look for options that request an EREG or PREG expression
1511 case WPAI_PCLZIP_OPT_BY_EREG:
1512 // ereg() is deprecated starting with PHP 5.3. Move WPAI_PCLZIP_OPT_BY_EREG
1513 // to WPAI_PCLZIP_OPT_BY_PREG
1514 $p_options_list[$i] = WPAI_PCLZIP_OPT_BY_PREG;
1515 case WPAI_PCLZIP_OPT_BY_PREG:
1516 //case WPAI_PCLZIP_OPT_CRYPT :
1517 // ----- Check the number of parameters
1518 if (($i+1) >= $p_size) {
1519 // ----- Error log
1520 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1521 // ----- Return
1522 return WpaiPclZip::errorCode();
1523 }
1524
1525 // ----- Get the value
1526 if (is_string($p_options_list[$i+1])) {
1527 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1528 } else {
1529 // ----- Error log
1530 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1531 // ----- Return
1532 return WpaiPclZip::errorCode();
1533 }
1534 $i++;
1535 break;
1536
1537 // ----- Look for options that takes a string
1538 case WPAI_PCLZIP_OPT_COMMENT:
1539 case WPAI_PCLZIP_OPT_ADD_COMMENT:
1540 case WPAI_PCLZIP_OPT_PREPEND_COMMENT:
1541 // ----- Check the number of parameters
1542 if (($i+1) >= $p_size) {
1543 // ----- Error log
1544 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1545
1546 // ----- Return
1547 return WpaiPclZip::errorCode();
1548 }
1549
1550 // ----- Get the value
1551 if (is_string($p_options_list[$i+1])) {
1552 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1553 } else {
1554 // ----- Error log
1555 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1556
1557 // ----- Return
1558 return WpaiPclZip::errorCode();
1559 }
1560 $i++;
1561 break;
1562
1563 // ----- Look for options that request an array of index
1564 case WPAI_PCLZIP_OPT_BY_INDEX:
1565 // ----- Check the number of parameters
1566 if (($i+1) >= $p_size) {
1567 // ----- Error log
1568 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1569
1570 // ----- Return
1571 return WpaiPclZip::errorCode();
1572 }
1573
1574 // ----- Get the value
1575 $v_work_list = array();
1576 if (is_string($p_options_list[$i+1])) {
1577 // ----- Remove spaces
1578 $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1579
1580 // ----- Parse items
1581 $v_work_list = explode(",", $p_options_list[$i+1]);
1582 } elseif (is_integer($p_options_list[$i+1])) {
1583 $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1584 } elseif (is_array($p_options_list[$i+1])) {
1585 $v_work_list = $p_options_list[$i+1];
1586 } else {
1587 // ----- Error log
1588 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1589
1590 // ----- Return
1591 return WpaiPclZip::errorCode();
1592 }
1593
1594 // ----- Reduce the index list
1595 // each index item in the list must be a couple with a start and
1596 // an end value : [0,3], [5-5], [8-10], ...
1597 // ----- Check the format of each item
1598 $v_sort_flag=false;
1599 $v_sort_value=0;
1600 for ($j=0; $j<sizeof($v_work_list); $j++) {
1601 // ----- Explode the item
1602 $v_item_list = explode("-", $v_work_list[$j]);
1603 $v_size_item_list = sizeof($v_item_list);
1604
1605 // ----- TBC : Here we might check that each item is a
1606 // real integer ...
1607
1608 // ----- Look for single value
1609 if ($v_size_item_list == 1) {
1610 // ----- Set the option value
1611 $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1612 $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1613 } elseif ($v_size_item_list == 2) {
1614 // ----- Set the option value
1615 $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1616 $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1617 } else {
1618 // ----- Error log
1619 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1620
1621 // ----- Return
1622 return WpaiPclZip::errorCode();
1623 }
1624
1625
1626 // ----- Look for list sort
1627 if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1628 $v_sort_flag=true;
1629
1630 // ----- TBC : An automatic sort should be writen ...
1631 // ----- Error log
1632 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1633
1634 // ----- Return
1635 return WpaiPclZip::errorCode();
1636 }
1637 $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1638 }
1639
1640 // ----- Sort the items
1641 if ($v_sort_flag) {
1642 // TBC : To Be Completed
1643 }
1644 // ----- Next option
1645 $i++;
1646 break;
1647 // ----- Look for options that request no value
1648 case WPAI_PCLZIP_OPT_REMOVE_ALL_PATH:
1649 case WPAI_PCLZIP_OPT_EXTRACT_AS_STRING:
1650 case WPAI_PCLZIP_OPT_NO_COMPRESSION:
1651 case WPAI_PCLZIP_OPT_EXTRACT_IN_OUTPUT:
1652 case WPAI_PCLZIP_OPT_REPLACE_NEWER:
1653 case WPAI_PCLZIP_OPT_STOP_ON_ERROR:
1654 $v_result_list[$p_options_list[$i]] = true;
1655 break;
1656 // ----- Look for options that request an octal value
1657 case WPAI_PCLZIP_OPT_SET_CHMOD:
1658 // ----- Check the number of parameters
1659 if (($i+1) >= $p_size) {
1660 // ----- Error log
1661 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1662 // ----- Return
1663 return WpaiPclZip::errorCode();
1664 }
1665 // ----- Get the value
1666 $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1667 $i++;
1668 break;
1669
1670 // ----- Look for options that request a call-back
1671 case WPAI_PCLZIP_CB_PRE_EXTRACT:
1672 case WPAI_PCLZIP_CB_POST_EXTRACT:
1673 case WPAI_PCLZIP_CB_PRE_ADD:
1674 case WPAI_PCLZIP_CB_POST_ADD:
1675 /* for futur use
1676 case WPAI_PCLZIP_CB_PRE_DELETE :
1677 case WPAI_PCLZIP_CB_POST_DELETE :
1678 case WPAI_PCLZIP_CB_PRE_LIST :
1679 case WPAI_PCLZIP_CB_POST_LIST :
1680 */
1681 // ----- Check the number of parameters
1682 if (($i+1) >= $p_size) {
1683 // ----- Error log
1684 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1685 // ----- Return
1686 return WpaiPclZip::errorCode();
1687 }
1688
1689 // ----- Get the value
1690 $v_function_name = $p_options_list[$i+1];
1691
1692 // ----- Check that the value is a valid existing function
1693 if (!function_exists($v_function_name)) {
1694 // ----- Error log
1695 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '" . WpaiPclZipUtilOptionText($p_options_list[$i]) . "'");
1696 // ----- Return
1697 return WpaiPclZip::errorCode();
1698 }
1699
1700 // ----- Set the attribute
1701 $v_result_list[$p_options_list[$i]] = $v_function_name;
1702 $i++;
1703 break;
1704 default:
1705 // ----- Error log
1706 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Unknown parameter '" .$p_options_list[$i]."'");
1707
1708 // ----- Return
1709 return WpaiPclZip::errorCode();
1710 }
1711
1712 // ----- Next options
1713 $i++;
1714 }
1715
1716 // ----- Look for mandatory options
1717 if ($v_requested_options !== false) {
1718 for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1719 // ----- Look for mandatory option
1720 if ($v_requested_options[$key] == 'mandatory') {
1721 // ----- Look if present
1722 if (!isset($v_result_list[$key])) {
1723 // ----- Error log
1724 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter " . WpaiPclZipUtilOptionText($key) . "(" . $key . ")");
1725
1726 // ----- Return
1727 return WpaiPclZip::errorCode();
1728 }
1729 }
1730 }
1731 }
1732
1733 // ----- Look for default values
1734 if (!isset($v_result_list[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1735 }
1736
1737 // ----- Return
1738 return $v_result;
1739 }
1740 // --------------------------------------------------------------------------------
1741
1742 // --------------------------------------------------------------------------------
1743 // Function : privOptionDefaultThreshold()
1744 // Description :
1745 // Parameters :
1746 // Return Values :
1747 // --------------------------------------------------------------------------------
1748 public function privOptionDefaultThreshold(&$p_options)
1749 {
1750 $v_result=1;
1751
1752 if (isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD]) || isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_OFF])) {
1753 return $v_result;
1754 }
1755
1756 // ----- Get 'memory_limit' configuration value
1757 $v_memory_limit = ini_get('memory_limit');
1758 $v_memory_limit = trim($v_memory_limit);
1759 $last = substr($v_memory_limit, -1);
1760 $v_memory_limit = trim($v_memory_limit, $last);
1761 $last = strtolower($last);
1762
1763 if ($last == 'g') {
1764 //$v_memory_limit = $v_memory_limit*1024*1024*1024;
1765 $v_memory_limit = $v_memory_limit*1073741824;
1766 }
1767 if ($last == 'm') {
1768 //$v_memory_limit = $v_memory_limit*1024*1024;
1769 $v_memory_limit = $v_memory_limit*1048576;
1770 }
1771 if ($last == 'k') {
1772 $v_memory_limit = $v_memory_limit*1024;
1773 }
1774
1775 $p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD] = is_numeric($v_memory_limit) ? floor($v_memory_limit*WPAI_PCLZIP_TEMPORARY_FILE_RATIO) : 0;
1776
1777 // ----- Sanity check : No threshold if value lower than 1M
1778 if ($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
1779 unset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
1780 }
1781
1782 // ----- Return
1783 return $v_result;
1784 }
1785 // --------------------------------------------------------------------------------
1786
1787 // --------------------------------------------------------------------------------
1788 // Function : privFileDescrParseAtt()
1789 // Description :
1790 // Parameters :
1791 // Return Values :
1792 // 1 on success.
1793 // 0 on failure.
1794 // --------------------------------------------------------------------------------
1795 public function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options = false)
1796 {
1797 $v_result=1;
1798
1799 // ----- For each file in the list check the attributes
1800 foreach ($p_file_list as $v_key => $v_value) {
1801 // ----- Check if the option is supported
1802 if (!isset($v_requested_options[$v_key])) {
1803 // ----- Error log
1804 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
1805
1806 // ----- Return
1807 return WpaiPclZip::errorCode();
1808 }
1809
1810 // ----- Look for attribute
1811 switch ($v_key) {
1812 case WPAI_PCLZIP_ATT_FILE_NAME:
1813 if (!is_string($v_value)) {
1814 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1815 return WpaiPclZip::errorCode();
1816 }
1817
1818 $p_filedescr['filename'] = WpaiPclZipUtilPathReduction($v_value);
1819
1820 if ($p_filedescr['filename'] == '') {
1821 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1822 return WpaiPclZip::errorCode();
1823 }
1824 break;
1825 case WPAI_PCLZIP_ATT_FILE_NEW_SHORT_NAME:
1826 if (!is_string($v_value)) {
1827 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1828 return WpaiPclZip::errorCode();
1829 }
1830
1831 $p_filedescr['new_short_name'] = WpaiPclZipUtilPathReduction($v_value);
1832
1833 if ($p_filedescr['new_short_name'] == '') {
1834 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1835 return WpaiPclZip::errorCode();
1836 }
1837 break;
1838 case WPAI_PCLZIP_ATT_FILE_NEW_FULL_NAME:
1839 if (!is_string($v_value)) {
1840 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1841 return WpaiPclZip::errorCode();
1842 }
1843
1844 $p_filedescr['new_full_name'] = WpaiPclZipUtilPathReduction($v_value);
1845
1846 if ($p_filedescr['new_full_name'] == '') {
1847 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1848 return WpaiPclZip::errorCode();
1849 }
1850 break;
1851 // ----- Look for options that takes a string
1852 case WPAI_PCLZIP_ATT_FILE_COMMENT:
1853 if (!is_string($v_value)) {
1854 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1855 return WpaiPclZip::errorCode();
1856 }
1857 $p_filedescr['comment'] = $v_value;
1858 break;
1859 case WPAI_PCLZIP_ATT_FILE_MTIME:
1860 if (!is_integer($v_value)) {
1861 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '" . WpaiPclZipUtilOptionText($v_key) . "'");
1862 return WpaiPclZip::errorCode();
1863 }
1864 $p_filedescr['mtime'] = $v_value;
1865 break;
1866 case WPAI_PCLZIP_ATT_FILE_CONTENT:
1867 $p_filedescr['content'] = $v_value;
1868 break;
1869 default:
1870 // ----- Error log
1871 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Unknown parameter '".$v_key."'");
1872
1873 // ----- Return
1874 return WpaiPclZip::errorCode();
1875 }
1876
1877 // ----- Look for mandatory options
1878 if ($v_requested_options !== false) {
1879 for ($key = reset($v_requested_options); $key = key($v_requested_options); $key = next($v_requested_options)) {
1880 // ----- Look for mandatory option
1881 if ($v_requested_options[$key] == 'mandatory') {
1882 // ----- Look if present
1883 if (!isset($p_file_list[$key])) {
1884 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter " . WpaiPclZipUtilOptionText($key) . "(" . $key . ")");
1885 return WpaiPclZip::errorCode();
1886 }
1887 }
1888 }
1889 }
1890 }
1891
1892 // ----- Return
1893 return $v_result;
1894 }
1895 // --------------------------------------------------------------------------------
1896
1897 // --------------------------------------------------------------------------------
1898 // Function : privFileDescrExpand()
1899 // Description :
1900 // This method look for each item of the list to see if its a file, a folder
1901 // or a string to be added as file. For any other type of files (link, other)
1902 // just ignore the item.
1903 // Then prepare the information that will be stored for that file.
1904 // When its a folder, expand the folder with all the files that are in that
1905 // folder (recursively).
1906 // Parameters :
1907 // Return Values :
1908 // 1 on success.
1909 // 0 on failure.
1910 // --------------------------------------------------------------------------------
1911 public function privFileDescrExpand(&$p_filedescr_list, &$p_options)
1912 {
1913 $v_result=1;
1914
1915 // ----- Create a result list
1916 $v_result_list = array();
1917
1918 // ----- Look each entry
1919 for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
1920 // ----- Get filedescr
1921 $v_descr = $p_filedescr_list[$i];
1922
1923 // ----- Reduce the filename
1924 $v_descr['filename'] = WpaiPclZipUtilTranslateWinPath($v_descr['filename'], false);
1925 $v_descr['filename'] = WpaiPclZipUtilPathReduction($v_descr['filename']);
1926
1927 // ----- Look for real file or folder
1928 if (file_exists($v_descr['filename'])) {
1929 if (@is_file($v_descr['filename'])) {
1930 $v_descr['type'] = 'file';
1931 } elseif (@is_dir($v_descr['filename'])) {
1932 $v_descr['type'] = 'folder';
1933 } elseif (@is_link($v_descr['filename'])) {
1934 // skip
1935 continue;
1936 } else {
1937 // skip
1938 continue;
1939 }
1940 } elseif (isset($v_descr['content'])) {
1941 // ----- Look for string added as file
1942 $v_descr['type'] = 'virtual_file';
1943 } else {
1944 // ----- Missing file
1945 // ----- Error log
1946 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
1947
1948 // ----- Return
1949 return WpaiPclZip::errorCode();
1950 }
1951
1952 // ----- Calculate the stored filename
1953 $this->privCalculateStoredFilename($v_descr, $p_options);
1954
1955 // ----- Add the descriptor in result list
1956 $v_result_list[sizeof($v_result_list)] = $v_descr;
1957
1958 // ----- Look for folder
1959 if ($v_descr['type'] == 'folder') {
1960 // ----- List of items in folder
1961 $v_dirlist_descr = array();
1962 $v_dirlist_nb = 0;
1963 if ($v_folder_handler = @opendir($v_descr['filename'])) {
1964 while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
1965 // ----- Skip '.' and '..'
1966 if (($v_item_handler == '.') || ($v_item_handler == '..')) {
1967 continue;
1968 }
1969
1970 // ----- Compose the full filename
1971 $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
1972
1973 // ----- Look for different stored filename
1974 // Because the name of the folder was changed, the name of the
1975 // files/sub-folders also change
1976 if (($v_descr['stored_filename'] != $v_descr['filename'])
1977 && (!isset($p_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH]))) {
1978 if ($v_descr['stored_filename'] != '') {
1979 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
1980 } else {
1981 $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
1982 }
1983 }
1984 $v_dirlist_nb++;
1985 }
1986
1987 @closedir($v_folder_handler);
1988 } else {
1989 // TBC : unable to open folder in read mode
1990 }
1991
1992 // ----- Expand each element of the list
1993 if ($v_dirlist_nb != 0) {
1994 // ----- Expand
1995 if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
1996 return $v_result;
1997 }
1998
1999 // ----- Concat the resulting list
2000 $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
2001 }
2002
2003 // ----- Free local array
2004 unset($v_dirlist_descr);
2005 }
2006 }
2007
2008 // ----- Get the result list
2009 $p_filedescr_list = $v_result_list;
2010
2011 // ----- Return
2012 return $v_result;
2013 }
2014 // --------------------------------------------------------------------------------
2015
2016 // --------------------------------------------------------------------------------
2017 // Function : privCreate()
2018 // Description :
2019 // Parameters :
2020 // Return Values :
2021 // --------------------------------------------------------------------------------
2022 public function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
2023 {
2024 $v_result=1;
2025 $v_list_detail = array();
2026
2027 // ----- Magic quotes trick
2028 $this->privDisableMagicQuotes();
2029
2030 // ----- Open the file in write mode
2031 if (($v_result = $this->privOpenFd('wb')) != 1) {
2032 // ----- Return
2033 return $v_result;
2034 }
2035
2036 // ----- Add the list of files
2037 $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2038
2039 // ----- Close
2040 $this->privCloseFd();
2041
2042 // ----- Magic quotes trick
2043 $this->privSwapBackMagicQuotes();
2044
2045 // ----- Return
2046 return $v_result;
2047 }
2048 // --------------------------------------------------------------------------------
2049
2050 // --------------------------------------------------------------------------------
2051 // Function : privAdd()
2052 // Description :
2053 // Parameters :
2054 // Return Values :
2055 // --------------------------------------------------------------------------------
2056 public function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2057 {
2058 $v_result=1;
2059 $v_list_detail = array();
2060
2061 // ----- Look if the archive exists or is empty
2062 if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) {
2063 // ----- Do a create
2064 $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2065
2066 // ----- Return
2067 return $v_result;
2068 }
2069 // ----- Magic quotes trick
2070 $this->privDisableMagicQuotes();
2071
2072 // ----- Open the zip file
2073 if (($v_result=$this->privOpenFd('rb')) != 1) {
2074 // ----- Magic quotes trick
2075 $this->privSwapBackMagicQuotes();
2076
2077 // ----- Return
2078 return $v_result;
2079 }
2080
2081 // ----- Read the central directory informations
2082 $v_central_dir = array();
2083 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
2084 $this->privCloseFd();
2085 $this->privSwapBackMagicQuotes();
2086 return $v_result;
2087 }
2088
2089 // ----- Go to beginning of File
2090 @rewind($this->zip_fd);
2091
2092 // ----- Creates a temporay file
2093 $v_zip_temp_name = WPAI_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2094
2095 // ----- Open the temporary file in write mode
2096 if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
2097 $this->privCloseFd();
2098 $this->privSwapBackMagicQuotes();
2099
2100 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2101
2102 // ----- Return
2103 return WpaiPclZip::errorCode();
2104 }
2105
2106 // ----- Copy the files from the archive to the temporary file
2107 // TBC : Here I should better append the file and go back to erase the central dir
2108 $v_size = $v_central_dir['offset'];
2109 while ($v_size != 0) {
2110 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
2111 $v_buffer = fread($this->zip_fd, $v_read_size);
2112 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2113 $v_size -= $v_read_size;
2114 }
2115
2116 // ----- Swap the file descriptor
2117 // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2118 // the following methods on the temporary fil and not the real archive
2119 $v_swap = $this->zip_fd;
2120 $this->zip_fd = $v_zip_temp_fd;
2121 $v_zip_temp_fd = $v_swap;
2122
2123 // ----- Add the files
2124 $v_header_list = array();
2125 if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
2126 fclose($v_zip_temp_fd);
2127 $this->privCloseFd();
2128 @unlink($v_zip_temp_name);
2129 $this->privSwapBackMagicQuotes();
2130
2131 // ----- Return
2132 return $v_result;
2133 }
2134
2135 // ----- Store the offset of the central dir
2136 $v_offset = @ftell($this->zip_fd);
2137
2138 // ----- Copy the block of file headers from the old archive
2139 $v_size = $v_central_dir['size'];
2140 while ($v_size != 0) {
2141 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
2142 $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2143 @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2144 $v_size -= $v_read_size;
2145 }
2146
2147 // ----- Create the Central Dir files header
2148 for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) {
2149 // ----- Create the file header
2150 if ($v_header_list[$i]['status'] == 'ok') {
2151 if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2152 fclose($v_zip_temp_fd);
2153 $this->privCloseFd();
2154 @unlink($v_zip_temp_name);
2155 $this->privSwapBackMagicQuotes();
2156
2157 // ----- Return
2158 return $v_result;
2159 }
2160 $v_count++;
2161 }
2162
2163 // ----- Transform the header to a 'usable' info
2164 $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2165 }
2166
2167 // ----- Zip file comment
2168 $v_comment = $v_central_dir['comment'];
2169 if (isset($p_options[WPAI_PCLZIP_OPT_COMMENT])) {
2170 $v_comment = $p_options[WPAI_PCLZIP_OPT_COMMENT];
2171 }
2172 if (isset($p_options[WPAI_PCLZIP_OPT_ADD_COMMENT])) {
2173 $v_comment = $v_comment.$p_options[WPAI_PCLZIP_OPT_ADD_COMMENT];
2174 }
2175 if (isset($p_options[WPAI_PCLZIP_OPT_PREPEND_COMMENT])) {
2176 $v_comment = $p_options[WPAI_PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2177 }
2178
2179 // ----- Calculate the size of the central header
2180 $v_size = @ftell($this->zip_fd)-$v_offset;
2181
2182 // ----- Create the central dir footer
2183 if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) {
2184 // ----- Reset the file list
2185 unset($v_header_list);
2186 $this->privSwapBackMagicQuotes();
2187
2188 // ----- Return
2189 return $v_result;
2190 }
2191
2192 // ----- Swap back the file descriptor
2193 $v_swap = $this->zip_fd;
2194 $this->zip_fd = $v_zip_temp_fd;
2195 $v_zip_temp_fd = $v_swap;
2196
2197 // ----- Close
2198 $this->privCloseFd();
2199
2200 // ----- Close the temporary file
2201 @fclose($v_zip_temp_fd);
2202
2203 // ----- Magic quotes trick
2204 $this->privSwapBackMagicQuotes();
2205
2206 // ----- Delete the zip file
2207 // TBC : I should test the result ...
2208 @unlink($this->zipname);
2209
2210 // ----- Rename the temporary file
2211 // TBC : I should test the result ...
2212 //@rename($v_zip_temp_name, $this->zipname);
2213 WpaiPclZipUtilRename($v_zip_temp_name, $this->zipname);
2214
2215 // ----- Return
2216 return $v_result;
2217 }
2218 // --------------------------------------------------------------------------------
2219
2220 // --------------------------------------------------------------------------------
2221 // Function : privOpenFd()
2222 // Description :
2223 // Parameters :
2224 // --------------------------------------------------------------------------------
2225 public function privOpenFd($p_mode)
2226 {
2227 $v_result=1;
2228
2229 // ----- Look if already open
2230 if ($this->zip_fd != 0) {
2231 // ----- Error log
2232 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2233
2234 // ----- Return
2235 return WpaiPclZip::errorCode();
2236 }
2237
2238 // ----- Open the zip file
2239 if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) {
2240 // ----- Error log
2241 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2242
2243 // ----- Return
2244 return WpaiPclZip::errorCode();
2245 }
2246
2247 // ----- Return
2248 return $v_result;
2249 }
2250 // --------------------------------------------------------------------------------
2251
2252 // --------------------------------------------------------------------------------
2253 // Function : privCloseFd()
2254 // Description :
2255 // Parameters :
2256 // --------------------------------------------------------------------------------
2257 public function privCloseFd()
2258 {
2259 $v_result=1;
2260
2261 if ($this->zip_fd != 0) {
2262 @fclose($this->zip_fd);
2263 }
2264 $this->zip_fd = 0;
2265
2266 // ----- Return
2267 return $v_result;
2268 }
2269 // --------------------------------------------------------------------------------
2270
2271 // --------------------------------------------------------------------------------
2272 // Function : privAddList()
2273 // Description :
2274 // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2275 // different from the real path of the file. This is usefull if you want to have PclTar
2276 // running in any directory, and memorize relative path from an other directory.
2277 // Parameters :
2278 // $p_list : An array containing the file or directory names to add in the tar
2279 // $p_result_list : list of added files with their properties (specially the status field)
2280 // $p_add_dir : Path to add in the filename path archived
2281 // $p_remove_dir : Path to remove in the filename path archived
2282 // Return Values :
2283 // --------------------------------------------------------------------------------
2284 // public function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2285 public function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2286 {
2287 $v_result=1;
2288
2289 // ----- Add the files
2290 $v_header_list = array();
2291 if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) {
2292 // ----- Return
2293 return $v_result;
2294 }
2295
2296 // ----- Store the offset of the central dir
2297 $v_offset = @ftell($this->zip_fd);
2298
2299 // ----- Create the Central Dir files header
2300 for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) {
2301 // ----- Create the file header
2302 if ($v_header_list[$i]['status'] == 'ok') {
2303 if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2304 // ----- Return
2305 return $v_result;
2306 }
2307 $v_count++;
2308 }
2309
2310 // ----- Transform the header to a 'usable' info
2311 $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2312 }
2313
2314 // ----- Zip file comment
2315 $v_comment = '';
2316 if (isset($p_options[WPAI_PCLZIP_OPT_COMMENT])) {
2317 $v_comment = $p_options[WPAI_PCLZIP_OPT_COMMENT];
2318 }
2319
2320 // ----- Calculate the size of the central header
2321 $v_size = @ftell($this->zip_fd)-$v_offset;
2322
2323 // ----- Create the central dir footer
2324 if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) {
2325 // ----- Reset the file list
2326 unset($v_header_list);
2327
2328 // ----- Return
2329 return $v_result;
2330 }
2331
2332 // ----- Return
2333 return $v_result;
2334 }
2335 // --------------------------------------------------------------------------------
2336
2337 // --------------------------------------------------------------------------------
2338 // Function : privAddFileList()
2339 // Description :
2340 // Parameters :
2341 // $p_filedescr_list : An array containing the file description
2342 // or directory names to add in the zip
2343 // $p_result_list : list of added files with their properties (specially the status field)
2344 // Return Values :
2345 // --------------------------------------------------------------------------------
2346 public function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2347 {
2348 $v_result=1;
2349 $v_header = array();
2350
2351 // ----- Recuperate the current number of elt in list
2352 $v_nb = sizeof($p_result_list);
2353
2354 // ----- Loop on the files
2355 for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2356 // ----- Format the filename
2357 $p_filedescr_list[$j]['filename'] = WpaiPclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2358
2359 // ----- Skip empty file names
2360 // TBC : Can this be possible ? not checked in DescrParseAtt ?
2361 if ($p_filedescr_list[$j]['filename'] == "") {
2362 continue;
2363 }
2364
2365 // ----- Check the filename
2366 if (($p_filedescr_list[$j]['type'] != 'virtual_file') && (!file_exists($p_filedescr_list[$j]['filename']))) {
2367 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2368 return WpaiPclZip::errorCode();
2369 }
2370
2371 // ----- Look if it is a file or a dir with no all path remove option
2372 // or a dir with all its path removed
2373 // if ( (is_file($p_filedescr_list[$j]['filename']))
2374 // || ( is_dir($p_filedescr_list[$j]['filename'])
2375 if (($p_filedescr_list[$j]['type'] == 'file') || ($p_filedescr_list[$j]['type'] == 'virtual_file') || (($p_filedescr_list[$j]['type'] == 'folder') && (!isset($p_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH]) || !$p_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH]))) {
2376 // ----- Add the file
2377 $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header, $p_options);
2378 if ($v_result != 1) {
2379 return $v_result;
2380 }
2381
2382 // ----- Store the file infos
2383 $p_result_list[$v_nb++] = $v_header;
2384 }
2385 }
2386
2387 // ----- Return
2388 return $v_result;
2389 }
2390 // --------------------------------------------------------------------------------
2391
2392 // --------------------------------------------------------------------------------
2393 // Function : privAddFile()
2394 // Description :
2395 // Parameters :
2396 // Return Values :
2397 // --------------------------------------------------------------------------------
2398 public function privAddFile($p_filedescr, &$p_header, &$p_options)
2399 {
2400 $v_result=1;
2401
2402 // ----- Working variable
2403 $p_filename = $p_filedescr['filename'];
2404
2405 // TBC : Already done in the fileAtt check ... ?
2406 if ($p_filename == "") {
2407 // ----- Error log
2408 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2409
2410 // ----- Return
2411 return WpaiPclZip::errorCode();
2412 }
2413
2414 // ----- Look for a stored different filename
2415 /* TBC : Removed
2416 if (isset($p_filedescr['stored_filename'])) {
2417 $v_stored_filename = $p_filedescr['stored_filename'];
2418 }
2419 else {
2420 $v_stored_filename = $p_filedescr['stored_filename'];
2421 }
2422 */
2423
2424 // ----- Set the file properties
2425 clearstatcache();
2426 $p_header['version'] = 20;
2427 $p_header['version_extracted'] = 10;
2428 $p_header['flag'] = 0;
2429 $p_header['compression'] = 0;
2430 $p_header['crc'] = 0;
2431 $p_header['compressed_size'] = 0;
2432 $p_header['filename_len'] = strlen($p_filename);
2433 $p_header['extra_len'] = 0;
2434 $p_header['disk'] = 0;
2435 $p_header['internal'] = 0;
2436 $p_header['offset'] = 0;
2437 $p_header['filename'] = $p_filename;
2438 // TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
2439 $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2440 $p_header['extra'] = '';
2441 $p_header['status'] = 'ok';
2442 $p_header['index'] = -1;
2443
2444 // ----- Look for regular file
2445 if ($p_filedescr['type']=='file') {
2446 $p_header['external'] = 0x00000000;
2447 $p_header['size'] = filesize($p_filename);
2448 } elseif ($p_filedescr['type']=='folder') {
2449 // ----- Look for regular folder
2450 $p_header['external'] = 0x00000010;
2451 $p_header['mtime'] = filemtime($p_filename);
2452 $p_header['size'] = filesize($p_filename);
2453 } elseif ($p_filedescr['type'] == 'virtual_file') {
2454 // ----- Look for virtual file
2455 $p_header['external'] = 0x00000000;
2456 $p_header['size'] = strlen($p_filedescr['content']);
2457 }
2458
2459 // ----- Look for filetime
2460 if (isset($p_filedescr['mtime'])) {
2461 $p_header['mtime'] = $p_filedescr['mtime'];
2462 } elseif ($p_filedescr['type'] == 'virtual_file') {
2463 $p_header['mtime'] = time();
2464 } else {
2465 $p_header['mtime'] = filemtime($p_filename);
2466 }
2467
2468 // ------ Look for file comment
2469 if (isset($p_filedescr['comment'])) {
2470 $p_header['comment_len'] = strlen($p_filedescr['comment']);
2471 $p_header['comment'] = $p_filedescr['comment'];
2472 } else {
2473 $p_header['comment_len'] = 0;
2474 $p_header['comment'] = '';
2475 }
2476
2477 // ----- Look for pre-add callback
2478 if (isset($p_options[WPAI_PCLZIP_CB_PRE_ADD])) {
2479 // ----- Generate a local information
2480 $v_local_header = array();
2481 $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2482
2483 // ----- Call the callback
2484 // Here I do not use call_user_func() because I need to send a reference to the
2485 // header.
2486 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_PRE_ADD].'(WPAI_PCLZIP_CB_PRE_ADD, $v_local_header);');
2487 $v_result = $p_options[WPAI_PCLZIP_CB_PRE_ADD](WPAI_PCLZIP_CB_PRE_ADD, $v_local_header);
2488 if ($v_result == 0) {
2489 // ----- Change the file status
2490 $p_header['status'] = "skipped";
2491 $v_result = 1;
2492 }
2493
2494 // ----- Update the informations
2495 // Only some fields can be modified
2496 if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2497 $p_header['stored_filename'] = WpaiPclZipUtilPathReduction($v_local_header['stored_filename']);
2498 }
2499 }
2500
2501 // ----- Look for empty stored filename
2502 if ($p_header['stored_filename'] == "") {
2503 $p_header['status'] = "filtered";
2504 }
2505
2506 // ----- Check the path length
2507 if (strlen($p_header['stored_filename']) > 0xFF) {
2508 $p_header['status'] = 'filename_too_long';
2509 }
2510
2511 // ----- Look if no error, or file not skipped
2512 if ($p_header['status'] == 'ok') {
2513 // ----- Look for a file
2514 if ($p_filedescr['type'] == 'file') {
2515 // ----- Look for using temporary file to zip
2516 if ((!isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_OFF])) && (isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_ON]) || (isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD]) && ($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])))) {
2517 $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
2518 if ($v_result < WPAI_PCLZIP_ERR_NO_ERROR) {
2519 return $v_result;
2520 }
2521 } else {
2522 // ----- Use "in memory" zip algo
2523 // ----- Open the source file
2524 if (($v_file = @fopen($p_filename, "rb")) == 0) {
2525 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2526 return WpaiPclZip::errorCode();
2527 }
2528
2529 // ----- Read the file content
2530 $v_content = @fread($v_file, $p_header['size']);
2531
2532 // ----- Close the file
2533 @fclose($v_file);
2534
2535 // ----- Calculate the CRC
2536 $p_header['crc'] = @crc32($v_content);
2537
2538 // ----- Look for no compression
2539 if ($p_options[WPAI_PCLZIP_OPT_NO_COMPRESSION]) {
2540 // ----- Set header parameters
2541 $p_header['compressed_size'] = $p_header['size'];
2542 $p_header['compression'] = 0;
2543 } else {
2544 // ----- Look for normal compression
2545 // ----- Compress the content
2546 $v_content = @gzdeflate($v_content);
2547
2548 // ----- Set header parameters
2549 $p_header['compressed_size'] = strlen($v_content);
2550 $p_header['compression'] = 8;
2551 }
2552
2553 // ----- Call the header generation
2554 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2555 @fclose($v_file);
2556 return $v_result;
2557 }
2558
2559 // ----- Write the compressed (or not) content
2560 @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2561 }
2562 } elseif ($p_filedescr['type'] == 'virtual_file') {
2563 // ----- Look for a virtual file (a file from string)
2564 $v_content = $p_filedescr['content'];
2565
2566 // ----- Calculate the CRC
2567 $p_header['crc'] = @crc32($v_content);
2568
2569 // ----- Look for no compression
2570 if ($p_options[WPAI_PCLZIP_OPT_NO_COMPRESSION]) {
2571 // ----- Set header parameters
2572 $p_header['compressed_size'] = $p_header['size'];
2573 $p_header['compression'] = 0;
2574 } else {
2575 // ----- Look for normal compression
2576 // ----- Compress the content
2577 $v_content = @gzdeflate($v_content);
2578
2579 // ----- Set header parameters
2580 $p_header['compressed_size'] = strlen($v_content);
2581 $p_header['compression'] = 8;
2582 }
2583
2584 // ----- Call the header generation
2585 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2586 @fclose($v_file);
2587 return $v_result;
2588 }
2589
2590 // ----- Write the compressed (or not) content
2591 @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2592 } elseif ($p_filedescr['type'] == 'folder') {
2593 // ----- Look for a directory
2594 // ----- Look for directory last '/'
2595 if (@substr($p_header['stored_filename'], -1) != '/') {
2596 $p_header['stored_filename'] .= '/';
2597 }
2598
2599 // ----- Set the file properties
2600 $p_header['size'] = 0;
2601 //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
2602 $p_header['external'] = 0x00000010; // Value for a folder : to be checked
2603
2604 // ----- Call the header generation
2605 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2606 return $v_result;
2607 }
2608 }
2609 }
2610
2611 // ----- Look for post-add callback
2612 if (isset($p_options[WPAI_PCLZIP_CB_POST_ADD])) {
2613 // ----- Generate a local information
2614 $v_local_header = array();
2615 $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2616
2617 // ----- Call the callback
2618 // Here I do not use call_user_func() because I need to send a reference to the
2619 // header.
2620 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_POST_ADD].'(WPAI_PCLZIP_CB_POST_ADD, $v_local_header);');
2621 $v_result = $p_options[WPAI_PCLZIP_CB_POST_ADD](WPAI_PCLZIP_CB_POST_ADD, $v_local_header);
2622 if ($v_result == 0) {
2623 // ----- Ignored
2624 $v_result = 1;
2625 }
2626
2627 // ----- Update the informations
2628 // Nothing can be modified
2629 }
2630
2631 // ----- Return
2632 return $v_result;
2633 }
2634 // --------------------------------------------------------------------------------
2635
2636 // --------------------------------------------------------------------------------
2637 // Function : privAddFileUsingTempFile()
2638 // Description :
2639 // Parameters :
2640 // Return Values :
2641 // --------------------------------------------------------------------------------
2642 public function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
2643 {
2644 $v_result=WPAI_PCLZIP_ERR_NO_ERROR;
2645
2646 // ----- Working variable
2647 $p_filename = $p_filedescr['filename'];
2648
2649
2650 // ----- Open the source file
2651 if (($v_file = @fopen($p_filename, "rb")) == 0) {
2652 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2653 return WpaiPclZip::errorCode();
2654 }
2655
2656 // ----- Creates a compressed temporary file
2657 $v_gzip_temp_name = WPAI_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
2658 if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
2659 fclose($v_file);
2660 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
2661 return WpaiPclZip::errorCode();
2662 }
2663
2664 // ----- Read the file by WPAI_PCLZIP_READ_BLOCK_SIZE octets blocks
2665 $v_size = filesize($p_filename);
2666 while ($v_size != 0) {
2667 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
2668 $v_buffer = @fread($v_file, $v_read_size);
2669 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2670 @gzputs($v_file_compressed, $v_buffer, $v_read_size);
2671 $v_size -= $v_read_size;
2672 }
2673
2674 // ----- Close the file
2675 @fclose($v_file);
2676 @gzclose($v_file_compressed);
2677
2678 // ----- Check the minimum file size
2679 if (filesize($v_gzip_temp_name) < 18) {
2680 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
2681 return WpaiPclZip::errorCode();
2682 }
2683
2684 // ----- Extract the compressed attributes
2685 if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2686 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2687 return WpaiPclZip::errorCode();
2688 }
2689
2690 // ----- Read the gzip file header
2691 $v_binary_data = @fread($v_file_compressed, 10);
2692 $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
2693
2694 // ----- Check some parameters
2695 $v_data_header['os'] = bin2hex($v_data_header['os']);
2696
2697 // ----- Read the gzip file footer
2698 @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
2699 $v_binary_data = @fread($v_file_compressed, 8);
2700 $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
2701
2702 // ----- Set the attributes
2703 $p_header['compression'] = ord($v_data_header['cm']);
2704 //$p_header['mtime'] = $v_data_header['mtime'];
2705 $p_header['crc'] = $v_data_footer['crc'];
2706 $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
2707
2708 // ----- Close the file
2709 @fclose($v_file_compressed);
2710
2711 // ----- Call the header generation
2712 if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2713 return $v_result;
2714 }
2715
2716 // ----- Add the compressed data
2717 if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2718 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2719 return WpaiPclZip::errorCode();
2720 }
2721
2722 // ----- Read the file by WPAI_PCLZIP_READ_BLOCK_SIZE octets blocks
2723 fseek($v_file_compressed, 10);
2724 $v_size = $p_header['compressed_size'];
2725 while ($v_size != 0) {
2726 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
2727 $v_buffer = @fread($v_file_compressed, $v_read_size);
2728 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2729 @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2730 $v_size -= $v_read_size;
2731 }
2732
2733 // ----- Close the file
2734 @fclose($v_file_compressed);
2735
2736 // ----- Unlink the temporary file
2737 @unlink($v_gzip_temp_name);
2738
2739 // ----- Return
2740 return $v_result;
2741 }
2742 // --------------------------------------------------------------------------------
2743
2744 // --------------------------------------------------------------------------------
2745 // Function : privCalculateStoredFilename()
2746 // Description :
2747 // Based on file descriptor properties and global options, this method
2748 // calculate the filename that will be stored in the archive.
2749 // Parameters :
2750 // Return Values :
2751 // --------------------------------------------------------------------------------
2752 public function privCalculateStoredFilename(&$p_filedescr, &$p_options)
2753 {
2754 $v_result=1;
2755
2756 // ----- Working variables
2757 $p_filename = $p_filedescr['filename'];
2758 if (isset($p_options[WPAI_PCLZIP_OPT_ADD_PATH])) {
2759 $p_add_dir = $p_options[WPAI_PCLZIP_OPT_ADD_PATH];
2760 } else {
2761 $p_add_dir = '';
2762 }
2763 if (isset($p_options[WPAI_PCLZIP_OPT_REMOVE_PATH])) {
2764 $p_remove_dir = $p_options[WPAI_PCLZIP_OPT_REMOVE_PATH];
2765 } else {
2766 $p_remove_dir = '';
2767 }
2768 if (isset($p_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH])) {
2769 $p_remove_all_dir = $p_options[WPAI_PCLZIP_OPT_REMOVE_ALL_PATH];
2770 } else {
2771 $p_remove_all_dir = 0;
2772 }
2773
2774 // ----- Look for full name change
2775 if (isset($p_filedescr['new_full_name'])) {
2776 // ----- Remove drive letter if any
2777 $v_stored_filename = WpaiPclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
2778 } else {
2779 // ----- Look for path and/or short name change
2780 // ----- Look for short name change
2781 // Its when we cahnge just the filename but not the path
2782 if (isset($p_filedescr['new_short_name'])) {
2783 $v_path_info = pathinfo($p_filename);
2784 $v_dir = '';
2785 if ($v_path_info['dirname'] != '') {
2786 $v_dir = $v_path_info['dirname'].'/';
2787 }
2788 $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2789 } else {
2790 // ----- Calculate the stored filename
2791 $v_stored_filename = $p_filename;
2792 }
2793
2794 // ----- Look for all path to remove
2795 if ($p_remove_all_dir) {
2796 $v_stored_filename = basename($p_filename);
2797 } elseif ($p_remove_dir != "") {
2798 // ----- Look for partial path remove
2799 if (substr($p_remove_dir, -1) != '/') {
2800 $p_remove_dir .= "/";
2801 }
2802
2803 if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./")) {
2804 if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./")) {
2805 $p_remove_dir = "./".$p_remove_dir;
2806 }
2807 if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./")) {
2808 $p_remove_dir = substr($p_remove_dir, 2);
2809 }
2810 }
2811
2812 $v_compare = WpaiPclZipUtilPathInclusion($p_remove_dir, $v_stored_filename);
2813 if ($v_compare > 0) {
2814 if ($v_compare == 2) {
2815 $v_stored_filename = "";
2816 } else {
2817 $v_stored_filename = substr($v_stored_filename, strlen($p_remove_dir));
2818 }
2819 }
2820 }
2821
2822 // ----- Remove drive letter if any
2823 $v_stored_filename = WpaiPclZipUtilTranslateWinPath($v_stored_filename);
2824
2825 // ----- Look for path to add
2826 if ($p_add_dir != "") {
2827 if (substr($p_add_dir, -1) == "/") {
2828 $v_stored_filename = $p_add_dir.$v_stored_filename;
2829 } else {
2830 $v_stored_filename = $p_add_dir."/".$v_stored_filename;
2831 }
2832 }
2833 }
2834
2835 // ----- Filename (reduce the path of stored name)
2836 $v_stored_filename = WpaiPclZipUtilPathReduction($v_stored_filename);
2837 $p_filedescr['stored_filename'] = $v_stored_filename;
2838
2839 // ----- Return
2840 return $v_result;
2841 }
2842 // --------------------------------------------------------------------------------
2843
2844 // --------------------------------------------------------------------------------
2845 // Function : privWriteFileHeader()
2846 // Description :
2847 // Parameters :
2848 // Return Values :
2849 // --------------------------------------------------------------------------------
2850 public function privWriteFileHeader(&$p_header)
2851 {
2852 $v_result=1;
2853
2854 // ----- Store the offset position of the file
2855 $p_header['offset'] = ftell($this->zip_fd);
2856
2857 // ----- Transform UNIX mtime to DOS format mdate/mtime
2858 $v_date = getdate($p_header['mtime']);
2859 $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
2860 $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
2861
2862 // ----- Packed data
2863 $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len']);
2864
2865 // ----- Write the first 148 bytes of the header in the archive
2866 fputs($this->zip_fd, $v_binary_data, 30);
2867
2868 // ----- Write the variable fields
2869 if (strlen($p_header['stored_filename']) != 0) {
2870 fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2871 }
2872 if ($p_header['extra_len'] != 0) {
2873 fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2874 }
2875
2876 // ----- Return
2877 return $v_result;
2878 }
2879 // --------------------------------------------------------------------------------
2880
2881 // --------------------------------------------------------------------------------
2882 // Function : privWriteCentralFileHeader()
2883 // Description :
2884 // Parameters :
2885 // Return Values :
2886 // --------------------------------------------------------------------------------
2887 public function privWriteCentralFileHeader(&$p_header)
2888 {
2889 $v_result=1;
2890
2891 // TBC
2892 //for(reset($p_header); $key = key($p_header); next($p_header)) {
2893 //}
2894
2895 // ----- Transform UNIX mtime to DOS format mdate/mtime
2896 $v_date = getdate($p_header['mtime']);
2897 $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
2898 $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
2899
2900
2901 // ----- Packed data
2902 $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'], $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']);
2903
2904 // ----- Write the 42 bytes of the header in the zip file
2905 fputs($this->zip_fd, $v_binary_data, 46);
2906
2907 // ----- Write the variable fields
2908 if (strlen($p_header['stored_filename']) != 0) {
2909 fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
2910 }
2911 if ($p_header['extra_len'] != 0) {
2912 fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
2913 }
2914 if ($p_header['comment_len'] != 0) {
2915 fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
2916 }
2917
2918 // ----- Return
2919 return $v_result;
2920 }
2921 // --------------------------------------------------------------------------------
2922
2923 // --------------------------------------------------------------------------------
2924 // Function : privWriteCentralHeader()
2925 // Description :
2926 // Parameters :
2927 // Return Values :
2928 // --------------------------------------------------------------------------------
2929 public function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
2930 {
2931 $v_result = 1;
2932
2933 // ----- Packed data
2934 $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment));
2935
2936 // ----- Write the 22 bytes of the header in the zip file
2937 fputs($this->zip_fd, $v_binary_data, 22);
2938
2939 // ----- Write the variable fields
2940 if (strlen($p_comment) != 0) {
2941 fputs($this->zip_fd, $p_comment, strlen($p_comment));
2942 }
2943
2944 // ----- Return
2945 return $v_result;
2946 }
2947 // --------------------------------------------------------------------------------
2948
2949 // --------------------------------------------------------------------------------
2950 // Function : privList()
2951 // Description :
2952 // Parameters :
2953 // Return Values :
2954 // --------------------------------------------------------------------------------
2955 public function privList(&$p_list)
2956 {
2957 $v_result = 1;
2958
2959 // ----- Magic quotes trick
2960 $this->privDisableMagicQuotes();
2961
2962 // ----- Open the zip file
2963 if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) {
2964 // ----- Magic quotes trick
2965 $this->privSwapBackMagicQuotes();
2966
2967 // ----- Error log
2968 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
2969
2970 // ----- Return
2971 return WpaiPclZip::errorCode();
2972 }
2973
2974 // ----- Read the central directory informations
2975 $v_central_dir = array();
2976 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
2977 $this->privSwapBackMagicQuotes();
2978 return $v_result;
2979 }
2980
2981 // ----- Go to beginning of Central Dir
2982 @rewind($this->zip_fd);
2983 if (@fseek($this->zip_fd, $v_central_dir['offset'])) {
2984 $this->privSwapBackMagicQuotes();
2985
2986 // ----- Error log
2987 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
2988
2989 // ----- Return
2990 return WpaiPclZip::errorCode();
2991 }
2992
2993 // ----- Read each entry
2994 for ($i=0; $i<$v_central_dir['entries']; $i++) {
2995 // ----- Read the file header
2996 if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) {
2997 $this->privSwapBackMagicQuotes();
2998 return $v_result;
2999 }
3000 $v_header['index'] = $i;
3001
3002 // ----- Get the only interesting attributes
3003 $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
3004 unset($v_header);
3005 }
3006
3007 // ----- Close the zip file
3008 $this->privCloseFd();
3009
3010 // ----- Magic quotes trick
3011 $this->privSwapBackMagicQuotes();
3012
3013 // ----- Return
3014 return $v_result;
3015 }
3016 // --------------------------------------------------------------------------------
3017
3018 // --------------------------------------------------------------------------------
3019 // Function : privConvertHeader2FileInfo()
3020 // Description :
3021 // This function takes the file informations from the central directory
3022 // entries and extract the interesting parameters that will be given back.
3023 // The resulting file infos are set in the array $p_info
3024 // $p_info['filename'] : Filename with full path. Given by user (add),
3025 // extracted in the filesystem (extract).
3026 // $p_info['stored_filename'] : Stored filename in the archive.
3027 // $p_info['size'] = Size of the file.
3028 // $p_info['compressed_size'] = Compressed size of the file.
3029 // $p_info['mtime'] = Last modification date of the file.
3030 // $p_info['comment'] = Comment associated with the file.
3031 // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3032 // $p_info['status'] = status of the action on the file.
3033 // $p_info['crc'] = CRC of the file content.
3034 // Parameters :
3035 // Return Values :
3036 // --------------------------------------------------------------------------------
3037 public function privConvertHeader2FileInfo($p_header, &$p_info)
3038 {
3039 $v_result=1;
3040
3041 // ----- Get the interesting attributes
3042 $v_temp_path = WpaiPclZipUtilPathReduction($p_header['filename']);
3043 $p_info['filename'] = $v_temp_path;
3044 $v_temp_path = WpaiPclZipUtilPathReduction($p_header['stored_filename']);
3045 $p_info['stored_filename'] = $v_temp_path;
3046 $p_info['size'] = $p_header['size'];
3047 $p_info['compressed_size'] = $p_header['compressed_size'];
3048 $p_info['mtime'] = $p_header['mtime'];
3049 $p_info['comment'] = $p_header['comment'];
3050 $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3051 $p_info['index'] = $p_header['index'];
3052 $p_info['status'] = $p_header['status'];
3053 $p_info['crc'] = $p_header['crc'];
3054
3055 // ----- Return
3056 return $v_result;
3057 }
3058 // --------------------------------------------------------------------------------
3059
3060 // --------------------------------------------------------------------------------
3061 // Function : privExtractByRule()
3062 // Description :
3063 // Extract a file or directory depending of rules (by index, by name, ...)
3064 // Parameters :
3065 // $p_file_list : An array where will be placed the properties of each
3066 // extracted file
3067 // $p_path : Path to add while writing the extracted files
3068 // $p_remove_path : Path to remove (from the file memorized path) while writing the
3069 // extracted files. If the path does not match the file path,
3070 // the file is extracted with its memorized path.
3071 // $p_remove_path does not apply to 'list' mode.
3072 // $p_path and $p_remove_path are commulative.
3073 // Return Values :
3074 // 1 on success,0 or less on error (see error code list)
3075 // --------------------------------------------------------------------------------
3076 public function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3077 {
3078 $v_result=1;
3079
3080 // ----- Magic quotes trick
3081 $this->privDisableMagicQuotes();
3082
3083 // ----- Check the path
3084 if (($p_path == "") || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path, 1, 2)!=":/"))) {
3085 $p_path = "./".$p_path;
3086 }
3087
3088 // ----- Reduce the path last (and duplicated) '/'
3089 if (($p_path != "./") && ($p_path != "/")) {
3090 // ----- Look for the path end '/'
3091 while (substr($p_path, -1) == "/") {
3092 $p_path = substr($p_path, 0, strlen($p_path)-1);
3093 }
3094 }
3095
3096 // ----- Look for path to remove format (should end by /)
3097 if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
3098 $p_remove_path .= '/';
3099 }
3100 $p_remove_path_size = strlen($p_remove_path);
3101
3102 // ----- Open the zip file
3103 if (($v_result = $this->privOpenFd('rb')) != 1) {
3104 $this->privSwapBackMagicQuotes();
3105 return $v_result;
3106 }
3107
3108 // ----- Read the central directory informations
3109 $v_central_dir = array();
3110 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
3111 // ----- Close the zip file
3112 $this->privCloseFd();
3113 $this->privSwapBackMagicQuotes();
3114
3115 return $v_result;
3116 }
3117
3118 // ----- Start at beginning of Central Dir
3119 $v_pos_entry = $v_central_dir['offset'];
3120
3121 // ----- Read each entry
3122 $j_start = 0;
3123 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
3124 // ----- Read next Central dir entry
3125 @rewind($this->zip_fd);
3126 if (@fseek($this->zip_fd, $v_pos_entry)) {
3127 // ----- Close the zip file
3128 $this->privCloseFd();
3129 $this->privSwapBackMagicQuotes();
3130
3131 // ----- Error log
3132 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3133
3134 // ----- Return
3135 return WpaiPclZip::errorCode();
3136 }
3137
3138 // ----- Read the file header
3139 $v_header = array();
3140 if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) {
3141 // ----- Close the zip file
3142 $this->privCloseFd();
3143 $this->privSwapBackMagicQuotes();
3144
3145 return $v_result;
3146 }
3147
3148 // ----- Convert filename to absolute path
3149 $v_header['filename'] = $v_header['stored_filename'] = WpaiPclZipGetAbsPath($v_header['stored_filename']);
3150
3151 // ----- Store the index
3152 $v_header['index'] = $i;
3153
3154 // ----- Store the file position
3155 $v_pos_entry = ftell($this->zip_fd);
3156
3157 // ----- Look for the specific extract rules
3158 $v_extract = false;
3159
3160 // ----- Look for extract by name rule
3161 if ((isset($p_options[WPAI_PCLZIP_OPT_BY_NAME])) && ($p_options[WPAI_PCLZIP_OPT_BY_NAME] != 0)) {
3162 // ----- Look if the filename is in the list
3163 for ($j=0; ($j<sizeof($p_options[WPAI_PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
3164 // ----- Look for a directory
3165 if (substr($p_options[WPAI_PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
3166 // ----- Look if the directory is in the filename path
3167 if ((strlen($v_header['stored_filename']) > strlen($p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) && (substr($v_header['stored_filename'], 0, strlen($p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) == $p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) {
3168 $v_extract = true;
3169 }
3170 } elseif ($v_header['stored_filename'] == $p_options[WPAI_PCLZIP_OPT_BY_NAME][$j]) {
3171 // ----- Look for a filename
3172 $v_extract = true;
3173 }
3174 }
3175 } elseif ((isset($p_options[WPAI_PCLZIP_OPT_BY_PREG])) && ($p_options[WPAI_PCLZIP_OPT_BY_PREG] != "")) {
3176 // ----- Look for extract by preg rule
3177 if (preg_match($p_options[WPAI_PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
3178 $v_extract = true;
3179 }
3180 } elseif ((isset($p_options[WPAI_PCLZIP_OPT_BY_INDEX])) && ($p_options[WPAI_PCLZIP_OPT_BY_INDEX] != 0)) {
3181 // ----- Look for extract by index rule
3182 // ----- Look if the index is in the list
3183 for ($j=$j_start; ($j<sizeof($p_options[WPAI_PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
3184 if (($i>=$p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['end'])) {
3185 $v_extract = true;
3186 }
3187 if ($i>=$p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['end']) {
3188 $j_start = $j+1;
3189 }
3190
3191 if ($p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
3192 break;
3193 }
3194 }
3195 } else {
3196 // ----- Look for no rule, which means extract all the archive
3197 $v_extract = true;
3198 }
3199
3200 // ----- Skip files with excluded file extensions
3201 if( ($v_extract) && isset($p_options[WPAI_PCLZIP_OPT_EXTRACT_EXT_RESTRICTIONS]) ){
3202
3203 // Process each provided extension.
3204 foreach($p_options[WPAI_PCLZIP_OPT_EXTRACT_EXT_RESTRICTIONS] as $ext){
3205 // Standardize extension.
3206 $ext = strtolower(trim($ext, '. '));
3207
3208 // Determine stored extension.
3209 $stored_ext = strtolower( pathinfo($v_header['stored_filename'], PATHINFO_EXTENSION) );
3210
3211 // Determine if extension is used.
3212 if ($ext === $stored_ext) {
3213 $v_extract = false;
3214 break;
3215 }
3216 }
3217 }
3218
3219 // ----- Only allow files with whitelisted file extensions
3220 if( ($v_extract) && isset($p_options[WPAI_PCLZIP_OPT_EXTRACT_WHITELIST_RESTRICTIONS]) ){
3221
3222 $v_extract = false; // Default to not extracting
3223
3224 // Process each allowed extension.
3225 foreach($p_options[WPAI_PCLZIP_OPT_EXTRACT_WHITELIST_RESTRICTIONS] as $ext){
3226 // Standardize extension.
3227 $ext = strtolower(trim($ext, '. '));
3228
3229 // Determine stored extension.
3230 $stored_ext = strtolower( pathinfo($v_header['stored_filename'], PATHINFO_EXTENSION) );
3231
3232 // Determine if extension is allowed.
3233 if ($ext === $stored_ext) {
3234 $v_extract = true;
3235 break;
3236 }
3237 }
3238 }
3239
3240 // ----- Check compression method
3241 if (($v_extract) && (($v_header['compression'] != 8) && ($v_header['compression'] != 0))) {
3242 $v_header['status'] = 'unsupported_compression';
3243
3244 // ----- Look for WPAI_PCLZIP_OPT_STOP_ON_ERROR
3245 if ((isset($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR] === true)) {
3246 $this->privSwapBackMagicQuotes();
3247
3248 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_UNSUPPORTED_COMPRESSION, "Filename '".$v_header['stored_filename']."' is compressed by an unsupported compression method (".$v_header['compression'].") ");
3249
3250 return WpaiPclZip::errorCode();
3251 }
3252 }
3253
3254 // ----- Check encrypted files
3255 if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3256 $v_header['status'] = 'unsupported_encryption';
3257 // ----- Look for WPAI_PCLZIP_OPT_STOP_ON_ERROR
3258 if ((isset($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR] === true)) {
3259 $this->privSwapBackMagicQuotes();
3260
3261 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, "Unsupported encryption for filename '".$v_header['stored_filename']."'");
3262
3263 return WpaiPclZip::errorCode();
3264 }
3265 }
3266
3267 // ----- Look for real extraction
3268 if (($v_extract) && ($v_header['status'] != 'ok')) {
3269 $v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++]);
3270 if ($v_result != 1) {
3271 $this->privCloseFd();
3272 $this->privSwapBackMagicQuotes();
3273 return $v_result;
3274 }
3275
3276 $v_extract = false;
3277 }
3278
3279 // ----- Look for real extraction
3280 if ($v_extract) {
3281 // ----- Go to the file position
3282 @rewind($this->zip_fd);
3283 if (@fseek($this->zip_fd, $v_header['offset'])) {
3284 // ----- Close the zip file
3285 $this->privCloseFd();
3286
3287 $this->privSwapBackMagicQuotes();
3288
3289 // ----- Error log
3290 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3291
3292 // ----- Return
3293 return WpaiPclZip::errorCode();
3294 }
3295
3296 // ----- Look for extraction as string
3297 if ($p_options[WPAI_PCLZIP_OPT_EXTRACT_AS_STRING]) {
3298 $v_string = '';
3299
3300 // ----- Extracting the file
3301 $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
3302 if ($v_result1 < 1) {
3303 $this->privCloseFd();
3304 $this->privSwapBackMagicQuotes();
3305 return $v_result1;
3306 }
3307
3308 // ----- Get the only interesting attributes
3309 if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) {
3310 // ----- Close the zip file
3311 $this->privCloseFd();
3312 $this->privSwapBackMagicQuotes();
3313
3314 return $v_result;
3315 }
3316
3317 // ----- Set the file content
3318 $p_file_list[$v_nb_extracted]['content'] = $v_string;
3319
3320 // ----- Next extracted file
3321 $v_nb_extracted++;
3322
3323 // ----- Look for user callback abort
3324 if ($v_result1 == 2) {
3325 break;
3326 }
3327 } elseif ((isset($p_options[WPAI_PCLZIP_OPT_EXTRACT_IN_OUTPUT])) && ($p_options[WPAI_PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
3328 // ----- Look for extraction in standard output
3329 // ----- Extracting the file in standard output
3330 $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
3331 if ($v_result1 < 1) {
3332 $this->privCloseFd();
3333 $this->privSwapBackMagicQuotes();
3334 return $v_result1;
3335 }
3336
3337 // ----- Get the only interesting attributes
3338 if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3339 $this->privCloseFd();
3340 $this->privSwapBackMagicQuotes();
3341 return $v_result;
3342 }
3343
3344 // ----- Look for user callback abort
3345 if ($v_result1 == 2) {
3346 break;
3347 }
3348 } else {
3349 // ----- Look for normal extraction
3350 // ----- Extracting the file
3351 $v_result1 = $this->privExtractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_options);
3352 if ($v_result1 < 1) {
3353 $this->privCloseFd();
3354 $this->privSwapBackMagicQuotes();
3355 return $v_result1;
3356 }
3357
3358 // ----- Get the only interesting attributes
3359 if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3360 // ----- Close the zip file
3361 $this->privCloseFd();
3362 $this->privSwapBackMagicQuotes();
3363
3364 return $v_result;
3365 }
3366
3367 // ----- Look for user callback abort
3368 if ($v_result1 == 2) {
3369 break;
3370 }
3371 }
3372 }
3373 }
3374
3375 // ----- Close the zip file
3376 $this->privCloseFd();
3377 $this->privSwapBackMagicQuotes();
3378
3379 // ----- Return
3380 return $v_result;
3381 }
3382 // --------------------------------------------------------------------------------
3383
3384 // --------------------------------------------------------------------------------
3385 // Function : privExtractFile()
3386 // Description :
3387 // Parameters :
3388 // Return Values :
3389 //
3390 // 1 : ... ?
3391 // WPAI_PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3392 // --------------------------------------------------------------------------------
3393 public function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3394 {
3395 $v_result=1;
3396
3397 // ----- Read the file header
3398 if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
3399 // ----- Return
3400 return $v_result;
3401 }
3402
3403 // ----- Check that the file header is coherent with $p_entry info
3404 if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3405 // TBC
3406 }
3407
3408 // ----- Look for all path to remove
3409 if ($p_remove_all_path == true) {
3410 // ----- Look for folder entry that not need to be extracted
3411 if (($p_entry['external']&0x00000010)==0x00000010) {
3412 $p_entry['status'] = "filtered";
3413
3414 return $v_result;
3415 }
3416
3417 // ----- Get the basename of the path
3418 $p_entry['filename'] = basename($p_entry['filename']);
3419 } elseif ($p_remove_path != "") {
3420 // ----- Look for path to remove
3421 if ( WpaiPclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) {
3422 // ----- Change the file status
3423 $p_entry['status'] = "filtered";
3424
3425 // ----- Return
3426 return $v_result;
3427 }
3428
3429 $p_remove_path_size = strlen($p_remove_path);
3430 if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) {
3431 // ----- Remove the path
3432 $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
3433 }
3434 }
3435
3436 // ----- Add the path
3437 if ($p_path != '') {
3438 $p_entry['filename'] = $p_path."/".$p_entry['filename'];
3439 }
3440
3441 // ----- Check a base_dir_restriction
3442 if (isset($p_options[WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
3443 $v_inclusion = WpaiPclZipUtilPathInclusion($p_options[WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], $p_entry['filename']);
3444 if ($v_inclusion == 0) {
3445 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_DIRECTORY_RESTRICTION, "Filename '".$p_entry['filename']."' is outside WPAI_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
3446
3447 return WpaiPclZip::errorCode();
3448 }
3449 }
3450
3451 // ----- Look for pre-extract callback
3452 if (isset($p_options[WPAI_PCLZIP_CB_PRE_EXTRACT])) {
3453 // ----- Generate a local information
3454 $v_local_header = array();
3455 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3456
3457 // ----- Call the callback
3458 // Here I do not use call_user_func() because I need to send a reference to the
3459 // header.
3460 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_PRE_EXTRACT].'(WPAI_PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3461 $v_result = $p_options[WPAI_PCLZIP_CB_PRE_EXTRACT](WPAI_PCLZIP_CB_PRE_EXTRACT, $v_local_header);
3462 if ($v_result == 0) {
3463 // ----- Change the file status
3464 $p_entry['status'] = "skipped";
3465 $v_result = 1;
3466 }
3467
3468 // ----- Look for abort result
3469 if ($v_result == 2) {
3470 // ----- This status is internal and will be changed in 'skipped'
3471 $p_entry['status'] = "aborted";
3472 $v_result = WPAI_PCLZIP_ERR_USER_ABORTED;
3473 }
3474
3475 // ----- Update the informations
3476 // Only some fields can be modified
3477 $p_entry['filename'] = $v_local_header['filename'];
3478 }
3479
3480 // ----- Look if extraction should be done
3481 if ($p_entry['status'] == 'ok') {
3482 // ----- Look for specific actions while the file exist
3483 if (file_exists($p_entry['filename'])) {
3484 // ----- Look if file is a directory
3485 if (is_dir($p_entry['filename'])) {
3486 // ----- Change the file status
3487 $p_entry['status'] = "already_a_directory";
3488
3489 // ----- Look for WPAI_PCLZIP_OPT_STOP_ON_ERROR
3490 // For historical reason first PclZip implementation does not stop
3491 // when this kind of error occurs.
3492 if ((isset($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3493 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_ALREADY_A_DIRECTORY, "Filename '".$p_entry['filename']."' is already used by an existing directory");
3494 return WpaiPclZip::errorCode();
3495 }
3496 } elseif (!is_writeable($p_entry['filename'])) {
3497 // ----- Look if file is write protected
3498 // ----- Change the file status
3499 $p_entry['status'] = "write_protected";
3500
3501 // ----- Look for WPAI_PCLZIP_OPT_STOP_ON_ERROR
3502 // For historical reason first PclZip implementation does not stop
3503 // when this kind of error occurs.
3504 if ((isset($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR] === true)) {
3505 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL, "Filename '".$p_entry['filename']."' exists and is write protected");
3506 return WpaiPclZip::errorCode();
3507 }
3508 } elseif (filemtime($p_entry['filename']) > $p_entry['mtime']) {
3509 // ----- Look if the extracted file is older
3510 // ----- Change the file status
3511 if ((isset($p_options[WPAI_PCLZIP_OPT_REPLACE_NEWER])) && ($p_options[WPAI_PCLZIP_OPT_REPLACE_NEWER] === true)) {
3512 } else {
3513 $p_entry['status'] = "newer_exist";
3514
3515 // ----- Look for WPAI_PCLZIP_OPT_STOP_ON_ERROR
3516 // For historical reason first PclZip implementation does not stop
3517 // when this kind of error occurs.
3518 if ((isset($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[WPAI_PCLZIP_OPT_STOP_ON_ERROR] === true)) {
3519 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL, "Newer version of '".$p_entry['filename']."' exists and option WPAI_PCLZIP_OPT_REPLACE_NEWER is not selected");
3520 return WpaiPclZip::errorCode();
3521 }
3522 }
3523 } else {
3524 }
3525 } else {
3526 // ----- Check the directory availability and create it if necessary
3527 if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) {
3528 $v_dir_to_check = $p_entry['filename'];
3529 } elseif (!strstr($p_entry['filename'], "/")) {
3530 $v_dir_to_check = "";
3531 } else {
3532 $v_dir_to_check = dirname($p_entry['filename']);
3533 }
3534
3535 if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
3536 // ----- Change the file status
3537 $p_entry['status'] = "path_creation_fail";
3538
3539 // ----- Return
3540 //return $v_result;
3541 $v_result = 1;
3542 }
3543 }
3544 }
3545
3546 // ----- Look if extraction should be done
3547 if ($p_entry['status'] == 'ok') {
3548 // ----- Do the extraction (if not a folder)
3549 if (!(($p_entry['external']&0x00000010) == 0x00000010)) {
3550 // ----- Look for not compressed file
3551 if ($p_entry['compression'] == 0) {
3552 // ----- Opening destination file
3553 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3554 // ----- Change the file status
3555 $p_entry['status'] = "write_error";
3556
3557 // ----- Return
3558 return $v_result;
3559 }
3560
3561 // ----- Read the file by WPAI_PCLZIP_READ_BLOCK_SIZE octets blocks
3562 $v_size = $p_entry['compressed_size'];
3563 while ($v_size != 0) {
3564 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
3565 $v_buffer = @fread($this->zip_fd, $v_read_size);
3566 /* Try to speed up the code
3567 $v_binary_data = pack('a'.$v_read_size, $v_buffer);
3568 @fwrite($v_dest_file, $v_binary_data, $v_read_size);
3569 */
3570 @fwrite($v_dest_file, $v_buffer, $v_read_size);
3571 $v_size -= $v_read_size;
3572 }
3573
3574 // ----- Closing the destination file
3575 fclose($v_dest_file);
3576
3577 // ----- Change the file mtime
3578 touch($p_entry['filename'], $p_entry['mtime']);
3579 } else {
3580 // ----- TBC
3581 // Need to be finished
3582 if (($p_entry['flag'] & 1) == 1) {
3583 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
3584 return WpaiPclZip::errorCode();
3585 }
3586
3587 // ----- Look for using temporary file to unzip
3588 if ((!isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_OFF])) && (isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_ON]) || (isset($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD]) && ($p_options[WPAI_PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])))) {
3589 $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
3590 if ($v_result < WPAI_PCLZIP_ERR_NO_ERROR) {
3591 return $v_result;
3592 }
3593 } else {
3594 // ----- Look for extract in memory
3595 // ----- Read the compressed file in a buffer (one shot)
3596 $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3597
3598 // ----- Decompress the file
3599 $v_file_content = @gzinflate($v_buffer);
3600 unset($v_buffer);
3601 if ($v_file_content === false) {
3602 // ----- Change the file status
3603 // TBC
3604 $p_entry['status'] = "error";
3605
3606 return $v_result;
3607 }
3608
3609 // ----- Opening destination file
3610 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3611 // ----- Change the file status
3612 $p_entry['status'] = "write_error";
3613
3614 return $v_result;
3615 }
3616
3617 // ----- Write the uncompressed data
3618 @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
3619 unset($v_file_content);
3620
3621 // ----- Closing the destination file
3622 @fclose($v_dest_file);
3623 }
3624
3625 // ----- Change the file mtime
3626 @touch($p_entry['filename'], $p_entry['mtime']);
3627 }
3628
3629 // ----- Look for chmod option
3630 if (isset($p_options[WPAI_PCLZIP_OPT_SET_CHMOD])) {
3631 // ----- Change the mode of the file
3632 @chmod($p_entry['filename'], $p_options[WPAI_PCLZIP_OPT_SET_CHMOD]);
3633 }
3634 }
3635 }
3636
3637 // ----- Change abort status
3638 if ($p_entry['status'] == "aborted") {
3639 $p_entry['status'] = "skipped";
3640 } elseif (isset($p_options[WPAI_PCLZIP_CB_POST_EXTRACT])) {
3641 // ----- Look for post-extract callback
3642 // ----- Generate a local information
3643 $v_local_header = array();
3644 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3645
3646 // ----- Call the callback
3647 // Here I do not use call_user_func() because I need to send a reference to the
3648 // header.
3649 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_POST_EXTRACT].'(WPAI_PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3650 $v_result = $p_options[WPAI_PCLZIP_CB_POST_EXTRACT](WPAI_PCLZIP_CB_POST_EXTRACT, $v_local_header);
3651
3652 // ----- Look for abort result
3653 if ($v_result == 2) {
3654 $v_result = WPAI_PCLZIP_ERR_USER_ABORTED;
3655 }
3656 }
3657
3658 // ----- Return
3659 return $v_result;
3660 }
3661 // --------------------------------------------------------------------------------
3662
3663 // --------------------------------------------------------------------------------
3664 // Function : privExtractFileUsingTempFile()
3665 // Description :
3666 // Parameters :
3667 // Return Values :
3668 // --------------------------------------------------------------------------------
3669 public function privExtractFileUsingTempFile(&$p_entry, &$p_options)
3670 {
3671 $v_result=1;
3672
3673 // ----- Creates a temporary file
3674 $v_gzip_temp_name = WPAI_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
3675 if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
3676 fclose($v_dest_file);
3677 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
3678 return WpaiPclZip::errorCode();
3679 }
3680
3681 // ----- Write gz file format header
3682 $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
3683 @fwrite($v_dest_file, $v_binary_data, 10);
3684
3685 // ----- Read the file by WPAI_PCLZIP_READ_BLOCK_SIZE octets blocks
3686 $v_size = $p_entry['compressed_size'];
3687 while ($v_size != 0) {
3688 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
3689 $v_buffer = @fread($this->zip_fd, $v_read_size);
3690 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3691 @fwrite($v_dest_file, $v_buffer, $v_read_size);
3692 $v_size -= $v_read_size;
3693 }
3694
3695 // ----- Write gz file format footer
3696 $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
3697 @fwrite($v_dest_file, $v_binary_data, 8);
3698
3699 // ----- Close the temporary file
3700 @fclose($v_dest_file);
3701
3702 // ----- Opening destination file
3703 if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3704 $p_entry['status'] = "write_error";
3705 return $v_result;
3706 }
3707
3708 // ----- Open the temporary gz file
3709 if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
3710 @fclose($v_dest_file);
3711 $p_entry['status'] = "read_error";
3712 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
3713 return WpaiPclZip::errorCode();
3714 }
3715
3716 // ----- Read the file by WPAI_PCLZIP_READ_BLOCK_SIZE octets blocks
3717 $v_size = $p_entry['size'];
3718 while ($v_size != 0) {
3719 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
3720 $v_buffer = @gzread($v_src_file, $v_read_size);
3721 //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3722 @fwrite($v_dest_file, $v_buffer, $v_read_size);
3723 $v_size -= $v_read_size;
3724 }
3725 @fclose($v_dest_file);
3726 @gzclose($v_src_file);
3727
3728 // ----- Delete the temporary file
3729 @unlink($v_gzip_temp_name);
3730
3731 // ----- Return
3732 return $v_result;
3733 }
3734 // --------------------------------------------------------------------------------
3735
3736 // --------------------------------------------------------------------------------
3737 // Function : privExtractFileInOutput()
3738 // Description :
3739 // Parameters :
3740 // Return Values :
3741 // --------------------------------------------------------------------------------
3742 public function privExtractFileInOutput(&$p_entry, &$p_options)
3743 {
3744 $v_result=1;
3745
3746 // ----- Read the file header
3747 if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
3748 return $v_result;
3749 }
3750
3751 // ----- Check that the file header is coherent with $p_entry info
3752 if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3753 // TBC
3754 }
3755
3756 // ----- Look for pre-extract callback
3757 if (isset($p_options[WPAI_PCLZIP_CB_PRE_EXTRACT])) {
3758 // ----- Generate a local information
3759 $v_local_header = array();
3760 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3761
3762 // ----- Call the callback
3763 // Here I do not use call_user_func() because I need to send a reference to the
3764 // header.
3765 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_PRE_EXTRACT].'(WPAI_PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3766 $v_result = $p_options[WPAI_PCLZIP_CB_PRE_EXTRACT](WPAI_PCLZIP_CB_PRE_EXTRACT, $v_local_header);
3767 if ($v_result == 0) {
3768 // ----- Change the file status
3769 $p_entry['status'] = "skipped";
3770 $v_result = 1;
3771 }
3772
3773 // ----- Look for abort result
3774 if ($v_result == 2) {
3775 // ----- This status is internal and will be changed in 'skipped'
3776 $p_entry['status'] = "aborted";
3777 $v_result = WPAI_PCLZIP_ERR_USER_ABORTED;
3778 }
3779
3780 // ----- Update the informations
3781 // Only some fields can be modified
3782 $p_entry['filename'] = $v_local_header['filename'];
3783 }
3784
3785 // ----- Trace
3786
3787 // ----- Look if extraction should be done
3788 if ($p_entry['status'] == 'ok') {
3789 // ----- Do the extraction (if not a folder)
3790 if (!(($p_entry['external']&0x00000010)==0x00000010)) {
3791 // ----- Look for not compressed file
3792 if ($p_entry['compressed_size'] == $p_entry['size']) {
3793 // ----- Read the file in a buffer (one shot)
3794 $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3795
3796 // ----- Send the file to the output
3797 echo $v_buffer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Raw archive extraction byte stream sent to PHP output.
3798 unset($v_buffer);
3799 } else {
3800 // ----- Read the compressed file in a buffer (one shot)
3801 $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3802
3803 // ----- Decompress the file
3804 $v_file_content = gzinflate($v_buffer);
3805 unset($v_buffer);
3806
3807 // ----- Send the file to the output
3808 echo $v_file_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Decompressed archive bytes sent to PHP output.
3809 unset($v_file_content);
3810 }
3811 }
3812 }
3813
3814 // ----- Change abort status
3815 if ($p_entry['status'] == "aborted") {
3816 $p_entry['status'] = "skipped";
3817 } elseif (isset($p_options[WPAI_PCLZIP_CB_POST_EXTRACT])) {
3818 // ----- Look for post-extract callback
3819
3820 // ----- Generate a local information
3821 $v_local_header = array();
3822 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3823
3824 // ----- Call the callback
3825 // Here I do not use call_user_func() because I need to send a reference to the
3826 // header.
3827 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_POST_EXTRACT].'(WPAI_PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3828 $v_result = $p_options[WPAI_PCLZIP_CB_POST_EXTRACT](WPAI_PCLZIP_CB_POST_EXTRACT, $v_local_header);
3829
3830 // ----- Look for abort result
3831 if ($v_result == 2) {
3832 $v_result = WPAI_PCLZIP_ERR_USER_ABORTED;
3833 }
3834 }
3835
3836 return $v_result;
3837 }
3838 // --------------------------------------------------------------------------------
3839
3840 // --------------------------------------------------------------------------------
3841 // Function : privExtractFileAsString()
3842 // Description :
3843 // Parameters :
3844 // Return Values :
3845 // --------------------------------------------------------------------------------
3846 public function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
3847 {
3848 $v_result=1;
3849
3850 // ----- Read the file header
3851 $v_header = array();
3852 if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
3853 // ----- Return
3854 return $v_result;
3855 }
3856
3857 // ----- Check that the file header is coherent with $p_entry info
3858 if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3859 // TBC
3860 }
3861
3862 // ----- Look for pre-extract callback
3863 if (isset($p_options[WPAI_PCLZIP_CB_PRE_EXTRACT])) {
3864 // ----- Generate a local information
3865 $v_local_header = array();
3866 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3867
3868 // ----- Call the callback
3869 // Here I do not use call_user_func() because I need to send a reference to the
3870 // header.
3871 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_PRE_EXTRACT].'(WPAI_PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3872 $v_result = $p_options[WPAI_PCLZIP_CB_PRE_EXTRACT](WPAI_PCLZIP_CB_PRE_EXTRACT, $v_local_header);
3873 if ($v_result == 0) {
3874 // ----- Change the file status
3875 $p_entry['status'] = "skipped";
3876 $v_result = 1;
3877 }
3878
3879 // ----- Look for abort result
3880 if ($v_result == 2) {
3881 // ----- This status is internal and will be changed in 'skipped'
3882 $p_entry['status'] = "aborted";
3883 $v_result = WPAI_PCLZIP_ERR_USER_ABORTED;
3884 }
3885
3886 // ----- Update the informations
3887 // Only some fields can be modified
3888 $p_entry['filename'] = $v_local_header['filename'];
3889 }
3890
3891 // ----- Look if extraction should be done
3892 if ($p_entry['status'] == 'ok') {
3893 // ----- Do the extraction (if not a folder)
3894 if (!(($p_entry['external']&0x00000010)==0x00000010)) {
3895 // ----- Look for not compressed file
3896 // if ($p_entry['compressed_size'] == $p_entry['size'])
3897 if ($p_entry['compression'] == 0) {
3898 // ----- Reading the file
3899 $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
3900 } else {
3901 // ----- Reading the file
3902 $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
3903
3904 // ----- Decompress the file
3905 if (($p_string = @gzinflate($v_data)) === false) {
3906 // TBC
3907 }
3908 }
3909 // ----- Trace
3910 } else {
3911 // TBC : error : can not extract a folder in a string
3912 }
3913 }
3914
3915 // ----- Change abort status
3916 if ($p_entry['status'] == "aborted") {
3917 $p_entry['status'] = "skipped";
3918 } elseif (isset($p_options[WPAI_PCLZIP_CB_POST_EXTRACT])) {
3919 // ----- Look for post-extract callback
3920 // ----- Generate a local information
3921 $v_local_header = array();
3922 $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3923
3924 // ----- Swap the content to header
3925 $v_local_header['content'] = $p_string;
3926 $p_string = '';
3927
3928 // ----- Call the callback
3929 // Here I do not use call_user_func() because I need to send a reference to the
3930 // header.
3931 // eval('$v_result = '.$p_options[WPAI_PCLZIP_CB_POST_EXTRACT].'(WPAI_PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3932 $v_result = $p_options[WPAI_PCLZIP_CB_POST_EXTRACT](WPAI_PCLZIP_CB_POST_EXTRACT, $v_local_header);
3933
3934 // ----- Swap back the content to header
3935 $p_string = $v_local_header['content'];
3936 unset($v_local_header['content']);
3937
3938 // ----- Look for abort result
3939 if ($v_result == 2) {
3940 $v_result = WPAI_PCLZIP_ERR_USER_ABORTED;
3941 }
3942 }
3943
3944 // ----- Return
3945 return $v_result;
3946 }
3947 // --------------------------------------------------------------------------------
3948
3949 // --------------------------------------------------------------------------------
3950 // Function : privReadFileHeader()
3951 // Description :
3952 // Parameters :
3953 // Return Values :
3954 // --------------------------------------------------------------------------------
3955 public function privReadFileHeader(&$p_header)
3956 {
3957 $v_result=1;
3958
3959 // ----- Read the 4 bytes signature
3960 $v_binary_data = @fread($this->zip_fd, 4);
3961 $v_data = unpack('Vid', $v_binary_data);
3962
3963 // ----- Check signature
3964 if ($v_data['id'] != 0x04034b50) {
3965 // ----- Error log
3966 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
3967
3968 // ----- Return
3969 return WpaiPclZip::errorCode();
3970 }
3971
3972 // ----- Read the first 42 bytes of the header
3973 $v_binary_data = fread($this->zip_fd, 26);
3974
3975 // ----- Look for invalid block size
3976 if (strlen($v_binary_data) != 26) {
3977 $p_header['filename'] = "";
3978 $p_header['status'] = "invalid_header";
3979
3980 // ----- Error log
3981 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
3982
3983 // ----- Return
3984 return WpaiPclZip::errorCode();
3985 }
3986
3987 // ----- Extract the values
3988 $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
3989
3990 // ----- Get filename
3991 $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
3992
3993 // ----- Get extra_fields
3994 if ($v_data['extra_len'] != 0) {
3995 $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
3996 } else {
3997 $p_header['extra'] = '';
3998 }
3999
4000 // ----- Extract properties
4001 $p_header['version_extracted'] = $v_data['version'];
4002 $p_header['compression'] = $v_data['compression'];
4003 $p_header['size'] = $v_data['size'];
4004 $p_header['compressed_size'] = $v_data['compressed_size'];
4005 $p_header['crc'] = $v_data['crc'];
4006 $p_header['flag'] = $v_data['flag'];
4007 $p_header['filename_len'] = $v_data['filename_len'];
4008
4009 // ----- Recuperate date in UNIX format
4010 $p_header['mdate'] = $v_data['mdate'];
4011 $p_header['mtime'] = $v_data['mtime'];
4012 if ($p_header['mdate'] && $p_header['mtime']) {
4013 // ----- Extract time
4014 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4015 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4016 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4017
4018 // ----- Extract date
4019 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4020 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4021 $v_day = $p_header['mdate'] & 0x001F;
4022
4023 // ----- Get UNIX date format
4024 $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4025
4026 } else {
4027 $p_header['mtime'] = time();
4028 }
4029
4030 // TBC
4031 //for(reset($v_data); $key = key($v_data); next($v_data)) {
4032 //}
4033
4034 // ----- Set the stored filename
4035 $p_header['stored_filename'] = $p_header['filename'];
4036
4037 // ----- Set the status field
4038 $p_header['status'] = "ok";
4039
4040 // ----- Return
4041 return $v_result;
4042 }
4043 // --------------------------------------------------------------------------------
4044
4045 // --------------------------------------------------------------------------------
4046 // Function : privReadCentralFileHeader()
4047 // Description :
4048 // Parameters :
4049 // Return Values :
4050 // --------------------------------------------------------------------------------
4051 public function privReadCentralFileHeader(&$p_header)
4052 {
4053 $v_result = 1;
4054
4055 // ----- Read the 4 bytes signature
4056 $v_binary_data = @fread($this->zip_fd, 4);
4057 $v_data = unpack('Vid', $v_binary_data);
4058
4059 // ----- Check signature
4060 if ($v_data['id'] != 0x02014b50) {
4061 // ----- Error log
4062 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4063
4064 // ----- Return
4065 return WpaiPclZip::errorCode();
4066 }
4067
4068 // ----- Read the first 42 bytes of the header
4069 $v_binary_data = fread($this->zip_fd, 42);
4070
4071 // ----- Look for invalid block size
4072 if (strlen($v_binary_data) != 42) {
4073 $p_header['filename'] = "";
4074 $p_header['status'] = "invalid_header";
4075
4076 // ----- Error log
4077 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4078
4079 // ----- Return
4080 return WpaiPclZip::errorCode();
4081 }
4082
4083 // ----- Extract the values
4084 $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);
4085
4086 // ----- Get filename
4087 if ($p_header['filename_len'] != 0) {
4088 $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
4089 } else {
4090 $p_header['filename'] = '';
4091 }
4092
4093 // ----- Get extra
4094 if ($p_header['extra_len'] != 0) {
4095 $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
4096 } else {
4097 $p_header['extra'] = '';
4098 }
4099
4100 // ----- Get comment
4101 if ($p_header['comment_len'] != 0) {
4102 $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
4103 } else {
4104 $p_header['comment'] = '';
4105 }
4106
4107 // ----- Extract properties
4108
4109 // ----- Recuperate date in UNIX format
4110 //if ($p_header['mdate'] && $p_header['mtime'])
4111 // TBC : bug : this was ignoring time with 0/0/0
4112 if (1) {
4113 // ----- Extract time
4114 $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4115 $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4116 $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4117
4118 // ----- Extract date
4119 $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4120 $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4121 $v_day = $p_header['mdate'] & 0x001F;
4122
4123 // ----- Get UNIX date format
4124 $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4125
4126 } else {
4127 $p_header['mtime'] = time();
4128 }
4129
4130 // ----- Set the stored filename
4131 $p_header['stored_filename'] = $p_header['filename'];
4132
4133 // ----- Set default status to ok
4134 $p_header['status'] = 'ok';
4135
4136 // ----- Look if it is a directory
4137 if (substr($p_header['filename'], -1) == '/') {
4138 //$p_header['external'] = 0x41FF0010;
4139 $p_header['external'] = 0x00000010;
4140 }
4141
4142
4143 // ----- Return
4144 return $v_result;
4145 }
4146 // --------------------------------------------------------------------------------
4147
4148 // --------------------------------------------------------------------------------
4149 // Function : privCheckFileHeaders()
4150 // Description :
4151 // Parameters :
4152 // Return Values :
4153 // 1 on success,
4154 // 0 on error;
4155 // --------------------------------------------------------------------------------
4156 public function privCheckFileHeaders(&$p_local_header, &$p_central_header)
4157 {
4158 $v_result=1;
4159
4160 // ----- Check the static values
4161 // TBC
4162 if ($p_local_header['filename'] != $p_central_header['filename']) {
4163 }
4164 if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4165 }
4166 if ($p_local_header['flag'] != $p_central_header['flag']) {
4167 }
4168 if ($p_local_header['compression'] != $p_central_header['compression']) {
4169 }
4170 if ($p_local_header['mtime'] != $p_central_header['mtime']) {
4171 }
4172 if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
4173 }
4174
4175 // ----- Look for flag bit 3
4176 if (($p_local_header['flag'] & 8) == 8) {
4177 $p_local_header['size'] = $p_central_header['size'];
4178 $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
4179 $p_local_header['crc'] = $p_central_header['crc'];
4180 }
4181
4182 // ----- Return
4183 return $v_result;
4184 }
4185 // --------------------------------------------------------------------------------
4186
4187 // --------------------------------------------------------------------------------
4188 // Function : privReadEndCentralDir()
4189 // Description :
4190 // Parameters :
4191 // Return Values :
4192 // --------------------------------------------------------------------------------
4193 public function privReadEndCentralDir(&$p_central_dir)
4194 {
4195 $v_result=1;
4196
4197 // ----- Go to the end of the zip file
4198 $v_size = filesize($this->zipname);
4199 @fseek($this->zip_fd, $v_size);
4200 if (@ftell($this->zip_fd) != $v_size) {
4201 // ----- Error log
4202 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
4203
4204 // ----- Return
4205 return WpaiPclZip::errorCode();
4206 }
4207
4208 // ----- First try : look if this is an archive with no commentaries (most of the time)
4209 // in this case the end of central dir is at 22 bytes of the file end
4210 $v_found = 0;
4211 if ($v_size > 26) {
4212 @fseek($this->zip_fd, $v_size-22);
4213 if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) {
4214 // ----- Error log
4215 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4216
4217 // ----- Return
4218 return WpaiPclZip::errorCode();
4219 }
4220
4221 // ----- Read for bytes
4222 $v_binary_data = @fread($this->zip_fd, 4);
4223 $v_data = @unpack('Vid', $v_binary_data);
4224
4225 // ----- Check signature
4226 if ($v_data['id'] == 0x06054b50) {
4227 $v_found = 1;
4228 }
4229
4230 $v_pos = ftell($this->zip_fd);
4231 }
4232
4233 // ----- Go back to the maximum possible size of the Central Dir End Record
4234 if (!$v_found) {
4235 $v_maximum_size = 65557; // 0xFFFF + 22;
4236 if ($v_maximum_size > $v_size) {
4237 $v_maximum_size = $v_size;
4238 }
4239 @fseek($this->zip_fd, $v_size-$v_maximum_size);
4240 if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) {
4241 // ----- Error log
4242 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4243
4244 // ----- Return
4245 return WpaiPclZip::errorCode();
4246 }
4247
4248 // ----- Read byte per byte in order to find the signature
4249 $v_pos = ftell($this->zip_fd);
4250 $v_bytes = 0x00000000;
4251 while ($v_pos < $v_size) {
4252 // ----- Read a byte
4253 $v_byte = @fread($this->zip_fd, 1);
4254
4255 // ----- Add the byte
4256 //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
4257 // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
4258 // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
4259 $v_bytes = (($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
4260
4261 // ----- Compare the bytes
4262 if ($v_bytes == 0x504b0506) {
4263 $v_pos++;
4264 break;
4265 }
4266
4267 $v_pos++;
4268 }
4269
4270 // ----- Look if not found end of central dir
4271 if ($v_pos == $v_size) {
4272 // ----- Error log
4273 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
4274
4275 // ----- Return
4276 return WpaiPclZip::errorCode();
4277 }
4278 }
4279
4280 // ----- Read the first 18 bytes of the header
4281 $v_binary_data = fread($this->zip_fd, 18);
4282
4283 // ----- Look for invalid block size
4284 if (strlen($v_binary_data) != 18) {
4285 // ----- Error log
4286 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
4287
4288 // ----- Return
4289 return WpaiPclZip::errorCode();
4290 }
4291
4292 // ----- Extract the values
4293 $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
4294
4295 // ----- Check the global size
4296 if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
4297 // ----- Removed in release 2.2 see readme file
4298 // The check of the file size is a little too strict.
4299 // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
4300 // While decrypted, zip has training 0 bytes
4301 if (0) {
4302 // ----- Error log
4303 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_BAD_FORMAT, 'The central dir is not at the end of the archive. Some trailing bytes exists after the archive.');
4304
4305 // ----- Return
4306 return WpaiPclZip::errorCode();
4307 }
4308 }
4309
4310 // ----- Get comment
4311 if ($v_data['comment_size'] != 0) {
4312 $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
4313 } else {
4314 $p_central_dir['comment'] = '';
4315 }
4316
4317 $p_central_dir['entries'] = $v_data['entries'];
4318 $p_central_dir['disk_entries'] = $v_data['disk_entries'];
4319 $p_central_dir['offset'] = $v_data['offset'];
4320 $p_central_dir['size'] = $v_data['size'];
4321 $p_central_dir['disk'] = $v_data['disk'];
4322 $p_central_dir['disk_start'] = $v_data['disk_start'];
4323
4324 // TBC
4325 //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
4326 //}
4327
4328 // ----- Return
4329 return $v_result;
4330 }
4331 // --------------------------------------------------------------------------------
4332
4333 // --------------------------------------------------------------------------------
4334 // Function : privDeleteByRule()
4335 // Description :
4336 // Parameters :
4337 // Return Values :
4338 // --------------------------------------------------------------------------------
4339 public function privDeleteByRule(&$p_result_list, &$p_options)
4340 {
4341 $v_result=1;
4342 $v_list_detail = array();
4343
4344 // ----- Open the zip file
4345 if (($v_result=$this->privOpenFd('rb')) != 1) {
4346 // ----- Return
4347 return $v_result;
4348 }
4349
4350 // ----- Read the central directory informations
4351 $v_central_dir = array();
4352 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
4353 $this->privCloseFd();
4354 return $v_result;
4355 }
4356
4357 // ----- Go to beginning of File
4358 @rewind($this->zip_fd);
4359
4360 // ----- Scan all the files
4361 // ----- Start at beginning of Central Dir
4362 $v_pos_entry = $v_central_dir['offset'];
4363 @rewind($this->zip_fd);
4364 if (@fseek($this->zip_fd, $v_pos_entry)) {
4365 // ----- Close the zip file
4366 $this->privCloseFd();
4367
4368 // ----- Error log
4369 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4370
4371 // ----- Return
4372 return WpaiPclZip::errorCode();
4373 }
4374
4375 // ----- Read each entry
4376 $v_header_list = array();
4377 $j_start = 0;
4378 for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
4379 // ----- Read the file header
4380 $v_header_list[$v_nb_extracted] = array();
4381 if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) {
4382 // ----- Close the zip file
4383 $this->privCloseFd();
4384
4385 return $v_result;
4386 }
4387
4388
4389 // ----- Store the index
4390 $v_header_list[$v_nb_extracted]['index'] = $i;
4391
4392 // ----- Look for the specific extract rules
4393 $v_found = false;
4394
4395 // ----- Look for extract by name rule
4396 if ((isset($p_options[WPAI_PCLZIP_OPT_BY_NAME])) && ($p_options[WPAI_PCLZIP_OPT_BY_NAME] != 0)) {
4397 // ----- Look if the filename is in the list
4398 for ($j=0; ($j<sizeof($p_options[WPAI_PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
4399 // ----- Look for a directory
4400 if (substr($p_options[WPAI_PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
4401 // ----- Look if the directory is in the filename path
4402 if ((strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) == $p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) {
4403 $v_found = true;
4404 } elseif ((($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[WPAI_PCLZIP_OPT_BY_NAME][$j])) {
4405 $v_found = true;
4406 }
4407 } elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[WPAI_PCLZIP_OPT_BY_NAME][$j]) {
4408 // ----- Look for a filename
4409 $v_found = true;
4410 }
4411 }
4412 } elseif ((isset($p_options[WPAI_PCLZIP_OPT_BY_PREG])) && ($p_options[WPAI_PCLZIP_OPT_BY_PREG] != "")) {
4413 // ----- Look for extract by preg rule
4414 if (preg_match($p_options[WPAI_PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4415 $v_found = true;
4416 }
4417 } elseif ((isset($p_options[WPAI_PCLZIP_OPT_BY_INDEX])) && ($p_options[WPAI_PCLZIP_OPT_BY_INDEX] != 0)) {
4418 // ----- Look for extract by index rule
4419 // ----- Look if the index is in the list
4420 for ($j=$j_start; ($j<sizeof($p_options[WPAI_PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
4421 if (($i>=$p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['end'])) {
4422 $v_found = true;
4423 }
4424 if ($i>=$p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['end']) {
4425 $j_start = $j+1;
4426 }
4427 if ($p_options[WPAI_PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
4428 break;
4429 }
4430 }
4431 } else {
4432 $v_found = true;
4433 }
4434
4435 // ----- Look for deletion
4436 if ($v_found) {
4437 unset($v_header_list[$v_nb_extracted]);
4438 } else {
4439 $v_nb_extracted++;
4440 }
4441 }
4442
4443 // ----- Look if something need to be deleted
4444 if ($v_nb_extracted > 0) {
4445 // ----- Creates a temporay file
4446 $v_zip_temp_name = WPAI_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4447
4448 // ----- Creates a temporary zip archive
4449 $v_temp_zip = new PclZip($v_zip_temp_name);
4450
4451 // ----- Open the temporary zip file in write mode
4452 if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4453 $this->privCloseFd();
4454
4455 // ----- Return
4456 return $v_result;
4457 }
4458
4459 // ----- Look which file need to be kept
4460 for ($i=0; $i<sizeof($v_header_list); $i++) {
4461 // ----- Calculate the position of the header
4462 @rewind($this->zip_fd);
4463 if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
4464 // ----- Close the zip file
4465 $this->privCloseFd();
4466 $v_temp_zip->privCloseFd();
4467 @unlink($v_zip_temp_name);
4468
4469 // ----- Error log
4470 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4471
4472 // ----- Return
4473 return WpaiPclZip::errorCode();
4474 }
4475
4476 // ----- Read the file header
4477 $v_local_header = array();
4478 if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
4479 // ----- Close the zip file
4480 $this->privCloseFd();
4481 $v_temp_zip->privCloseFd();
4482 @unlink($v_zip_temp_name);
4483
4484 // ----- Return
4485 return $v_result;
4486 }
4487
4488 // ----- Check that local file header is same as central file header
4489 if ($this->privCheckFileHeaders($v_local_header, $v_header_list[$i]) != 1) {
4490 // TBC
4491 }
4492 unset($v_local_header);
4493
4494 // ----- Write the file header
4495 if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4496 // ----- Close the zip file
4497 $this->privCloseFd();
4498 $v_temp_zip->privCloseFd();
4499 @unlink($v_zip_temp_name);
4500
4501 // ----- Return
4502 return $v_result;
4503 }
4504
4505 // ----- Read/write the data block
4506 if ( ($v_result = WpaiPclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4507 // ----- Close the zip file
4508 $this->privCloseFd();
4509 $v_temp_zip->privCloseFd();
4510 @unlink($v_zip_temp_name);
4511
4512 // ----- Return
4513 return $v_result;
4514 }
4515 }
4516
4517 // ----- Store the offset of the central dir
4518 $v_offset = @ftell($v_temp_zip->zip_fd);
4519
4520 // ----- Re-Create the Central Dir files header
4521 for ($i=0; $i<sizeof($v_header_list); $i++) {
4522 // ----- Create the file header
4523 if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4524 $v_temp_zip->privCloseFd();
4525 $this->privCloseFd();
4526 @unlink($v_zip_temp_name);
4527
4528 // ----- Return
4529 return $v_result;
4530 }
4531
4532 // ----- Transform the header to a 'usable' info
4533 $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4534 }
4535
4536
4537 // ----- Zip file comment
4538 $v_comment = '';
4539 if (isset($p_options[WPAI_PCLZIP_OPT_COMMENT])) {
4540 $v_comment = $p_options[WPAI_PCLZIP_OPT_COMMENT];
4541 }
4542
4543 // ----- Calculate the size of the central header
4544 $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
4545
4546 // ----- Create the central dir footer
4547 if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
4548 // ----- Reset the file list
4549 unset($v_header_list);
4550 $v_temp_zip->privCloseFd();
4551 $this->privCloseFd();
4552 @unlink($v_zip_temp_name);
4553
4554 // ----- Return
4555 return $v_result;
4556 }
4557
4558 // ----- Close
4559 $v_temp_zip->privCloseFd();
4560 $this->privCloseFd();
4561
4562 // ----- Delete the zip file
4563 // TBC : I should test the result ...
4564 @unlink($this->zipname);
4565
4566 // ----- Rename the temporary file
4567 // TBC : I should test the result ...
4568 //@rename($v_zip_temp_name, $this->zipname);
4569 WpaiPclZipUtilRename($v_zip_temp_name, $this->zipname);
4570
4571 // ----- Destroy the temporary archive
4572 unset($v_temp_zip);
4573 } elseif ($v_central_dir['entries'] != 0) {
4574 // ----- Remove every files : reset the file
4575 $this->privCloseFd();
4576
4577 if (($v_result = $this->privOpenFd('wb')) != 1) {
4578 return $v_result;
4579 }
4580
4581 if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
4582 return $v_result;
4583 }
4584
4585 $this->privCloseFd();
4586 }
4587
4588 // ----- Return
4589 return $v_result;
4590 }
4591 // --------------------------------------------------------------------------------
4592
4593 // --------------------------------------------------------------------------------
4594 // Function : privDirCheck()
4595 // Description :
4596 // Check if a directory exists, if not it creates it and all the parents directory
4597 // which may be useful.
4598 // Parameters :
4599 // $p_dir : Directory path to check.
4600 // Return Values :
4601 // 1 : OK
4602 // -1 : Unable to create directory
4603 // --------------------------------------------------------------------------------
4604 public function privDirCheck($p_dir, $p_is_dir = false)
4605 {
4606 $v_result = 1;
4607
4608 // ----- Remove the final '/'
4609 if (($p_is_dir) && (substr($p_dir, -1)=='/')) {
4610 $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
4611 }
4612
4613 // ----- Check the directory availability
4614 if ((is_dir($p_dir)) || ($p_dir == "")) {
4615 return 1;
4616 }
4617
4618 // ----- Extract parent directory
4619 $p_parent_dir = dirname($p_dir);
4620
4621 // ----- Just a check
4622 if ($p_parent_dir != $p_dir) {
4623 // ----- Look for parent directory
4624 if ($p_parent_dir != "") {
4625 if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) {
4626 return $v_result;
4627 }
4628 }
4629 }
4630
4631 // ----- Create the directory
4632 if (!@mkdir($p_dir, 0777)) {
4633 // ----- Error log
4634 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
4635
4636 // ----- Return
4637 return WpaiPclZip::errorCode();
4638 }
4639
4640 // ----- Return
4641 return $v_result;
4642 }
4643 // --------------------------------------------------------------------------------
4644
4645 // --------------------------------------------------------------------------------
4646 // Function : privMerge()
4647 // Description :
4648 // If $p_archive_to_add does not exist, the function exit with a success result.
4649 // Parameters :
4650 // Return Values :
4651 // --------------------------------------------------------------------------------
4652 public function privMerge(&$p_archive_to_add)
4653 {
4654 $v_result=1;
4655
4656 // ----- Look if the archive_to_add exists
4657 if (!is_file($p_archive_to_add->zipname)) {
4658 // ----- Nothing to merge, so merge is a success
4659 $v_result = 1;
4660
4661 // ----- Return
4662 return $v_result;
4663 }
4664
4665 // ----- Look if the archive exists
4666 if (!is_file($this->zipname)) {
4667 // ----- Do a duplicate
4668 $v_result = $this->privDuplicate($p_archive_to_add->zipname);
4669
4670 // ----- Return
4671 return $v_result;
4672 }
4673
4674 // ----- Open the zip file
4675 if (($v_result=$this->privOpenFd('rb')) != 1) {
4676 // ----- Return
4677 return $v_result;
4678 }
4679
4680 // ----- Read the central directory informations
4681 $v_central_dir = array();
4682 if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) {
4683 $this->privCloseFd();
4684 return $v_result;
4685 }
4686
4687 // ----- Go to beginning of File
4688 @rewind($this->zip_fd);
4689
4690 // ----- Open the archive_to_add file
4691 if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) {
4692 $this->privCloseFd();
4693
4694 // ----- Return
4695 return $v_result;
4696 }
4697
4698 // ----- Read the central directory informations
4699 $v_central_dir_to_add = array();
4700 if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) {
4701 $this->privCloseFd();
4702 $p_archive_to_add->privCloseFd();
4703
4704 return $v_result;
4705 }
4706
4707 // ----- Go to beginning of File
4708 @rewind($p_archive_to_add->zip_fd);
4709
4710 // ----- Creates a temporay file
4711 $v_zip_temp_name = WPAI_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4712
4713 // ----- Open the temporary file in write mode
4714 if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
4715 $this->privCloseFd();
4716 $p_archive_to_add->privCloseFd();
4717
4718 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
4719
4720 // ----- Return
4721 return WpaiPclZip::errorCode();
4722 }
4723
4724 // ----- Copy the files from the archive to the temporary file
4725 // TBC : Here I should better append the file and go back to erase the central dir
4726 $v_size = $v_central_dir['offset'];
4727 while ($v_size != 0) {
4728 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
4729 $v_buffer = fread($this->zip_fd, $v_read_size);
4730 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4731 $v_size -= $v_read_size;
4732 }
4733
4734 // ----- Copy the files from the archive_to_add into the temporary file
4735 $v_size = $v_central_dir_to_add['offset'];
4736 while ($v_size != 0) {
4737 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
4738 $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
4739 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4740 $v_size -= $v_read_size;
4741 }
4742
4743 // ----- Store the offset of the central dir
4744 $v_offset = @ftell($v_zip_temp_fd);
4745
4746 // ----- Copy the block of file headers from the old archive
4747 $v_size = $v_central_dir['size'];
4748 while ($v_size != 0) {
4749 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
4750 $v_buffer = @fread($this->zip_fd, $v_read_size);
4751 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4752 $v_size -= $v_read_size;
4753 }
4754
4755 // ----- Copy the block of file headers from the archive_to_add
4756 $v_size = $v_central_dir_to_add['size'];
4757 while ($v_size != 0) {
4758 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
4759 $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
4760 @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
4761 $v_size -= $v_read_size;
4762 }
4763
4764 // ----- Merge the file comments
4765 $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
4766
4767 // ----- Calculate the size of the (new) central header
4768 $v_size = @ftell($v_zip_temp_fd)-$v_offset;
4769
4770 // ----- Swap the file descriptor
4771 // Here is a trick : I swap the temporary fd with the zip fd, in order to use
4772 // the following methods on the temporary fil and not the real archive fd
4773 $v_swap = $this->zip_fd;
4774 $this->zip_fd = $v_zip_temp_fd;
4775 $v_zip_temp_fd = $v_swap;
4776
4777 // ----- Create the central dir footer
4778 if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) {
4779 $this->privCloseFd();
4780 $p_archive_to_add->privCloseFd();
4781 @fclose($v_zip_temp_fd);
4782 $this->zip_fd = null;
4783
4784 // ----- Reset the file list
4785 unset($v_header_list);
4786
4787 // ----- Return
4788 return $v_result;
4789 }
4790
4791 // ----- Swap back the file descriptor
4792 $v_swap = $this->zip_fd;
4793 $this->zip_fd = $v_zip_temp_fd;
4794 $v_zip_temp_fd = $v_swap;
4795
4796 // ----- Close
4797 $this->privCloseFd();
4798 $p_archive_to_add->privCloseFd();
4799
4800 // ----- Close the temporary file
4801 @fclose($v_zip_temp_fd);
4802
4803 // ----- Delete the zip file
4804 // TBC : I should test the result ...
4805 @unlink($this->zipname);
4806
4807 // ----- Rename the temporary file
4808 // TBC : I should test the result ...
4809 //@rename($v_zip_temp_name, $this->zipname);
4810 WpaiPclZipUtilRename($v_zip_temp_name, $this->zipname);
4811
4812 // ----- Return
4813 return $v_result;
4814 }
4815 // --------------------------------------------------------------------------------
4816
4817 // --------------------------------------------------------------------------------
4818 // Function : privDuplicate()
4819 // Description :
4820 // Parameters :
4821 // Return Values :
4822 // --------------------------------------------------------------------------------
4823 public function privDuplicate($p_archive_filename)
4824 {
4825 $v_result=1;
4826
4827 // ----- Look if the $p_archive_filename exists
4828 if (!is_file($p_archive_filename)) {
4829 // ----- Nothing to duplicate, so duplicate is a success.
4830 $v_result = 1;
4831
4832 // ----- Return
4833 return $v_result;
4834 }
4835
4836 // ----- Open the zip file
4837 if (($v_result=$this->privOpenFd('wb')) != 1) {
4838 // ----- Return
4839 return $v_result;
4840 }
4841
4842 // ----- Open the temporary file in write mode
4843 if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) {
4844 $this->privCloseFd();
4845
4846 WpaiPclZip::privErrorLog(WPAI_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
4847
4848 // ----- Return
4849 return WpaiPclZip::errorCode();
4850 }
4851
4852 // ----- Copy the files from the archive to the temporary file
4853 // TBC : Here I should better append the file and go back to erase the central dir
4854 $v_size = filesize($p_archive_filename);
4855 while ($v_size != 0) {
4856 $v_read_size = ($v_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $v_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
4857 $v_buffer = fread($v_zip_temp_fd, $v_read_size);
4858 @fwrite($this->zip_fd, $v_buffer, $v_read_size);
4859 $v_size -= $v_read_size;
4860 }
4861
4862 // ----- Close
4863 $this->privCloseFd();
4864
4865 // ----- Close the temporary file
4866 @fclose($v_zip_temp_fd);
4867
4868 // ----- Return
4869 return $v_result;
4870 }
4871 // --------------------------------------------------------------------------------
4872
4873 // --------------------------------------------------------------------------------
4874 // Function : privErrorLog()
4875 // Description :
4876 // Parameters :
4877 // --------------------------------------------------------------------------------
4878 public function privErrorLog($p_error_code = 0, $p_error_string = '')
4879 {
4880 if (WPAI_PCLZIP_ERROR_EXTERNAL == 1) {
4881 // External error handling not implemented - fallback to internal
4882 $this->error_code = $p_error_code;
4883 $this->error_string = $p_error_string;
4884 } else {
4885 $this->error_code = $p_error_code;
4886 $this->error_string = $p_error_string;
4887 }
4888 }
4889 // --------------------------------------------------------------------------------
4890
4891 // --------------------------------------------------------------------------------
4892 // Function : privErrorReset()
4893 // Description :
4894 // Parameters :
4895 // --------------------------------------------------------------------------------
4896 public function privErrorReset()
4897 {
4898 if (WPAI_PCLZIP_ERROR_EXTERNAL == 1) {
4899 // External error handling not implemented - fallback to internal
4900 $this->error_code = 0;
4901 $this->error_string = '';
4902 } else {
4903 $this->error_code = 0;
4904 $this->error_string = '';
4905 }
4906 }
4907 // --------------------------------------------------------------------------------
4908
4909 // --------------------------------------------------------------------------------
4910 // Function : privDisableMagicQuotes()
4911 // Description :
4912 // Parameters :
4913 // Return Values :
4914 // --------------------------------------------------------------------------------
4915 public function privDisableMagicQuotes()
4916 {
4917 $v_result=1;
4918
4919 // ----- Look if function exists or if functions are deprecated/removed in running PHP version.
4920 if (version_compare(PHP_VERSION, '7.4.0', '>=') || (!function_exists("get_magic_quotes_runtime")) || (!function_exists("set_magic_quotes_runtime"))) {
4921 return $v_result;
4922 }
4923
4924 // ----- Look if already done
4925 if ($this->magic_quotes_status != -1) {
4926 return $v_result;
4927 }
4928
4929 // ----- Get and memorize the magic_quote value
4930 $this->magic_quotes_status = @get_magic_quotes_runtime();
4931
4932 // ----- Return
4933 return $v_result;
4934 }
4935 // --------------------------------------------------------------------------------
4936
4937 // --------------------------------------------------------------------------------
4938 // Function : privSwapBackMagicQuotes()
4939 // Description :
4940 // Parameters :
4941 // Return Values :
4942 // --------------------------------------------------------------------------------
4943 public function privSwapBackMagicQuotes()
4944 {
4945 $v_result=1;
4946
4947 // ----- Look if function exists
4948 if ((!function_exists("get_magic_quotes_runtime")) || (!function_exists("set_magic_quotes_runtime"))) {
4949 return $v_result;
4950 }
4951
4952 // ----- Look if something to do
4953 if ($this->magic_quotes_status != -1) {
4954 return $v_result;
4955 }
4956
4957 // ----- Return
4958 return $v_result;
4959 }
4960 // --------------------------------------------------------------------------------
4961 }
4962 // End of class
4963 // --------------------------------------------------------------------------------
4964
4965 // --------------------------------------------------------------------------------
4966 // Function : WpaiPclZipUtilPathReduction()
4967 // Description :
4968 // Parameters :
4969 // Return Values :
4970 // --------------------------------------------------------------------------------
4971 function WpaiPclZipUtilPathReduction($p_dir)
4972 {
4973 $v_result = "";
4974
4975 // ----- Look for not empty path
4976 if ($p_dir != "") {
4977 // ----- Explode path by directory names
4978 $v_list = explode("/", $p_dir);
4979
4980 // ----- Study directories from last to first
4981 $v_skip = 0;
4982 for ($i=sizeof($v_list)-1; $i>=0; $i--) {
4983 // ----- Look for current path
4984 if ($v_list[$i] == ".") {
4985 // ----- Ignore this directory
4986 // Should be the first $i=0, but no check is done
4987 } elseif ($v_list[$i] == "..") {
4988 $v_skip++;
4989 } elseif ($v_list[$i] == "") {
4990 // ----- First '/' i.e. root slash
4991 if ($i == 0) {
4992 $v_result = "/".$v_result;
4993 if ($v_skip > 0) {
4994 // ----- It is an invalid path, so the path is not modified
4995 // TBC
4996 $v_result = $p_dir;
4997 $v_skip = 0;
4998 }
4999 } elseif ($i == (sizeof($v_list)-1)) {
5000 // ----- Last '/' i.e. indicates a directory
5001 $v_result = $v_list[$i];
5002 } else {
5003 // ----- Double '/' inside the path
5004 // ----- Ignore only the double '//' in path,
5005 // but not the first and last '/'
5006 }
5007 } else {
5008 // ----- Look for item to skip
5009 if ($v_skip > 0) {
5010 $v_skip--;
5011 } else {
5012 $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
5013 }
5014 }
5015 }
5016
5017 // ----- Look for skip
5018 if ($v_skip > 0) {
5019 while ($v_skip > 0) {
5020 $v_result = '../'.$v_result;
5021 $v_skip--;
5022 }
5023 }
5024 }
5025
5026 // ----- Return
5027 return $v_result;
5028 }
5029 // --------------------------------------------------------------------------------
5030
5031 // --------------------------------------------------------------------------------
5032 // Function : WpaiPclZipUtilPathInclusion()
5033 // Description :
5034 // This function indicates if the path $p_path is under the $p_dir tree. Or,
5035 // said in an other way, if the file or sub-dir $p_path is inside the dir
5036 // $p_dir.
5037 // The function indicates also if the path is exactly the same as the dir.
5038 // This function supports path with duplicated '/' like '//', but does not
5039 // support '.' or '..' statements.
5040 // Parameters :
5041 // Return Values :
5042 // 0 if $p_path is not inside directory $p_dir
5043 // 1 if $p_path is inside directory $p_dir
5044 // 2 if $p_path is exactly the same as $p_dir
5045 // --------------------------------------------------------------------------------
5046 function WpaiPclZipUtilPathInclusion($p_dir, $p_path)
5047 {
5048 $v_result = 1;
5049
5050 // ----- Look for path beginning by ./
5051 if (($p_dir == '.') || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
5052 $p_dir = WpaiPclZipUtilTranslateWinPath(getcwd(), false) . '/' . substr($p_dir, 1);
5053 }
5054 if (($p_path == '.') || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
5055 $p_path = WpaiPclZipUtilTranslateWinPath(getcwd(), false) . '/' . substr($p_path, 1);
5056 }
5057
5058 // ----- Explode dir and path by directory separator
5059 $v_list_dir = explode("/", $p_dir);
5060 $v_list_dir_size = sizeof($v_list_dir);
5061 $v_list_path = explode("/", $p_path);
5062 $v_list_path_size = sizeof($v_list_path);
5063
5064 // ----- Study directories paths
5065 $i = 0;
5066 $j = 0;
5067 while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
5068 // ----- Look for empty dir (path reduction)
5069 if ($v_list_dir[$i] == '') {
5070 $i++;
5071 continue;
5072 }
5073 if ($v_list_path[$j] == '') {
5074 $j++;
5075 continue;
5076 }
5077
5078 // ----- Compare the items
5079 if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ($v_list_path[$j] != '')) {
5080 $v_result = 0;
5081 }
5082
5083 // ----- Next items
5084 $i++;
5085 $j++;
5086 }
5087
5088 // ----- Look if everything seems to be the same
5089 if ($v_result) {
5090 // ----- Skip all the empty items
5091 while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) {
5092 $j++;
5093 }
5094 while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) {
5095 $i++;
5096 }
5097
5098 if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
5099 // ----- There are exactly the same
5100 $v_result = 2;
5101 } elseif ($i < $v_list_dir_size) {
5102 // ----- The path is shorter than the dir
5103 $v_result = 0;
5104 }
5105 }
5106
5107 // ----- Return
5108 return $v_result;
5109 }
5110 // --------------------------------------------------------------------------------
5111
5112 // --------------------------------------------------------------------------------
5113 // Function : WpaiPclZipUtilCopyBlock()
5114 // Description :
5115 // Parameters :
5116 // $p_mode : read/write compression mode
5117 // 0 : src & dest normal
5118 // 1 : src gzip, dest normal
5119 // 2 : src normal, dest gzip
5120 // 3 : src & dest gzip
5121 // Return Values :
5122 // --------------------------------------------------------------------------------
5123 function WpaiPclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode = 0)
5124 {
5125 $v_result = 1;
5126
5127 if ($p_mode==0) {
5128 while ($p_size != 0) {
5129 $v_read_size = ($p_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $p_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
5130 $v_buffer = @fread($p_src, $v_read_size);
5131 @fwrite($p_dest, $v_buffer, $v_read_size);
5132 $p_size -= $v_read_size;
5133 }
5134 } elseif ($p_mode==1) {
5135 while ($p_size != 0) {
5136 $v_read_size = ($p_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $p_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
5137 $v_buffer = @gzread($p_src, $v_read_size);
5138 @fwrite($p_dest, $v_buffer, $v_read_size);
5139 $p_size -= $v_read_size;
5140 }
5141 } elseif ($p_mode==2) {
5142 while ($p_size != 0) {
5143 $v_read_size = ($p_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $p_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
5144 $v_buffer = @fread($p_src, $v_read_size);
5145 @gzwrite($p_dest, $v_buffer, $v_read_size);
5146 $p_size -= $v_read_size;
5147 }
5148 } elseif ($p_mode==3) {
5149 while ($p_size != 0) {
5150 $v_read_size = ($p_size < WPAI_PCLZIP_READ_BLOCK_SIZE ? $p_size : WPAI_PCLZIP_READ_BLOCK_SIZE);
5151 $v_buffer = @gzread($p_src, $v_read_size);
5152 @gzwrite($p_dest, $v_buffer, $v_read_size);
5153 $p_size -= $v_read_size;
5154 }
5155 }
5156
5157 // ----- Return
5158 return $v_result;
5159 }
5160 // --------------------------------------------------------------------------------
5161
5162 // --------------------------------------------------------------------------------
5163 // Function : WpaiPclZipUtilRename()
5164 // Description :
5165 // This function tries to do a simple rename() function. If it fails, it
5166 // tries to copy the $p_src file in a new $p_dest file and then unlink the
5167 // first one.
5168 // Parameters :
5169 // $p_src : Old filename
5170 // $p_dest : New filename
5171 // Return Values :
5172 // 1 on success, 0 on failure.
5173 // --------------------------------------------------------------------------------
5174 function WpaiPclZipUtilRename($p_src, $p_dest)
5175 {
5176 $v_result = 1;
5177
5178 // ----- Try to rename the files
5179 if (!@rename($p_src, $p_dest)) {
5180 // ----- Try to copy & unlink the src
5181 if (!@copy($p_src, $p_dest)) {
5182 $v_result = 0;
5183 } elseif (!@unlink($p_src)) {
5184 $v_result = 0;
5185 }
5186 }
5187
5188 // ----- Return
5189 return $v_result;
5190 }
5191 // --------------------------------------------------------------------------------
5192
5193 // --------------------------------------------------------------------------------
5194 // Function : WpaiPclZipUtilOptionText()
5195 // Description :
5196 // Translate option value in text. Mainly for debug purpose.
5197 // Parameters :
5198 // $p_option : the option value.
5199 // Return Values :
5200 // The option text value.
5201 // --------------------------------------------------------------------------------
5202 function WpaiPclZipUtilOptionText($p_option)
5203 {
5204 $v_list = get_defined_constants();
5205 for (reset($v_list); $v_key = key($v_list); next($v_list)) {
5206 $v_prefix = substr($v_key, 0, 10);
5207 if ((($v_prefix == 'WPAI_PCLZIP_OPT') || ($v_prefix == 'WPAI_PCLZIP_CB_') || ($v_prefix == 'WPAI_PCLZIP_ATT')) && ($v_list[$v_key] == $p_option)) {
5208 return $v_key;
5209 }
5210 }
5211
5212 $v_result = 'Unknown';
5213
5214 return $v_result;
5215 }
5216 // --------------------------------------------------------------------------------
5217
5218 // --------------------------------------------------------------------------------
5219 // Function : WpaiPclZipUtilTranslateWinPath()
5220 // Description :
5221 // Translate windows path by replacing '\' by '/' and optionally removing
5222 // drive letter.
5223 // Parameters :
5224 // $p_path : path to translate.
5225 // $p_remove_disk_letter : true | false
5226 // Return Values :
5227 // The path translated.
5228 // --------------------------------------------------------------------------------
5229 function WpaiPclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter = true)
5230 {
5231 if (stristr(php_uname(), 'windows')) {
5232 // ----- Look for potential disk letter
5233 if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
5234 $p_path = substr($p_path, $v_position+1);
5235 }
5236 // ----- Change potential windows directory separator
5237 if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
5238 $p_path = strtr($p_path, '\\', '/');
5239 }
5240 }
5241 return $p_path;
5242 }
5243
5244 function WpaiPclZipGetAbsPath($path) {
5245 $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
5246 $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
5247 $absolutes = array();
5248 foreach ($parts as $part) {
5249 if ('.' == $part) continue;
5250 if ('..' == $part) {
5251 array_pop($absolutes);
5252 } else {
5253 $absolutes[] = $part;
5254 }
5255 }
5256 return implode(DIRECTORY_SEPARATOR, $absolutes);
5257 }
5258 endif;
5259