PHPExcel

# Source for file pclzip.lib.php

Documentation is available at pclzip.lib.php

1. <?php
2. // --------------------------------------------------------------------------------
3. // PhpConcept Library - Zip Module 2.8.2
4. // --------------------------------------------------------------------------------
5. // License GNU/LGPL - Vincent Blavet - August 2009
6. // http://www.phpconcept.net
7. // --------------------------------------------------------------------------------
8. //
9. // Presentation :
10. // PclZip is a PHP library that manage ZIP archives.
11. // So far tests show that archives generated by PclZip are readable by
12. // WinZip application and other tools.
13. //
14. // Description :
15. // See readme.txt and http://www.phpconcept.net
16. //
17. // Warning :
18. // This library and the associated files are non commercial, non professional
19. // work.
20. // It should not have unexpected results. However if any damage is caused by
21. // this software the author can not be responsible.
22. // The use of this software is at the risk of the user.
23. //
24. // --------------------------------------------------------------------------------
25. // $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
26. // --------------------------------------------------------------------------------
28. // ----- Constants
29. if (! defined ('PCLZIP_READ_BLOCK_SIZE')) {
30. define ( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
31. }
33. // ----- File list separator
34. // In version 1.x of PclZip, the separator for file list is a space
35. // (which is not a very smart choice, specifically for windows paths !).
36. // A better separator should be a comma (,). This constant gives you the
37. // abilty to change that.
38. // However notice that changing this value, may have impact on existing
39. // scripts, using space separated filenames.
40. // Recommanded values for compatibility with older versions :
41. //define( 'PCLZIP_SEPARATOR', ' ' );
42. // Recommanded values for smart separation of filenames.
43. if (! defined ('PCLZIP_SEPARATOR')) {
44. define ( 'PCLZIP_SEPARATOR', ',' );
45. }
47. // ----- Error configuration
48. // 0 : PclZip Class integrated error handling
49. // 1 : PclError external library error handling. By enabling this
50. // you must ensure that you have included PclError library.
51. // [2,...] : reserved for futur use
52. if (! defined ('PCLZIP_ERROR_EXTERNAL')) {
53. define ( 'PCLZIP_ERROR_EXTERNAL', 0 );
54. }
56. // ----- Optional static temporary directory
57. // By default temporary files are generated in the script current
58. // path.
59. // If defined :
60. // - MUST BE terminated by a '/'.
61. // - MUST be a valid, already created directory
62. // Samples :
63. // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
64. // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
65. if (! defined ('PCLZIP_TEMPORARY_DIR')) {
66. define ( 'PCLZIP_TEMPORARY_DIR', '' );
67. }
69. // ----- Optional threshold ratio for use of temporary files
70. // Pclzip sense the size of the file to add/extract and decide to
71. // use or not temporary file. The algorythm is looking for
72. // memory_limit of PHP and apply a ratio.
73. // threshold = memory_limit * ratio.
74. // Recommended values are under 0.5. Default 0.47.
75. // Samples :
76. // define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
77. if (! defined ('PCLZIP_TEMPORARY_FILE_RATIO')) {
78. define ( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
79. }
81. // --------------------------------------------------------------------------------
82. // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
83. // --------------------------------------------------------------------------------
85. // ----- Global variables
86. $g_pclzip_version = "2.8.2";
88. // ----- Error codes
89. // -1 : Unable to open file in binary write mode
90. // -2 : Unable to open file in binary read mode
91. // -3 : Invalid parameters
92. // -4 : File does not exist
93. // -5 : Filename is too long (max. 255)
94. // -6 : Not a valid zip file
95. // -7 : Invalid extracted file size
96. // -8 : Unable to create directory
97. // -9 : Invalid archive extension
98. // -10 : Invalid archive format
99. // -11 : Unable to delete file (unlink)
100. // -12 : Unable to rename file (rename)
101. // -13 : Invalid header checksum
102. // -14 : Invalid archive size
103. define ( 'PCLZIP_ERR_USER_ABORTED', 2 );
104. define ( 'PCLZIP_ERR_NO_ERROR', 0 );
105. define ( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
106. define ( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
107. define ( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
108. define ( 'PCLZIP_ERR_MISSING_FILE', -4 );
109. define ( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
110. define ( 'PCLZIP_ERR_INVALID_ZIP', -6 );
111. define ( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
112. define ( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
113. define ( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
114. define ( 'PCLZIP_ERR_BAD_FORMAT', -10 );
115. define ( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
116. define ( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
117. define ( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
118. define ( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
119. define ( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
120. define ( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
121. define ( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
122. define ( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
123. define ( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
124. define ( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
125. define ( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
127. // ----- Options values
128. define ( 'PCLZIP_OPT_PATH', 77001 );
129. define ( 'PCLZIP_OPT_ADD_PATH', 77002 );
130. define ( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
131. define ( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
132. define ( 'PCLZIP_OPT_SET_CHMOD', 77005 );
133. define ( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
134. define ( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
135. define ( 'PCLZIP_OPT_BY_NAME', 77008 );
136. define ( 'PCLZIP_OPT_BY_INDEX', 77009 );
137. define ( 'PCLZIP_OPT_BY_EREG', 77010 );
138. define ( 'PCLZIP_OPT_BY_PREG', 77011 );
139. define ( 'PCLZIP_OPT_COMMENT', 77012 );
140. define ( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
141. define ( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
142. define ( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
143. define ( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
144. define ( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
145. // Having big trouble with crypt. Need to multiply 2 long int
146. // which is not correctly supported by PHP ...
147. //define( 'PCLZIP_OPT_CRYPT', 77018 );
148. define ( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
149. define ( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
150. define ( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
151. define ( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
152. define ( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
153. define ( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
154. define ( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
156. // ----- File description attributes
157. define ( 'PCLZIP_ATT_FILE_NAME', 79001 );
158. define ( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
159. define ( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
160. define ( 'PCLZIP_ATT_FILE_MTIME', 79004 );
161. define ( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
162. define ( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
164. // ----- Call backs values
165. define ( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
166. define ( 'PCLZIP_CB_POST_EXTRACT', 78002 );
167. define ( 'PCLZIP_CB_PRE_ADD', 78003 );
168. define ( 'PCLZIP_CB_POST_ADD', 78004 );
169. /* For futur use
170. define( 'PCLZIP_CB_PRE_LIST', 78005 );
171. define( 'PCLZIP_CB_POST_LIST', 78006 );
172. define( 'PCLZIP_CB_PRE_DELETE', 78007 );
173. define( 'PCLZIP_CB_POST_DELETE', 78008 );
174. */
176. // --------------------------------------------------------------------------------
177. // Class : PclZip
178. // Description :
179. // PclZip is the class that represent a Zip archive.
180. // The public methods allow the manipulation of the archive.
181. // Attributes :
182. // Attributes must not be accessed directly.
183. // Methods :
184. // PclZip() : Object creator
185. // create() : Creates the Zip archive
186. // listContent() : List the content of the Zip archive
187. // extract() : Extract the content of the archive
188. // properties() : List the properties of the archive
189. // --------------------------------------------------------------------------------
190. class PclZip
191. {
192. // ----- Filename of the zip file
193. var $zipname = '';
195. // ----- File descriptor of the zip file
196. var $zip_fd = 0;
198. // ----- Internal error handling
199. var $error_code = 1;
200. var $error_string = '';
202. // ----- Current status of the magic_quotes_runtime
203. // This value store the php configuration for magic_quotes
204. // The class can then disable the magic_quotes and reset it after
205. var $magic_quotes_status ;
207. // --------------------------------------------------------------------------------
208. // Function : PclZip()
209. // Description :
210. // Creates a PclZip object and set the name of the associated Zip archive
211. // filename.
212. // Note that no real action is taken, if the archive does not exist it is not
213. // created. Use create() for that.
214. // --------------------------------------------------------------------------------
215. function PclZip ($p_zipname)
216. {
218. // ----- Tests the zlib
219. if (! function_exists ('gzopen'))
220. {
221. die('Abort '.basename (__FILE__).' : Missing zlib extensions');
222. }
224. // ----- Set the attributes
225. $this-> zipname = $p_zipname;
226. $this-> zip_fd = 0;
227. $this-> magic_quotes_status = -1;
229. // ----- Return
230. return;
231. }
232. // --------------------------------------------------------------------------------
234. // --------------------------------------------------------------------------------
235. // Function :
236. // create($p_filelist, $p_add_dir="", $p_remove_dir="")
237. // create($p_filelist, $p_option, $p_option_value, ...)
238. // Description :
239. // This method supports two different synopsis. The first one is historical.
240. // This method creates a Zip Archive. The Zip file is created in the
241. // filesystem. The files and directories indicated in $p_filelist
242. // are added in the archive. See the parameters description for the
243. // supported format of $p_filelist.
244. // When a directory is in the list, the directory and its content is added
245. // in the archive.
246. // In this synopsis, the function takes an optional variable list of
247. // options. See bellow the supported options.
248. // Parameters :
249. // $p_filelist : An array containing file or directory names, or
250. // a string containing one filename or one directory name, or
251. // a string containing a list of filenames and/or directory
252. // names separated by spaces.
253. // $p_add_dir : A path to add before the real path of the archived file,
254. // in order to have it memorized in the archive.
255. // $p_remove_dir : A path to remove from the real path of the file to archive,
256. // in order to have a shorter path memorized in the archive.
257. // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
258. // is removed first, before $p_add_dir is added.
259. // Options :
260. // PCLZIP_OPT_ADD_PATH :
261. // PCLZIP_OPT_REMOVE_PATH :
262. // PCLZIP_OPT_REMOVE_ALL_PATH :
263. // PCLZIP_OPT_COMMENT :
264. // PCLZIP_CB_PRE_ADD :
265. // PCLZIP_CB_POST_ADD :
266. // Return Values :
267. // 0 on failure,
268. // The list of the added files, with a status of the add action.
269. // (see PclZip::listContent() for list entry format)
270. // --------------------------------------------------------------------------------
271. function create ($p_filelist)
272. {
273. $v_result=1;
275. // ----- Reset the error handler
276. $this-> privErrorReset ();
278. // ----- Set default values
279. $v_options = array();
280. $v_options[ PCLZIP_OPT_NO_COMPRESSION ] = FALSE;
282. // ----- Look for variable options arguments
283. $v_size = func_num_args ();
285. // ----- Look for arguments
286. if ($v_size > 1) {
287. // ----- Get the arguments
288. $v_arg_list = func_get_args ();
290. // ----- Remove from the options list the first argument
291. array_shift ($v_arg_list);
292. $v_size--;
294. // ----- Look for first arg
295. if (( is_integer ($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
297. // ----- Parse the options
298. $v_result = $this-> privParseOptions ($v_arg_list, $v_size, $v_options,
299. array ( PCLZIP_OPT_REMOVE_PATH => 'optional',
300. PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
301. PCLZIP_OPT_ADD_PATH => 'optional',
302. PCLZIP_CB_PRE_ADD => 'optional',
303. PCLZIP_CB_POST_ADD => 'optional',
304. PCLZIP_OPT_NO_COMPRESSION => 'optional',
305. PCLZIP_OPT_COMMENT => 'optional',
306. PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
307. PCLZIP_OPT_TEMP_FILE_ON => 'optional',
308. PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
309. //, PCLZIP_OPT_CRYPT => 'optional'
310. ));
311. if ($v_result != 1) {
312. return 0;
313. }
314. }
316. // ----- Look for 2 args
317. // Here we need to support the first historic synopsis of the
318. // method.
319. else {
321. // ----- Get the first argument
322. $v_options[ PCLZIP_OPT_ADD_PATH ] = $v_arg_list[0];
324. // ----- Look for the optional second argument
325. if ($v_size == 2) {
326. $v_options[ PCLZIP_OPT_REMOVE_PATH ] = $v_arg_list[1];
327. }
328. else if ($v_size > 2) {
329. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER ,
330. "Invalid number / type of arguments");
331. return 0;
332. }
333. }
334. }
336. // ----- Look for default option values
337. $this-> privOptionDefaultThreshold ($v_options);
339. // ----- Init
340. $v_string_list = array();
341. $v_att_list = array();
342. $v_filedescr_list = array();
343. $p_result_list = array();
345. // ----- Look if the $p_filelist is really an array
346. if ( is_array ($p_filelist)) {
348. // ----- Look if the first element is also an array
349. // This will mean that this is a file description entry
350. if (isset($p_filelist[0]) && is_array ($p_filelist[0])) {
351. $v_att_list = $p_filelist;
352. }
354. // ----- The list is a list of string names
355. else {
356. $v_string_list = $p_filelist;
357. }
358. }
360. // ----- Look if the $p_filelist is a string
361. else if ( is_string ($p_filelist)) {
362. // ----- Create a list from the string
363. $v_string_list = explode ( PCLZIP_SEPARATOR , $p_filelist);
364. }
366. // ----- Invalid variable type for $p_filelist
367. else {
368. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid variable type p_filelist");
369. return 0;
370. }
372. // ----- Reformat the string list
373. if ( sizeof ($v_string_list) != 0) {
374. foreach ($v_string_list as $v_string) {
375. if ($v_string != '') {
376. $v_att_list[][ PCLZIP_ATT_FILE_NAME ] = $v_string;
377. }
378. else {
379. }
380. }
381. }
383. // ----- For each file in the list check the attributes
384. $v_supported_attributes
385. = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
386. , PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
387. , PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
388. , PCLZIP_ATT_FILE_MTIME => 'optional'
389. , PCLZIP_ATT_FILE_CONTENT => 'optional'
390. , PCLZIP_ATT_FILE_COMMENT => 'optional'
391. );
392. foreach ($v_att_list as $v_entry) {
393. $v_result = $this-> privFileDescrParseAtt ($v_entry,
394. $v_filedescr_list[],
395. $v_options,
396. $v_supported_attributes);
397. if ($v_result != 1) {
398. return 0;
399. }
400. }
402. // ----- Expand the filelist (expand directories)
403. $v_result = $this-> privFileDescrExpand ($v_filedescr_list, $v_options);
404. if ($v_result != 1) {
405. return 0;
406. }
408. // ----- Call the create fct
409. $v_result = $this-> privCreate ($v_filedescr_list, $p_result_list, $v_options);
410. if ($v_result != 1) {
411. return 0;
412. }
414. // ----- Return
415. return $p_result_list;
416. }
417. // --------------------------------------------------------------------------------
419. // --------------------------------------------------------------------------------
420. // Function :
421. // add($p_filelist, $p_add_dir="", $p_remove_dir="")
422. // add($p_filelist, $p_option, $p_option_value, ...)
423. // Description :
424. // This method supports two synopsis. The first one is historical.
425. // This methods add the list of files in an existing archive.
426. // If a file with the same name already exists, it is added at the end of the
427. // archive, the first one is still present.
428. // If the archive does not exist, it is created.
429. // Parameters :
430. // $p_filelist : An array containing file or directory names, or
431. // a string containing one filename or one directory name, or
432. // a string containing a list of filenames and/or directory
433. // names separated by spaces.
434. // $p_add_dir : A path to add before the real path of the archived file,
435. // in order to have it memorized in the archive.
436. // $p_remove_dir : A path to remove from the real path of the file to archive,
437. // in order to have a shorter path memorized in the archive.
438. // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
439. // is removed first, before $p_add_dir is added.
440. // Options :
441. // PCLZIP_OPT_ADD_PATH :
442. // PCLZIP_OPT_REMOVE_PATH :
443. // PCLZIP_OPT_REMOVE_ALL_PATH :
444. // PCLZIP_OPT_COMMENT :
445. // PCLZIP_OPT_ADD_COMMENT :
446. // PCLZIP_OPT_PREPEND_COMMENT :
447. // PCLZIP_CB_PRE_ADD :
448. // PCLZIP_CB_POST_ADD :
449. // Return Values :
450. // 0 on failure,
451. // The list of the added files, with a status of the add action.
452. // (see PclZip::listContent() for list entry format)
453. // --------------------------------------------------------------------------------
454. function add ($p_filelist)
455. {
456. $v_result=1;
458. // ----- Reset the error handler
459. $this-> privErrorReset ();
461. // ----- Set default values
462. $v_options = array();
463. $v_options[ PCLZIP_OPT_NO_COMPRESSION ] = FALSE;
465. // ----- Look for variable options arguments
466. $v_size = func_num_args ();
468. // ----- Look for arguments
469. if ($v_size > 1) {
470. // ----- Get the arguments
471. $v_arg_list = func_get_args ();
473. // ----- Remove form the options list the first argument
474. array_shift ($v_arg_list);
475. $v_size--;
477. // ----- Look for first arg
478. if (( is_integer ($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
480. // ----- Parse the options
481. $v_result = $this-> privParseOptions ($v_arg_list, $v_size, $v_options,
482. array ( PCLZIP_OPT_REMOVE_PATH => 'optional',
483. PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
484. PCLZIP_OPT_ADD_PATH => 'optional',
485. PCLZIP_CB_PRE_ADD => 'optional',
486. PCLZIP_CB_POST_ADD => 'optional',
487. PCLZIP_OPT_NO_COMPRESSION => 'optional',
488. PCLZIP_OPT_COMMENT => 'optional',
489. PCLZIP_OPT_ADD_COMMENT => 'optional',
490. PCLZIP_OPT_PREPEND_COMMENT => 'optional',
491. PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
492. PCLZIP_OPT_TEMP_FILE_ON => 'optional',
493. PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
494. //, PCLZIP_OPT_CRYPT => 'optional'
495. ));
496. if ($v_result != 1) {
497. return 0;
498. }
499. }
501. // ----- Look for 2 args
502. // Here we need to support the first historic synopsis of the
503. // method.
504. else {
506. // ----- Get the first argument
507. $v_options[ PCLZIP_OPT_ADD_PATH ] = $v_add_path = $v_arg_list[0];
509. // ----- Look for the optional second argument
510. if ($v_size == 2) {
511. $v_options[ PCLZIP_OPT_REMOVE_PATH ] = $v_arg_list[1];
512. }
513. else if ($v_size > 2) {
514. // ----- Error log
515. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid number / type of arguments");
517. // ----- Return
518. return 0;
519. }
520. }
521. }
523. // ----- Look for default option values
524. $this-> privOptionDefaultThreshold ($v_options);
526. // ----- Init
527. $v_string_list = array();
528. $v_att_list = array();
529. $v_filedescr_list = array();
530. $p_result_list = array();
532. // ----- Look if the $p_filelist is really an array
533. if ( is_array ($p_filelist)) {
535. // ----- Look if the first element is also an array
536. // This will mean that this is a file description entry
537. if (isset($p_filelist[0]) && is_array ($p_filelist[0])) {
538. $v_att_list = $p_filelist;
539. }
541. // ----- The list is a list of string names
542. else {
543. $v_string_list = $p_filelist;
544. }
545. }
547. // ----- Look if the $p_filelist is a string
548. else if ( is_string ($p_filelist)) {
549. // ----- Create a list from the string
550. $v_string_list = explode ( PCLZIP_SEPARATOR , $p_filelist);
551. }
553. // ----- Invalid variable type for $p_filelist
554. else {
555. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid variable type '".gettype ($p_filelist)."' for p_filelist");
556. return 0;
557. }
559. // ----- Reformat the string list
560. if ( sizeof ($v_string_list) != 0) {
561. foreach ($v_string_list as $v_string) {
562. $v_att_list[][ PCLZIP_ATT_FILE_NAME ] = $v_string;
563. }
564. }
566. // ----- For each file in the list check the attributes
567. $v_supported_attributes
568. = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
569. , PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
570. , PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
571. , PCLZIP_ATT_FILE_MTIME => 'optional'
572. , PCLZIP_ATT_FILE_CONTENT => 'optional'
573. , PCLZIP_ATT_FILE_COMMENT => 'optional'
574. );
575. foreach ($v_att_list as $v_entry) {
576. $v_result = $this-> privFileDescrParseAtt ($v_entry,
577. $v_filedescr_list[],
578. $v_options,
579. $v_supported_attributes);
580. if ($v_result != 1) {
581. return 0;
582. }
583. }
585. // ----- Expand the filelist (expand directories)
586. $v_result = $this-> privFileDescrExpand ($v_filedescr_list, $v_options);
587. if ($v_result != 1) {
588. return 0;
589. }
591. // ----- Call the create fct
592. $v_result = $this-> privAdd ($v_filedescr_list, $p_result_list, $v_options);
593. if ($v_result != 1) {
594. return 0;
595. }
597. // ----- Return
598. return $p_result_list;
599. }
600. // --------------------------------------------------------------------------------
602. // --------------------------------------------------------------------------------
603. // Function : listContent()
604. // Description :
605. // This public method, gives the list of the files and directories, with their
606. // properties.
607. // The properties of each entries in the list are (used also in other functions) :
608. // filename : Name of the file. For a create or add action it is the filename
609. // given by the user. For an extract function it is the filename
610. // of the extracted file.
611. // stored_filename : Name of the file / directory stored in the archive.
612. // size : Size of the stored file.
613. // compressed_size : Size of the file's data compressed in the archive
614. // (without the headers overhead)
615. // mtime : Last known modification date of the file (UNIX timestamp)
616. // comment : Comment associated with the file
617. // folder : true | false
618. // index : index of the file in the archive
619. // status : status of the action (depending of the action) :
620. // Values are :
621. // ok : OK !
622. // filtered : the file / dir is not extracted (filtered by user)
623. // already_a_directory : the file can not be extracted because a
624. // directory with the same name already exists
625. // write_protected : the file can not be extracted because a file
626. // with the same name already exists and is
627. // write protected
628. // newer_exist : the file was not extracted because a newer file exists
629. // path_creation_fail : the file is not extracted because the folder
630. // does not exist and can not be created
631. // write_error : the file was not extracted because there was a
632. // error while writing the file
633. // read_error : the file was not extracted because there was a error
634. // while reading the file
635. // invalid_header : the file was not extracted because of an archive
636. // format error (bad file header)
637. // Note that each time a method can continue operating when there
638. // is an action error on a file, the error is only logged in the file status.
639. // Return Values :
640. // 0 on an unrecoverable failure,
641. // The list of the files in the archive.
642. // --------------------------------------------------------------------------------
643. function listContent ()
644. {
645. $v_result=1;
647. // ----- Reset the error handler
648. $this-> privErrorReset ();
650. // ----- Check archive
651. if (!$this-> privCheckFormat ()) {
652. return(0);
653. }
655. // ----- Call the extracting fct
656. $p_list = array();
657. if (($v_result = $this-> privList ($p_list)) != 1)
658. {
659. unset($p_list);
660. return(0);
661. }
663. // ----- Return
664. return $p_list;
665. }
666. // --------------------------------------------------------------------------------
668. // --------------------------------------------------------------------------------
669. // Function :
670. // extract($p_path="./", $p_remove_path="")
671. // extract([$p_option, $p_option_value, ...])
672. // Description :
673. // This method supports two synopsis. The first one is historical.
674. // This method extract all the files / directories from the archive to the
675. // folder indicated in $p_path.
676. // If you want to ignore the 'root' part of path of the memorized files
677. // you can indicate this in the optional $p_remove_path parameter.
678. // By default, if a newer file with the same name already exists, the
679. // file is not extracted.
680. //
681. // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
682. // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
683. // at the end of the path value of PCLZIP_OPT_PATH.
684. // Parameters :
685. // $p_path : Path where the files and directories are to be extracted
686. // $p_remove_path : First part ('root' part) of the memorized path
687. // (if any similar) to remove while extracting.
688. // Options :
689. // PCLZIP_OPT_PATH :
690. // PCLZIP_OPT_ADD_PATH :
691. // PCLZIP_OPT_REMOVE_PATH :
692. // PCLZIP_OPT_REMOVE_ALL_PATH :
693. // PCLZIP_CB_PRE_EXTRACT :
694. // PCLZIP_CB_POST_EXTRACT :
695. // Return Values :
696. // 0 or a negative value on failure,
697. // The list of the extracted files, with a status of the action.
698. // (see PclZip::listContent() for list entry format)
699. // --------------------------------------------------------------------------------
700. function extract ()
701. {
702. $v_result=1;
704. // ----- Reset the error handler
705. $this-> privErrorReset ();
707. // ----- Check archive
708. if (!$this-> privCheckFormat ()) {
709. return(0);
710. }
712. // ----- Set default values
713. $v_options = array();
714. // $v_path = "./";
715. $v_path = '';
716. $v_remove_path = "";
717. $v_remove_all_path = false;
719. // ----- Look for variable options arguments
720. $v_size = func_num_args ();
722. // ----- Default values for option
723. $v_options[ PCLZIP_OPT_EXTRACT_AS_STRING ] = FALSE;
725. // ----- Look for arguments
726. if ($v_size > 0) {
727. // ----- Get the arguments
728. $v_arg_list = func_get_args ();
730. // ----- Look for first arg
731. if (( is_integer ($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
733. // ----- Parse the options
734. $v_result = $this-> privParseOptions ($v_arg_list, $v_size, $v_options,
735. array ( PCLZIP_OPT_PATH => 'optional',
736. PCLZIP_OPT_REMOVE_PATH => 'optional',
737. PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
738. PCLZIP_OPT_ADD_PATH => 'optional',
739. PCLZIP_CB_PRE_EXTRACT => 'optional',
740. PCLZIP_CB_POST_EXTRACT => 'optional',
741. PCLZIP_OPT_SET_CHMOD => 'optional',
742. PCLZIP_OPT_BY_NAME => 'optional',
743. PCLZIP_OPT_BY_EREG => 'optional',
744. PCLZIP_OPT_BY_PREG => 'optional',
745. PCLZIP_OPT_BY_INDEX => 'optional',
746. PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
747. PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
748. PCLZIP_OPT_REPLACE_NEWER => 'optional'
749. , PCLZIP_OPT_STOP_ON_ERROR => 'optional'
750. , PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
751. PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
752. PCLZIP_OPT_TEMP_FILE_ON => 'optional',
753. PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
754. ));
755. if ($v_result != 1) {
756. return 0;
757. }
759. // ----- Set the arguments
760. if (isset($v_options[ PCLZIP_OPT_PATH ])) {
761. $v_path = $v_options[ PCLZIP_OPT_PATH ];
762. }
763. if (isset($v_options[ PCLZIP_OPT_REMOVE_PATH ])) {
764. $v_remove_path = $v_options[ PCLZIP_OPT_REMOVE_PATH ];
765. }
766. if (isset($v_options[ PCLZIP_OPT_REMOVE_ALL_PATH ])) {
767. $v_remove_all_path = $v_options[ PCLZIP_OPT_REMOVE_ALL_PATH ];
768. }
769. if (isset($v_options[ PCLZIP_OPT_ADD_PATH ])) {
770. // ----- Check for '/' in last path char
771. if (( strlen ($v_path) > 0) && ( substr ($v_path, -1) != '/')) {
772. $v_path .= '/';
773. }
774. $v_path .= $v_options[ PCLZIP_OPT_ADD_PATH ];
775. }
776. }
778. // ----- Look for 2 args
779. // Here we need to support the first historic synopsis of the
780. // method.
781. else {
783. // ----- Get the first argument
784. $v_path = $v_arg_list[0];
786. // ----- Look for the optional second argument
787. if ($v_size == 2) {
788. $v_remove_path = $v_arg_list[1];
789. }
790. else if ($v_size > 2) {
791. // ----- Error log
792. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid number / type of arguments");
794. // ----- Return
795. return 0;
796. }
797. }
798. }
800. // ----- Look for default option values
801. $this-> privOptionDefaultThreshold ($v_options);
803. // ----- Trace
805. // ----- Call the extracting fct
806. $p_list = array();
807. $v_result = $this-> privExtractByRule ($p_list, $v_path, $v_remove_path,
808. $v_remove_all_path, $v_options);
809. if ($v_result < 1) {
810. unset($p_list);
811. return(0);
812. }
814. // ----- Return
815. return $p_list;
816. }
817. // --------------------------------------------------------------------------------
820. // --------------------------------------------------------------------------------
821. // Function :
822. // extractByIndex($p_index, $p_path="./", $p_remove_path="")
823. // extractByIndex($p_index, [$p_option, $p_option_value, ...])
824. // Description :
825. // This method supports two synopsis. The first one is historical.
826. // This method is doing a partial extract of the archive.
827. // The extracted files or folders are identified by their index in the
828. // archive (from 0 to n).
829. // Note that if the index identify a folder, only the folder entry is
830. // extracted, not all the files included in the archive.
831. // Parameters :
832. // $p_index : A single index (integer) or a string of indexes of files to
833. // extract. The form of the string is "0,4-6,8-12" with only numbers
834. // and '-' for range or ',' to separate ranges. No spaces or ';'
835. // are allowed.
836. // $p_path : Path where the files and directories are to be extracted
837. // $p_remove_path : First part ('root' part) of the memorized path
838. // (if any similar) to remove while extracting.
839. // Options :
840. // PCLZIP_OPT_PATH :
841. // PCLZIP_OPT_ADD_PATH :
842. // PCLZIP_OPT_REMOVE_PATH :
843. // PCLZIP_OPT_REMOVE_ALL_PATH :
844. // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
845. // not as files.
846. // The resulting content is in a new field 'content' in the file
847. // structure.
848. // This option must be used alone (any other options are ignored).
849. // PCLZIP_CB_PRE_EXTRACT :
850. // PCLZIP_CB_POST_EXTRACT :
851. // Return Values :
852. // 0 on failure,
853. // The list of the extracted files, with a status of the action.
854. // (see PclZip::listContent() for list entry format)
855. // --------------------------------------------------------------------------------
856. //function extractByIndex($p_index, options...)
857. function extractByIndex ($p_index)
858. {
859. $v_result=1;
861. // ----- Reset the error handler
862. $this-> privErrorReset ();
864. // ----- Check archive
865. if (!$this-> privCheckFormat ()) {
866. return(0);
867. }
869. // ----- Set default values
870. $v_options = array();
871. // $v_path = "./";
872. $v_path = '';
873. $v_remove_path = "";
874. $v_remove_all_path = false;
876. // ----- Look for variable options arguments
877. $v_size = func_num_args ();
879. // ----- Default values for option
880. $v_options[ PCLZIP_OPT_EXTRACT_AS_STRING ] = FALSE;
882. // ----- Look for arguments
883. if ($v_size > 1) {
884. // ----- Get the arguments
885. $v_arg_list = func_get_args ();
887. // ----- Remove form the options list the first argument
888. array_shift ($v_arg_list);
889. $v_size--;
891. // ----- Look for first arg
892. if (( is_integer ($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
894. // ----- Parse the options
895. $v_result = $this-> privParseOptions ($v_arg_list, $v_size, $v_options,
896. array ( PCLZIP_OPT_PATH => 'optional',
897. PCLZIP_OPT_REMOVE_PATH => 'optional',
898. PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
899. PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
900. PCLZIP_OPT_ADD_PATH => 'optional',
901. PCLZIP_CB_PRE_EXTRACT => 'optional',
902. PCLZIP_CB_POST_EXTRACT => 'optional',
903. PCLZIP_OPT_SET_CHMOD => 'optional',
904. PCLZIP_OPT_REPLACE_NEWER => 'optional'
905. , PCLZIP_OPT_STOP_ON_ERROR => 'optional'
906. , PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
907. PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
908. PCLZIP_OPT_TEMP_FILE_ON => 'optional',
909. PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
910. ));
911. if ($v_result != 1) {
912. return 0;
913. }
915. // ----- Set the arguments
916. if (isset($v_options[ PCLZIP_OPT_PATH ])) {
917. $v_path = $v_options[ PCLZIP_OPT_PATH ];
918. }
919. if (isset($v_options[ PCLZIP_OPT_REMOVE_PATH ])) {
920. $v_remove_path = $v_options[ PCLZIP_OPT_REMOVE_PATH ];
921. }
922. if (isset($v_options[ PCLZIP_OPT_REMOVE_ALL_PATH ])) {
923. $v_remove_all_path = $v_options[ PCLZIP_OPT_REMOVE_ALL_PATH ];
924. }
925. if (isset($v_options[ PCLZIP_OPT_ADD_PATH ])) {
926. // ----- Check for '/' in last path char
927. if (( strlen ($v_path) > 0) && ( substr ($v_path, -1) != '/')) {
928. $v_path .= '/';
929. }
930. $v_path .= $v_options[ PCLZIP_OPT_ADD_PATH ];
931. }
932. if (!isset($v_options[ PCLZIP_OPT_EXTRACT_AS_STRING ])) {
933. $v_options[ PCLZIP_OPT_EXTRACT_AS_STRING ] = FALSE;
934. }
935. else {
936. }
937. }
939. // ----- Look for 2 args
940. // Here we need to support the first historic synopsis of the
941. // method.
942. else {
944. // ----- Get the first argument
945. $v_path = $v_arg_list[0];
947. // ----- Look for the optional second argument
948. if ($v_size == 2) {
949. $v_remove_path = $v_arg_list[1];
950. }
951. else if ($v_size > 2) {
952. // ----- Error log
953. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid number / type of arguments");
955. // ----- Return
956. return 0;
957. }
958. }
959. }
961. // ----- Trace
963. // ----- Trick
964. // Here I want to reuse extractByRule(), so I need to parse the $p_index
965. // with privParseOptions()
966. $v_arg_trick = array ( PCLZIP_OPT_BY_INDEX , $p_index);
967. $v_options_trick = array();
968. $v_result = $this-> privParseOptions ($v_arg_trick, sizeof ($v_arg_trick), $v_options_trick,
969. array ( PCLZIP_OPT_BY_INDEX => 'optional' ));
970. if ($v_result != 1) {
971. return 0;
972. }
973. $v_options[ PCLZIP_OPT_BY_INDEX ] = $v_options_trick[ PCLZIP_OPT_BY_INDEX ];
975. // ----- Look for default option values
976. $this-> privOptionDefaultThreshold ($v_options);
978. // ----- Call the extracting fct
979. if (($v_result = $this-> privExtractByRule ($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
980. return(0);
981. }
983. // ----- Return
984. return $p_list;
985. }
986. // --------------------------------------------------------------------------------
988. // --------------------------------------------------------------------------------
989. // Function :
990. // delete([$p_option, $p_option_value, ...])
991. // Description :
992. // This method removes files from the archive.
993. // If no parameters are given, then all the archive is emptied.
994. // Parameters :
995. // None or optional arguments.
996. // Options :
997. // PCLZIP_OPT_BY_INDEX :
998. // PCLZIP_OPT_BY_NAME :
999. // PCLZIP_OPT_BY_EREG :
1000. // PCLZIP_OPT_BY_PREG :
1001. // Return Values :
1002. // 0 on failure,
1003. // The list of the files which are still present in the archive.
1004. // (see PclZip::listContent() for list entry format)
1005. // --------------------------------------------------------------------------------
1006. function delete ()
1007. {
1008. $v_result=1;
1010. // ----- Reset the error handler
1011. $this-> privErrorReset ();
1013. // ----- Check archive
1014. if (!$this-> privCheckFormat ()) {
1015. return(0);
1016. }
1018. // ----- Set default values
1019. $v_options = array();
1021. // ----- Look for variable options arguments
1022. $v_size = func_num_args ();
1024. // ----- Look for arguments
1025. if ($v_size > 0) {
1026. // ----- Get the arguments
1027. $v_arg_list = func_get_args ();
1029. // ----- Parse the options
1030. $v_result = $this-> privParseOptions ($v_arg_list, $v_size, $v_options,
1031. array ( PCLZIP_OPT_BY_NAME => 'optional',
1032. PCLZIP_OPT_BY_EREG => 'optional',
1033. PCLZIP_OPT_BY_PREG => 'optional',
1034. PCLZIP_OPT_BY_INDEX => 'optional' ));
1035. if ($v_result != 1) {
1036. return 0;
1037. }
1038. }
1040. // ----- Magic quotes trick
1041. $this-> privDisableMagicQuotes ();
1043. // ----- Call the delete fct
1044. $v_list = array();
1045. if (($v_result = $this-> privDeleteByRule ($v_list, $v_options)) != 1) {
1046. $this-> privSwapBackMagicQuotes ();
1047. unset($v_list);
1048. return(0);
1049. }
1051. // ----- Magic quotes trick
1052. $this-> privSwapBackMagicQuotes ();
1054. // ----- Return
1055. return $v_list;
1056. }
1057. // --------------------------------------------------------------------------------
1059. // --------------------------------------------------------------------------------
1060. // Function : deleteByIndex()
1061. // Description :
1062. // ***** Deprecated *****
1063. // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1064. // --------------------------------------------------------------------------------
1065. function deleteByIndex ($p_index)
1066. {
1068. $p_list = $this-> delete ( PCLZIP_OPT_BY_INDEX , $p_index);
1070. // ----- Return
1071. return $p_list;
1072. }
1073. // --------------------------------------------------------------------------------
1075. // --------------------------------------------------------------------------------
1076. // Function : properties()
1077. // Description :
1078. // This method gives the properties of the archive.
1079. // The properties are :
1080. // nb : Number of files in the archive
1081. // comment : Comment associated with the archive file
1082. // status : not_exist, ok
1083. // Parameters :
1084. // None
1085. // Return Values :
1086. // 0 on failure,
1087. // An array with the archive properties.
1088. // --------------------------------------------------------------------------------
1089. function properties ()
1090. {
1092. // ----- Reset the error handler
1093. $this-> privErrorReset ();
1095. // ----- Magic quotes trick
1096. $this-> privDisableMagicQuotes ();
1098. // ----- Check archive
1099. if (!$this-> privCheckFormat ()) {
1100. $this-> privSwapBackMagicQuotes ();
1101. return(0);
1102. }
1104. // ----- Default properties
1105. $v_prop = array();
1106. $v_prop['comment'] = '';
1107. $v_prop['nb'] = 0;
1108. $v_prop['status'] = 'not_exist';
1110. // ----- Look if file exists
1111. if (@ is_file ($this-> zipname ))
1112. {
1113. // ----- Open the zip file
1114. if (($this-> zip_fd = @ fopen ($this-> zipname , 'rb')) == 0)
1115. {
1116. $this-> privSwapBackMagicQuotes ();
1118. // ----- Error log
1119. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open archive \''.$this-> zipname.'\' in binary read mode');
1121. // ----- Return
1122. return 0;
1123. }
1125. // ----- Read the central directory informations
1126. $v_central_dir = array();
1127. if (($v_result = $this-> privReadEndCentralDir ($v_central_dir)) != 1)
1128. {
1129. $this-> privSwapBackMagicQuotes ();
1130. return 0;
1131. }
1133. // ----- Close the zip file
1134. $this-> privCloseFd ();
1136. // ----- Set the user attributes
1137. $v_prop['comment'] = $v_central_dir['comment'];
1138. $v_prop['nb'] = $v_central_dir['entries'];
1139. $v_prop['status'] = 'ok';
1140. }
1142. // ----- Magic quotes trick
1143. $this-> privSwapBackMagicQuotes ();
1145. // ----- Return
1146. return $v_prop;
1147. }
1148. // --------------------------------------------------------------------------------
1150. // --------------------------------------------------------------------------------
1151. // Function : duplicate()
1152. // Description :
1153. // This method creates an archive by copying the content of an other one. If
1154. // the archive already exist, it is replaced by the new one without any warning.
1155. // Parameters :
1156. // $p_archive : The filename of a valid archive, or
1157. // a valid PclZip object.
1158. // Return Values :
1159. // 1 on success.
1160. // 0 or a negative value on error (error code).
1161. // --------------------------------------------------------------------------------
1162. function duplicate ($p_archive)
1163. {
1164. $v_result = 1;
1166. // ----- Reset the error handler
1167. $this-> privErrorReset ();
1169. // ----- Look if the $p_archive is a PclZip object
1170. if (( is_object ($p_archive)) && ( get_class ($p_archive) == 'pclzip'))
1171. {
1173. // ----- Duplicate the archive
1174. $v_result = $this-> privDuplicate ($p_archive->zipname);
1175. }
1177. // ----- Look if the $p_archive is a string (so a filename)
1178. else if ( is_string ($p_archive))
1179. {
1181. // ----- Check that $p_archive is a valid zip file
1182. // TBC : Should also check the archive format
1183. if (! is_file ($p_archive)) {
1184. // ----- Error log
1185. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_FILE , "No file with filename '".$p_archive."'");
1186. $v_result = PCLZIP_ERR_MISSING_FILE ;
1187. }
1188. else {
1189. // ----- Duplicate the archive
1190. $v_result = $this-> privDuplicate ($p_archive);
1191. }
1192. }
1194. // ----- Invalid variable
1195. else
1196. {
1197. // ----- Error log
1198. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid variable type p_archive_to_add");
1199. $v_result = PCLZIP_ERR_INVALID_PARAMETER ;
1200. }
1202. // ----- Return
1203. return $v_result;
1204. }
1205. // --------------------------------------------------------------------------------
1207. // --------------------------------------------------------------------------------
1208. // Function : merge()
1209. // Description :
1210. // This method merge the $p_archive_to_add archive at the end of the current
1211. // one ($this).
1212. // If the archive ($this) does not exist, the merge becomes a duplicate.
1213. // If the $p_archive_to_add archive does not exist, the merge is a success.
1214. // Parameters :
1215. // $p_archive_to_add : It can be directly the filename of a valid zip archive,
1216. // or a PclZip object archive.
1217. // Return Values :
1218. // 1 on success,
1219. // 0 or negative values on error (see below).
1220. // --------------------------------------------------------------------------------
1221. function merge ($p_archive_to_add)
1222. {
1223. $v_result = 1;
1225. // ----- Reset the error handler
1226. $this-> privErrorReset ();
1228. // ----- Check archive
1229. if (!$this-> privCheckFormat ()) {
1230. return(0);
1231. }
1233. // ----- Look if the $p_archive_to_add is a PclZip object
1234. if (( is_object ($p_archive_to_add)) && ( get_class ($p_archive_to_add) == 'pclzip'))
1235. {
1237. // ----- Merge the archive
1238. $v_result = $this-> privMerge ($p_archive_to_add);
1239. }
1241. // ----- Look if the $p_archive_to_add is a string (so a filename)
1242. else if ( is_string ($p_archive_to_add))
1243. {
1245. // ----- Create a temporary archive
1246. $v_object_archive = new PclZip ($p_archive_to_add);
1248. // ----- Merge the archive
1249. $v_result = $this-> privMerge ($v_object_archive);
1250. }
1252. // ----- Invalid variable
1253. else
1254. {
1255. // ----- Error log
1256. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid variable type p_archive_to_add");
1257. $v_result = PCLZIP_ERR_INVALID_PARAMETER ;
1258. }
1260. // ----- Return
1261. return $v_result;
1262. }
1263. // --------------------------------------------------------------------------------
1267. // --------------------------------------------------------------------------------
1268. // Function : errorCode()
1269. // Description :
1270. // Parameters :
1271. // --------------------------------------------------------------------------------
1272. function errorCode ()
1273. {
1274. if ( PCLZIP_ERROR_EXTERNAL == 1) {
1275. return(PclErrorCode());
1276. }
1277. else {
1278. return($this-> error_code );
1279. }
1280. }
1281. // --------------------------------------------------------------------------------
1283. // --------------------------------------------------------------------------------
1284. // Function : errorName()
1285. // Description :
1286. // Parameters :
1287. // --------------------------------------------------------------------------------
1288. function errorName ($p_with_code=false)
1289. {
1290. $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1291. PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1292. PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1293. PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1294. PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1295. PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1296. PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1297. PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1298. PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1299. PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1300. PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1301. PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1302. PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1303. PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1304. PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1305. PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1306. PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1307. PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1308. PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
1309. , PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
1310. , PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
1311. );
1313. if (isset($v_name[$this-> error_code ])) {
1314. $v_value = $v_name[$this-> error_code ];
1315. }
1316. else {
1317. $v_value = 'NoName';
1318. }
1320. if ($p_with_code) {
1321. return($v_value.' ('.$this-> error_code.')');
1322. }
1323. else {
1324. return($v_value);
1325. }
1326. }
1327. // --------------------------------------------------------------------------------
1329. // --------------------------------------------------------------------------------
1330. // Function : errorInfo()
1331. // Description :
1332. // Parameters :
1333. // --------------------------------------------------------------------------------
1334. function errorInfo ($p_full=false)
1335. {
1336. if ( PCLZIP_ERROR_EXTERNAL == 1) {
1337. return(PclErrorString());
1338. }
1339. else {
1340. if ($p_full) {
1341. return($this-> errorName (true)." : ".$this-> error_string );
1342. }
1343. else {
1344. return($this-> error_string." [code ".$this-> error_code."]");
1345. }
1346. }
1347. }
1348. // --------------------------------------------------------------------------------
1351. // --------------------------------------------------------------------------------
1352. // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1353. // ***** *****
1354. // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1355. // --------------------------------------------------------------------------------
1359. // --------------------------------------------------------------------------------
1360. // Function : privCheckFormat()
1361. // Description :
1362. // This method check that the archive exists and is a valid zip archive.
1363. // Several level of check exists. (futur)
1364. // Parameters :
1365. // $p_level : Level of check. Default 0.
1366. // 0 : Check the first bytes (magic codes) (default value))
1367. // 1 : 0 + Check the central directory (futur)
1368. // 2 : 1 + Check each file header (futur)
1369. // Return Values :
1370. // true on success,
1371. // false on error, the error code is set.
1372. // --------------------------------------------------------------------------------
1373. function privCheckFormat ($p_level=0)
1374. {
1375. $v_result = true;
1377. // ----- Reset the file system cache
1378. clearstatcache ();
1380. // ----- Reset the error handler
1381. $this-> privErrorReset ();
1383. // ----- Look if the file exits
1384. if (! is_file ($this-> zipname )) {
1385. // ----- Error log
1386. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_FILE , "Missing archive file '".$this-> zipname."'");
1387. return(false);
1388. }
1390. // ----- Check that the file is readeable
1391. if (! is_readable ($this-> zipname )) {
1392. // ----- Error log
1393. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , "Unable to read archive '".$this-> zipname."'");
1394. return(false);
1395. }
1397. // ----- Check the magic code
1398. // TBC
1400. // ----- Check the central header
1401. // TBC
1403. // ----- Check each file header
1404. // TBC
1406. // ----- Return
1407. return $v_result;
1408. }
1409. // --------------------------------------------------------------------------------
1411. // --------------------------------------------------------------------------------
1412. // Function : privParseOptions()
1413. // Description :
1414. // This internal methods reads the variable list of arguments ($p_options_list,
1415. // $p_size) and generate an array with the options and values ($v_result_list).
1416. // $v_requested_options contains the options that can be present and those that
1417. // must be present.
1418. // $v_requested_options is an array, with the option value as key, and 'optional',
1419. // or 'mandatory' as value.
1420. // Parameters :
1421. // See above.
1422. // Return Values :
1423. // 1 on success.
1424. // 0 on failure.
1425. // --------------------------------------------------------------------------------
1426. function privParseOptions (&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1427. {
1428. $v_result=1;
1430. // ----- Read the options
1431. $i=0;
1432. while ($i<$p_size) {
1434. // ----- Check if the option is supported
1435. if (!isset($v_requested_options[$p_options_list[$i]])) {
1436. // ----- Error log
1437. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1439. // ----- Return
1440. return PclZip :: errorCode ();
1441. }
1443. // ----- Look for next option
1444. switch ($p_options_list[$i]) {
1445. // ----- Look for options that request a path value
1446. case PCLZIP_OPT_PATH :
1447. case PCLZIP_OPT_REMOVE_PATH :
1448. case PCLZIP_OPT_ADD_PATH :
1449. // ----- Check the number of parameters
1450. if (($i+1) >= $p_size) {
1451. // ----- Error log
1452. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1454. // ----- Return
1455. return PclZip :: errorCode ();
1456. }
1458. // ----- Get the value
1459. $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath ($p_options_list[$i+1], FALSE);
1460. $i++;
1461. break;
1463. case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
1464. // ----- Check the number of parameters
1465. if (($i+1) >= $p_size) {
1466. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1467. return PclZip :: errorCode ();
1468. }
1470. // ----- Check for incompatible options
1471. if (isset($v_result_list[ PCLZIP_OPT_TEMP_FILE_OFF ])) {
1472. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Option '".PclZipUtilOptionText ($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1473. return PclZip :: errorCode ();
1474. }
1476. // ----- Check the value
1477. $v_value = $p_options_list[$i+1];
1478. if ((! is_integer ($v_value)) || ($v_value<0)) {
1479. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Integer expected for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1480. return PclZip :: errorCode ();
1481. }
1483. // ----- Get the value (and convert it in bytes)
1484. $v_result_list[$p_options_list[$i]] = $v_value*1048576;
1485. $i++;
1486. break;
1488. case PCLZIP_OPT_TEMP_FILE_ON :
1489. // ----- Check for incompatible options
1490. if (isset($v_result_list[ PCLZIP_OPT_TEMP_FILE_OFF ])) {
1491. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Option '".PclZipUtilOptionText ($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1492. return PclZip :: errorCode ();
1493. }
1495. $v_result_list[$p_options_list[$i]] = true;
1496. break;
1498. case PCLZIP_OPT_TEMP_FILE_OFF :
1499. // ----- Check for incompatible options
1500. if (isset($v_result_list[ PCLZIP_OPT_TEMP_FILE_ON ])) {
1501. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Option '".PclZipUtilOptionText ($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
1502. return PclZip :: errorCode ();
1503. }
1504. // ----- Check for incompatible options
1505. if (isset($v_result_list[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ])) {
1506. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Option '".PclZipUtilOptionText ($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1507. return PclZip :: errorCode ();
1508. }
1510. $v_result_list[$p_options_list[$i]] = true;
1511. break;
1513. case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
1514. // ----- Check the number of parameters
1515. if (($i+1) >= $p_size) {
1516. // ----- Error log
1517. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1519. // ----- Return
1520. return PclZip :: errorCode ();
1521. }
1523. // ----- Get the value
1524. if ( is_string ($p_options_list[$i+1])
1525. && ($p_options_list[$i+1] != '')) {
1526. $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath ($p_options_list[$i+1], FALSE);
1527. $i++;
1528. }
1529. else {
1530. }
1531. break;
1533. // ----- Look for options that request an array of string for value
1534. case PCLZIP_OPT_BY_NAME :
1535. // ----- Check the number of parameters
1536. if (($i+1) >= $p_size) {
1537. // ----- Error log
1538. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1540. // ----- Return
1541. return PclZip :: errorCode ();
1542. }
1544. // ----- Get the value
1545. if ( is_string ($p_options_list[$i+1])) {
1546. $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1547. }
1548. else if ( is_array ($p_options_list[$i+1])) {
1549. $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1550. }
1551. else {
1552. // ----- Error log
1553. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Wrong parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1555. // ----- Return
1556. return PclZip :: errorCode ();
1557. }
1558. $i++;
1559. break;
1561. // ----- Look for options that request an EREG or PREG expression
1562. case PCLZIP_OPT_BY_EREG :
1563. // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
1564. // to PCLZIP_OPT_BY_PREG
1565. $p_options_list[$i] = PCLZIP_OPT_BY_PREG ;
1566. case PCLZIP_OPT_BY_PREG :
1567. //case PCLZIP_OPT_CRYPT :
1568. // ----- Check the number of parameters
1569. if (($i+1) >= $p_size) {
1570. // ----- Error log
1571. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1573. // ----- Return
1574. return PclZip :: errorCode ();
1575. }
1577. // ----- Get the value
1578. if ( is_string ($p_options_list[$i+1])) {
1579. $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1580. }
1581. else {
1582. // ----- Error log
1583. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Wrong parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1585. // ----- Return
1586. return PclZip :: errorCode ();
1587. }
1588. $i++;
1589. break;
1591. // ----- Look for options that takes a string
1592. case PCLZIP_OPT_COMMENT :
1593. case PCLZIP_OPT_ADD_COMMENT :
1594. case PCLZIP_OPT_PREPEND_COMMENT :
1595. // ----- Check the number of parameters
1596. if (($i+1) >= $p_size) {
1597. // ----- Error log
1598. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE ,
1599. "Missing parameter value for option '"
1600. .PclZipUtilOptionText ($p_options_list[$i])
1601. ."'");
1603. // ----- Return
1604. return PclZip :: errorCode ();
1605. }
1607. // ----- Get the value
1608. if ( is_string ($p_options_list[$i+1])) {
1609. $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1610. }
1611. else {
1612. // ----- Error log
1613. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE ,
1614. "Wrong parameter value for option '"
1615. .PclZipUtilOptionText ($p_options_list[$i])
1616. ."'");
1618. // ----- Return
1619. return PclZip :: errorCode ();
1620. }
1621. $i++;
1622. break;
1624. // ----- Look for options that request an array of index
1625. case PCLZIP_OPT_BY_INDEX :
1626. // ----- Check the number of parameters
1627. if (($i+1) >= $p_size) {
1628. // ----- Error log
1629. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1631. // ----- Return
1632. return PclZip :: errorCode ();
1633. }
1635. // ----- Get the value
1636. $v_work_list = array();
1637. if ( is_string ($p_options_list[$i+1])) {
1639. // ----- Remove spaces
1640. $p_options_list[$i+1] = strtr ($p_options_list[$i+1], ' ', '');
1642. // ----- Parse items
1643. $v_work_list = explode (",", $p_options_list[$i+1]);
1644. }
1645. else if ( is_integer ($p_options_list[$i+1])) {
1646. $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1647. }
1648. else if ( is_array ($p_options_list[$i+1])) {
1649. $v_work_list = $p_options_list[$i+1];
1650. }
1651. else {
1652. // ----- Error log
1653. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Value must be integer, string or array for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1655. // ----- Return
1656. return PclZip :: errorCode ();
1657. }
1659. // ----- Reduce the index list
1660. // each index item in the list must be a couple with a start and
1661. // an end value : [0,3], [5-5], [8-10], ...
1662. // ----- Check the format of each item
1663. $v_sort_flag=false;
1664. $v_sort_value=0;
1665. for ($j=0; $j<sizeof ($v_work_list); $j++) {
1666. // ----- Explode the item
1667. $v_item_list = explode ("-", $v_work_list[$j]);
1668. $v_size_item_list = sizeof ($v_item_list);
1670. // ----- TBC : Here we might check that each item is a
1671. // real integer ...
1673. // ----- Look for single value
1674. if ($v_size_item_list == 1) {
1675. // ----- Set the option value
1676. $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1677. $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1678. }
1679. elseif ($v_size_item_list == 2) {
1680. // ----- Set the option value
1681. $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1682. $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1683. }
1684. else {
1685. // ----- Error log
1686. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Too many values in index range for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1688. // ----- Return
1689. return PclZip :: errorCode ();
1690. }
1693. // ----- Look for list sort
1694. if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1695. $v_sort_flag=true;
1697. // ----- TBC : An automatic sort should be writen ...
1698. // ----- Error log
1699. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Invalid order of index range for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1701. // ----- Return
1702. return PclZip :: errorCode ();
1703. }
1704. $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1705. }
1707. // ----- Sort the items
1708. if ($v_sort_flag) {
1709. // TBC : To Be Completed
1710. }
1712. // ----- Next option
1713. $i++;
1714. break;
1716. // ----- Look for options that request no value
1717. case PCLZIP_OPT_REMOVE_ALL_PATH :
1718. case PCLZIP_OPT_EXTRACT_AS_STRING :
1719. case PCLZIP_OPT_NO_COMPRESSION :
1720. case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1721. case PCLZIP_OPT_REPLACE_NEWER :
1722. case PCLZIP_OPT_STOP_ON_ERROR :
1723. $v_result_list[$p_options_list[$i]] = true;
1724. break;
1726. // ----- Look for options that request an octal value
1727. case PCLZIP_OPT_SET_CHMOD :
1728. // ----- Check the number of parameters
1729. if (($i+1) >= $p_size) {
1730. // ----- Error log
1731. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1733. // ----- Return
1734. return PclZip :: errorCode ();
1735. }
1737. // ----- Get the value
1738. $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1739. $i++;
1740. break;
1742. // ----- Look for options that request a call-back
1743. case PCLZIP_CB_PRE_EXTRACT :
1744. case PCLZIP_CB_POST_EXTRACT :
1745. case PCLZIP_CB_PRE_ADD :
1746. case PCLZIP_CB_POST_ADD :
1747. /* for futur use
1748. case PCLZIP_CB_PRE_DELETE :
1749. case PCLZIP_CB_POST_DELETE :
1750. case PCLZIP_CB_PRE_LIST :
1751. case PCLZIP_CB_POST_LIST :
1752. */
1753. // ----- Check the number of parameters
1754. if (($i+1) >= $p_size) {
1755. // ----- Error log
1756. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_OPTION_VALUE , "Missing parameter value for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1758. // ----- Return
1759. return PclZip :: errorCode ();
1760. }
1762. // ----- Get the value
1763. $v_function_name = $p_options_list[$i+1];
1765. // ----- Check that the value is a valid existing function
1766. if (! function_exists ($v_function_name)) {
1767. // ----- Error log
1768. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_OPTION_VALUE , "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText ($p_options_list[$i])."'");
1770. // ----- Return
1771. return PclZip :: errorCode ();
1772. }
1774. // ----- Set the attribute
1775. $v_result_list[$p_options_list[$i]] = $v_function_name;
1776. $i++;
1777. break;
1779. default :
1780. // ----- Error log
1781. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER ,
1782. "Unknown parameter '"
1783. .$p_options_list[$i]."'");
1785. // ----- Return
1786. return PclZip :: errorCode ();
1787. }
1789. // ----- Next options
1790. $i++;
1791. }
1793. // ----- Look for mandatory options
1794. if ($v_requested_options !== false) {
1795. for ($key=reset ($v_requested_options); $key=key ($v_requested_options); $key=next ($v_requested_options)) {
1796. // ----- Look for mandatory option
1797. if ($v_requested_options[$key] == 'mandatory') {
1798. // ----- Look if present
1799. if (!isset($v_result_list[$key])) {
1800. // ----- Error log
1801. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Missing mandatory parameter ".PclZipUtilOptionText ($key)."(".$key.")");
1803. // ----- Return
1804. return PclZip :: errorCode ();
1805. }
1806. }
1807. }
1808. }
1810. // ----- Look for default values
1811. if (!isset($v_result_list[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ])) {
1813. }
1815. // ----- Return
1816. return $v_result;
1817. }
1818. // --------------------------------------------------------------------------------
1820. // --------------------------------------------------------------------------------
1821. // Function : privOptionDefaultThreshold()
1822. // Description :
1823. // Parameters :
1824. // Return Values :
1825. // --------------------------------------------------------------------------------
1826. function privOptionDefaultThreshold (&$p_options)
1827. {
1828. $v_result=1;
1830. if (isset($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ])
1831. || isset($p_options[ PCLZIP_OPT_TEMP_FILE_OFF ])) {
1832. return $v_result;
1833. }
1835. // ----- Get 'memory_limit' configuration value
1836. $v_memory_limit = ini_get ('memory_limit');
1837. $v_memory_limit = trim ($v_memory_limit);
1838. $last = strtolower ( substr ($v_memory_limit, -1));
1840. if($last == 'g')
1841. //$v_memory_limit = $v_memory_limit*1024*1024*1024;
1842. $v_memory_limit = $v_memory_limit*1073741824;
1843. if($last == 'm')
1844. //$v_memory_limit = $v_memory_limit*1024*1024;
1845. $v_memory_limit = $v_memory_limit*1048576;
1846. if($last == 'k')
1847. $v_memory_limit = $v_memory_limit*1024;
1849. $p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ] = floor ($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO );
1852. // ----- Sanity check : No threshold if value lower than 1M
1853. if ($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ] < 1048576) {
1854. unset($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ]);
1855. }
1857. // ----- Return
1858. return $v_result;
1859. }
1860. // --------------------------------------------------------------------------------
1862. // --------------------------------------------------------------------------------
1863. // Function : privFileDescrParseAtt()
1864. // Description :
1865. // Parameters :
1866. // Return Values :
1867. // 1 on success.
1868. // 0 on failure.
1869. // --------------------------------------------------------------------------------
1870. function privFileDescrParseAtt (&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
1871. {
1872. $v_result=1;
1874. // ----- For each file in the list check the attributes
1875. foreach ($p_file_list as $v_key => $v_value) {
1877. // ----- Check if the option is supported
1878. if (!isset($v_requested_options[$v_key])) {
1879. // ----- Error log
1880. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid file attribute '".$v_key."' for this file");
1882. // ----- Return
1883. return PclZip :: errorCode ();
1884. }
1886. // ----- Look for attribute
1887. switch ($v_key) {
1888. case PCLZIP_ATT_FILE_NAME :
1889. if (! is_string ($v_value)) {
1890. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid type ".gettype ($v_value).". String expected for attribute '".PclZipUtilOptionText ($v_key)."'");
1891. return PclZip :: errorCode ();
1892. }
1894. $p_filedescr['filename'] = PclZipUtilPathReduction ($v_value);
1896. if ($p_filedescr['filename'] == '') {
1897. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid empty filename for attribute '".PclZipUtilOptionText ($v_key)."'");
1898. return PclZip :: errorCode ();
1899. }
1901. break;
1903. case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
1904. if (! is_string ($v_value)) {
1905. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid type ".gettype ($v_value).". String expected for attribute '".PclZipUtilOptionText ($v_key)."'");
1906. return PclZip :: errorCode ();
1907. }
1909. $p_filedescr['new_short_name'] = PclZipUtilPathReduction ($v_value);
1911. if ($p_filedescr['new_short_name'] == '') {
1912. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid empty short filename for attribute '".PclZipUtilOptionText ($v_key)."'");
1913. return PclZip :: errorCode ();
1914. }
1915. break;
1917. case PCLZIP_ATT_FILE_NEW_FULL_NAME :
1918. if (! is_string ($v_value)) {
1919. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid type ".gettype ($v_value).". String expected for attribute '".PclZipUtilOptionText ($v_key)."'");
1920. return PclZip :: errorCode ();
1921. }
1923. $p_filedescr['new_full_name'] = PclZipUtilPathReduction ($v_value);
1925. if ($p_filedescr['new_full_name'] == '') {
1926. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid empty full filename for attribute '".PclZipUtilOptionText ($v_key)."'");
1927. return PclZip :: errorCode ();
1928. }
1929. break;
1931. // ----- Look for options that takes a string
1932. case PCLZIP_ATT_FILE_COMMENT :
1933. if (! is_string ($v_value)) {
1934. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid type ".gettype ($v_value).". String expected for attribute '".PclZipUtilOptionText ($v_key)."'");
1935. return PclZip :: errorCode ();
1936. }
1938. $p_filedescr['comment'] = $v_value;
1939. break;
1941. case PCLZIP_ATT_FILE_MTIME :
1942. if (! is_integer ($v_value)) {
1943. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE , "Invalid type ".gettype ($v_value).". Integer expected for attribute '".PclZipUtilOptionText ($v_key)."'");
1944. return PclZip :: errorCode ();
1945. }
1947. $p_filedescr['mtime'] = $v_value;
1948. break;
1950. case PCLZIP_ATT_FILE_CONTENT :
1951. $p_filedescr['content'] = $v_value;
1952. break;
1954. default :
1955. // ----- Error log
1956. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER ,
1957. "Unknown parameter '".$v_key."'");
1959. // ----- Return
1960. return PclZip :: errorCode ();
1961. }
1963. // ----- Look for mandatory options
1964. if ($v_requested_options !== false) {
1965. for ($key=reset ($v_requested_options); $key=key ($v_requested_options); $key=next ($v_requested_options)) {
1966. // ----- Look for mandatory option
1967. if ($v_requested_options[$key] == 'mandatory') {
1968. // ----- Look if present
1969. if (!isset($p_file_list[$key])) {
1970. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Missing mandatory parameter ".PclZipUtilOptionText ($key)."(".$key.")");
1971. return PclZip :: errorCode ();
1972. }
1973. }
1974. }
1975. }
1977. // end foreach
1978. }
1980. // ----- Return
1981. return $v_result;
1982. }
1983. // --------------------------------------------------------------------------------
1985. // --------------------------------------------------------------------------------
1986. // Function : privFileDescrExpand()
1987. // Description :
1988. // This method look for each item of the list to see if its a file, a folder
1989. // or a string to be added as file. For any other type of files (link, other)
1990. // just ignore the item.
1991. // Then prepare the information that will be stored for that file.
1992. // When its a folder, expand the folder with all the files that are in that
1993. // folder (recursively).
1994. // Parameters :
1995. // Return Values :
1996. // 1 on success.
1997. // 0 on failure.
1998. // --------------------------------------------------------------------------------
1999. function privFileDescrExpand (&$p_filedescr_list, &$p_options)
2000. {
2001. $v_result=1;
2003. // ----- Create a result list
2004. $v_result_list = array();
2006. // ----- Look each entry
2007. for ($i=0; $i<sizeof ($p_filedescr_list); $i++) {
2009. // ----- Get filedescr
2010. $v_descr = $p_filedescr_list[$i];
2012. // ----- Reduce the filename
2013. $v_descr['filename'] = PclZipUtilTranslateWinPath ($v_descr['filename'], false);
2014. $v_descr['filename'] = PclZipUtilPathReduction ($v_descr['filename']);
2016. // ----- Look for real file or folder
2017. if ( file_exists ($v_descr['filename'])) {
2018. if (@ is_file ($v_descr['filename'])) {
2019. $v_descr['type'] = 'file';
2020. }
2021. else if (@ is_dir ($v_descr['filename'])) {
2022. $v_descr['type'] = 'folder';
2023. }
2024. else if (@ is_link ($v_descr['filename'])) {
2025. // skip
2026. continue;
2027. }
2028. else {
2029. // skip
2030. continue;
2031. }
2032. }
2034. // ----- Look for string added as file
2035. else if (isset($v_descr['content'])) {
2036. $v_descr['type'] = 'virtual_file';
2037. }
2039. // ----- Missing file
2040. else {
2041. // ----- Error log
2042. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_FILE , "File '".$v_descr['filename']."' does not exist");
2044. // ----- Return
2045. return PclZip :: errorCode ();
2046. }
2048. // ----- Calculate the stored filename
2049. $this-> privCalculateStoredFilename ($v_descr, $p_options);
2051. // ----- Add the descriptor in result list
2052. $v_result_list[ sizeof ($v_result_list)] = $v_descr;
2054. // ----- Look for folder
2055. if ($v_descr['type'] == 'folder') {
2056. // ----- List of items in folder
2057. $v_dirlist_descr = array();
2058. $v_dirlist_nb = 0;
2059. if ($v_folder_handler = @ opendir ($v_descr['filename'])) {
2060. while (($v_item_handler = @ readdir ($v_folder_handler)) !== false) {
2062. // ----- Skip '.' and '..'
2063. if (($v_item_handler == '.') || ($v_item_handler == '..')) {
2064. continue;
2065. }
2067. // ----- Compose the full filename
2068. $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
2070. // ----- Look for different stored filename
2071. // Because the name of the folder was changed, the name of the
2072. // files/sub-folders also change
2073. if (($v_descr['stored_filename'] != $v_descr['filename'])
2074. && (!isset($p_options[ PCLZIP_OPT_REMOVE_ALL_PATH ]))) {
2075. if ($v_descr['stored_filename'] != '') {
2076. $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
2077. }
2078. else {
2079. $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
2080. }
2081. }
2083. $v_dirlist_nb++;
2084. }
2086. @ closedir ($v_folder_handler);
2087. }
2088. else {
2089. // TBC : unable to open folder in read mode
2090. }
2092. // ----- Expand each element of the list
2093. if ($v_dirlist_nb != 0) {
2094. // ----- Expand
2095. if (($v_result = $this-> privFileDescrExpand ($v_dirlist_descr, $p_options)) != 1) {
2096. return $v_result;
2097. }
2099. // ----- Concat the resulting list
2100. $v_result_list = array_merge ($v_result_list, $v_dirlist_descr);
2101. }
2102. else {
2103. }
2105. // ----- Free local array
2106. unset($v_dirlist_descr);
2107. }
2108. }
2110. // ----- Get the result list
2111. $p_filedescr_list = $v_result_list;
2113. // ----- Return
2114. return $v_result;
2115. }
2116. // --------------------------------------------------------------------------------
2118. // --------------------------------------------------------------------------------
2119. // Function : privCreate()
2120. // Description :
2121. // Parameters :
2122. // Return Values :
2123. // --------------------------------------------------------------------------------
2124. function privCreate ($p_filedescr_list, &$p_result_list, &$p_options)
2125. {
2126. $v_result=1;
2127. $v_list_detail = array();
2129. // ----- Magic quotes trick
2130. $this-> privDisableMagicQuotes ();
2132. // ----- Open the file in write mode
2133. if (($v_result = $this-> privOpenFd ('wb')) != 1)
2134. {
2135. // ----- Return
2136. return $v_result;
2137. }
2139. // ----- Add the list of files
2140. $v_result = $this-> privAddList ($p_filedescr_list, $p_result_list, $p_options);
2142. // ----- Close
2143. $this-> privCloseFd ();
2145. // ----- Magic quotes trick
2146. $this-> privSwapBackMagicQuotes ();
2148. // ----- Return
2149. return $v_result;
2150. }
2151. // --------------------------------------------------------------------------------
2153. // --------------------------------------------------------------------------------
2154. // Function : privAdd()
2155. // Description :
2156. // Parameters :
2157. // Return Values :
2158. // --------------------------------------------------------------------------------
2159. function privAdd ($p_filedescr_list, &$p_result_list, &$p_options)
2160. {
2161. $v_result=1;
2162. $v_list_detail = array();
2164. // ----- Look if the archive exists or is empty
2165. if ((! is_file ($this-> zipname )) || ( filesize ($this-> zipname ) == 0))
2166. {
2168. // ----- Do a create
2169. $v_result = $this-> privCreate ($p_filedescr_list, $p_result_list, $p_options);
2171. // ----- Return
2172. return $v_result;
2173. }
2174. // ----- Magic quotes trick
2175. $this-> privDisableMagicQuotes ();
2177. // ----- Open the zip file
2178. if (($v_result=$this-> privOpenFd ('rb')) != 1)
2179. {
2180. // ----- Magic quotes trick
2181. $this-> privSwapBackMagicQuotes ();
2183. // ----- Return
2184. return $v_result;
2185. }
2187. // ----- Read the central directory informations
2188. $v_central_dir = array();
2189. if (($v_result = $this-> privReadEndCentralDir ($v_central_dir)) != 1)
2190. {
2191. $this-> privCloseFd ();
2192. $this-> privSwapBackMagicQuotes ();
2193. return $v_result;
2194. }
2196. // ----- Go to beginning of File
2197. @ rewind ($this-> zip_fd );
2199. // ----- Creates a temporay file
2200. $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid ('pclzip-').'.tmp';
2202. // ----- Open the temporary file in write mode
2203. if (($v_zip_temp_fd = @ fopen ($v_zip_temp_name, 'wb')) == 0)
2204. {
2205. $this-> privCloseFd ();
2206. $this-> privSwapBackMagicQuotes ();
2208. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2210. // ----- Return
2211. return PclZip :: errorCode ();
2212. }
2214. // ----- Copy the files from the archive to the temporary file
2215. // TBC : Here I should better append the file and go back to erase the central dir
2216. $v_size = $v_central_dir['offset'];
2217. while ($v_size != 0)
2218. {
2219. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
2220. $v_buffer = fread ($this-> zip_fd , $v_read_size);
2221. @ fwrite ($v_zip_temp_fd, $v_buffer, $v_read_size);
2222. $v_size -= $v_read_size;
2223. }
2225. // ----- Swap the file descriptor
2226. // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2227. // the following methods on the temporary fil and not the real archive
2228. $v_swap = $this-> zip_fd ;
2229. $this-> zip_fd = $v_zip_temp_fd;
2230. $v_zip_temp_fd = $v_swap;
2232. // ----- Add the files
2233. $v_header_list = array();
2234. if (($v_result = $this-> privAddFileList ($p_filedescr_list, $v_header_list, $p_options)) != 1)
2235. {
2236. fclose ($v_zip_temp_fd);
2237. $this-> privCloseFd ();
2238. @ unlink ($v_zip_temp_name);
2239. $this-> privSwapBackMagicQuotes ();
2241. // ----- Return
2242. return $v_result;
2243. }
2245. // ----- Store the offset of the central dir
2246. $v_offset = @ ftell ($this-> zip_fd );
2248. // ----- Copy the block of file headers from the old archive
2249. $v_size = $v_central_dir['size'];
2250. while ($v_size != 0)
2251. {
2252. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
2253. $v_buffer = @ fread ($v_zip_temp_fd, $v_read_size);
2254. @ fwrite ($this-> zip_fd , $v_buffer, $v_read_size);
2255. $v_size -= $v_read_size;
2256. }
2258. // ----- Create the Central Dir files header
2259. for ($i=0, $v_count=0; $i<sizeof ($v_header_list); $i++)
2260. {
2261. // ----- Create the file header
2262. if ($v_header_list[$i]['status'] == 'ok') {
2263. if (($v_result = $this-> privWriteCentralFileHeader ($v_header_list[$i])) != 1) {
2264. fclose ($v_zip_temp_fd);
2265. $this-> privCloseFd ();
2266. @ unlink ($v_zip_temp_name);
2267. $this-> privSwapBackMagicQuotes ();
2269. // ----- Return
2270. return $v_result;
2271. }
2272. $v_count++;
2273. }
2275. // ----- Transform the header to a 'usable' info
2276. $this-> privConvertHeader2FileInfo ($v_header_list[$i], $p_result_list[$i]);
2277. }
2279. // ----- Zip file comment
2280. $v_comment = $v_central_dir['comment'];
2281. if (isset($p_options[ PCLZIP_OPT_COMMENT ])) {
2282. $v_comment = $p_options[ PCLZIP_OPT_COMMENT ];
2283. }
2284. if (isset($p_options[ PCLZIP_OPT_ADD_COMMENT ])) {
2285. $v_comment = $v_comment.$p_options[ PCLZIP_OPT_ADD_COMMENT ];
2286. }
2287. if (isset($p_options[ PCLZIP_OPT_PREPEND_COMMENT ])) {
2288. $v_comment = $p_options[ PCLZIP_OPT_PREPEND_COMMENT ].$v_comment;
2289. }
2291. // ----- Calculate the size of the central header
2292. $v_size = @ ftell ($this-> zip_fd )-$v_offset;
2294. // ----- Create the central dir footer
2295. if (($v_result = $this-> privWriteCentralHeader ($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
2296. {
2297. // ----- Reset the file list
2298. unset($v_header_list);
2299. $this-> privSwapBackMagicQuotes ();
2301. // ----- Return
2302. return $v_result;
2303. }
2305. // ----- Swap back the file descriptor
2306. $v_swap = $this-> zip_fd ;
2307. $this-> zip_fd = $v_zip_temp_fd;
2308. $v_zip_temp_fd = $v_swap;
2310. // ----- Close
2311. $this-> privCloseFd ();
2313. // ----- Close the temporary file
2314. @ fclose ($v_zip_temp_fd);
2316. // ----- Magic quotes trick
2317. $this-> privSwapBackMagicQuotes ();
2319. // ----- Delete the zip file
2320. // TBC : I should test the result ...
2321. @ unlink ($this-> zipname );
2323. // ----- Rename the temporary file
2324. // TBC : I should test the result ...
2325. //@rename($v_zip_temp_name, $this->zipname);
2326. PclZipUtilRename ($v_zip_temp_name, $this-> zipname );
2328. // ----- Return
2329. return $v_result;
2330. }
2331. // --------------------------------------------------------------------------------
2333. // --------------------------------------------------------------------------------
2334. // Function : privOpenFd()
2335. // Description :
2336. // Parameters :
2337. // --------------------------------------------------------------------------------
2338. function privOpenFd ($p_mode)
2339. {
2340. $v_result=1;
2342. // ----- Look if already open
2343. if ($this-> zip_fd != 0)
2344. {
2345. // ----- Error log
2346. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Zip file \''.$this-> zipname.'\' already open');
2348. // ----- Return
2349. return PclZip :: errorCode ();
2350. }
2352. // ----- Open the zip file
2353. if (($this-> zip_fd = @ fopen ($this-> zipname , $p_mode)) == 0)
2354. {
2355. // ----- Error log
2356. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open archive \''.$this-> zipname.'\' in '.$p_mode.' mode');
2358. // ----- Return
2359. return PclZip :: errorCode ();
2360. }
2362. // ----- Return
2363. return $v_result;
2364. }
2365. // --------------------------------------------------------------------------------
2367. // --------------------------------------------------------------------------------
2368. // Function : privCloseFd()
2369. // Description :
2370. // Parameters :
2371. // --------------------------------------------------------------------------------
2372. function privCloseFd ()
2373. {
2374. $v_result=1;
2376. if ($this-> zip_fd != 0)
2377. @ fclose ($this-> zip_fd );
2378. $this-> zip_fd = 0;
2380. // ----- Return
2381. return $v_result;
2382. }
2383. // --------------------------------------------------------------------------------
2385. // --------------------------------------------------------------------------------
2386. // Function : privAddList()
2387. // Description :
2388. // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2389. // different from the real path of the file. This is usefull if you want to have PclTar
2390. // running in any directory, and memorize relative path from an other directory.
2391. // Parameters :
2392. // $p_list : An array containing the file or directory names to add in the tar
2393. // $p_result_list : list of added files with their properties (specially the status field)
2394. // $p_add_dir : Path to add in the filename path archived
2395. // $p_remove_dir : Path to remove in the filename path archived
2396. // Return Values :
2397. // --------------------------------------------------------------------------------
2398. // function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2399. function privAddList ($p_filedescr_list, &$p_result_list, &$p_options)
2400. {
2401. $v_result=1;
2403. // ----- Add the files
2404. $v_header_list = array();
2405. if (($v_result = $this-> privAddFileList ($p_filedescr_list, $v_header_list, $p_options)) != 1)
2406. {
2407. // ----- Return
2408. return $v_result;
2409. }
2411. // ----- Store the offset of the central dir
2412. $v_offset = @ ftell ($this-> zip_fd );
2414. // ----- Create the Central Dir files header
2415. for ($i=0,$v_count=0; $i<sizeof ($v_header_list); $i++)
2416. {
2417. // ----- Create the file header
2418. if ($v_header_list[$i]['status'] == 'ok') {
2419. if (($v_result = $this-> privWriteCentralFileHeader ($v_header_list[$i])) != 1) {
2420. // ----- Return
2421. return $v_result;
2422. }
2423. $v_count++;
2424. }
2426. // ----- Transform the header to a 'usable' info
2427. $this-> privConvertHeader2FileInfo ($v_header_list[$i], $p_result_list[$i]);
2428. }
2430. // ----- Zip file comment
2431. $v_comment = '';
2432. if (isset($p_options[ PCLZIP_OPT_COMMENT ])) {
2433. $v_comment = $p_options[ PCLZIP_OPT_COMMENT ];
2434. }
2436. // ----- Calculate the size of the central header
2437. $v_size = @ ftell ($this-> zip_fd )-$v_offset;
2439. // ----- Create the central dir footer
2440. if (($v_result = $this-> privWriteCentralHeader ($v_count, $v_size, $v_offset, $v_comment)) != 1)
2441. {
2442. // ----- Reset the file list
2443. unset($v_header_list);
2445. // ----- Return
2446. return $v_result;
2447. }
2449. // ----- Return
2450. return $v_result;
2451. }
2452. // --------------------------------------------------------------------------------
2454. // --------------------------------------------------------------------------------
2455. // Function : privAddFileList()
2456. // Description :
2457. // Parameters :
2458. // $p_filedescr_list : An array containing the file description
2459. // or directory names to add in the zip
2460. // $p_result_list : list of added files with their properties (specially the status field)
2461. // Return Values :
2462. // --------------------------------------------------------------------------------
2463. function privAddFileList ($p_filedescr_list, &$p_result_list, &$p_options)
2464. {
2465. $v_result=1;
2466. $v_header = array();
2468. // ----- Recuperate the current number of elt in list
2469. $v_nb = sizeof ($p_result_list);
2471. // ----- Loop on the files
2472. for ($j=0; ($j<sizeof ($p_filedescr_list)) && ($v_result==1); $j++) {
2473. // ----- Format the filename
2474. $p_filedescr_list[$j]['filename']
2475. = PclZipUtilTranslateWinPath ($p_filedescr_list[$j]['filename'], false);
2478. // ----- Skip empty file names
2479. // TBC : Can this be possible ? not checked in DescrParseAtt ?
2480. if ($p_filedescr_list[$j]['filename'] == "") {
2481. continue;
2482. }
2484. // ----- Check the filename
2485. if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
2486. && (! file_exists ($p_filedescr_list[$j]['filename']))) {
2487. PclZip :: privErrorLog ( PCLZIP_ERR_MISSING_FILE , "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2488. return PclZip :: errorCode ();
2489. }
2491. // ----- Look if it is a file or a dir with no all path remove option
2492. // or a dir with all its path removed
2493. // if ( (is_file($p_filedescr_list[$j]['filename']))
2494. // || ( is_dir($p_filedescr_list[$j]['filename'])
2495. if ( ($p_filedescr_list[$j]['type'] == 'file')
2496. || ($p_filedescr_list[$j]['type'] == 'virtual_file')
2497. || ( ($p_filedescr_list[$j]['type'] == 'folder')
2498. && ( !isset($p_options[ PCLZIP_OPT_REMOVE_ALL_PATH ])
2499. || !$p_options[ PCLZIP_OPT_REMOVE_ALL_PATH ]))
2500. ) {
2502. // ----- Add the file
2503. $v_result = $this-> privAddFile ($p_filedescr_list[$j], $v_header,
2504. $p_options);
2505. if ($v_result != 1) {
2506. return $v_result;
2507. }
2509. // ----- Store the file infos
2510. $p_result_list[$v_nb++] = $v_header;
2511. }
2512. }
2514. // ----- Return
2515. return $v_result;
2516. }
2517. // --------------------------------------------------------------------------------
2519. // --------------------------------------------------------------------------------
2520. // Function : privAddFile()
2521. // Description :
2522. // Parameters :
2523. // Return Values :
2524. // --------------------------------------------------------------------------------
2525. function privAddFile ($p_filedescr, &$p_header, &$p_options)
2526. {
2527. $v_result=1;
2529. // ----- Working variable
2530. $p_filename = $p_filedescr['filename'];
2532. // TBC : Already done in the fileAtt check ... ?
2533. if ($p_filename == "") {
2534. // ----- Error log
2535. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_PARAMETER , "Invalid file list parameter (invalid or empty list)");
2537. // ----- Return
2538. return PclZip :: errorCode ();
2539. }
2541. // ----- Look for a stored different filename
2542. /* TBC : Removed
2543. if (isset($p_filedescr['stored_filename'])) {
2544. $v_stored_filename = $p_filedescr['stored_filename'];
2545. }
2546. else {
2547. $v_stored_filename = $p_filedescr['stored_filename'];
2548. }
2549. */
2551. // ----- Set the file properties
2552. clearstatcache ();
2553. $p_header['version'] = 20;
2554. $p_header['version_extracted'] = 10;
2555. $p_header['flag'] = 0;
2556. $p_header['compression'] = 0;
2557. $p_header['crc'] = 0;
2558. $p_header['compressed_size'] = 0;
2559. $p_header['filename_len'] = strlen ($p_filename);
2560. $p_header['extra_len'] = 0;
2561. $p_header['disk'] = 0;
2562. $p_header['internal'] = 0;
2563. $p_header['offset'] = 0;
2564. $p_header['filename'] = $p_filename;
2565. // TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
2566. $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2567. $p_header['extra'] = '';
2568. $p_header['status'] = 'ok';
2569. $p_header['index'] = -1;
2571. // ----- Look for regular file
2572. if ($p_filedescr['type']=='file') {
2573. $p_header['external'] = 0x00000000;
2574. $p_header['size'] = filesize ($p_filename);
2575. }
2577. // ----- Look for regular folder
2578. else if ($p_filedescr['type']=='folder') {
2579. $p_header['external'] = 0x00000010;
2580. $p_header['mtime'] = filemtime ($p_filename);
2581. $p_header['size'] = filesize ($p_filename);
2582. }
2584. // ----- Look for virtual file
2585. else if ($p_filedescr['type'] == 'virtual_file') {
2586. $p_header['external'] = 0x00000000;
2587. $p_header['size'] = strlen ($p_filedescr['content']);
2588. }
2591. // ----- Look for filetime
2592. if (isset($p_filedescr['mtime'])) {
2593. $p_header['mtime'] = $p_filedescr['mtime'];
2594. }
2595. else if ($p_filedescr['type'] == 'virtual_file') {
2596. $p_header['mtime'] = time ();
2597. }
2598. else {
2599. $p_header['mtime'] = filemtime ($p_filename);
2600. }
2602. // ------ Look for file comment
2603. if (isset($p_filedescr['comment'])) {
2604. $p_header['comment_len'] = strlen ($p_filedescr['comment']);
2605. $p_header['comment'] = $p_filedescr['comment'];
2606. }
2607. else {
2608. $p_header['comment_len'] = 0;
2609. $p_header['comment'] = '';
2610. }
2612. // ----- Look for pre-add callback
2613. if (isset($p_options[ PCLZIP_CB_PRE_ADD ])) {
2615. // ----- Generate a local information
2616. $v_local_header = array();
2617. $this-> privConvertHeader2FileInfo ($p_header, $v_local_header);
2619. // ----- Call the callback
2620. // Here I do not use call_user_func() because I need to send a reference to the
2621. // header.
2622. // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
2623. $v_result = $p_options[ PCLZIP_CB_PRE_ADD ]( PCLZIP_CB_PRE_ADD , $v_local_header);
2624. if ($v_result == 0) {
2625. // ----- Change the file status
2626. $p_header['status'] = "skipped";
2627. $v_result = 1;
2628. }
2630. // ----- Update the informations
2631. // Only some fields can be modified
2632. if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2633. $p_header['stored_filename'] = PclZipUtilPathReduction ($v_local_header['stored_filename']);
2634. }
2635. }
2637. // ----- Look for empty stored filename
2638. if ($p_header['stored_filename'] == "") {
2639. $p_header['status'] = "filtered";
2640. }
2642. // ----- Check the path length
2643. if ( strlen ($p_header['stored_filename']) > 0xFF) {
2644. $p_header['status'] = 'filename_too_long';
2645. }
2647. // ----- Look if no error, or file not skipped
2648. if ($p_header['status'] == 'ok') {
2650. // ----- Look for a file
2651. if ($p_filedescr['type'] == 'file') {
2652. // ----- Look for using temporary file to zip
2653. if ( (!isset($p_options[ PCLZIP_OPT_TEMP_FILE_OFF ]))
2654. && (isset($p_options[ PCLZIP_OPT_TEMP_FILE_ON ])
2655. || (isset($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ])
2656. && ($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ] <= $p_header['size'])) ) ) {
2657. $v_result = $this-> privAddFileUsingTempFile ($p_filedescr, $p_header, $p_options);
2658. if ($v_result < PCLZIP_ERR_NO_ERROR ) {
2659. return $v_result;
2660. }
2661. }
2663. // ----- Use "in memory" zip algo
2664. else {
2666. // ----- Open the source file
2667. if (($v_file = @ fopen ($p_filename, "rb")) == 0) {
2668. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , "Unable to open file '$p_filename' in binary read mode");
2669. return PclZip :: errorCode ();
2670. }
2672. // ----- Read the file content
2673. $v_content = @ fread ($v_file, $p_header['size']);
2675. // ----- Close the file
2676. @ fclose ($v_file);
2678. // ----- Calculate the CRC
2679. $p_header['crc'] = @ crc32 ($v_content);
2681. // ----- Look for no compression
2682. if ($p_options[ PCLZIP_OPT_NO_COMPRESSION ]) {
2683. // ----- Set header parameters
2684. $p_header['compressed_size'] = $p_header['size'];
2685. $p_header['compression'] = 0;
2686. }
2688. // ----- Look for normal compression
2689. else {
2690. // ----- Compress the content
2691. $v_content = @ gzdeflate ($v_content);
2693. // ----- Set header parameters
2694. $p_header['compressed_size'] = strlen ($v_content);
2695. $p_header['compression'] = 8;
2696. }
2698. // ----- Call the header generation
2699. if (($v_result = $this-> privWriteFileHeader ($p_header)) != 1) {
2700. @ fclose ($v_file);
2701. return $v_result;
2702. }
2704. // ----- Write the compressed (or not) content
2705. @ fwrite ($this-> zip_fd , $v_content, $p_header['compressed_size']);
2707. }
2709. }
2711. // ----- Look for a virtual file (a file from string)
2712. else if ($p_filedescr['type'] == 'virtual_file') {
2714. $v_content = $p_filedescr['content'];
2716. // ----- Calculate the CRC
2717. $p_header['crc'] = @ crc32 ($v_content);
2719. // ----- Look for no compression
2720. if ($p_options[ PCLZIP_OPT_NO_COMPRESSION ]) {
2721. // ----- Set header parameters
2722. $p_header['compressed_size'] = $p_header['size'];
2723. $p_header['compression'] = 0;
2724. }
2726. // ----- Look for normal compression
2727. else {
2728. // ----- Compress the content
2729. $v_content = @ gzdeflate ($v_content);
2731. // ----- Set header parameters
2732. $p_header['compressed_size'] = strlen ($v_content);
2733. $p_header['compression'] = 8;
2734. }
2736. // ----- Call the header generation
2737. if (($v_result = $this-> privWriteFileHeader ($p_header)) != 1) {
2738. @ fclose ($v_file);
2739. return $v_result;
2740. }
2742. // ----- Write the compressed (or not) content
2743. @ fwrite ($this-> zip_fd , $v_content, $p_header['compressed_size']);
2744. }
2746. // ----- Look for a directory
2747. else if ($p_filedescr['type'] == 'folder') {
2748. // ----- Look for directory last '/'
2749. if (@ substr ($p_header['stored_filename'], -1) != '/') {
2750. $p_header['stored_filename'] .= '/';
2751. }
2753. // ----- Set the file properties
2754. $p_header['size'] = 0;
2755. //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
2756. $p_header['external'] = 0x00000010; // Value for a folder : to be checked
2758. // ----- Call the header generation
2759. if (($v_result = $this-> privWriteFileHeader ($p_header)) != 1)
2760. {
2761. return $v_result;
2762. }
2763. }
2764. }
2766. // ----- Look for post-add callback
2767. if (isset($p_options[ PCLZIP_CB_POST_ADD ])) {
2769. // ----- Generate a local information
2770. $v_local_header = array();
2771. $this-> privConvertHeader2FileInfo ($p_header, $v_local_header);
2773. // ----- Call the callback
2774. // Here I do not use call_user_func() because I need to send a reference to the
2775. // header.
2776. // eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
2777. $v_result = $p_options[ PCLZIP_CB_POST_ADD ]( PCLZIP_CB_POST_ADD , $v_local_header);
2778. if ($v_result == 0) {
2779. // ----- Ignored
2780. $v_result = 1;
2781. }
2783. // ----- Update the informations
2784. // Nothing can be modified
2785. }
2787. // ----- Return
2788. return $v_result;
2789. }
2790. // --------------------------------------------------------------------------------
2792. // --------------------------------------------------------------------------------
2793. // Function : privAddFileUsingTempFile()
2794. // Description :
2795. // Parameters :
2796. // Return Values :
2797. // --------------------------------------------------------------------------------
2798. function privAddFileUsingTempFile ($p_filedescr, &$p_header, &$p_options)
2799. {
2800. $v_result=PCLZIP_ERR_NO_ERROR ;
2802. // ----- Working variable
2803. $p_filename = $p_filedescr['filename'];
2806. // ----- Open the source file
2807. if (($v_file = @ fopen ($p_filename, "rb")) == 0) {
2808. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , "Unable to open file '$p_filename' in binary read mode");
2809. return PclZip :: errorCode ();
2810. }
2812. // ----- Creates a compressed temporary file
2813. $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid ('pclzip-').'.gz';
2814. if (($v_file_compressed = @ gzopen ($v_gzip_temp_name, "wb")) == 0) {
2815. fclose ($v_file);
2816. PclZip :: privErrorLog ( PCLZIP_ERR_WRITE_OPEN_FAIL , 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
2817. return PclZip :: errorCode ();
2818. }
2820. // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2821. $v_size = filesize ($p_filename);
2822. while ($v_size != 0) {
2823. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
2824. $v_buffer = @ fread ($v_file, $v_read_size);
2825. //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2826. @ gzputs ($v_file_compressed, $v_buffer, $v_read_size);
2827. $v_size -= $v_read_size;
2828. }
2830. // ----- Close the file
2831. @ fclose ($v_file);
2832. @ gzclose ($v_file_compressed);
2834. // ----- Check the minimum file size
2835. if ( filesize ($v_gzip_temp_name) < 18) {
2836. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
2837. return PclZip :: errorCode ();
2838. }
2840. // ----- Extract the compressed attributes
2841. if (($v_file_compressed = @ fopen ($v_gzip_temp_name, "rb")) == 0) {
2842. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2843. return PclZip :: errorCode ();
2844. }
2846. // ----- Read the gzip file header
2847. $v_binary_data = @ fread ($v_file_compressed, 10);
2848. $v_data_header = unpack ('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
2850. // ----- Check some parameters
2851. $v_data_header['os'] = bin2hex ($v_data_header['os']);
2853. // ----- Read the gzip file footer
2854. @ fseek ($v_file_compressed, filesize ($v_gzip_temp_name)-8);
2855. $v_binary_data = @ fread ($v_file_compressed, 8);
2856. $v_data_footer = unpack ('Vcrc/Vcompressed_size', $v_binary_data);
2858. // ----- Set the attributes
2859. $p_header['compression'] = ord ($v_data_header['cm']);
2860. //$p_header['mtime'] = $v_data_header['mtime'];
2861. $p_header['crc'] = $v_data_footer['crc'];
2862. $p_header['compressed_size'] = filesize ($v_gzip_temp_name)-18;
2864. // ----- Close the file
2865. @ fclose ($v_file_compressed);
2867. // ----- Call the header generation
2868. if (($v_result = $this-> privWriteFileHeader ($p_header)) != 1) {
2869. return $v_result;
2870. }
2872. // ----- Add the compressed data
2873. if (($v_file_compressed = @ fopen ($v_gzip_temp_name, "rb")) == 0)
2874. {
2875. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2876. return PclZip :: errorCode ();
2877. }
2879. // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2880. fseek ($v_file_compressed, 10);
2881. $v_size = $p_header['compressed_size'];
2882. while ($v_size != 0)
2883. {
2884. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
2885. $v_buffer = @ fread ($v_file_compressed, $v_read_size);
2886. //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2887. @ fwrite ($this-> zip_fd , $v_buffer, $v_read_size);
2888. $v_size -= $v_read_size;
2889. }
2891. // ----- Close the file
2892. @ fclose ($v_file_compressed);
2894. // ----- Unlink the temporary file
2895. @ unlink ($v_gzip_temp_name);
2897. // ----- Return
2898. return $v_result;
2899. }
2900. // --------------------------------------------------------------------------------
2902. // --------------------------------------------------------------------------------
2903. // Function : privCalculateStoredFilename()
2904. // Description :
2905. // Based on file descriptor properties and global options, this method
2906. // calculate the filename that will be stored in the archive.
2907. // Parameters :
2908. // Return Values :
2909. // --------------------------------------------------------------------------------
2910. function privCalculateStoredFilename (&$p_filedescr, &$p_options)
2911. {
2912. $v_result=1;
2914. // ----- Working variables
2915. $p_filename = $p_filedescr['filename'];
2916. if (isset($p_options[ PCLZIP_OPT_ADD_PATH ])) {
2917. $p_add_dir = $p_options[ PCLZIP_OPT_ADD_PATH ];
2918. }
2919. else {
2920. $p_add_dir = '';
2921. }
2922. if (isset($p_options[ PCLZIP_OPT_REMOVE_PATH ])) {
2923. $p_remove_dir = $p_options[ PCLZIP_OPT_REMOVE_PATH ];
2924. }
2925. else {
2926. $p_remove_dir = '';
2927. }
2928. if (isset($p_options[ PCLZIP_OPT_REMOVE_ALL_PATH ])) {
2929. $p_remove_all_dir = $p_options[ PCLZIP_OPT_REMOVE_ALL_PATH ];
2930. }
2931. else {
2932. $p_remove_all_dir = 0;
2933. }
2936. // ----- Look for full name change
2937. if (isset($p_filedescr['new_full_name'])) {
2938. // ----- Remove drive letter if any
2939. $v_stored_filename = PclZipUtilTranslateWinPath ($p_filedescr['new_full_name']);
2940. }
2942. // ----- Look for path and/or short name change
2943. else {
2945. // ----- Look for short name change
2946. // Its when we cahnge just the filename but not the path
2947. if (isset($p_filedescr['new_short_name'])) {
2948. $v_path_info = pathinfo ($p_filename);
2949. $v_dir = '';
2950. if ($v_path_info['dirname'] != '') {
2951. $v_dir = $v_path_info['dirname'].'/';
2952. }
2953. $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2954. }
2955. else {
2956. // ----- Calculate the stored filename
2957. $v_stored_filename = $p_filename;
2958. }
2960. // ----- Look for all path to remove
2961. if ($p_remove_all_dir) {
2962. $v_stored_filename = basename ($p_filename);
2963. }
2964. // ----- Look for partial path remove
2965. else if ($p_remove_dir != "") {
2966. if ( substr ($p_remove_dir, -1) != '/')
2967. $p_remove_dir .= "/";
2969. if ( ( substr ($p_filename, 0, 2) == "./")
2970. || ( substr ($p_remove_dir, 0, 2) == "./")) {
2972. if ( ( substr ($p_filename, 0, 2) == "./")
2973. && ( substr ($p_remove_dir, 0, 2) != "./")) {
2974. $p_remove_dir = "./".$p_remove_dir;
2975. }
2976. if ( ( substr ($p_filename, 0, 2) != "./")
2977. && ( substr ($p_remove_dir, 0, 2) == "./")) {
2978. $p_remove_dir = substr ($p_remove_dir, 2);
2979. }
2980. }
2982. $v_compare = PclZipUtilPathInclusion ($p_remove_dir,
2983. $v_stored_filename);
2984. if ($v_compare > 0) {
2985. if ($v_compare == 2) {
2986. $v_stored_filename = "";
2987. }
2988. else {
2989. $v_stored_filename = substr ($v_stored_filename,
2990. strlen ($p_remove_dir));
2991. }
2992. }
2993. }
2995. // ----- Remove drive letter if any
2996. $v_stored_filename = PclZipUtilTranslateWinPath ($v_stored_filename);
2998. // ----- Look for path to add
2999. if ($p_add_dir != "") {
3000. if ( substr ($p_add_dir, -1) == "/")
3001. $v_stored_filename = $p_add_dir.$v_stored_filename;
3002. else
3003. $v_stored_filename = $p_add_dir."/".$v_stored_filename;
3004. }
3005. }
3007. // ----- Filename (reduce the path of stored name)
3008. $v_stored_filename = PclZipUtilPathReduction ($v_stored_filename);
3009. $p_filedescr['stored_filename'] = $v_stored_filename;
3011. // ----- Return
3012. return $v_result;
3013. }
3014. // --------------------------------------------------------------------------------
3016. // --------------------------------------------------------------------------------
3017. // Function : privWriteFileHeader()
3018. // Description :
3019. // Parameters :
3020. // Return Values :
3021. // --------------------------------------------------------------------------------
3022. function privWriteFileHeader (&$p_header)
3023. {
3024. $v_result=1;
3026. // ----- Store the offset position of the file
3027. $p_header['offset'] = ftell ($this-> zip_fd );
3029. // ----- Transform UNIX mtime to DOS format mdate/mtime
3030. $v_date = getdate ($p_header['mtime']);
3031. $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3032. $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3034. // ----- Packed data
3035. $v_binary_data = pack ("VvvvvvVVVvv", 0x04034b50,
3036. $p_header['version_extracted'], $p_header['flag'],
3037. $p_header['compression'], $v_mtime, $v_mdate,
3038. $p_header['crc'], $p_header['compressed_size'],
3039. $p_header['size'],
3040. strlen ($p_header['stored_filename']),
3041. $p_header['extra_len']);
3043. // ----- Write the first 148 bytes of the header in the archive
3044. fputs ($this-> zip_fd , $v_binary_data, 30);
3046. // ----- Write the variable fields
3047. if ( strlen ($p_header['stored_filename']) != 0)
3048. {
3049. fputs ($this-> zip_fd , $p_header['stored_filename'], strlen ($p_header['stored_filename']));
3050. }
3051. if ($p_header['extra_len'] != 0)
3052. {
3053. fputs ($this-> zip_fd , $p_header['extra'], $p_header['extra_len']);
3054. }
3056. // ----- Return
3057. return $v_result;
3058. }
3059. // --------------------------------------------------------------------------------
3061. // --------------------------------------------------------------------------------
3062. // Function : privWriteCentralFileHeader()
3063. // Description :
3064. // Parameters :
3065. // Return Values :
3066. // --------------------------------------------------------------------------------
3067. function privWriteCentralFileHeader (&$p_header)
3068. {
3069. $v_result=1;
3071. // TBC
3072. //for(reset($p_header); $key = key($p_header); next($p_header)) {
3073. //}
3075. // ----- Transform UNIX mtime to DOS format mdate/mtime
3076. $v_date = getdate ($p_header['mtime']);
3077. $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3078. $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3081. // ----- Packed data
3082. $v_binary_data = pack ("VvvvvvvVVVvvvvvVV", 0x02014b50,
3083. $p_header['version'], $p_header['version_extracted'],
3084. $p_header['flag'], $p_header['compression'],
3085. $v_mtime, $v_mdate, $p_header['crc'],
3086. $p_header['compressed_size'], $p_header['size'],
3087. strlen ($p_header['stored_filename']),
3088. $p_header['extra_len'], $p_header['comment_len'],
3089. $p_header['disk'], $p_header['internal'],
3090. $p_header['external'], $p_header['offset']);
3092. // ----- Write the 42 bytes of the header in the zip file
3093. fputs ($this-> zip_fd , $v_binary_data, 46);
3095. // ----- Write the variable fields
3096. if ( strlen ($p_header['stored_filename']) != 0)
3097. {
3098. fputs ($this-> zip_fd , $p_header['stored_filename'], strlen ($p_header['stored_filename']));
3099. }
3100. if ($p_header['extra_len'] != 0)
3101. {
3102. fputs ($this-> zip_fd , $p_header['extra'], $p_header['extra_len']);
3103. }
3104. if ($p_header['comment_len'] != 0)
3105. {
3106. fputs ($this-> zip_fd , $p_header['comment'], $p_header['comment_len']);
3107. }
3109. // ----- Return
3110. return $v_result;
3111. }
3112. // --------------------------------------------------------------------------------
3114. // --------------------------------------------------------------------------------
3115. // Function : privWriteCentralHeader()
3116. // Description :
3117. // Parameters :
3118. // Return Values :
3119. // --------------------------------------------------------------------------------
3120. function privWriteCentralHeader ($p_nb_entries, $p_size, $p_offset, $p_comment)
3121. {
3122. $v_result=1;
3124. // ----- Packed data
3125. $v_binary_data = pack ("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
3126. $p_nb_entries, $p_size,
3127. $p_offset, strlen ($p_comment));
3129. // ----- Write the 22 bytes of the header in the zip file
3130. fputs ($this-> zip_fd , $v_binary_data, 22);
3132. // ----- Write the variable fields
3133. if ( strlen ($p_comment) != 0)
3134. {
3135. fputs ($this-> zip_fd , $p_comment, strlen ($p_comment));
3136. }
3138. // ----- Return
3139. return $v_result;
3140. }
3141. // --------------------------------------------------------------------------------
3143. // --------------------------------------------------------------------------------
3144. // Function : privList()
3145. // Description :
3146. // Parameters :
3147. // Return Values :
3148. // --------------------------------------------------------------------------------
3149. function privList (&$p_list)
3150. {
3151. $v_result=1;
3153. // ----- Magic quotes trick
3154. $this-> privDisableMagicQuotes ();
3156. // ----- Open the zip file
3157. if (($this-> zip_fd = @ fopen ($this-> zipname , 'rb')) == 0)
3158. {
3159. // ----- Magic quotes trick
3160. $this-> privSwapBackMagicQuotes ();
3162. // ----- Error log
3163. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open archive \''.$this-> zipname.'\' in binary read mode');
3165. // ----- Return
3166. return PclZip :: errorCode ();
3167. }
3169. // ----- Read the central directory informations
3170. $v_central_dir = array();
3171. if (($v_result = $this-> privReadEndCentralDir ($v_central_dir)) != 1)
3172. {
3173. $this-> privSwapBackMagicQuotes ();
3174. return $v_result;
3175. }
3177. // ----- Go to beginning of Central Dir
3178. @ rewind ($this-> zip_fd );
3179. if (@ fseek ($this-> zip_fd , $v_central_dir['offset']))
3180. {
3181. $this-> privSwapBackMagicQuotes ();
3183. // ----- Error log
3184. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ARCHIVE_ZIP , 'Invalid archive size');
3186. // ----- Return
3187. return PclZip :: errorCode ();
3188. }
3190. // ----- Read each entry
3191. for ($i=0; $i<$v_central_dir['entries']; $i++)
3192. {
3193. // ----- Read the file header
3194. if (($v_result = $this-> privReadCentralFileHeader ($v_header)) != 1)
3195. {
3196. $this-> privSwapBackMagicQuotes ();
3197. return $v_result;
3198. }
3199. $v_header['index'] = $i;
3201. // ----- Get the only interesting attributes
3202. $this-> privConvertHeader2FileInfo ($v_header, $p_list[$i]);
3203. unset($v_header);
3204. }
3206. // ----- Close the zip file
3207. $this-> privCloseFd ();
3209. // ----- Magic quotes trick
3210. $this-> privSwapBackMagicQuotes ();
3212. // ----- Return
3213. return $v_result;
3214. }
3215. // --------------------------------------------------------------------------------
3217. // --------------------------------------------------------------------------------
3218. // Function : privConvertHeader2FileInfo()
3219. // Description :
3220. // This function takes the file informations from the central directory
3221. // entries and extract the interesting parameters that will be given back.
3222. // The resulting file infos are set in the array $p_info
3223. // $p_info['filename'] : Filename with full path. Given by user (add),
3224. // extracted in the filesystem (extract).
3225. // $p_info['stored_filename'] : Stored filename in the archive.
3226. // $p_info['size'] = Size of the file.
3227. // $p_info['compressed_size'] = Compressed size of the file.
3228. // $p_info['mtime'] = Last modification date of the file.
3229. // $p_info['comment'] = Comment associated with the file.
3230. // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3231. // $p_info['status'] = status of the action on the file.
3232. // $p_info['crc'] = CRC of the file content.
3233. // Parameters :
3234. // Return Values :
3235. // --------------------------------------------------------------------------------
3236. function privConvertHeader2FileInfo ($p_header, &$p_info)
3237. {
3238. $v_result=1;
3240. // ----- Get the interesting attributes
3241. $v_temp_path = PclZipUtilPathReduction ($p_header['filename']);
3242. $p_info['filename'] = $v_temp_path;
3243. $v_temp_path = PclZipUtilPathReduction ($p_header['stored_filename']);
3244. $p_info['stored_filename'] = $v_temp_path;
3245. $p_info['size'] = $p_header['size'];
3246. $p_info['compressed_size'] = $p_header['compressed_size'];
3247. $p_info['mtime'] = $p_header['mtime'];
3248. $p_info['comment'] = $p_header['comment'];
3249. $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3250. $p_info['index'] = $p_header['index'];
3251. $p_info['status'] = $p_header['status'];
3252. $p_info['crc'] = $p_header['crc'];
3254. // ----- Return
3255. return $v_result;
3256. }
3257. // --------------------------------------------------------------------------------
3259. // --------------------------------------------------------------------------------
3260. // Function : privExtractByRule()
3261. // Description :
3262. // Extract a file or directory depending of rules (by index, by name, ...)
3263. // Parameters :
3264. // $p_file_list : An array where will be placed the properties of each
3265. // extracted file
3266. // $p_path : Path to add while writing the extracted files
3267. // $p_remove_path : Path to remove (from the file memorized path) while writing the
3268. // extracted files. If the path does not match the file path,
3269. // the file is extracted with its memorized path.
3270. // $p_remove_path does not apply to 'list' mode.
3271. // $p_path and $p_remove_path are commulative.
3272. // Return Values :
3273. // 1 on success,0 or less on error (see error code list)
3274. // --------------------------------------------------------------------------------
3275. function privExtractByRule (&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3276. {
3277. $v_result=1;
3279. // ----- Magic quotes trick
3280. $this-> privDisableMagicQuotes ();
3282. // ----- Check the path
3283. if ( ($p_path == "")
3284. || ( ( substr ($p_path, 0, 1) != "/")
3285. && ( substr ($p_path, 0, 3) != "../")
3286. && ( substr ($p_path,1,2)!=":/")))
3287. $p_path = "./".$p_path;
3289. // ----- Reduce the path last (and duplicated) '/'
3290. if (($p_path != "./") && ($p_path != "/"))
3291. {
3292. // ----- Look for the path end '/'
3293. while ( substr ($p_path, -1) == "/")
3294. {
3295. $p_path = substr ($p_path, 0, strlen ($p_path)-1);
3296. }
3297. }
3299. // ----- Look for path to remove format (should end by /)
3300. if (($p_remove_path != "") && ( substr ($p_remove_path, -1) != '/'))
3301. {
3302. $p_remove_path .= '/';
3303. }
3304. $p_remove_path_size = strlen ($p_remove_path);
3306. // ----- Open the zip file
3307. if (($v_result = $this-> privOpenFd ('rb')) != 1)
3308. {
3309. $this-> privSwapBackMagicQuotes ();
3310. return $v_result;
3311. }
3313. // ----- Read the central directory informations
3314. $v_central_dir = array();
3315. if (($v_result = $this-> privReadEndCentralDir ($v_central_dir)) != 1)
3316. {
3317. // ----- Close the zip file
3318. $this-> privCloseFd ();
3319. $this-> privSwapBackMagicQuotes ();
3321. return $v_result;
3322. }
3324. // ----- Start at beginning of Central Dir
3325. $v_pos_entry = $v_central_dir['offset'];
3327. // ----- Read each entry
3328. $j_start = 0;
3329. for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3330. {
3332. // ----- Read next Central dir entry
3333. @ rewind ($this-> zip_fd );
3334. if (@ fseek ($this-> zip_fd , $v_pos_entry))
3335. {
3336. // ----- Close the zip file
3337. $this-> privCloseFd ();
3338. $this-> privSwapBackMagicQuotes ();
3340. // ----- Error log
3341. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ARCHIVE_ZIP , 'Invalid archive size');
3343. // ----- Return
3344. return PclZip :: errorCode ();
3345. }
3347. // ----- Read the file header
3348. $v_header = array();
3349. if (($v_result = $this-> privReadCentralFileHeader ($v_header)) != 1)
3350. {
3351. // ----- Close the zip file
3352. $this-> privCloseFd ();
3353. $this-> privSwapBackMagicQuotes ();
3355. return $v_result;
3356. }
3358. // ----- Store the index
3359. $v_header['index'] = $i;
3361. // ----- Store the file position
3362. $v_pos_entry = ftell ($this-> zip_fd );
3364. // ----- Look for the specific extract rules
3365. $v_extract = false;
3367. // ----- Look for extract by name rule
3368. if ( (isset($p_options[ PCLZIP_OPT_BY_NAME ]))
3369. && ($p_options[ PCLZIP_OPT_BY_NAME ] != 0)) {
3371. // ----- Look if the filename is in the list
3372. for ($j=0; ($j<sizeof ($p_options[ PCLZIP_OPT_BY_NAME ])) && (!$v_extract); $j++) {
3374. // ----- Look for a directory
3375. if ( substr ($p_options[ PCLZIP_OPT_BY_NAME ][$j], -1) == "/") {
3377. // ----- Look if the directory is in the filename path
3378. if ( ( strlen ($v_header['stored_filename']) > strlen ($p_options[ PCLZIP_OPT_BY_NAME ][$j]))
3379. && ( substr ($v_header['stored_filename'], 0, strlen ($p_options[ PCLZIP_OPT_BY_NAME ][$j])) == $p_options[ PCLZIP_OPT_BY_NAME ][$j])) {
3380. $v_extract = true;
3381. }
3382. }
3383. // ----- Look for a filename
3384. elseif ($v_header['stored_filename'] == $p_options[ PCLZIP_OPT_BY_NAME ][$j]) {
3385. $v_extract = true;
3386. }
3387. }
3388. }
3390. // ----- Look for extract by ereg rule
3391. // ereg() is deprecated with PHP 5.3
3392. /*
3393. else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
3394. && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
3396. if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
3397. $v_extract = true;
3398. }
3399. }
3400. */
3402. // ----- Look for extract by preg rule
3403. else if ( (isset($p_options[ PCLZIP_OPT_BY_PREG ]))
3404. && ($p_options[ PCLZIP_OPT_BY_PREG ] != "")) {
3406. if ( preg_match ($p_options[ PCLZIP_OPT_BY_PREG ], $v_header['stored_filename'])) {
3407. $v_extract = true;
3408. }
3409. }
3411. // ----- Look for extract by index rule
3412. else if ( (isset($p_options[ PCLZIP_OPT_BY_INDEX ]))
3413. && ($p_options[ PCLZIP_OPT_BY_INDEX ] != 0)) {
3415. // ----- Look if the index is in the list
3416. for ($j=$j_start; ($j<sizeof ($p_options[ PCLZIP_OPT_BY_INDEX ])) && (!$v_extract); $j++) {
3418. if (($i>=$p_options[ PCLZIP_OPT_BY_INDEX ][$j]['start']) && ($i<=$p_options[ PCLZIP_OPT_BY_INDEX ][$j]['end'])) {
3419. $v_extract = true;
3420. }
3421. if ($i>=$p_options[ PCLZIP_OPT_BY_INDEX ][$j]['end']) {
3422. $j_start = $j+1;
3423. }
3425. if ($p_options[ PCLZIP_OPT_BY_INDEX ][$j]['start']>$i) {
3426. break;
3427. }
3428. }
3429. }
3431. // ----- Look for no rule, which means extract all the archive
3432. else {
3433. $v_extract = true;
3434. }
3436. // ----- Check compression method
3437. if ( ($v_extract)
3438. && ( ($v_header['compression'] != 8)
3439. && ($v_header['compression'] != 0))) {
3440. $v_header['status'] = 'unsupported_compression';
3442. // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3443. if ( (isset($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]))
3444. && ($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]===true)) {
3446. $this-> privSwapBackMagicQuotes ();
3448. PclZip :: privErrorLog ( PCLZIP_ERR_UNSUPPORTED_COMPRESSION ,
3449. "Filename '".$v_header['stored_filename']."' is "
3450. ."compressed by an unsupported compression "
3451. ."method (".$v_header['compression'].") ");
3453. return PclZip :: errorCode ();
3454. }
3455. }
3457. // ----- Check encrypted files
3458. if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3459. $v_header['status'] = 'unsupported_encryption';
3461. // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3462. if ( (isset($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]))
3463. && ($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]===true)) {
3465. $this-> privSwapBackMagicQuotes ();
3467. PclZip :: privErrorLog ( PCLZIP_ERR_UNSUPPORTED_ENCRYPTION ,
3468. "Unsupported encryption for "
3469. ." filename '".$v_header['stored_filename']
3470. ."'");
3472. return PclZip :: errorCode ();
3473. }
3474. }
3476. // ----- Look for real extraction
3477. if (($v_extract) && ($v_header['status'] != 'ok')) {
3478. $v_result = $this-> privConvertHeader2FileInfo ($v_header,
3479. $p_file_list[$v_nb_extracted++]);
3480. if ($v_result != 1) {
3481. $this-> privCloseFd ();
3482. $this-> privSwapBackMagicQuotes ();
3483. return $v_result;
3484. }
3486. $v_extract = false;
3487. }
3489. // ----- Look for real extraction
3490. if ($v_extract)
3491. {
3493. // ----- Go to the file position
3494. @ rewind ($this-> zip_fd );
3495. if (@ fseek ($this-> zip_fd , $v_header['offset']))
3496. {
3497. // ----- Close the zip file
3498. $this-> privCloseFd ();
3500. $this-> privSwapBackMagicQuotes ();
3502. // ----- Error log
3503. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ARCHIVE_ZIP , 'Invalid archive size');
3505. // ----- Return
3506. return PclZip :: errorCode ();
3507. }
3509. // ----- Look for extraction as string
3510. if ($p_options[ PCLZIP_OPT_EXTRACT_AS_STRING ]) {
3512. $v_string = '';
3514. // ----- Extracting the file
3515. $v_result1 = $this-> privExtractFileAsString ($v_header, $v_string, $p_options);
3516. if ($v_result1 < 1) {
3517. $this-> privCloseFd ();
3518. $this-> privSwapBackMagicQuotes ();
3519. return $v_result1;
3520. }
3522. // ----- Get the only interesting attributes
3523. if (($v_result = $this-> privConvertHeader2FileInfo ($v_header, $p_file_list[$v_nb_extracted])) != 1)
3524. {
3525. // ----- Close the zip file
3526. $this-> privCloseFd ();
3527. $this-> privSwapBackMagicQuotes ();
3529. return $v_result;
3530. }
3532. // ----- Set the file content
3533. $p_file_list[$v_nb_extracted]['content'] = $v_string;
3535. // ----- Next extracted file
3536. $v_nb_extracted++;
3538. // ----- Look for user callback abort
3539. if ($v_result1 == 2) {
3540. break;
3541. }
3542. }
3543. // ----- Look for extraction in standard output
3544. elseif ( (isset($p_options[ PCLZIP_OPT_EXTRACT_IN_OUTPUT ]))
3545. && ($p_options[ PCLZIP_OPT_EXTRACT_IN_OUTPUT ])) {
3546. // ----- Extracting the file in standard output
3547. $v_result1 = $this-> privExtractFileInOutput ($v_header, $p_options);
3548. if ($v_result1 < 1) {
3549. $this-> privCloseFd ();
3550. $this-> privSwapBackMagicQuotes ();
3551. return $v_result1;
3552. }
3554. // ----- Get the only interesting attributes
3555. if (($v_result = $this-> privConvertHeader2FileInfo ($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3556. $this-> privCloseFd ();
3557. $this-> privSwapBackMagicQuotes ();
3558. return $v_result;
3559. }
3561. // ----- Look for user callback abort
3562. if ($v_result1 == 2) {
3563. break;
3564. }
3565. }
3566. // ----- Look for normal extraction
3567. else {
3568. // ----- Extracting the file
3569. $v_result1 = $this-> privExtractFile ($v_header,
3570. $p_path, $p_remove_path,
3571. $p_remove_all_path,
3572. $p_options);
3573. if ($v_result1 < 1) {
3574. $this-> privCloseFd ();
3575. $this-> privSwapBackMagicQuotes ();
3576. return $v_result1;
3577. }
3579. // ----- Get the only interesting attributes
3580. if (($v_result = $this-> privConvertHeader2FileInfo ($v_header, $p_file_list[$v_nb_extracted++])) != 1)
3581. {
3582. // ----- Close the zip file
3583. $this-> privCloseFd ();
3584. $this-> privSwapBackMagicQuotes ();
3586. return $v_result;
3587. }
3589. // ----- Look for user callback abort
3590. if ($v_result1 == 2) {
3591. break;
3592. }
3593. }
3594. }
3595. }
3597. // ----- Close the zip file
3598. $this-> privCloseFd ();
3599. $this-> privSwapBackMagicQuotes ();
3601. // ----- Return
3602. return $v_result;
3603. }
3604. // --------------------------------------------------------------------------------
3606. // --------------------------------------------------------------------------------
3607. // Function : privExtractFile()
3608. // Description :
3609. // Parameters :
3610. // Return Values :
3611. //
3612. // 1 : ... ?
3613. // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3614. // --------------------------------------------------------------------------------
3615. function privExtractFile (&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3616. {
3617. $v_result=1;
3619. // ----- Read the file header
3620. if (($v_result = $this-> privReadFileHeader ($v_header)) != 1)
3621. {
3622. // ----- Return
3623. return $v_result;
3624. }
3627. // ----- Check that the file header is coherent with $p_entry info
3628. if ($this-> privCheckFileHeaders ($v_header, $p_entry) != 1) {
3629. // TBC
3630. }
3632. // ----- Look for all path to remove
3633. if ($p_remove_all_path == true) {
3634. // ----- Look for folder entry that not need to be extracted
3635. if (($p_entry['external']&0x00000010)==0x00000010) {
3637. $p_entry['status'] = "filtered";
3639. return $v_result;
3640. }
3642. // ----- Get the basename of the path
3643. $p_entry['filename'] = basename ($p_entry['filename']);
3644. }
3646. // ----- Look for path to remove
3647. else if ($p_remove_path != "")
3648. {
3649. if ( PclZipUtilPathInclusion ($p_remove_path, $p_entry['filename']) == 2)
3650. {
3652. // ----- Change the file status
3653. $p_entry['status'] = "filtered";
3655. // ----- Return
3656. return $v_result;
3657. }
3659. $p_remove_path_size = strlen ($p_remove_path);
3660. if ( substr ($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
3661. {
3663. // ----- Remove the path
3664. $p_entry['filename'] = substr ($p_entry['filename'], $p_remove_path_size);
3666. }
3667. }
3669. // ----- Add the path
3670. if ($p_path != '') {
3671. $p_entry['filename'] = $p_path."/".$p_entry['filename'];
3672. }
3674. // ----- Check a base_dir_restriction
3675. if (isset($p_options[ PCLZIP_OPT_EXTRACT_DIR_RESTRICTION ])) {
3676. $v_inclusion
3677. = PclZipUtilPathInclusion ($p_options[ PCLZIP_OPT_EXTRACT_DIR_RESTRICTION ],
3678. $p_entry['filename']);
3679. if ($v_inclusion == 0) {
3681. PclZip :: privErrorLog ( PCLZIP_ERR_DIRECTORY_RESTRICTION ,
3682. "Filename '".$p_entry['filename']."' is "
3683. ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
3685. return PclZip :: errorCode ();
3686. }
3687. }
3689. // ----- Look for pre-extract callback
3690. if (isset($p_options[ PCLZIP_CB_PRE_EXTRACT ])) {
3692. // ----- Generate a local information
3693. $v_local_header = array();
3694. $this-> privConvertHeader2FileInfo ($p_entry, $v_local_header);
3696. // ----- Call the callback
3697. // Here I do not use call_user_func() because I need to send a reference to the
3698. // header.
3699. // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3700. $v_result = $p_options[ PCLZIP_CB_PRE_EXTRACT ]( PCLZIP_CB_PRE_EXTRACT , $v_local_header);
3701. if ($v_result == 0) {
3702. // ----- Change the file status
3703. $p_entry['status'] = "skipped";
3704. $v_result = 1;
3705. }
3707. // ----- Look for abort result
3708. if ($v_result == 2) {
3709. // ----- This status is internal and will be changed in 'skipped'
3710. $p_entry['status'] = "aborted";
3711. $v_result = PCLZIP_ERR_USER_ABORTED ;
3712. }
3714. // ----- Update the informations
3715. // Only some fields can be modified
3716. $p_entry['filename'] = $v_local_header['filename'];
3717. }
3720. // ----- Look if extraction should be done
3721. if ($p_entry['status'] == 'ok') {
3723. // ----- Look for specific actions while the file exist
3724. if ( file_exists ($p_entry['filename']))
3725. {
3727. // ----- Look if file is a directory
3728. if ( is_dir ($p_entry['filename']))
3729. {
3731. // ----- Change the file status
3732. $p_entry['status'] = "already_a_directory";
3734. // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3735. // For historical reason first PclZip implementation does not stop
3736. // when this kind of error occurs.
3737. if ( (isset($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]))
3738. && ($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]===true)) {
3740. PclZip :: privErrorLog ( PCLZIP_ERR_ALREADY_A_DIRECTORY ,
3741. "Filename '".$p_entry['filename']."' is "
3742. ."already used by an existing directory");
3744. return PclZip :: errorCode ();
3745. }
3746. }
3747. // ----- Look if file is write protected
3748. else if (! is_writeable ($p_entry['filename']))
3749. {
3751. // ----- Change the file status
3752. $p_entry['status'] = "write_protected";
3754. // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3755. // For historical reason first PclZip implementation does not stop
3756. // when this kind of error occurs.
3757. if ( (isset($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]))
3758. && ($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]===true)) {
3760. PclZip :: privErrorLog ( PCLZIP_ERR_WRITE_OPEN_FAIL ,
3761. "Filename '".$p_entry['filename']."' exists "
3762. ."and is write protected");
3764. return PclZip :: errorCode ();
3765. }
3766. }
3768. // ----- Look if the extracted file is older
3769. else if ( filemtime ($p_entry['filename']) > $p_entry['mtime'])
3770. {
3771. // ----- Change the file status
3772. if ( (isset($p_options[ PCLZIP_OPT_REPLACE_NEWER ]))
3773. && ($p_options[ PCLZIP_OPT_REPLACE_NEWER ]===true)) {
3774. }
3775. else {
3776. $p_entry['status'] = "newer_exist";
3778. // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3779. // For historical reason first PclZip implementation does not stop
3780. // when this kind of error occurs.
3781. if ( (isset($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]))
3782. && ($p_options[ PCLZIP_OPT_STOP_ON_ERROR ]===true)) {
3784. PclZip :: privErrorLog ( PCLZIP_ERR_WRITE_OPEN_FAIL ,
3785. "Newer version of '".$p_entry['filename']."' exists "
3786. ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
3788. return PclZip :: errorCode ();
3789. }
3790. }
3791. }
3792. else {
3793. }
3794. }
3796. // ----- Check the directory availability and create it if necessary
3797. else {
3798. if ((($p_entry['external']&0x00000010)==0x00000010) || ( substr ($p_entry['filename'], -1) == '/'))
3799. $v_dir_to_check = $p_entry['filename'];
3800. else if (! strstr ($p_entry['filename'], "/"))
3801. $v_dir_to_check = "";
3802. else
3803. $v_dir_to_check = dirname ($p_entry['filename']);
3805. if (($v_result = $this-> privDirCheck ($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
3807. // ----- Change the file status
3808. $p_entry['status'] = "path_creation_fail";
3810. // ----- Return
3811. //return $v_result;
3812. $v_result = 1;
3813. }
3814. }
3815. }
3817. // ----- Look if extraction should be done
3818. if ($p_entry['status'] == 'ok') {
3820. // ----- Do the extraction (if not a folder)
3821. if (!(($p_entry['external']&0x00000010)==0x00000010))
3822. {
3823. // ----- Look for not compressed file
3824. if ($p_entry['compression'] == 0) {
3826. // ----- Opening destination file
3827. if (($v_dest_file = @ fopen ($p_entry['filename'], 'wb')) == 0)
3828. {
3830. // ----- Change the file status
3831. $p_entry['status'] = "write_error";
3833. // ----- Return
3834. return $v_result;
3835. }
3838. // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3839. $v_size = $p_entry['compressed_size'];
3840. while ($v_size != 0)
3841. {
3842. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
3843. $v_buffer = @ fread ($this-> zip_fd , $v_read_size);
3844. /* Try to speed up the code
3845. $v_binary_data = pack('a'.$v_read_size, $v_buffer);
3846. @fwrite($v_dest_file, $v_binary_data, $v_read_size);
3847. */
3848. @ fwrite ($v_dest_file, $v_buffer, $v_read_size);
3849. $v_size -= $v_read_size;
3850. }
3852. // ----- Closing the destination file
3853. fclose ($v_dest_file);
3855. // ----- Change the file mtime
3856. touch ($p_entry['filename'], $p_entry['mtime']);
3859. }
3860. else {
3861. // ----- TBC
3862. // Need to be finished
3863. if (($p_entry['flag'] & 1) == 1) {
3864. PclZip :: privErrorLog ( PCLZIP_ERR_UNSUPPORTED_ENCRYPTION , 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
3865. return PclZip :: errorCode ();
3866. }
3869. // ----- Look for using temporary file to unzip
3870. if ( (!isset($p_options[ PCLZIP_OPT_TEMP_FILE_OFF ]))
3871. && (isset($p_options[ PCLZIP_OPT_TEMP_FILE_ON ])
3872. || (isset($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ])
3873. && ($p_options[ PCLZIP_OPT_TEMP_FILE_THRESHOLD ] <= $p_entry['size'])) ) ) {
3874. $v_result = $this-> privExtractFileUsingTempFile ($p_entry, $p_options);
3875. if ($v_result < PCLZIP_ERR_NO_ERROR ) {
3876. return $v_result;
3877. }
3878. }
3880. // ----- Look for extract in memory
3881. else {
3884. // ----- Read the compressed file in a buffer (one shot)
3885. $v_buffer = @ fread ($this-> zip_fd , $p_entry['compressed_size']);
3887. // ----- Decompress the file
3888. $v_file_content = @ gzinflate ($v_buffer);
3889. unset($v_buffer);
3890. if ($v_file_content === FALSE) {
3892. // ----- Change the file status
3893. // TBC
3894. $p_entry['status'] = "error";
3896. return $v_result;
3897. }
3899. // ----- Opening destination file
3900. if (($v_dest_file = @ fopen ($p_entry['filename'], 'wb')) == 0) {
3902. // ----- Change the file status
3903. $p_entry['status'] = "write_error";
3905. return $v_result;
3906. }
3908. // ----- Write the uncompressed data
3909. @ fwrite ($v_dest_file, $v_file_content, $p_entry['size']);
3910. unset($v_file_content);
3912. // ----- Closing the destination file
3913. @ fclose ($v_dest_file);
3915. }
3917. // ----- Change the file mtime
3918. @ touch ($p_entry['filename'], $p_entry['mtime']);
3919. }
3921. // ----- Look for chmod option
3922. if (isset($p_options[ PCLZIP_OPT_SET_CHMOD ])) {
3924. // ----- Change the mode of the file
3925. @ chmod ($p_entry['filename'], $p_options[ PCLZIP_OPT_SET_CHMOD ]);
3926. }
3928. }
3929. }
3931. // ----- Change abort status
3932. if ($p_entry['status'] == "aborted") {
3933. $p_entry['status'] = "skipped";
3934. }
3936. // ----- Look for post-extract callback
3937. elseif (isset($p_options[ PCLZIP_CB_POST_EXTRACT ])) {
3939. // ----- Generate a local information
3940. $v_local_header = array();
3941. $this-> privConvertHeader2FileInfo ($p_entry, $v_local_header);
3943. // ----- Call the callback
3944. // Here I do not use call_user_func() because I need to send a reference to the
3945. // header.
3946. // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3947. $v_result = $p_options[ PCLZIP_CB_POST_EXTRACT ]( PCLZIP_CB_POST_EXTRACT , $v_local_header);
3949. // ----- Look for abort result
3950. if ($v_result == 2) {
3951. $v_result = PCLZIP_ERR_USER_ABORTED ;
3952. }
3953. }
3955. // ----- Return
3956. return $v_result;
3957. }
3958. // --------------------------------------------------------------------------------
3960. // --------------------------------------------------------------------------------
3961. // Function : privExtractFileUsingTempFile()
3962. // Description :
3963. // Parameters :
3964. // Return Values :
3965. // --------------------------------------------------------------------------------
3966. function privExtractFileUsingTempFile (&$p_entry, &$p_options)
3967. {
3968. $v_result=1;
3970. // ----- Creates a temporary file
3971. $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid ('pclzip-').'.gz';
3972. if (($v_dest_file = @ fopen ($v_gzip_temp_name, "wb")) == 0) {
3973. fclose ($v_file);
3974. PclZip :: privErrorLog ( PCLZIP_ERR_WRITE_OPEN_FAIL , 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
3975. return PclZip :: errorCode ();
3976. }
3979. // ----- Write gz file format header
3980. $v_binary_data = pack ('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time (), Chr(0x00), Chr(3));
3981. @ fwrite ($v_dest_file, $v_binary_data, 10);
3983. // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3984. $v_size = $p_entry['compressed_size'];
3985. while ($v_size != 0)
3986. {
3987. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
3988. $v_buffer = @ fread ($this-> zip_fd , $v_read_size);
3989. //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3990. @ fwrite ($v_dest_file, $v_buffer, $v_read_size);
3991. $v_size -= $v_read_size;
3992. }
3994. // ----- Write gz file format footer
3995. $v_binary_data = pack ('VV', $p_entry['crc'], $p_entry['size']);
3996. @ fwrite ($v_dest_file, $v_binary_data, 8);
3998. // ----- Close the temporary file
3999. @ fclose ($v_dest_file);
4001. // ----- Opening destination file
4002. if (($v_dest_file = @ fopen ($p_entry['filename'], 'wb')) == 0) {
4003. $p_entry['status'] = "write_error";
4004. return $v_result;
4005. }
4007. // ----- Open the temporary gz file
4008. if (($v_src_file = @ gzopen ($v_gzip_temp_name, 'rb')) == 0) {
4009. @ fclose ($v_dest_file);
4010. $p_entry['status'] = "read_error";
4011. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
4012. return PclZip :: errorCode ();
4013. }
4016. // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
4017. $v_size = $p_entry['size'];
4018. while ($v_size != 0) {
4019. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
4020. $v_buffer = @ gzread ($v_src_file, $v_read_size);
4021. //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
4022. @ fwrite ($v_dest_file, $v_buffer, $v_read_size);
4023. $v_size -= $v_read_size;
4024. }
4025. @ fclose ($v_dest_file);
4026. @ gzclose ($v_src_file);
4028. // ----- Delete the temporary file
4029. @ unlink ($v_gzip_temp_name);
4031. // ----- Return
4032. return $v_result;
4033. }
4034. // --------------------------------------------------------------------------------
4036. // --------------------------------------------------------------------------------
4037. // Function : privExtractFileInOutput()
4038. // Description :
4039. // Parameters :
4040. // Return Values :
4041. // --------------------------------------------------------------------------------
4042. function privExtractFileInOutput (&$p_entry, &$p_options)
4043. {
4044. $v_result=1;
4046. // ----- Read the file header
4047. if (($v_result = $this-> privReadFileHeader ($v_header)) != 1) {
4048. return $v_result;
4049. }
4052. // ----- Check that the file header is coherent with $p_entry info
4053. if ($this-> privCheckFileHeaders ($v_header, $p_entry) != 1) {
4054. // TBC
4055. }
4057. // ----- Look for pre-extract callback
4058. if (isset($p_options[ PCLZIP_CB_PRE_EXTRACT ])) {
4060. // ----- Generate a local information
4061. $v_local_header = array();
4062. $this-> privConvertHeader2FileInfo ($p_entry, $v_local_header);
4064. // ----- Call the callback
4065. // Here I do not use call_user_func() because I need to send a reference to the
4066. // header.
4067. // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4068. $v_result = $p_options[ PCLZIP_CB_PRE_EXTRACT ]( PCLZIP_CB_PRE_EXTRACT , $v_local_header);
4069. if ($v_result == 0) {
4070. // ----- Change the file status
4071. $p_entry['status'] = "skipped";
4072. $v_result = 1;
4073. }
4075. // ----- Look for abort result
4076. if ($v_result == 2) {
4077. // ----- This status is internal and will be changed in 'skipped'
4078. $p_entry['status'] = "aborted";
4079. $v_result = PCLZIP_ERR_USER_ABORTED ;
4080. }
4082. // ----- Update the informations
4083. // Only some fields can be modified
4084. $p_entry['filename'] = $v_local_header['filename'];
4085. }
4087. // ----- Trace
4089. // ----- Look if extraction should be done
4090. if ($p_entry['status'] == 'ok') {
4092. // ----- Do the extraction (if not a folder)
4093. if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4094. // ----- Look for not compressed file
4095. if ($p_entry['compressed_size'] == $p_entry['size']) {
4097. // ----- Read the file in a buffer (one shot)
4098. $v_buffer = @ fread ($this-> zip_fd , $p_entry['compressed_size']);
4100. // ----- Send the file to the output
4101. echo $v_buffer;
4102. unset($v_buffer);
4103. }
4104. else {
4106. // ----- Read the compressed file in a buffer (one shot)
4107. $v_buffer = @ fread ($this-> zip_fd , $p_entry['compressed_size']);
4109. // ----- Decompress the file
4110. $v_file_content = gzinflate ($v_buffer);
4111. unset($v_buffer);
4113. // ----- Send the file to the output
4114. echo $v_file_content;
4115. unset($v_file_content);
4116. }
4117. }
4118. }
4120. // ----- Change abort status
4121. if ($p_entry['status'] == "aborted") {
4122. $p_entry['status'] = "skipped";
4123. }
4125. // ----- Look for post-extract callback
4126. elseif (isset($p_options[ PCLZIP_CB_POST_EXTRACT ])) {
4128. // ----- Generate a local information
4129. $v_local_header = array();
4130. $this-> privConvertHeader2FileInfo ($p_entry, $v_local_header);
4132. // ----- Call the callback
4133. // Here I do not use call_user_func() because I need to send a reference to the
4134. // header.
4135. // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4136. $v_result = $p_options[ PCLZIP_CB_POST_EXTRACT ]( PCLZIP_CB_POST_EXTRACT , $v_local_header);
4138. // ----- Look for abort result
4139. if ($v_result == 2) {
4140. $v_result = PCLZIP_ERR_USER_ABORTED ;
4141. }
4142. }
4144. return $v_result;
4145. }
4146. // --------------------------------------------------------------------------------
4148. // --------------------------------------------------------------------------------
4149. // Function : privExtractFileAsString()
4150. // Description :
4151. // Parameters :
4152. // Return Values :
4153. // --------------------------------------------------------------------------------
4154. function privExtractFileAsString (&$p_entry, &$p_string, &$p_options)
4155. {
4156. $v_result=1;
4158. // ----- Read the file header
4159. $v_header = array();
4160. if (($v_result = $this-> privReadFileHeader ($v_header)) != 1)
4161. {
4162. // ----- Return
4163. return $v_result;
4164. }
4167. // ----- Check that the file header is coherent with $p_entry info
4168. if ($this-> privCheckFileHeaders ($v_header, $p_entry) != 1) {
4169. // TBC
4170. }
4172. // ----- Look for pre-extract callback
4173. if (isset($p_options[ PCLZIP_CB_PRE_EXTRACT ])) {
4175. // ----- Generate a local information
4176. $v_local_header = array();
4177. $this-> privConvertHeader2FileInfo ($p_entry, $v_local_header);
4179. // ----- Call the callback
4180. // Here I do not use call_user_func() because I need to send a reference to the
4181. // header.
4182. // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4183. $v_result = $p_options[ PCLZIP_CB_PRE_EXTRACT ]( PCLZIP_CB_PRE_EXTRACT , $v_local_header);
4184. if ($v_result == 0) {
4185. // ----- Change the file status
4186. $p_entry['status'] = "skipped";
4187. $v_result = 1;
4188. }
4190. // ----- Look for abort result
4191. if ($v_result == 2) {
4192. // ----- This status is internal and will be changed in 'skipped'
4193. $p_entry['status'] = "aborted";
4194. $v_result = PCLZIP_ERR_USER_ABORTED ;
4195. }
4197. // ----- Update the informations
4198. // Only some fields can be modified
4199. $p_entry['filename'] = $v_local_header['filename'];
4200. }
4203. // ----- Look if extraction should be done
4204. if ($p_entry['status'] == 'ok') {
4206. // ----- Do the extraction (if not a folder)
4207. if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4208. // ----- Look for not compressed file
4209. // if ($p_entry['compressed_size'] == $p_entry['size'])
4210. if ($p_entry['compression'] == 0) {
4212. // ----- Reading the file
4213. $p_string = @ fread ($this-> zip_fd , $p_entry['compressed_size']);
4214. }
4215. else {
4217. // ----- Reading the file
4218. $v_data = @ fread ($this-> zip_fd , $p_entry['compressed_size']);
4220. // ----- Decompress the file
4221. if (($p_string = @ gzinflate ($v_data)) === FALSE) {
4222. // TBC
4223. }
4224. }
4226. // ----- Trace
4227. }
4228. else {
4229. // TBC : error : can not extract a folder in a string
4230. }
4232. }
4234. // ----- Change abort status
4235. if ($p_entry['status'] == "aborted") {
4236. $p_entry['status'] = "skipped";
4237. }
4239. // ----- Look for post-extract callback
4240. elseif (isset($p_options[ PCLZIP_CB_POST_EXTRACT ])) {
4242. // ----- Generate a local information
4243. $v_local_header = array();
4244. $this-> privConvertHeader2FileInfo ($p_entry, $v_local_header);
4246. // ----- Swap the content to header
4247. $v_local_header['content'] = $p_string;
4248. $p_string = '';
4250. // ----- Call the callback
4251. // Here I do not use call_user_func() because I need to send a reference to the
4252. // header.
4253. // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4254. $v_result = $p_options[ PCLZIP_CB_POST_EXTRACT ]( PCLZIP_CB_POST_EXTRACT , $v_local_header);
4256. // ----- Swap back the content to header
4257. $p_string = $v_local_header['content'];
4258. unset($v_local_header['content']);
4260. // ----- Look for abort result
4261. if ($v_result == 2) {
4262. $v_result = PCLZIP_ERR_USER_ABORTED ;
4263. }
4264. }
4266. // ----- Return
4267. return $v_result;
4268. }
4269. // --------------------------------------------------------------------------------
4271. // --------------------------------------------------------------------------------
4272. // Function : privReadFileHeader()
4273. // Description :
4274. // Parameters :
4275. // Return Values :
4276. // --------------------------------------------------------------------------------
4277. function privReadFileHeader (&$p_header)
4278. {
4279. $v_result=1;
4281. // ----- Read the 4 bytes signature
4282. $v_binary_data = @ fread ($this-> zip_fd , 4);
4283. $v_data = unpack ('Vid', $v_binary_data);
4285. // ----- Check signature
4286. if ($v_data['id'] != 0x04034b50)
4287. {
4289. // ----- Error log
4290. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , 'Invalid archive structure');
4292. // ----- Return
4293. return PclZip :: errorCode ();
4294. }
4296. // ----- Read the first 42 bytes of the header
4297. $v_binary_data = fread ($this-> zip_fd , 26);
4299. // ----- Look for invalid block size
4300. if ( strlen ($v_binary_data) != 26)
4301. {
4302. $p_header['filename'] = "";
4303. $p_header['status'] = "invalid_header";
4305. // ----- Error log
4306. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , "Invalid block size : ".strlen ($v_binary_data));
4308. // ----- Return
4309. return PclZip :: errorCode ();
4310. }
4312. // ----- Extract the values
4313. $v_data = unpack ('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
4315. // ----- Get filename
4316. $p_header['filename'] = fread ($this-> zip_fd , $v_data['filename_len']);
4318. // ----- Get extra_fields
4319. if ($v_data['extra_len'] != 0) {
4320. $p_header['extra'] = fread ($this-> zip_fd , $v_data['extra_len']);
4321. }
4322. else {
4323. $p_header['extra'] = '';
4324. }
4326. // ----- Extract properties
4327. $p_header['version_extracted'] = $v_data['version'];
4328. $p_header['compression'] = $v_data['compression'];
4329. $p_header['size'] = $v_data['size'];
4330. $p_header['compressed_size'] = $v_data['compressed_size'];
4331. $p_header['crc'] = $v_data['crc'];
4332. $p_header['flag'] = $v_data['flag'];
4333. $p_header['filename_len'] = $v_data['filename_len'];
4335. // ----- Recuperate date in UNIX format
4336. $p_header['mdate'] = $v_data['mdate'];
4337. $p_header['mtime'] = $v_data['mtime'];
4338. if ($p_header['mdate'] && $p_header['mtime'])
4339. {
4340. // ----- Extract time
4341. $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4342. $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4343. $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4345. // ----- Extract date
4346. $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4347. $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4348. $v_day = $p_header['mdate'] & 0x001F;
4350. // ----- Get UNIX date format
4351. $p_header['mtime'] = @ mktime ($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4353. }
4354. else
4355. {
4356. $p_header['mtime'] = time ();
4357. }
4359. // TBC
4360. //for(reset($v_data); $key = key($v_data); next($v_data)) {
4361. //}
4363. // ----- Set the stored filename
4364. $p_header['stored_filename'] = $p_header['filename'];
4366. // ----- Set the status field
4367. $p_header['status'] = "ok";
4369. // ----- Return
4370. return $v_result;
4371. }
4372. // --------------------------------------------------------------------------------
4374. // --------------------------------------------------------------------------------
4375. // Function : privReadCentralFileHeader()
4376. // Description :
4377. // Parameters :
4378. // Return Values :
4379. // --------------------------------------------------------------------------------
4380. function privReadCentralFileHeader (&$p_header)
4381. {
4382. $v_result=1;
4384. // ----- Read the 4 bytes signature
4385. $v_binary_data = @ fread ($this-> zip_fd , 4);
4386. $v_data = unpack ('Vid', $v_binary_data);
4388. // ----- Check signature
4389. if ($v_data['id'] != 0x02014b50)
4390. {
4392. // ----- Error log
4393. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , 'Invalid archive structure');
4395. // ----- Return
4396. return PclZip :: errorCode ();
4397. }
4399. // ----- Read the first 42 bytes of the header
4400. $v_binary_data = fread ($this-> zip_fd , 42);
4402. // ----- Look for invalid block size
4403. if ( strlen ($v_binary_data) != 42)
4404. {
4405. $p_header['filename'] = "";
4406. $p_header['status'] = "invalid_header";
4408. // ----- Error log
4409. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , "Invalid block size : ".strlen ($v_binary_data));
4411. // ----- Return
4412. return PclZip :: errorCode ();
4413. }
4415. // ----- Extract the values
4416. $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);
4418. // ----- Get filename
4419. if ($p_header['filename_len'] != 0)
4420. $p_header['filename'] = fread ($this-> zip_fd , $p_header['filename_len']);
4421. else
4422. $p_header['filename'] = '';
4424. // ----- Get extra
4425. if ($p_header['extra_len'] != 0)
4426. $p_header['extra'] = fread ($this-> zip_fd , $p_header['extra_len']);
4427. else
4428. $p_header['extra'] = '';
4430. // ----- Get comment
4431. if ($p_header['comment_len'] != 0)
4432. $p_header['comment'] = fread ($this-> zip_fd , $p_header['comment_len']);
4433. else
4434. $p_header['comment'] = '';
4436. // ----- Extract properties
4438. // ----- Recuperate date in UNIX format
4439. //if ($p_header['mdate'] && $p_header['mtime'])
4440. // TBC : bug : this was ignoring time with 0/0/0
4441. if (1)
4442. {
4443. // ----- Extract time
4444. $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4445. $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4446. $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4448. // ----- Extract date
4449. $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4450. $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4451. $v_day = $p_header['mdate'] & 0x001F;
4453. // ----- Get UNIX date format
4454. $p_header['mtime'] = @ mktime ($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4456. }
4457. else
4458. {
4459. $p_header['mtime'] = time ();
4460. }
4462. // ----- Set the stored filename
4463. $p_header['stored_filename'] = $p_header['filename'];
4465. // ----- Set default status to ok
4466. $p_header['status'] = 'ok';
4468. // ----- Look if it is a directory
4469. if ( substr ($p_header['filename'], -1) == '/') {
4470. //$p_header['external'] = 0x41FF0010;
4471. $p_header['external'] = 0x00000010;
4472. }
4475. // ----- Return
4476. return $v_result;
4477. }
4478. // --------------------------------------------------------------------------------
4480. // --------------------------------------------------------------------------------
4481. // Function : privCheckFileHeaders()
4482. // Description :
4483. // Parameters :
4484. // Return Values :
4485. // 1 on success,
4486. // 0 on error;
4487. // --------------------------------------------------------------------------------
4488. function privCheckFileHeaders (&$p_local_header, &$p_central_header)
4489. {
4490. $v_result=1;
4492. // ----- Check the static values
4493. // TBC
4494. if ($p_local_header['filename'] != $p_central_header['filename']) {
4495. }
4496. if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4497. }
4498. if ($p_local_header['flag'] != $p_central_header['flag']) {
4499. }
4500. if ($p_local_header['compression'] != $p_central_header['compression']) {
4501. }
4502. if ($p_local_header['mtime'] != $p_central_header['mtime']) {
4503. }
4504. if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
4505. }
4507. // ----- Look for flag bit 3
4508. if (($p_local_header['flag'] & 8) == 8) {
4509. $p_local_header['size'] = $p_central_header['size'];
4510. $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
4511. $p_local_header['crc'] = $p_central_header['crc'];
4512. }
4514. // ----- Return
4515. return $v_result;
4516. }
4517. // --------------------------------------------------------------------------------
4519. // --------------------------------------------------------------------------------
4520. // Function : privReadEndCentralDir()
4521. // Description :
4522. // Parameters :
4523. // Return Values :
4524. // --------------------------------------------------------------------------------
4525. function privReadEndCentralDir (&$p_central_dir)
4526. {
4527. $v_result=1;
4529. // ----- Go to the end of the zip file
4530. $v_size = filesize ($this-> zipname );
4531. @ fseek ($this-> zip_fd , $v_size);
4532. if (@ ftell ($this-> zip_fd ) != $v_size)
4533. {
4534. // ----- Error log
4535. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , 'Unable to go to the end of the archive \''.$this-> zipname.'\'');
4537. // ----- Return
4538. return PclZip :: errorCode ();
4539. }
4541. // ----- First try : look if this is an archive with no commentaries (most of the time)
4542. // in this case the end of central dir is at 22 bytes of the file end
4543. $v_found = 0;
4544. if ($v_size > 26) {
4545. @ fseek ($this-> zip_fd , $v_size-22);
4546. if (($v_pos = @ ftell ($this-> zip_fd )) != ($v_size-22))
4547. {
4548. // ----- Error log
4549. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , 'Unable to seek back to the middle of the archive \''.$this-> zipname.'\'');
4551. // ----- Return
4552. return PclZip :: errorCode ();
4553. }
4555. // ----- Read for bytes
4556. $v_binary_data = @ fread ($this-> zip_fd , 4);
4557. $v_data = @ unpack ('Vid', $v_binary_data);
4559. // ----- Check signature
4560. if ($v_data['id'] == 0x06054b50) {
4561. $v_found = 1;
4562. }
4564. $v_pos = ftell ($this-> zip_fd );
4565. }
4567. // ----- Go back to the maximum possible size of the Central Dir End Record
4568. if (!$v_found) {
4569. $v_maximum_size = 65557; // 0xFFFF + 22;
4570. if ($v_maximum_size > $v_size)
4571. $v_maximum_size = $v_size;
4572. @ fseek ($this-> zip_fd , $v_size-$v_maximum_size);
4573. if (@ ftell ($this-> zip_fd ) != ($v_size-$v_maximum_size))
4574. {
4575. // ----- Error log
4576. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , 'Unable to seek back to the middle of the archive \''.$this-> zipname.'\'');
4578. // ----- Return
4579. return PclZip :: errorCode ();
4580. }
4582. // ----- Read byte per byte in order to find the signature
4583. $v_pos = ftell ($this-> zip_fd );
4584. $v_bytes = 0x00000000;
4585. while ($v_pos < $v_size)
4586. {
4587. // ----- Read a byte
4588. $v_byte = @ fread ($this-> zip_fd , 1);
4590. // ----- Add the byte
4591. //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
4592. // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
4593. // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
4594. $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
4596. // ----- Compare the bytes
4597. if ($v_bytes == 0x504b0506)
4598. {
4599. $v_pos++;
4600. break;
4601. }
4603. $v_pos++;
4604. }
4606. // ----- Look if not found end of central dir
4607. if ($v_pos == $v_size)
4608. {
4610. // ----- Error log
4611. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , "Unable to find End of Central Dir Record signature");
4613. // ----- Return
4614. return PclZip :: errorCode ();
4615. }
4616. }
4618. // ----- Read the first 18 bytes of the header
4619. $v_binary_data = fread ($this-> zip_fd , 18);
4621. // ----- Look for invalid block size
4622. if ( strlen ($v_binary_data) != 18)
4623. {
4625. // ----- Error log
4626. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT , "Invalid End of Central Dir Record size : ".strlen ($v_binary_data));
4628. // ----- Return
4629. return PclZip :: errorCode ();
4630. }
4632. // ----- Extract the values
4633. $v_data = unpack ('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
4635. // ----- Check the global size
4636. if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
4638. // ----- Removed in release 2.2 see readme file
4639. // The check of the file size is a little too strict.
4640. // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
4641. // While decrypted, zip has training 0 bytes
4642. if (0) {
4643. // ----- Error log
4644. PclZip :: privErrorLog ( PCLZIP_ERR_BAD_FORMAT ,
4645. 'The central dir is not at the end of the archive.'
4646. .' Some trailing bytes exists after the archive.');
4648. // ----- Return
4649. return PclZip :: errorCode ();
4650. }
4651. }
4653. // ----- Get comment
4654. if ($v_data['comment_size'] != 0) {
4655. $p_central_dir['comment'] = fread ($this-> zip_fd , $v_data['comment_size']);
4656. }
4657. else
4658. $p_central_dir['comment'] = '';
4660. $p_central_dir['entries'] = $v_data['entries'];
4661. $p_central_dir['disk_entries'] = $v_data['disk_entries'];
4662. $p_central_dir['offset'] = $v_data['offset'];
4663. $p_central_dir['size'] = $v_data['size'];
4664. $p_central_dir['disk'] = $v_data['disk'];
4665. $p_central_dir['disk_start'] = $v_data['disk_start'];
4667. // TBC
4668. //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
4669. //}
4671. // ----- Return
4672. return $v_result;
4673. }
4674. // --------------------------------------------------------------------------------
4676. // --------------------------------------------------------------------------------
4677. // Function : privDeleteByRule()
4678. // Description :
4679. // Parameters :
4680. // Return Values :
4681. // --------------------------------------------------------------------------------
4682. function privDeleteByRule (&$p_result_list, &$p_options)
4683. {
4684. $v_result=1;
4685. $v_list_detail = array();
4687. // ----- Open the zip file
4688. if (($v_result=$this-> privOpenFd ('rb')) != 1)
4689. {
4690. // ----- Return
4691. return $v_result;
4692. }
4694. // ----- Read the central directory informations
4695. $v_central_dir = array();
4696. if (($v_result = $this-> privReadEndCentralDir ($v_central_dir)) != 1)
4697. {
4698. $this-> privCloseFd ();
4699. return $v_result;
4700. }
4702. // ----- Go to beginning of File
4703. @ rewind ($this-> zip_fd );
4705. // ----- Scan all the files
4706. // ----- Start at beginning of Central Dir
4707. $v_pos_entry = $v_central_dir['offset'];
4708. @ rewind ($this-> zip_fd );
4709. if (@ fseek ($this-> zip_fd , $v_pos_entry))
4710. {
4711. // ----- Close the zip file
4712. $this-> privCloseFd ();
4714. // ----- Error log
4715. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ARCHIVE_ZIP , 'Invalid archive size');
4717. // ----- Return
4718. return PclZip :: errorCode ();
4719. }
4721. // ----- Read each entry
4722. $v_header_list = array();
4723. $j_start = 0;
4724. for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
4725. {
4727. // ----- Read the file header
4728. $v_header_list[$v_nb_extracted] = array();
4729. if (($v_result = $this-> privReadCentralFileHeader ($v_header_list[$v_nb_extracted])) != 1)
4730. {
4731. // ----- Close the zip file
4732. $this-> privCloseFd ();
4734. return $v_result;
4735. }
4738. // ----- Store the index
4739. $v_header_list[$v_nb_extracted]['index'] = $i;
4741. // ----- Look for the specific extract rules
4742. $v_found = false;
4744. // ----- Look for extract by name rule
4745. if ( (isset($p_options[ PCLZIP_OPT_BY_NAME ]))
4746. && ($p_options[ PCLZIP_OPT_BY_NAME ] != 0)) {
4748. // ----- Look if the filename is in the list
4749. for ($j=0; ($j<sizeof ($p_options[ PCLZIP_OPT_BY_NAME ])) && (!$v_found); $j++) {
4751. // ----- Look for a directory
4752. if ( substr ($p_options[ PCLZIP_OPT_BY_NAME ][$j], -1) == "/") {
4754. // ----- Look if the directory is in the filename path
4755. if ( ( strlen ($v_header_list[$v_nb_extracted]['stored_filename']) > strlen ($p_options[ PCLZIP_OPT_BY_NAME ][$j]))
4756. && ( substr ($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen ($p_options[ PCLZIP_OPT_BY_NAME ][$j])) == $p_options[ PCLZIP_OPT_BY_NAME ][$j])) {
4757. $v_found = true;
4758. }
4759. elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
4760. && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[ PCLZIP_OPT_BY_NAME ][$j])) {
4761. $v_found = true;
4762. }
4763. }
4764. // ----- Look for a filename
4765. elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[ PCLZIP_OPT_BY_NAME ][$j]) {
4766. $v_found = true;
4767. }
4768. }
4769. }
4771. // ----- Look for extract by ereg rule
4772. // ereg() is deprecated with PHP 5.3
4773. /*
4774. else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
4775. && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
4777. if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4778. $v_found = true;
4779. }
4780. }
4781. */
4783. // ----- Look for extract by preg rule
4784. else if ( (isset($p_options[ PCLZIP_OPT_BY_PREG ]))
4785. && ($p_options[ PCLZIP_OPT_BY_PREG ] != "")) {
4787. if ( preg_match ($p_options[ PCLZIP_OPT_BY_PREG ], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4788. $v_found = true;
4789. }
4790. }
4792. // ----- Look for extract by index rule
4793. else if ( (isset($p_options[ PCLZIP_OPT_BY_INDEX ]))
4794. && ($p_options[ PCLZIP_OPT_BY_INDEX ] != 0)) {
4796. // ----- Look if the index is in the list
4797. for ($j=$j_start; ($j<sizeof ($p_options[ PCLZIP_OPT_BY_INDEX ])) && (!$v_found); $j++) {
4799. if (($i>=$p_options[ PCLZIP_OPT_BY_INDEX ][$j]['start']) && ($i<=$p_options[ PCLZIP_OPT_BY_INDEX ][$j]['end'])) {
4800. $v_found = true;
4801. }
4802. if ($i>=$p_options[ PCLZIP_OPT_BY_INDEX ][$j]['end']) {
4803. $j_start = $j+1;
4804. }
4806. if ($p_options[ PCLZIP_OPT_BY_INDEX ][$j]['start']>$i) {
4807. break;
4808. }
4809. }
4810. }
4811. else {
4812. $v_found = true;
4813. }
4815. // ----- Look for deletion
4816. if ($v_found)
4817. {
4818. unset($v_header_list[$v_nb_extracted]);
4819. }
4820. else
4821. {
4822. $v_nb_extracted++;
4823. }
4824. }
4826. // ----- Look if something need to be deleted
4827. if ($v_nb_extracted > 0) {
4829. // ----- Creates a temporay file
4830. $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid ('pclzip-').'.tmp';
4832. // ----- Creates a temporary zip archive
4833. $v_temp_zip = new PclZip ($v_zip_temp_name);
4835. // ----- Open the temporary zip file in write mode
4836. if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4837. $this-> privCloseFd ();
4839. // ----- Return
4840. return $v_result;
4841. }
4843. // ----- Look which file need to be kept
4844. for ($i=0; $i<sizeof ($v_header_list); $i++) {
4846. // ----- Calculate the position of the header
4847. @ rewind ($this-> zip_fd );
4848. if (@ fseek ($this-> zip_fd , $v_header_list[$i]['offset'])) {
4849. // ----- Close the zip file
4850. $this-> privCloseFd ();
4851. $v_temp_zip->privCloseFd();
4852. @ unlink ($v_zip_temp_name);
4854. // ----- Error log
4855. PclZip :: privErrorLog ( PCLZIP_ERR_INVALID_ARCHIVE_ZIP , 'Invalid archive size');
4857. // ----- Return
4858. return PclZip :: errorCode ();
4859. }
4861. // ----- Read the file header
4862. $v_local_header = array();
4863. if (($v_result = $this-> privReadFileHeader ($v_local_header)) != 1) {
4864. // ----- Close the zip file
4865. $this-> privCloseFd ();
4866. $v_temp_zip->privCloseFd();
4867. @ unlink ($v_zip_temp_name);
4869. // ----- Return
4870. return $v_result;
4871. }
4873. // ----- Check that local file header is same as central file header
4874. if ($this-> privCheckFileHeaders ($v_local_header,
4875. $v_header_list[$i]) != 1) {
4876. // TBC
4877. }
4878. unset($v_local_header);
4880. // ----- Write the file header
4881. if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4882. // ----- Close the zip file
4883. $this-> privCloseFd ();
4884. $v_temp_zip->privCloseFd();
4885. @ unlink ($v_zip_temp_name);
4887. // ----- Return
4888. return $v_result;
4889. }
4891. // ----- Read/write the data block
4892. if (($v_result = PclZipUtilCopyBlock ($this-> zip_fd , $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4893. // ----- Close the zip file
4894. $this-> privCloseFd ();
4895. $v_temp_zip->privCloseFd();
4896. @ unlink ($v_zip_temp_name);
4898. // ----- Return
4899. return $v_result;
4900. }
4901. }
4903. // ----- Store the offset of the central dir
4904. $v_offset = @ ftell ($v_temp_zip->zip_fd);
4906. // ----- Re-Create the Central Dir files header
4907. for ($i=0; $i<sizeof ($v_header_list); $i++) {
4908. // ----- Create the file header
4909. if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4910. $v_temp_zip->privCloseFd();
4911. $this-> privCloseFd ();
4912. @ unlink ($v_zip_temp_name);
4914. // ----- Return
4915. return $v_result;
4916. }
4918. // ----- Transform the header to a 'usable' info
4919. $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4920. }
4923. // ----- Zip file comment
4924. $v_comment = '';
4925. if (isset($p_options[ PCLZIP_OPT_COMMENT ])) {
4926. $v_comment = $p_options[ PCLZIP_OPT_COMMENT ];
4927. }
4929. // ----- Calculate the size of the central header
4930. $v_size = @ ftell ($v_temp_zip->zip_fd)-$v_offset;
4932. // ----- Create the central dir footer
4933. if (($v_result = $v_temp_zip->privWriteCentralHeader( sizeof ($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
4934. // ----- Reset the file list
4935. unset($v_header_list);
4936. $v_temp_zip->privCloseFd();
4937. $this-> privCloseFd ();
4938. @ unlink ($v_zip_temp_name);
4940. // ----- Return
4941. return $v_result;
4942. }
4944. // ----- Close
4945. $v_temp_zip->privCloseFd();
4946. $this-> privCloseFd ();
4948. // ----- Delete the zip file
4949. // TBC : I should test the result ...
4950. @ unlink ($this-> zipname );
4952. // ----- Rename the temporary file
4953. // TBC : I should test the result ...
4954. //@rename($v_zip_temp_name, $this->zipname);
4955. PclZipUtilRename ($v_zip_temp_name, $this-> zipname );
4957. // ----- Destroy the temporary archive
4958. unset($v_temp_zip);
4959. }
4961. // ----- Remove every files : reset the file
4962. else if ($v_central_dir['entries'] != 0) {
4963. $this-> privCloseFd ();
4965. if (($v_result = $this-> privOpenFd ('wb')) != 1) {
4966. return $v_result;
4967. }
4969. if (($v_result = $this-> privWriteCentralHeader (0, 0, 0, '')) != 1) {
4970. return $v_result;
4971. }
4973. $this-> privCloseFd ();
4974. }
4976. // ----- Return
4977. return $v_result;
4978. }
4979. // --------------------------------------------------------------------------------
4981. // --------------------------------------------------------------------------------
4982. // Function : privDirCheck()
4983. // Description :
4984. // Check if a directory exists, if not it creates it and all the parents directory
4985. // which may be useful.
4986. // Parameters :
4987. // $p_dir : Directory path to check.
4988. // Return Values :
4989. // 1 : OK
4990. // -1 : Unable to create directory
4991. // --------------------------------------------------------------------------------
4992. function privDirCheck ($p_dir, $p_is_dir=false)
4993. {
4994. $v_result = 1;
4997. // ----- Remove the final '/'
4998. if (($p_is_dir) && ( substr ($p_dir, -1)=='/'))
4999. {
5000. $p_dir = substr ($p_dir, 0, strlen ($p_dir)-1);
5001. }
5003. // ----- Check the directory availability
5004. if (( is_dir ($p_dir)) || ($p_dir == ""))
5005. {
5006. return 1;
5007. }
5009. // ----- Extract parent directory
5010. $p_parent_dir = dirname ($p_dir);
5012. // ----- Just a check
5013. if ($p_parent_dir != $p_dir)
5014. {
5015. // ----- Look for parent directory
5016. if ($p_parent_dir != "")
5017. {
5018. if (($v_result = $this-> privDirCheck ($p_parent_dir)) != 1)
5019. {
5020. return $v_result;
5021. }
5022. }
5023. }
5025. // ----- Create the directory
5026. if (!@ mkdir ($p_dir, 0777))
5027. {
5028. // ----- Error log
5029. PclZip :: privErrorLog ( PCLZIP_ERR_DIR_CREATE_FAIL , "Unable to create directory '$p_dir'");
5031. // ----- Return
5032. return PclZip :: errorCode ();
5033. }
5035. // ----- Return
5036. return $v_result;
5037. }
5038. // --------------------------------------------------------------------------------
5040. // --------------------------------------------------------------------------------
5041. // Function : privMerge()
5042. // Description :
5043. // If $p_archive_to_add does not exist, the function exit with a success result.
5044. // Parameters :
5045. // Return Values :
5046. // --------------------------------------------------------------------------------
5047. function privMerge (&$p_archive_to_add)
5048. {
5049. $v_result=1;
5051. // ----- Look if the archive_to_add exists
5052. if (! is_file ($p_archive_to_add->zipname))
5053. {
5055. // ----- Nothing to merge, so merge is a success
5056. $v_result = 1;
5058. // ----- Return
5059. return $v_result;
5060. }
5062. // ----- Look if the archive exists
5063. if (! is_file ($this-> zipname ))
5064. {
5066. // ----- Do a duplicate
5067. $v_result = $this-> privDuplicate ($p_archive_to_add->zipname);
5069. // ----- Return
5070. return $v_result;
5071. }
5073. // ----- Open the zip file
5074. if (($v_result=$this-> privOpenFd ('rb')) != 1)
5075. {
5076. // ----- Return
5077. return $v_result;
5078. }
5080. // ----- Read the central directory informations
5081. $v_central_dir = array();
5082. if (($v_result = $this-> privReadEndCentralDir ($v_central_dir)) != 1)
5083. {
5084. $this-> privCloseFd ();
5085. return $v_result;
5086. }
5088. // ----- Go to beginning of File
5089. @ rewind ($this-> zip_fd );
5091. // ----- Open the archive_to_add file
5092. if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
5093. {
5094. $this-> privCloseFd ();
5096. // ----- Return
5097. return $v_result;
5098. }
5100. // ----- Read the central directory informations
5101. $v_central_dir_to_add = array();
5102. if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
5103. {
5104. $this-> privCloseFd ();
5105. $p_archive_to_add->privCloseFd();
5107. return $v_result;
5108. }
5110. // ----- Go to beginning of File
5111. @ rewind ($p_archive_to_add->zip_fd);
5113. // ----- Creates a temporay file
5114. $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid ('pclzip-').'.tmp';
5116. // ----- Open the temporary file in write mode
5117. if (($v_zip_temp_fd = @ fopen ($v_zip_temp_name, 'wb')) == 0)
5118. {
5119. $this-> privCloseFd ();
5120. $p_archive_to_add->privCloseFd();
5122. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
5124. // ----- Return
5125. return PclZip :: errorCode ();
5126. }
5128. // ----- Copy the files from the archive to the temporary file
5129. // TBC : Here I should better append the file and go back to erase the central dir
5130. $v_size = $v_central_dir['offset'];
5131. while ($v_size != 0)
5132. {
5133. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
5134. $v_buffer = fread ($this-> zip_fd , $v_read_size);
5135. @ fwrite ($v_zip_temp_fd, $v_buffer, $v_read_size);
5136. $v_size -= $v_read_size;
5137. }
5139. // ----- Copy the files from the archive_to_add into the temporary file
5140. $v_size = $v_central_dir_to_add['offset'];
5141. while ($v_size != 0)
5142. {
5143. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
5144. $v_buffer = fread ($p_archive_to_add->zip_fd, $v_read_size);
5145. @ fwrite ($v_zip_temp_fd, $v_buffer, $v_read_size);
5146. $v_size -= $v_read_size;
5147. }
5149. // ----- Store the offset of the central dir
5150. $v_offset = @ ftell ($v_zip_temp_fd);
5152. // ----- Copy the block of file headers from the old archive
5153. $v_size = $v_central_dir['size'];
5154. while ($v_size != 0)
5155. {
5156. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
5157. $v_buffer = @ fread ($this-> zip_fd , $v_read_size);
5158. @ fwrite ($v_zip_temp_fd, $v_buffer, $v_read_size);
5159. $v_size -= $v_read_size;
5160. }
5162. // ----- Copy the block of file headers from the archive_to_add
5163. $v_size = $v_central_dir_to_add['size'];
5164. while ($v_size != 0)
5165. {
5166. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
5167. $v_buffer = @ fread ($p_archive_to_add->zip_fd, $v_read_size);
5168. @ fwrite ($v_zip_temp_fd, $v_buffer, $v_read_size);
5169. $v_size -= $v_read_size;
5170. }
5172. // ----- Merge the file comments
5173. $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
5175. // ----- Calculate the size of the (new) central header
5176. $v_size = @ ftell ($v_zip_temp_fd)-$v_offset;
5178. // ----- Swap the file descriptor
5179. // Here is a trick : I swap the temporary fd with the zip fd, in order to use
5180. // the following methods on the temporary fil and not the real archive fd
5181. $v_swap = $this-> zip_fd ;
5182. $this-> zip_fd = $v_zip_temp_fd;
5183. $v_zip_temp_fd = $v_swap;
5185. // ----- Create the central dir footer
5186. if (($v_result = $this-> privWriteCentralHeader ($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
5187. {
5188. $this-> privCloseFd ();
5189. $p_archive_to_add->privCloseFd();
5190. @ fclose ($v_zip_temp_fd);
5191. $this-> zip_fd = null;
5193. // ----- Reset the file list
5194. unset($v_header_list);
5196. // ----- Return
5197. return $v_result;
5198. }
5200. // ----- Swap back the file descriptor
5201. $v_swap = $this-> zip_fd ;
5202. $this-> zip_fd = $v_zip_temp_fd;
5203. $v_zip_temp_fd = $v_swap;
5205. // ----- Close
5206. $this-> privCloseFd ();
5207. $p_archive_to_add->privCloseFd();
5209. // ----- Close the temporary file
5210. @ fclose ($v_zip_temp_fd);
5212. // ----- Delete the zip file
5213. // TBC : I should test the result ...
5214. @ unlink ($this-> zipname );
5216. // ----- Rename the temporary file
5217. // TBC : I should test the result ...
5218. //@rename($v_zip_temp_name, $this->zipname);
5219. PclZipUtilRename ($v_zip_temp_name, $this-> zipname );
5221. // ----- Return
5222. return $v_result;
5223. }
5224. // --------------------------------------------------------------------------------
5226. // --------------------------------------------------------------------------------
5227. // Function : privDuplicate()
5228. // Description :
5229. // Parameters :
5230. // Return Values :
5231. // --------------------------------------------------------------------------------
5232. function privDuplicate ($p_archive_filename)
5233. {
5234. $v_result=1;
5236. // ----- Look if the $p_archive_filename exists
5237. if (! is_file ($p_archive_filename))
5238. {
5240. // ----- Nothing to duplicate, so duplicate is a success.
5241. $v_result = 1;
5243. // ----- Return
5244. return $v_result;
5245. }
5247. // ----- Open the zip file
5248. if (($v_result=$this-> privOpenFd ('wb')) != 1)
5249. {
5250. // ----- Return
5251. return $v_result;
5252. }
5254. // ----- Open the temporary file in write mode
5255. if (($v_zip_temp_fd = @ fopen ($p_archive_filename, 'rb')) == 0)
5256. {
5257. $this-> privCloseFd ();
5259. PclZip :: privErrorLog ( PCLZIP_ERR_READ_OPEN_FAIL , 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
5261. // ----- Return
5262. return PclZip :: errorCode ();
5263. }
5265. // ----- Copy the files from the archive to the temporary file
5266. // TBC : Here I should better append the file and go back to erase the central dir
5267. $v_size = filesize ($p_archive_filename);
5268. while ($v_size != 0)
5269. {
5270. $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE );
5271. $v_buffer = fread ($v_zip_temp_fd, $v_read_size);
5272. @ fwrite ($this-> zip_fd , $v_buffer, $v_read_size);
5273. $v_size -= $v_read_size;
5274. }
5276. // ----- Close
5277. $this-> privCloseFd ();
5279. // ----- Close the temporary file
5280. @ fclose ($v_zip_temp_fd);
5282. // ----- Return
5283. return $v_result;
5284. }
5285. // --------------------------------------------------------------------------------
5287. // --------------------------------------------------------------------------------
5288. // Function : privErrorLog()
5289. // Description :
5290. // Parameters :
5291. // --------------------------------------------------------------------------------
5292. function privErrorLog ($p_error_code=0, $p_error_string='')
5293. {
5294. if ( PCLZIP_ERROR_EXTERNAL == 1) {
5295. PclError($p_error_code, $p_error_string);
5296. }
5297. else {
5298. $this-> error_code = $p_error_code;
5299. $this-> error_string = $p_error_string;
5300. }
5301. }
5302. // --------------------------------------------------------------------------------
5304. // --------------------------------------------------------------------------------
5305. // Function : privErrorReset()
5306. // Description :
5307. // Parameters :
5308. // --------------------------------------------------------------------------------
5309. function privErrorReset ()
5310. {
5311. if ( PCLZIP_ERROR_EXTERNAL == 1) {
5312. PclErrorReset();
5313. }
5314. else {
5315. $this-> error_code = 0;
5316. $this-> error_string = '';
5317. }
5318. }
5319. // --------------------------------------------------------------------------------
5321. // --------------------------------------------------------------------------------
5322. // Function : privDisableMagicQuotes()
5323. // Description :
5324. // Parameters :
5325. // Return Values :
5326. // --------------------------------------------------------------------------------
5327. function privDisableMagicQuotes ()
5328. {
5329. $v_result=1;
5331. // ----- Look if function exists
5332. if ( (! function_exists ("get_magic_quotes_runtime"))
5333. || (! function_exists ("set_magic_quotes_runtime"))) {
5334. return $v_result;
5335. }
5337. // ----- Look if already done
5338. if ($this-> magic_quotes_status != -1) {
5339. return $v_result;
5340. }
5342. // ----- Get and memorize the magic_quote value
5343. $this-> magic_quotes_status = @ get_magic_quotes_runtime ();
5345. // ----- Disable magic_quotes
5346. if ($this-> magic_quotes_status == 1) {
5347. @ set_magic_quotes_runtime (0);
5348. }
5350. // ----- Return
5351. return $v_result;
5352. }
5353. // --------------------------------------------------------------------------------
5355. // --------------------------------------------------------------------------------
5356. // Function : privSwapBackMagicQuotes()
5357. // Description :
5358. // Parameters :
5359. // Return Values :
5360. // --------------------------------------------------------------------------------
5361. function privSwapBackMagicQuotes ()
5362. {
5363. $v_result=1;
5365. // ----- Look if function exists
5366. if ( (! function_exists ("get_magic_quotes_runtime"))
5367. || (! function_exists ("set_magic_quotes_runtime"))) {
5368. return $v_result;
5369. }
5371. // ----- Look if something to do
5372. if ($this-> magic_quotes_status != -1) {
5373. return $v_result;
5374. }
5376. // ----- Swap back magic_quotes
5377. if ($this-> magic_quotes_status == 1) {
5378. @ set_magic_quotes_runtime ($this-> magic_quotes_status );
5379. }
5381. // ----- Return
5382. return $v_result;
5383. }
5384. // --------------------------------------------------------------------------------
5386. }
5387. // End of class
5388. // --------------------------------------------------------------------------------
5390. // --------------------------------------------------------------------------------
5391. // Function : PclZipUtilPathReduction()
5392. // Description :
5393. // Parameters :
5394. // Return Values :
5395. // --------------------------------------------------------------------------------
5396. function PclZipUtilPathReduction ($p_dir)
5397. {
5398. $v_result = "";
5400. // ----- Look for not empty path
5401. if ($p_dir != "") {
5402. // ----- Explode path by directory names
5403. $v_list = explode ("/", $p_dir);
5405. // ----- Study directories from last to first
5406. $v_skip = 0;
5407. for ($i=sizeof ($v_list)-1; $i>=0; $i--) {
5408. // ----- Look for current path
5409. if ($v_list[$i] == ".") {
5410. // ----- Ignore this directory
5411. // Should be the first $i=0, but no check is done
5412. }
5413. else if ($v_list[$i] == "..") {
5414. $v_skip++;
5415. }
5416. else if ($v_list[$i] == "") {
5417. // ----- First '/' i.e. root slash
5418. if ($i == 0) {
5419. $v_result = "/".$v_result;
5420. if ($v_skip > 0) {
5421. // ----- It is an invalid path, so the path is not modified
5422. // TBC
5423. $v_result = $p_dir;
5424. $v_skip = 0;
5425. }
5426. }
5427. // ----- Last '/' i.e. indicates a directory
5428. else if ($i == ( sizeof ($v_list)-1)) {
5429. $v_result = $v_list[$i];
5430. }
5431. // ----- Double '/' inside the path
5432. else {
5433. // ----- Ignore only the double '//' in path,
5434. // but not the first and last '/'
5435. }
5436. }
5437. else {
5438. // ----- Look for item to skip
5439. if ($v_skip > 0) {
5440. $v_skip--;
5441. }
5442. else {
5443. $v_result = $v_list[$i].($i!=( sizeof ($v_list)-1)?"/".$v_result:"");
5444. }
5445. }
5446. }
5448. // ----- Look for skip
5449. if ($v_skip > 0) {
5450. while ($v_skip > 0) {
5451. $v_result = '../'.$v_result;
5452. $v_skip--;
5453. }
5454. }
5455. }
5457. // ----- Return
5458. return $v_result;
5459. }
5460. // --------------------------------------------------------------------------------
5462. // --------------------------------------------------------------------------------
5463. // Function : PclZipUtilPathInclusion()
5464. // Description :
5465. // This function indicates if the path $p_path is under the $p_dir tree. Or,
5466. // said in an other way, if the file or sub-dir $p_path is inside the dir
5467. // $p_dir.
5468. // The function indicates also if the path is exactly the same as the dir.
5469. // This function supports path with duplicated '/' like '//', but does not
5470. // support '.' or '..' statements.
5471. // Parameters :
5472. // Return Values :
5473. // 0 if $p_path is not inside directory $p_dir
5474. // 1 if $p_path is inside directory $p_dir
5475. // 2 if $p_path is exactly the same as $p_dir
5476. // --------------------------------------------------------------------------------
5477. function PclZipUtilPathInclusion ($p_dir, $p_path)
5478. {
5479. $v_result = 1;
5481. // ----- Look for path beginning by ./
5482. if ( ($p_dir == '.')
5483. || (( strlen ($p_dir) >=2) && ( substr ($p_dir, 0, 2) == './'))) {
5484. $p_dir = PclZipUtilTranslateWinPath ( getcwd (), FALSE).'/'.substr ($p_dir, 1);
5485. }
5486. if ( ($p_path == '.')
5487. || (( strlen ($p_path) >=2) && ( substr ($p_path, 0, 2) == './'))) {
5488. $p_path = PclZipUtilTranslateWinPath ( getcwd (), FALSE).'/'.substr ($p_path, 1);
5489. }
5491. // ----- Explode dir and path by directory separator
5492. $v_list_dir = explode ("/", $p_dir);
5493. $v_list_dir_size = sizeof ($v_list_dir);
5494. $v_list_path = explode ("/", $p_path);
5495. $v_list_path_size = sizeof ($v_list_path);
5497. // ----- Study directories paths
5498. $i = 0;
5499. $j = 0;
5500. while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
5502. // ----- Look for empty dir (path reduction)
5503. if ($v_list_dir[$i] == '') {
5504. $i++;
5505. continue;
5506. }
5507. if ($v_list_path[$j] == '') {
5508. $j++;
5509. continue;
5510. }
5512. // ----- Compare the items
5513. if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
5514. $v_result = 0;
5515. }
5517. // ----- Next items
5518. $i++;
5519. $j++;
5520. }
5522. // ----- Look if everything seems to be the same
5523. if ($v_result) {
5524. // ----- Skip all the empty items
5525. while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
5526. while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
5528. if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
5529. // ----- There are exactly the same
5530. $v_result = 2;
5531. }
5532. else if ($i < $v_list_dir_size) {
5533. // ----- The path is shorter than the dir
5534. $v_result = 0;
5535. }
5536. }
5538. // ----- Return
5539. return $v_result;
5540. }
5541. // --------------------------------------------------------------------------------
5543. // --------------------------------------------------------------------------------
5544. // Function : PclZipUtilCopyBlock()
5545. // Description :
5546. // Parameters :
5547. // $p_mode : read/write compression mode
5548. // 0 : src & dest normal
5549. // 1 : src gzip, dest normal
5550. // 2 : src normal, dest gzip
5551. // 3 : src & dest gzip
5552. // Return Values :
5553. // --------------------------------------------------------------------------------
5554. function PclZipUtilCopyBlock ($p_src, $p_dest, $p_size, $p_mode=0)
5555. {
5556. $v_result = 1;
5558. if ($p_mode==0)
5559. {
5560. while ($p_size != 0)
5561. {
5562. $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE );
5563. $v_buffer = @ fread ($p_src, $v_read_size);
5564. @ fwrite ($p_dest, $v_buffer, $v_read_size);
5565. $p_size -= $v_read_size;
5566. }
5567. }
5568. else if ($p_mode==1)
5569. {
5570. while ($p_size != 0)
5571. {
5572. $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE );
5573. $v_buffer = @ gzread ($p_src, $v_read_size);
5574. @ fwrite ($p_dest, $v_buffer, $v_read_size);
5575. $p_size -= $v_read_size;
5576. }
5577. }
5578. else if ($p_mode==2)
5579. {
5580. while ($p_size != 0)
5581. {
5582. $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE );
5583. $v_buffer = @ fread ($p_src, $v_read_size);
5584. @ gzwrite ($p_dest, $v_buffer, $v_read_size);
5585. $p_size -= $v_read_size;
5586. }
5587. }
5588. else if ($p_mode==3)
5589. {
5590. while ($p_size != 0)
5591. {
5592. $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE );
5593. $v_buffer = @ gzread ($p_src, $v_read_size);
5594. @ gzwrite ($p_dest, $v_buffer, $v_read_size);
5595. $p_size -= $v_read_size;
5596. }
5597. }
5599. // ----- Return
5600. return $v_result;
5601. }
5602. // --------------------------------------------------------------------------------
5604. // --------------------------------------------------------------------------------
5605. // Function : PclZipUtilRename()
5606. // Description :
5607. // This function tries to do a simple rename() function. If it fails, it
5608. // tries to copy the $p_src file in a new $p_dest file and then unlink the
5609. // first one.
5610. // Parameters :
5611. // $p_src : Old filename
5612. // $p_dest : New filename
5613. // Return Values :
5614. // 1 on success, 0 on failure.
5615. // --------------------------------------------------------------------------------
5616. function PclZipUtilRename ($p_src, $p_dest)
5617. {
5618. $v_result = 1;
5620. // ----- Try to rename the files
5621. if (!@ rename ($p_src, $p_dest)) {
5623. // ----- Try to copy & unlink the src
5624. if (!@ copy ($p_src, $p_dest)) {
5625. $v_result = 0;
5626. }
5627. else if (!@ unlink ($p_src)) {
5628. $v_result = 0;
5629. }
5630. }
5632. // ----- Return
5633. return $v_result;
5634. }
5635. // --------------------------------------------------------------------------------
5637. // --------------------------------------------------------------------------------
5638. // Function : PclZipUtilOptionText()
5639. // Description :
5640. // Translate option value in text. Mainly for debug purpose.
5641. // Parameters :
5642. // $p_option : the option value.
5643. // Return Values :
5644. // The option text value.
5645. // --------------------------------------------------------------------------------
5646. function PclZipUtilOptionText ($p_option)
5647. {
5649. $v_list = get_defined_constants ();
5650. for ( reset ($v_list); $v_key = key ($v_list); next ($v_list)) {
5651. $v_prefix = substr ($v_key, 0, 10);
5652. if (( ($v_prefix == 'PCLZIP_OPT')
5653. || ($v_prefix == 'PCLZIP_CB_')
5654. || ($v_prefix == 'PCLZIP_ATT'))
5655. && ($v_list[$v_key] == $p_option)) {
5656. return $v_key;
5657. }
5658. }
5660. $v_result = 'Unknown';
5662. return $v_result;
5663. }
5664. // --------------------------------------------------------------------------------
5666. // --------------------------------------------------------------------------------
5667. // Function : PclZipUtilTranslateWinPath()
5668. // Description :
5669. // Translate windows path by replacing '\' by '/' and optionally removing
5670. // drive letter.
5671. // Parameters :
5672. // $p_path : path to translate.
5673. // $p_remove_disk_letter : true | false
5674. // Return Values :
5675. // The path translated.
5676. // --------------------------------------------------------------------------------
5677. function PclZipUtilTranslateWinPath ($p_path, $p_remove_disk_letter=true)
5678. {
5679. if ( stristr ( php_uname (), 'windows')) {
5680. // ----- Look for potential disk letter
5681. if (($p_remove_disk_letter) && (($v_position = strpos ($p_path, ':')) != false)) {
5682. $p_path = substr ($p_path, $v_position+1);
5683. }
5684. // ----- Change potential windows directory separator
5685. if (( strpos ($p_path, '\\') > 0) || ( substr ($p_path, 0,1) == '\\')) {
5686. $p_path = strtr ($p_path, '\\', '/');
5687. }
5688. }
5689. return $p_path;
5690. }
5691. // --------------------------------------------------------------------------------
5694. ?>

Documentation generated on Fri, 12 Oct 2012 00:17:25 +0200 by phpDocumentor 1.4.4